مشروع مصغر: سكربت Ansible يجهز سيرفر Ubuntu خام بالكامل كخادم ويب جاهز
مشروع مصغر: سكربت Ansible يجهز سيرفر Ubuntu خام بالكامل كخادم ويب جاهز
عندما تستلم سيرفر Ubuntu جديداً من مزود سحابي، فأنت عملياً تبدأ من بيئة غير مكتملة: تحديثات نظام غير مطبقة، حزم أساسية ناقصة، جدار ناري غير مضبوط، ومستخدمون وصلاحيات قد لا تتوافق مع معايير الإنتاج. هنا تظهر القيمة الحقيقية لـ ما هو Ansible؟ وكيف تتحكم في 100 سيرفر Linux من حاسوبك المكتبي؟ لأنه يحول الإعداد اليدوي المتكرر إلى عملية موحدة، قابلة للإعادة، ويمكن تدقيقها بسهولة.
في هذا المشروع المصغر سنبني Playbook متقدماً يجهز السيرفر ليعمل كخادم ويب جاهز عبر تثبيت Nginx، تأمين الوصول، ضبط UFW، وإنشاء صفحة اختبار. الأهم أننا سنفكر بعقلية هندسية تجعل هذا الملف لاحقاً جزءاً من CI/CD Pipeline متكامل بدلاً من كونه مجرد سكربت عابر.
لماذا هذا المشروع مهم عملياً؟
الإعداد اليدوي لسيرفر واحد قد يبدو بسيطاً، لكن عند تكرار المهمة على عدة بيئات مثل staging وproduction تبدأ الفروقات الصغيرة في التراكم. نتيجة ذلك قد تواجه مشكلة اختلاف الإعدادات، أو خدمة تعمل في بيئة وتتوقف في أخرى، أو منافذ مفتوحة بلا داعٍ.
هذا النوع من الأتمتة يرتبط مباشرة بمفاهيم ما هو DevOps؟ ولماذا تدفع الشركات ثروات لمهندسي الأتمتة السحابية؟ لأن الهدف ليس فقط تنفيذ أوامر أسرع، بل بناء بيئة يمكن الوثوق بها. أي تغيير يصبح موثقاً داخل ملف YAML بدل أن يبقى معرفة شفوية داخل رأس مسؤول النظام.
المعمارية التي سنطبقها
سنفترض وجود جهاز تحكم محلي مثبت عليه Ansible، وسيرفر Ubuntu خام يمكن الوصول إليه عبر SSH. إذا لم تكن جهزت الاتصال مسبقاً فراجع إعداد الاتصال الآمن (SSH Keys) بدون كلمات مرور بين جهازك والخوادم لأن تشغيل الأتمتة بمفاتيح آمنة أفضل كثيراً من الاعتماد على كلمات المرور.
سنبني المشروع على ثلاثة مكونات أساسية:
- ملف
inventoryلتعريف الخادم. - ملف
playbookلتنفيذ المهام. - ملف قالب لصفحة ويب اختبارية للتأكد أن الخادم جاهز للخدمة.
ملف الجرد وتعريف الخادم
إذا كنت تريد فهماً أعمق لبناء ملفات الجرد فمقال كتابة ملفات الجرد (Inventory) لتعريف وتصنيف الخوادم يشرح الفكرة من الأساس. في مشروعنا سنستخدم ملفاً بسيطاً يكفي لسيرفر واحد، مع إمكانية توسعه لاحقاً لمجموعة كاملة.
all:
hosts:
web-01:
ansible_host: 192.0.2.10
ansible_user: ubuntu
ansible_ssh_private_key_file: ~/.ssh/id_rsa
هذا التوصيف يفصل اسم الخادم المنطقي عن عنوانه الحقيقي. وهذه نقطة مهمة جداً عند العمل ضمن فرق أو داخل بيئات متعددة، لأن اسم web-01 سيبقى ثابتاً حتى لو تغيرت البنية السحابية أو عنوان IP.
الـ Playbook الكامل لتجهيز السيرفر
الملف التالي يمثل قلب المشروع. وهو يجمع بين تحديث النظام، تثبيت الحزم، إنشاء مستخدم إداري، ضبط الجدار الناري، نشر صفحة ويب، وضمان تشغيل الخدمة تلقائياً بعد الإقلاع. إذا كنت جديداً نسبياً على بناء ملفات المهام فاطلع أيضاً على أول Playbook لك: تثبيت البرامج (مثل Nginx و Node) آلياً بلغة YAML.
---
- name: Prepare raw Ubuntu server as ready web server
hosts: all
become: true
vars:
new_admin_user: deploy
web_root: /var/www/html
allowed_ssh_port: 22
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
tasks:
- name: Update apt cache
apt:
update_cache: true
cache_valid_time: 3600
- name: Upgrade all packages
apt:
upgrade: dist
- name: Install required packages
apt:
name:
- nginx
- ufw
- fail2ban
- curl
- git
state: present
- name: Ensure admin group sudo exists
group:
name: sudo
state: present
- name: Create deploy user
user:
name: "{{ new_admin_user }}"
groups: sudo
append: true
shell: /bin/bash
create_home: true
- name: Add authorized key for deploy user
authorized_key:
user: "{{ new_admin_user }}"
state: present
key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"
- name: Allow OpenSSH in UFW
ufw:
rule: allow
name: OpenSSH
- name: Allow HTTP in UFW
ufw:
rule: allow
port: "80"
proto: tcp
- name: Allow HTTPS in UFW
ufw:
rule: allow
port: "443"
proto: tcp
- name: Enable UFW
ufw:
state: enabled
policy: deny
- name: Deploy custom index page
copy:
dest: "{{ web_root }}/index.html"
content: |
Ansible Provisioned Server
Server is ready
This Ubuntu web server was provisioned automatically using Ansible.
owner: www-data
group: www-data
mode: '0644'
notify: restart nginx
- name: Ensure nginx is enabled and running
service:
name: nginx
state: started
enabled: true
- name: Ensure fail2ban is enabled and running
service:
name: fail2ban
state: started
enabled: true
كيف نفهم هذا الملف هندسياً؟
1) مبدأ Idempotency
أهم ما يميز Ansible أنه لا يعيد تنفيذ التغييرات دون حاجة. إذا كان Nginx مثبتاً بالفعل فلن تتم إعادة تثبيته، وإذا كان المستخدم موجوداً فلن يُنشأ من جديد. هذا يتيح تشغيل الملف عشرات المرات بأمان نسبي، وهي خاصية محورية عند ربطه مع ما هو الـ CI/CD؟ ولماذا نؤتمت عمليات اختبار ونشر الأكواد؟.
2) المعالجات الذكية Handlers
لاحظ أن إعادة تشغيل Nginx لا تحدث إلا عند تغيير الصفحة فعلاً. هذه الممارسة تقلل الانقطاعات غير الضرورية، ويمكنك التوسع فيها أكثر عبر مقال المعالجات (Handlers): إعادة تشغيل الخدمات فقط عند حدوث تغيير في السيرفر.
3) الحماية ليست خطوة لاحقة
الكثيرون يثبتون الخدمة أولاً ثم يفكرون بالأمان لاحقاً، وهذه مقاربة خطرة. داخل هذا المشروع تم تضمين UFW وfail2ban منذ البداية لأن الأمان الجيد يجب أن يكون جزءاً من عملية provisioning نفسها.
لا تفعّل الجدار الناري على السيرفرات البعيدة قبل التأكد أن منفذ SSH المسموح صحيح، وإلا قد تعزل نفسك عن الخادم بالكامل. اختبر دائماً على بيئة تجريبية أو استخدم جلسة احتياطية مفتوحة قبل تطبيق القواعد النهائية.
تشغيل المشروع واختباره
بعد حفظ الملفين، نفذ أمر الفحص أولاً ثم أمر التطبيق. هذه الممارسة تقلل المفاجآت وتكشف مبكراً عن أخطاء المسارات أو المفاتيح أو البنية.
ansible-inventory -i inventory.yml --graph
ansible all -i inventory.yml -m ping
ansible-playbook -i inventory.yml webserver.yml
إذا نجح التنفيذ، افتح عنوان السيرفر في المتصفح وستظهر صفحة الاختبار. كما يمكنك فحص الخدمة يدوياً عبر curl للتأكد من أن طبقة الويب تستجيب خارجياً.
curl http://192.0.2.10
كيف نطوره إلى مسار إنتاج حقيقي؟
هذا المشروع هو نواة ممتازة لتوسعات أكبر. يمكنك مثلاً إضافة قوالب Jinja2 لملفات المواقع، أو تقسيم المهام إلى roles مستقلة، أو ربطه مع مقدمة في GitHub Actions: كتابة أول مسار عمل (Workflow) بحيث يُشغّل تلقائياً بعد مراجعة الكود.
وفي البيئات الحديثة قد لا يكون Nginx هو التطبيق النهائي، بل مجرد طبقة أمامية تستقبل حركة المرور قبل تمريرها إلى تطبيقات تعمل داخل حاويات. عندها يصبح من المفيد الربط مع مفاهيم مثل مشكلة “الكود يعمل على جهازي فقط” وكيف يحلها Docker نهائياً؟ ثم بناء مسار أوسع يشمل التحزيم والنشر والتهيئة.
في بيئات الإنتاج الحقيقية، لا تضع المفاتيح العامة والخاصة أو الأسرار الحساسة مباشرة داخل المستودع. استخدم آليات تخزين آمنة مثل Vault أو أسرار منصات الأتمتة، وراجع أيضاً إدارة الأسرار (GitHub Secrets) لحماية كلمات المرور ومفاتيح الـ API في الأتمتة.
خلاصة هندسية
قيمة هذا المشروع لا تكمن في تثبيت Nginx فقط، بل في تحويل إعداد السيرفر من مهمة يدوية معرضة للنسيان والخطأ إلى وصف بنيوي يمكن تتبعه وتكراره. هذا هو جوهر البنية التحتية ككود: أن يصبح الخادم نفسه قابلاً للنسخ، والمراجعة، والتحسين المستمر.
ومتى أتقنت هذا النمط، ستصبح قادراً على بناء سلاسل نشر أكثر نضجاً تشمل إنشاء الخوادم، تهيئتها، نشر التطبيقات، ثم اختبارها تلقائياً. عندها لا يعود السيرفر “خاماً” إلا لدقائق معدودة، لأن الأتمتة ستتكفل بتحويله إلى بيئة ويب جاهزة بثقة وسرعة واتساق.
2 comments