SSD Nodes Learn Hosting plans →
تعلیمی Matt Connorتحریر: Matt Connor · اپ ڈیٹ شدہ 2026-08-01

Ubuntu 24.04 VPS کے لیے پہلا Ansible playbook

Ubuntu 24.04 پر pipx سے Ansible انسٹال کریں، inventory اور پہلا hardening playbook بنائیں، اور Permission denied اور sudo errors کو درست کریں۔

آپ کیا بنا رہے ہیں

ایک ایسی control machine جس پر Ansible انسٹال ہو، اور ایک یا زیادہ نئی Ubuntu 24.04 VPSes جن پر stock image کے علاوہ کچھ نہ ہو۔ آخر میں آپ کے پاس ایک inventory file ہوگی جس میں آپ کے servers کے نام درج ہوں گے، ایک ad-hoc ping ہوگا جو ثابت کرے گا کہ authentication ابتدا سے انتہا تک کام کرتی ہے، اور ایک playbook ہوگی جو نئے VPS کی مکمل checklist کو code کے طور پر چلاتی ہے: آپ کی SSH key والا deploy user، محفوظ sshd، fail2ban، unattended upgrades، اور ایسا firewall جو باقی تمام traffic کو مسترد کرنے سے پہلے OpenSSH کی اجازت دیتا ہے۔ اسے ایک server یا بیس servers پر چلائیں۔ اسے دوسری بار چلانے پر کچھ تبدیل نہیں ہوگا؛ اصل مقصد یہی ہے۔

VPSes provision کرنے کے پندرہ سال کے بعد میں یہ واضح طور پر کہہ سکتا ہوں: ہر شخص پہلے پانچ servers کو دستی طور پر setup کرتا ہے، پھر چھٹے server پر پورا weekend ضائع کر دیتا ہے، کیونکہ کسی کو یاد نہیں رہتا کہ پہلے پانچ servers کے ساتھ کیا کیا گیا تھا۔ یہ guide متعدد Linux servers کا انتظام کے جائزے کو مزید آگے بڑھاتی ہے؛ جب آپ خود کو ایک ہی apt install تین terminals میں ٹائپ کرتے ہوئے پائیں، تو اسے پڑھیں۔

ایک پیراگراف میں Ansible کی اصل حقیقت

Ansible agentless ہے۔ اس کے زیرِ انتظام سرورز پر کوئی daemon نصب کرنے کی ضرورت نہیں ہوتی۔ control machine عام SSH کے ذریعے منسلک ہوتی ہے، target پر ایک چھوٹا Python module نقل کرتی ہے، اسے چلاتی ہے، اس کے تیار کردہ JSON کو پڑھتی ہے، اور اسے حذف کر دیتی ہے۔ target کے لیے صرف python3 درکار ہے، جو ہر stock Ubuntu image میں پہلے سے موجود ہوتا ہے۔ اہم اصطلاح idempotent ہے، جس کا سادہ مطلب ہے: کوئی task کسی action کے بجائے ایک state بیان کرتا ہے۔ کسی package کے لیے state: present کا مطلب ہے "یقینی بنائیں کہ یہ installed ہے"، نہ کہ "installer چلائیں"۔ اگر state پہلے ہی برقرار ہو تو Ansible کچھ بھی تبدیل نہیں کرتا اور اسے ok کے طور پر رپورٹ کرتا ہے، changed کے طور پر نہیں۔ یہی خاصیت پورا product ہے۔ اسی کی وجہ سے playbook کو دوبارہ چلانا محفوظ رہتا ہے، اور محفوظ دوبارہ اجرا ہی shell script کو infrastructure میں تبدیل کرتا ہے۔

پیشگی تقاضے اور اہم احتیاطیں

  • ایک کنٹرول مشین: آپ کا لیپ ٹاپ یا ایک چھوٹا VPS۔ یہاں Ubuntu 24.04 فرض کیا گیا ہے؛ Homebrew سے pipx انسٹال ہونے کے بعد macOS بھی اسی طرح کام کرتا ہے۔
  • ایک یا زیادہ ہدف VPS، جو KVM پر Ubuntu 24.04 چلا رہے ہوں اور root کے طور پر قابلِ رسائی ہوں۔ ان پر کچھ بھی انسٹال نہیں کیا جائے گا۔
  • ہر ہدف کے لیے SSH key authentication۔ Ansible کو بھی اتنی ہی authentication حاصل ہوتی ہے جتنی آپ کے ssh command کو۔ اگر ssh root@host password طلب کرے تو Ansible ناکام ہو جاتا ہے۔
  • Ubuntu 24.04 پر pip install ansible، error: externally-managed-environment کے ساتھ ناکام ہو جاتا ہے۔ یہ distro policy کے مطابق جان بوجھ کر ہے، خرابی نہیں۔ pipx استعمال کریں۔
  • YAML میں whitespace syntax کا حصہ ہے۔ غلط indentation سے mapping values are not allowed in this context پیدا ہوتا ہے، اور کہیں بھی tab character موجود ہو تو عمل ناکام ہو جاتا ہے۔
  • جب playbook، sshd کو سخت حفاظتی ترتیب دے رہا ہو تو ہر ہدف پر ایک فعال SSH session کھلا رکھیں۔ جن تمام lockout واقعات سے میں نے صارفین کو بحال کرنے میں مدد کی، ان میں آخری session کو "clean سے آزمائش" کے لیے بند کرنا شامل تھا۔

مرحلہ 1: pip کے بجائے pipx سے کنٹرول مشین پر Ansible انسٹال کریں

عام طور پر پہلا خیال pip3 install ansible ہوتا ہے۔ بالکل نئی 24.04 image پر یہ ایک مرحلہ پہلے ہی ناکام ہو جاتا ہے، یعنی Command 'pip3' not found, but can be installed with: sudo apt install python3-pip، اور صرف pip انسٹال کرنے سے آپ اصل رکاوٹ تک پہنچ جاتے ہیں:

pip3 install ansible
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

Ubuntu 24.04 سسٹم Python کو externally managed (PEP 668) قرار دیتا ہے، اس لیے pip، apt کے ساتھ ایک ہی فائلوں پر تنازع نہیں کر سکتا۔ --break-system-packages استعمال نہ کریں؛ اس flag کا نام اس کا مقصد واضح طور پر بتاتا ہے۔ صاف حل pipx ہے۔ یہ Ansible کے لیے الگ تھلگ virtualenv بناتا ہے اور binaries کو آپ کے PATH میں شامل کرتا ہے:

sudo apt update && sudo apt install -y pipx
pipx ensurepath
pipx install --include-deps ansible

pipx ensurepath کے بعد نیا shell کھولیں تاکہ PATH کی تبدیلی لاگو ہو جائے۔ --include-deps محض آرائشی نہیں ہے: ansible package خود کوئی console scripts فراہم نہیں کرتا، ansible، ansible-playbook، اور باقی تمام scripts اس کی ansible-core dependency کے entry points ہیں۔ اس flag کے بغیر pipx انسٹالیشن سے انکار کرتے ہوئے No apps associated with package ansible or its dependencies دکھاتا ہے۔ `ansible package انسٹال کریں، صرف ansible-core نہیں۔ مکمل package میں community collections شامل ہوتی ہیں، اور یہ playbook ان میں سے دو کے modules استعمال کرتی ہے (ansible.posix اور community.general`)۔

ansible --version

درست نتیجہ ansible [core 2.19.x] جیسی سطر سے شروع ہوتا ہے اور اس Python کا نام دکھاتا ہے جس کے تحت یہ چل رہا ہے؛ یہاں ہر موجودہ core release کافی ہے۔ ansible: command not found کا مطلب ہے کہ ~/.local/bin ابھی آپ کے PATH میں موجود نہیں، اس لیے نیا shell کھولیں، یا source ~/.bashrc۔

بس اتنی ہی انسٹالیشن درکار ہے۔ targets پر کچھ بھی انسٹال نہیں ہوتا۔

مرحلہ 2: ہر ہدف تک SSH key کے ذریعے رسائی

ssh-keygen -t ed25519 -C "ansible control"
ssh-copy-id root@10.0.0.10
ssh-copy-id root@10.0.0.20

پھر ہر host کے لیے ایک بار اس کی تصدیق کریں:

ssh root@10.0.0.10 true && echo ok

یہ ایک سطر دو کام کرتی ہے: یہ تصدیق کرتی ہے کہ key authentication پاس ورڈ کے بغیر کام کر رہی ہے، اور host key کو known_hosts میں محفوظ کرتی ہے۔ یہ کام ابھی کریں، کیونکہ Ansible غیر محفوظ شدہ host key کو run کے دوران اندر چھپے ہوئے interactive prompt کے طور پر دکھاتا ہے، جو بالکل hang جیسا محسوس ہوتا ہے۔

مرحلہ 3: انوینٹری، پہلے INI، پھیلنے پر YAML

انوینٹری ایک متنی فائل ہے جس میں ان مشینوں کی فہرست ہوتی ہے جن پر Ansible کارروائی کر سکتا ہے۔ نئے project directory میں inventory.ini بنائیں:

[vps]
web1 ansible_host=10.0.0.10
web2 ansible_host=10.0.0.20

[vps:vars]
ansible_user=root

web1 آپ کا منتخب کردہ alias ہے۔ یہ output میں ظاہر ہوتا ہے اور --limit web1 کے ذریعے target کیا جاتا ہے۔ ansible_host اصل address ہے۔ [vps] ایک group ہے، اور [vps:vars] اس کے ہر host کے لیے variables مقرر کرتا ہے؛ ansible_user وہ account ہے جس کے ذریعے Ansible login کرتا ہے۔ اس کے ساتھ ansible.cfg بھی شامل کریں، تاکہ آپ کو دوبارہ -i لکھنے کی ضرورت نہ پڑے:

[defaults]
inventory = inventory.ini

Ansible موجودہ directory سے ansible.cfg پڑھتا ہے۔ یہی inventory YAML میں بھی لکھی جا سکتی ہے۔ اسے inventory.yml کے نام سے محفوظ کریں اور ansible.cfg کو اس نام کی طرف point کریں۔ جب ہر host کے ساتھ کئی variables ہوں، تو یہی طریقہ زیادہ موزوں ہوگا:

vps:
  hosts:
    web1:
      ansible_host: 10.0.0.10
    web2:
      ansible_host: 10.0.0.20
  vars:
    ansible_user: root

دونوں یکساں ہیں۔ دو servers کے لیے INI کو دیکھ کر سمجھنا آسان ہے؛ بیس servers پر YAML بہتر طور پر scale ہوتی ہے۔ ایک طریقہ منتخب کریں اور اسی پر قائم رہیں۔

مرحلہ 4: ad-hoc کمانڈز، سب کچھ درست ہونے کا ثبوت دینے والا سبز pong

ansible all -m ping

یہ ICMP نہیں ہے۔ ping ماڈیول مکمل جانچ کرتا ہے: SSH لاگ اِن، ماڈیول کی نقل، ہدف پر Python کا اجرا، اور صفائی۔ درست نتیجہ سبز ہوتا ہے، اور ہر host کے لیے ایک بلاک دکھاتا ہے:

web1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

سبز SUCCESS کا مطلب ہے کہ authentication، Python interpreter، اور transport سب درست کام کر رہے ہیں، اس لیے playbook بھی کام کرے گا۔ سرخ UNREACHABLE! کا مطلب ہے کہ کوئی module چلنے سے پہلے transport ناکام ہو گیا۔ ناکامی کی اصل string اور اس کا حل ذیل میں موجود failure modes سیکشن میں دیا گیا ہے۔ جاننے کے قابل مزید دو ad-hoc کمانڈز:

ansible all -a "uptime"
ansible all -m apt -a "update_cache=true upgrade=dist" --become

ad-hoc کمانڈز ایک بار کے کاموں اور جانچ کے لیے ہیں۔ جس کام کو آپ دو بار چلائیں گے، اسے playbook میں شامل کریں۔

مرحلہ 5: پہلی playbook، نئے VPS کی چیک لسٹ بطور code

نئے server پر پہلے دس منٹ میں آپ جو کچھ دستی طور پر کرتے، یہ سب اس میں شامل ہے۔ اسے site.yml کے طور پر محفوظ کریں:

---
- name: Baseline a fresh Ubuntu VPS
  hosts: vps
  become: true

  vars:
    deploy_user: deploy
    deploy_pubkey: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
    baseline_packages:
      - fail2ban
      - unattended-upgrades
      - ufw
    baseline_services:
      - fail2ban
      - unattended-upgrades

  tasks:
    - name: Create the deploy user
      ansible.builtin.user:
        name: "{{ deploy_user }}"
        groups: sudo
        append: true
        shell: /bin/bash

    - name: Install the deploy user's SSH key
      ansible.posix.authorized_key:
        user: "{{ deploy_user }}"
        key: "{{ deploy_pubkey }}"

    - name: Passwordless sudo for the deploy user
      ansible.builtin.copy:
        dest: /etc/sudoers.d/deploy
        content: "{{ deploy_user }} ALL=(ALL) NOPASSWD:ALL\n"
        mode: "0440"
        validate: /usr/sbin/visudo -cf %s

    - name: Install baseline packages
      ansible.builtin.apt:
        name: "{{ baseline_packages }}"
        state: present
        update_cache: true

    - name: Enable and start baseline services
      ansible.builtin.service:
        name: "{{ item }}"
        state: started
        enabled: true
      loop: "{{ baseline_services }}"

    - name: Harden sshd with a drop-in
      ansible.builtin.copy:
        dest: /etc/ssh/sshd_config.d/00-hardening.conf
        content: |
          PasswordAuthentication no
          KbdInteractiveAuthentication no
          PermitRootLogin prohibit-password
          X11Forwarding no
        mode: "0644"
        validate: /usr/sbin/sshd -t -f %s
      notify: Restart ssh

    - name: Allow OpenSSH through ufw
      community.general.ufw:
        rule: allow
        name: OpenSSH

    - name: Enable ufw with default deny
      community.general.ufw:
        state: enabled
        policy: deny

  handlers:
    - name: Restart ssh
      ansible.builtin.service:
        name: ssh
        state: restarted

یہ وہ سطریں ہیں جنہیں نقل کرنے کے بجائے سمجھنا ضروری ہے:

Variables، vars: کے تحت ہوتی ہیں اور "{{ deploy_user }}" کے ذریعے ان کا حوالہ دیا جاتا ہے۔ جب value کسی brace سے شروع ہو تو پوری expression کو quotes میں لکھیں، ورنہ YAML parser اسے غلط سمجھ سکتا ہے۔ lookup('file', ...) runtime پر control machine سے آپ کی public key پڑھتا ہے، اس لیے playbook میں key material شامل نہیں ہوتا۔

Loop۔ loop: "{{ baseline_services }}" ہر item کے لیے service task ایک بار چلاتا ہے، اور output میں ہر item اپنی الگ سطر پر دکھائی دیتا ہے۔ یاد رکھیں کہ apt task پوری package list کو ایک ہی بار میں لیتا ہے۔ packages کے لیے ایک apt transaction زیادہ تیز اور ترجیحی طریقہ ہے؛ loops ان modules کے لیے ہیں جو واقعی ایک وقت میں صرف ایک چیز پر کارروائی کرتے ہیں۔

Handler وہ تصور ہے جسے اچھی طرح سمجھنا ضروری ہے۔ notify: Restart ssh کا مطلب یہ نہیں کہ "ssh کو ابھی restart کریں"۔ یہ handler کو queue میں رکھتا ہے۔ handler play کے اختتام پر صرف ایک بار چلتا ہے، اور صرف اس وقت جب notifying task نے واقعی changed report کیا ہو۔ کل playbook دوبارہ چلائیں: drop-in file پہلے ہی درست ہوگی، copy task ok report کرے گا، اور sshd کو restart نہیں کیا جائے گا۔ validate: line trigger پر safety فراہم کرتی ہے۔ sshd پرانی file تبدیل کرنے سے پہلے اس کی جانچ کرتا ہے، اس لیے typo کی صورت میں task ناکام ہوگا، daemon خراب نہیں ہوگا۔

PermitRootLogin prohibit-password، no نہیں، دانستہ طور پر۔ یہ playbook key کے ذریعے root کے طور پر login کرتی ہے۔ prohibit-password password کے ذریعے root logins بند کرتا ہے، جبکہ آپ کا موجودہ login برقرار رہتا ہے۔ جب deploy user ثابت ہو جائے (ssh deploy@10.0.0.10 sudo true، یعنی plain address، کیونکہ web1 صرف Ansible کو معلوم alias ہے)، تو inventory میں ansible_user=deploy تبدیل کریں اور بعد کے run میں اسے no تک محدود کریں۔ Hardening ہمیشہ ایسی ترتیب سے کریں جس میں آپ خود کو server سے باہر نہ کر دیں۔

00- prefix اہم ہے۔ زیادہ تر keywords کے لیے sshd اپنی parsing میں ملنے والی پہلی occurrence کو استعمال کرتا ہے، اور Ubuntu کا sshd_config اپنی body سے پہلے lexical order میں sshd_config.d/*.conf شامل کرتا ہے۔ Ubuntu 24.04 cloud images میں اس directory کے اندر پہلے ہی 60-cloudimg-settings.conf موجود ہوتی ہے، جبکہ cloud-init کے ذریعے password logins فعال کرنے والے providers 50-cloud-init.conf کو PasswordAuthentication yes کے ساتھ شامل کرتے ہیں۔ ہماری file کو 00-hardening.conf کا نام دینے سے وہ پہلے sort ہوتی ہے اور دونوں پر غالب آتی ہے۔

Task order firewall کی safety ہے۔ Allow OpenSSH، Enable ufw سے پہلے deny policy کے ساتھ چلتا ہے۔ Ansible tasks کو درج شدہ ترتیب میں سختی سے چلاتا ہے، اس لیے hole اس وقت موجود ہوتا ہے جب تک wall فعال نہیں ہو جاتی۔ یہاں fail2ban کو مفید ہونے کے لیے کسی configuration کی ضرورت نہیں؛ اس کے Ubuntu defaults sshd کو فوراً monitor کرتے ہیں۔ jails عملی طور پر کیا کرتی ہیں اور کن settings کو tune کرنا چاہیے، اس کی وضاحت Ubuntu 24.04 پر fail2ban guide میں ہے۔

مرحلہ 6: --check کے ساتھ آزمائشی اجرا کریں، پھر اسے حقیقی طور پر چلائیں

ansible-playbook site.yml --check

چیک موڈ کنکشن قائم کرتا ہے، یہ حساب لگاتا ہے کہ وہ کیا کرے گا، اور کچھ بھی تبدیل نہیں کرتا۔ نیچے موجود PLAY RECAP میں changed= کی تعداد دیکھیں۔ یہ ان ٹاسکس کی تعداد ہے جو ہر host میں تبدیلی کریں گے۔ ایک اہم حد یہ ہے کہ جہاں بعد کا task، پہلے task کی تبدیلیوں پر منحصر ہو، وہاں چیک موڈ کی ساختی پابندی ہوتی ہے۔ Ubuntu کی معیاری server image میں ufw پہلے سے شامل ہوتا ہے، اس لیے یہ playbook آزمائشی اجرا میں درست طور پر مکمل ہوتا ہے۔ لیکن ایسی minimal image میں جس میں ufw موجود نہ ہو، ufw والے tasks چیک موڈ میں ناکام ہو جاتے ہیں، کیونکہ چیک موڈ package کو حقیقت میں install نہیں کرتا اور module کے پاس کال کرنے کے لیے کچھ نہیں ہوتا۔ یہ dry run کی حد ہے، آپ کی playbook کی خرابی نہیں۔ جب منصوبہ درست نظر آئے:

ansible-playbook site.yml

ہر task ہر host کے لیے ایک سطر دکھاتا ہے، زرد رنگ میں changed، سبز رنگ میں ok، اور recap اس طرح ہونا چاہیے:

PLAY RECAP *********************************************************************
web1 : ok=10  changed=9  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0
web2 : ok=10  changed=9  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

دس ok، facts جمع کرنے، آٹھ tasks، اور handler پر مشتمل ہیں۔ آپ کا changed میرے نتیجے سے ایک یا دو کا فرق رکھ سکتا ہے۔ Ubuntu کی معیاری image میں ufw اور unattended-upgrades پہلے سے شامل ہوتے ہیں، اور apt کے install کرتے ہی fail2ban خود شروع ہو جاتا ہے۔ اس لیے پہلے ہی اجرا میں کوئی task جائز طور پر ok رپورٹ کر سکتا ہے، کیونکہ اس کی اعلان کردہ حالت پہلے ہی برقرار ہے۔ جن اعداد کا صفر ہونا ضروری ہے وہ unreachable اور failed ہیں۔ become: true کے بارے میں ایک بات: جب آپ root کے طور پر connect کرتے ہیں تو یہ محض رسمی ضرورت ہے، لیکن جیسے ہی آپ ansible_user کو deploy میں تبدیل کرتے ہیں، sudo حقیقی طور پر استعمال ہوتا ہے۔ یہ playbook جو NOPASSWD sudoers file install کرتی ہے، وہی -K کو آپ کی command line سے دور رکھتی ہے۔ اس کے بغیر آپ کو Missing sudo password ملے گا، جس کی وضاحت نیچے دی گئی ہے۔

مرحلہ 7: اسے دو بار چلائیں، idempotence کی شکل

اسی command کو فوراً دوبارہ چلائیں:

web1 : ok=9  changed=0  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0

changed=0 اور ok میں ایک کی کمی ہوئی، کیونکہ اطلاع نہ دیے گئے handler نے کبھی اجرا نہیں کیا۔ کچھ بھی دوبارہ install نہیں ہوا، sshd restart نہیں ہوا، اور ufw میں کوئی تبدیلی نہیں کی گئی۔ اسی وجہ سے playbook صرف provisioner نہیں بلکہ audit بھی ہے: اگلے ماہ inventory میں web3 شامل کریں اور دوبارہ چلائیں؛ نیا box تیار ہو جائے گا اور پرانے boxes کی تصدیق ہو جائے گی۔ جس box کو آپ نے چھوا تک نہیں، اس پر nonzero changed drift کی علامت ہے۔ اس سے معلوم ہوتا ہے کہ کسی نے وہ ترتیب دستی طور پر تبدیل کی جسے playbook میں تبدیل کیا جانا چاہیے تھا۔

یہاں سے یہ طریقہ مزید وسیع ہوتا ہے۔ اگلی قابلِ تحریر playbook اسی VPS پر WireGuard VPN قائم کرے گی اور ufw rule کو مزید محدود کرے گی، تاکہ SSH صرف tunnel پر جواب دے۔ اس کے بعد ایسی playbook لکھی جا سکتی ہے جو ہر app server پر Docker اور Compose install کرے۔ جب site.yml تین screens سے تجاوز کر جائے تو اسے roles میں تقسیم کریں، لیکن اس سے پہلے نہیں۔

ناکامی کی صورتیں، ان پیغامات کے ساتھ جو آپ دیکھیں گے

UNREACHABLE with Permission denied۔

web1 | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: root@10.0.0.10: Permission denied (publickey).",
    "unreachable": true
}

کسی بھی module کے چلنے سے پہلے SSH transport ناکام ہو گیا۔ ansible_user غلط ہے، key اس host پر کبھی copy نہیں کی گئی، یا غلط key پیش کی جا رہی ہے۔ سادہ ssh root@10.0.0.10 کے ذریعے دوبارہ کوشش کریں، پھر یہ دیکھنے کے لیے ssh -v چلائیں کہ کون سی keys پیش کی گئیں۔ اگر password کے ذریعے SSH کام کرتا ہے لیکن Ansible نہیں، تو آپ نے ssh-copy-id چھوڑ دیا ہے۔

sudo password موجود نہیں ہے۔

web1 | FAILED! => {
    "msg": "Missing sudo password"
}

آپ نے become: true مقرر کیا، non-root user کے طور پر connect کیا، اور اس user کو sudo کے لیے password درکار ہے۔ یا تو command line میں -K (--ask-become-pass) شامل کریں، یا user کو NOPASSWD sudoers entry دیں۔ اسی وجہ سے playbook آپ کے اس user پر switch کرنے سے پہلے deploy کے لیے یہ entry install کرتا ہے۔

error: externally-managed-environment۔ آپ نے Ubuntu 24.04 کے system Python کے خلاف pip چلایا۔ اس کا حل step 1 میں دیا گیا ہے: pipx استعمال کریں، pip نہیں، اور --break-system-packages بھی نہیں۔

mapping values are not allowed in this context۔

ERROR! Syntax Error while loading YAML.
  mapping values are not allowed in this context

تقریباً ہمیشہ مسئلہ indentation کا ہوتا ہے: کوئی key غلط سطح پر ہے، یا colon کے بعد space موجود نہیں۔ ظاہر کی گئی line number عموماً غلطی کے قریب ہوتی ہے، خود غلطی پر نہیں؛ اس لیے اس سے پچھلی line بھی چیک کریں۔ اس سے ملتا جلتا found character '\t' that cannot start any token پیغام بتاتا ہے کہ tab شامل ہو گیا ہے؛ YAML میں tabs ممنوع ہیں۔ ہر run سے پہلے ansible-playbook site.yml --syntax-check چلانے کی عادت بنائیں، اور YAML کے لیے اپنے editor میں دو spaces کی indentation مقرر کریں۔

/usr/bin/python3: not found۔ معیاری Ubuntu 24.04 images میں یہ شاذونادر ہوتا ہے، لیکن minimal یا netboot images میں عام ہے۔ module execution ناکام ہو جاتی ہے کیونکہ target پر Python موجود نہیں۔ اسے raw module کے ذریعے bootstrap کریں۔ یہ واحد module ہے جسے far side پر کسی چیز کی ضرورت نہیں: ansible all -m raw -a "apt-get update && apt-get install -y python3" --become، پھر playbook دوبارہ چلائیں۔

FAQ

کیا ان سرورز پر Ansible انسٹال کرنا ضروری ہے جن کا یہ انتظام کرتا ہے؟

نہیں۔ Ansible ایجنٹ کے بغیر کام کرتا ہے: کنٹرول مشین چھوٹے Python modules کو SSH کے ذریعے بھیجتی ہے، انہیں چلاتی ہے، اور پھر حذف کر دیتی ہے۔ ہدف مشین پر صرف python3 اور SSH access درکار ہوتا ہے، اور دونوں پہلے سے فراہم کردہ Ubuntu images میں موجود ہوتے ہیں۔ اس پوری رہنما میں واحد installation آپ کی control machine پر ہوتی ہے۔

Ansible کو "Permission denied (publickey)" کیوں دکھائی دیتا ہے؟

Permission denied (publickey) کے ساتھ UNREACHABLE! block کا مطلب ہے کہ Ansible کے کچھ چلانے سے پہلے SSH authentication ناکام ہو گئی۔ جانچیں کہ inventory میں ansible_user اسی account سے مطابقت رکھتا ہے جسے آپ نے واقعی تیار کیا ہے، آپ نے اس host پر ssh-copy-id چلایا ہے، اور سادہ ssh user@host بغیر password کے login کر لیتا ہے۔ سادہ ssh command کو درست کرنے سے Ansible بھی درست ہو جاتا ہے، کیونکہ دونوں ایک ہی transport استعمال کرتے ہیں۔

Ansible میں idempotent کا کیا مطلب ہے؟

Task انجام دی جانے والی کارروائی کے بجائے مطلوبہ حالت بیان کرتا ہے، جیسے "یہ package موجود ہے" یا "یہ line اس file میں موجود ہے"۔ اگر حالت پہلے ہی برقرار ہو تو Ansible کچھ نہیں کرتا اور changed کے بجائے ok رپورٹ کرتا ہے۔ اسی لیے playbook دوسری بار چلانے پر changed=0 دکھائی دیتا ہے، اور دوبارہ چلانا خطرناک re-install کے بجائے محفوظ audit ہوتا ہے۔

کیا Ubuntu 24.04 پر Ansible انسٹال کرنے کے لیے pip یا pipx استعمال کرنا چاہیے؟

pipx۔ Ubuntu 24.04 کے system Python کو externally managed قرار دیتا ہے، اس لیے pip install ansible جان بوجھ کر error: externally-managed-environment کے ساتھ ناکام ہوتا ہے۔ pipx install --include-deps ansible Ansible کو الگ تھلگ virtualenv میں رکھتا ہے اور ansible، ansible-playbook، اور باقی commands کو صاف طور پر آپ کے PATH میں دستیاب کرتا ہے۔

ansible اور ansible-core packages میں کیا فرق ہے؟

ansible-core صرف ansible.builtin modules کے ساتھ engine فراہم کرتا ہے۔ ansible package core کے ساتھ منتخب community collections بھی شامل کرتا ہے، جن میں ansible.posix (authorized_key module) اور community.general (ufw module) شامل ہیں؛ اس رہنما میں دونوں استعمال ہوتے ہیں۔ مکمل package سے شروع کریں۔ صرف اس وقت core اور اپنی منتخب collections تک محدود ہوں جب اس کی واضح ضرورت ہو۔