Ansible টিউটোরিয়াল: VPS এ প্রথম playbook
Ubuntu 24.04 এ pipx দিয়ে Ansible ইনস্টল করুন, inventory ও প্রথম playbook লিখুন যা নতুন VPS হার্ডেন করবে। Permission denied ও sudo এরর সমাধানও দেওয়া আছে।
আপনি যা তৈরি করছেন
একটি কন্ট্রোল মেশিনে Ansible ইনস্টল করা থাকবে, এবং এক বা একাধিক সম্পূর্ণ নতুন Ubuntu 24.04 VPS থাকবে যেখানে স্টক ইমেজ ছাড়া আর কিছুই থাকবে না। শেষ হওয়ার আগে আপনার কাছে একটি ইনভেন্টরি ফাইল থাকবে যা আপনার সার্ভারগুলোর নাম উল্লেখ করবে, একটি ad-hoc ping থাকবে যা প্রমাণ করবে যে শেষ পর্যন্ত অথেনটিকেশন কাজ করছে, এবং একটি প্লেবুক থাকবে যা সম্পূর্ণ নতুন-VPS চেকলিস্টটিকে কোড হিসেবে চালাবে: আপনার SSH key সহ একজন deploy ইউজার, হার্ডেন্ড sshd, fail2ban, unattended আপগ্রেড, এবং একটি ফায়ারওয়াল যা সবকিছু ব্লক করার আগে OpenSSH অনুমোদন করবে। এটি একটি সার্ভারে বা বিশটিতে নির্দেশ করুন। দুবার চালান এবং দ্বিতীয়বার চালালে কিছুই পরিবর্তন হবে না — এটাই মূল উদ্দেশ্য।
পনেরো বছর ধরে VPS প্রোভিশন করার অভিজ্ঞতা থেকে আমি সৎ প্যাটার্নটি বলতে পারি: প্রত্যেকেই প্রথম পাঁচটি সার্ভার হাতে সেট আপ করে, তারপর ষষ্ঠটিতে একটি সাপ্তাহিক ছুটি নষ্ট করে কারণ কেউ মনে রাখে না প্রথম পাঁচটিতে কী করেছিল। এই গাইডটি একাধিক Linux সার্ভার পরিচালনা বিষয়ে আলোচনাকে আরও গভীর করে — যেদিন আপনি নিজেকে তিনটি টার্মিনালে একই apt install টাইপ করতে দেখবেন সেদিন এটি হাতে নিন।
Ansible আসলে কী, এক প্যারায়
Ansible এজেন্টবিহীন। এটি যে সার্ভারগুলো পরিচালনা করে, সেগুলোতে কোনো ডেমন ইনস্টল করতে হয় না: কন্ট্রোল মেশিন সাধারণ SSH-এর মাধ্যমে সংযুক্ত হয়, টার্গেটে একটি ছোট Python মডিউল কপি করে, সেটি এক্সিকিউট করে, এটি যে JSON প্রিন্ট করে তা পড়ে, এবং মডিউলটি ডিলিট করে দেয়। একটি টার্গেটের প্রয়োজন শুধু python3, যা প্রতিটি স্টক Ubuntu ইমেজে আগে থেকেই থাকে। এখানে গুরুত্বপূর্ণ শব্দটি হলো idempotent, এর অর্থ সহজ: একটি টাস্ক একটি অবস্থা বর্ণনা করে, কোনো ক্রিয়া নয়। কোনো প্যাকেজের জন্য state: present মানে "নিশ্চিত করুন এটি ইনস্টল আছে", "ইনস্টলার চালান" নয়। অবস্থা যদি আগে থেকেই বহাল থাকে, তাহলে Ansible কিছুই স্পর্শ করে না এবং এটিকে changed-এর বদলে ok হিসেবে রিপোর্ট করে। এই বৈশিষ্ট্যটিই পুরো প্রোডাক্ট — এটিই একটি প্লেবুক পুনরায় চালানো নিরাপদ করে তোলে, আর নিরাপদ পুনরায় চালানোই একটি শেল স্ক্রিপ্টকে ইনফ্রাস্ট্রাকচারে পরিণত করে।
পূর্বশর্ত, এবং শুরুতেই সতর্কতামূলক বিষয়গুলি
- একটি কন্ট্রোল মেশিন: আপনার ল্যাপটপ বা একটি ছোট VPS। আমি Ubuntu 24.04 ধরে নিচ্ছি; Homebrew থেকে pipx ইনস্টল করা হলে macOS-এ একইভাবে কাজ করে।
- এক বা একাধিক টার্গেট VPS, KVM-এ Ubuntu 24.04 চলছে, root হিসেবে অ্যাক্সেসযোগ্য। এগুলোতে কিছু ইনস্টল করা হবে না।
- প্রতিটি টার্গেটে SSH কী অথেনটিকেশন। Ansible-এর অথেনটিকেশন আপনার
sshকমান্ডের সমান — যদিssh root@hostপাসওয়ার্ড চায়, তবে Ansible ব্যর্থ হয়। - Ubuntu 24.04-এ,
pip install ansibleerror: externally-managed-environmentত্রুটি দিয়ে বন্ধ হয়ে যায়। এটি ইচ্ছাকৃত ডিস্ট্রো নীতি, কোনো ত্রুটি নয়। pipx ব্যবহার করুন। - YAML-এ হোয়াইটস্পেস হলো সিনট্যাক্স। ভুল ইনডেন্টেশন
mapping values are not allowed in this contextতৈরি করে, এবং যেকোনো জায়গায় একটি tab ক্যারেক্টার থাকলে তা মারাত্মক। - প্লেবুক sshd হার্ডেন করার সময় প্রতিটি টার্গেটে একটি করে চালু SSH সেশন খোলা রাখুন। আমি যে প্রতিটি লকআউট থেকে কাস্টমারকে পুনরুদ্ধার করতে সাহায্য করেছি, তার প্রত্যেকটিতে শেষ সেশনটি বন্ধ করার ঘটনা ছিল "পরিষ্কার অবস্থা থেকে পরীক্ষা করার জন্য"।
ধাপ 1: pip নয়, pipx দিয়ে কন্ট্রোল মেশিনে Ansible ইনস্টল করুন
প্রচলিত অভ্যাস হলো pip3 install ansible। সম্পূর্ণ নতুন 24.04 ইমেজে এটি এক ধাপ আগেই ব্যর্থ হয় — Command 'pip3' not found, but can be installed with: sudo apt install python3-pip — এবং pip ইনস্টল করলে আপনি শুধু আসল বাধায় পৌঁান।
pip3 install ansibleerror: 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 ব্যবহার করবেন না; এই ফ্ল্যাগের নাম সৎভাবেই রাখা হয়েছে। পরিষ্কার সমাধান হলো pipx, যা Ansible-কে একটি আলাদা isolated virtualenv দেয় এবং বাইনারিগুলো আপনার PATH-এ যুক্ত করে:
sudo apt update && sudo apt install -y pipx
pipx ensurepath
pipx install --include-deps ansiblepipx ensurepath এর পরে একটি নতুন শেল খুলুন যাতে PATH পরিবর্তনটি কার্যকর হয়। --include-deps কোনো আস্তরণ নয়: ansible প্যাকেজটি নিজে কোনো console script দেয় না — ansible, ansible-playbook, এবং বাকিরা এর ansible-core ডিপেন্ডেন্সির entry point — তাই ফ্ল্যাগ ছাড়া pipx No apps associated with package ansible or its dependencies দিয়ে ইনস্টল প্রত্যাখ্যান করে। আর নগ্ন ansible-core নয়, ansible প্যাকেজ ইনস্টল করুন — সম্পূর্ণ প্যাকেজটি community collections বহন করে, এবং এই playbook এর দুটি থেকে মডিউল ব্যবহার করে (ansible.posix এবং community.general)।
ansible --versionসঠিক ফলাফল ansible [core 2.19.x] এর মতো একটি লাইন দিয়ে শুরু হয় এবং এটি যে Python-এ চলে তার নাম দেখায়; এখানকার সব কাজের জন্য যেকোনো বর্তমান core রিলিজ যথেষ্ট। ansible: command not found দেখলে বোঝাবে ~/.local/bin এখনও আপনার PATH-এ নেই — নতুন শেল খুলুন, বা source ~/.bashrc।
ইনস্টল এটুকুই। টার্গেট মেশিনে কিছু লাগে না।
ধাপ 2: প্রতিটি টার্গেটে SSH কী অ্যাক্সেস
ssh-keygen -t ed25519 -C "ansible control"
ssh-copy-id root@10.0.0.10
ssh-copy-id root@10.0.0.20এরপর প্রতিটি হোস্টে একবার করে তা যাচাই করুন:
ssh root@10.0.0.10 true && echo okএই একটি লাইন দুটি কাজ করে: এটি নিশ্চিত করে যে পাসওয়ার্ড ছাড়াই কী অথেনটিকেশন কাজ করছে, এবং এটি হোস্ট কী known_hosts এ সংরক্ষণ করে। এটি এখনই করুন, কারণ Ansible কোনো অসংরক্ষিত হোস্ট কীকে একটি রানের মাঝখানে ইন্টারঅ্যাকটিভ প্রম্পট হিসেবে দেখায়, যা হুবহু একটি হ্যাংয়ের মতো মনে হয়।
ধাপ 3: ইনভেন্টরি — প্রথমে INI, বড় হলে YAML
ইনভেন্টরি হলো একটি টেক্সট ফাইল, যেখানে Ansible দ্বারা পরিচালিত হতে পারে এমন সব মেশিনের তালিকা থাকে। একটি নতুন প্রজেক্ট ডিরেক্টরিতে inventory.ini তৈরি করুন:
[vps]
web1 ansible_host=10.0.0.10
web2 ansible_host=10.0.0.20
[vps:vars]
ansible_user=rootweb1 হলো আপনার বেছে নেওয়া একটি উপনাম — এটিই আউটপুটে দেখায় এবং --limit web1 দিয়ে আপনি এটিকেই টার্গেট করেন। ansible_host হলো আসল ঠিকানা। [vps] হলো একটি গ্রুপ, এবং [vps:vars] এই গ্রুপের প্রতিটি হোস্টের জন্য ভেরিয়েবল নির্ধারণ করে; ansible_user হলো সেই ব্যবহারকারী যেভাবে Ansible লগইন করে। এর পাশেই একটি ansible.cfg, যাতে আপনাকে আর -i টাইপ করতে না হয়:
[defaults]
inventory = inventory.iniAnsible বর্তমান ডিরেক্টরি থেকে ansible.cfg পড়ে। একই ইনভেন্টরির YAML রূপ — এটি inventory.yml নামে সেভ করুন এবং ansible.cfg-কে সেই নামের দিকে নির্দেশ করুন — যখন প্রতিটি হোস্টে একাধিক ভেরিয়েবল থাকবে, তখন আপনি এটিকেই বেছে নেবেন:
vps:
hosts:
web1:
ansible_host: 10.0.0.10
web2:
ansible_host: 10.0.0.20
vars:
ansible_user: rootএগুলো সমতুল্য। দুটি সার্ভারে INI দেখতে সহজ; বিশটিতে YAML ভালোভাবে স্কেল করে। একটি বেছে নিন এবং এ নিয়ে আর ভাববেন না।
ধাপ 4: ad-hoc কমান্ড — সবকিছু প্রমাণকারী সবুজ pong
ansible all -m pingএটি ICMP নয়। ping মডিউলটি একটি সম্পূর্ণ রিহার্সাল: SSH লগইন, মডিউল কপি, টার্গেটে Python এক্সিকিউশন, ক্লিনআপ। সঠিক ফলাফল হলো সবুজ, প্রতিটি হোস্টের জন্য একটি ব্লক:
web1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}সবুজ SUCCESS মানে অথেনটিকেশন, Python ইন্টারপ্রেটার এবং ট্রান্সপোর্ট সবই কাজ করছে — playbook-টিও চলবে। লাল UNREACHABLE! মানে কোনো মডিউল চলার আগেই ট্রান্সপোর্ট ব্যর্থ হয়েছে; সঠিক স্ট্রিং এবং সমাধান নিচের ব্যর্থতার ধরন বিভাগে দেওয়া আছে। আরও দুটি ad-hoc কমান্ড জেনে রাখা ভালো:
ansible all -a "uptime"
ansible all -m apt -a "update_cache=true upgrade=dist" --becomeAd-hoc কমান্ড এককালীন কাজ এবং যাচাইয়ের জন্য। আপনি যা দুবার চালাবেন তা playbook-এ রাখা উচিত।
ধাপ 5: প্রথম প্লেবুক — নতুন VPS চেকলিস্ট কোড আকারে
এটি একটি নতুন সার্ভারে প্রথম দশ মিনিটে আপনি যা যা নিজে করতেন, তার সবকিছু। এটি 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যে লাইনগুলো শুধু কপি না করে বুঝে নেওয়া উচিত:
ভেরিয়েবল vars:-এর অধীনে থাকে এবং "{{ deploy_user }}" দিয়ে উল্লেখ করা হয়। কোনো মান ব্রেস দিয়ে শুরু হলে পুরো এক্সপ্রেশনটি কোট করুন, অন্যথায় YAML পার্সার ভুল বুঝবে। lookup('file', ...) রানটাইমে control মেশিন থেকে আপনার পাবলিক কী পড়ে, তাই প্লেবুকে কোনো কী উপাদান থাকে না।
লুপ। loop: "{{ baseline_services }}" প্রতিটি আইটেমের জন্য একবার করে সার্ভিস টাস্ক চালায়, এবং আউটপুটে প্রতিটি আইটেম আলাদা লাইনে দেখা যায়। লক্ষ্য করুন, apt টাস্ক পুরো প্যাকেজ তালিকা একসাথে নেয় — একটি apt লেনদেন দ্রুত হয় এবং প্যাকেজের জন্য এটিই পছন্দনীয় প্যাটার্ন; লুপ ব্যবহার করা হয় সেইসব মডিউলের জন্য যা সত্যিই একসময়ে একটি জিনিসের উপর কাজ করে।
হ্যান্ডলার হলো এমন একটি ধারণা যা আত্মস্থ করা দরকার। notify: Restart ssh মানে "এখন ssh রিস্টার্ট করো" নয়। এটি হ্যান্ডলারটিকে সারিবদ্ধ করে, যা প্লের শেষে একবার চলে, এবং শুধুমাত্র যদি নোটিফাই করা টাস্ক াস্তবে changed রিপোর্ট করে। আগামীকাল প্লেবুকটি পুনরায় চালান: drop-in ফাইলটি ইতিমধ্যে সঠিক, copy টাস্ক ok রিপোর্ট করে, এবং sshd কখনো বাউন্স হয় না। validate: লাইনটি হলো ট্রিগারের নিরাপত্তা — sshd পুরোনো ফাইলটি প্রতিস্থাপনের আগে ফাইলটি পরীক্ষা করে, তাই টাইপো থাকলে ডেমন ভেঙে যাওয়ার বদলে টাস্ক ব্যর্থ হয়।
PermitRootLogin prohibit-password, no নয় — ইচ্ছাকৃতভাবে। এই প্লেবুকটি কী সহ root হিসেবে লগইন করে। prohibit-password পাসওয়ার্ড root লগইন বন্ধ করে দেয় এবং আপনার লগইন বহাল রাখে। একবার deploy ইউজার প্রমাণিত হলে (ssh deploy@10.0.0.10 sudo true — সাধারণ ঠিকানা, কারণ web1 হলো এমন একটি অ্যালিয়াস যা শুধু Ansible জানে), ইনভেন্টরিতে ansible_user=deploy পরিবর্তন করুন এবং পরবর্তী রানে এটি no-এ আরও কঠোর করুন। এমন ক্রমে নিরাপত্তা বাড়ান যাতে আপনি বাইরে আটকে না পড়েন।
00- প্রিফিক্সটি গুরুত্বপূর্ণ। বেশিরভাগ কীওয়ার্ডের ক্ষেত্রে sshd যে ঘটনাটি প্রথমে পার্স করে সেটিকেই গ্রহণ করে, এবং Ubuntu-র sshd_config নিজের বডির আগে লেক্সিক্যাল ক্রমে sshd_config.d/*.conf অন্তর্ভুক্ত করে। Ubuntu 24.04 ক্লাউড ইমেজে ইতিমধ্যে সেই ডিরেক্টরিতে একটি 60-cloudimg-settings.conf থাকে, এবং যেসব প্রোভাইডার cloud-init-এর মাধ্যমে পাসওয়ার্ড লগইন চালু করে তারা PasswordAuthentication yes সহ একটি 50-cloud-init.conf যোগ করে; আমাদেরটির নাম 00-hardening.conf দিলে এটি আগে সাজে এবং উভয়ের উপর জয়ী হয়।
টাস্কের ক্রম হলো ফায়ারওয়াল নিরাপত্তা। Allow OpenSSH ডিনাই পলিসি সহ Enable ufw-এর আগে চলে — Ansible টাস্কগুলো কঠোরভাবে তালিকাভুক্ত ক্রমে কার্যকর করে, তাই দেয়াল ওঠার আগেই ছিদ্রটি তৈরি হয়ে যায়। fail2ban-এর এখানে কাজ করার জন্য কোনো কনফিগারেশনের প্রয়োজন নেই; এর Ubuntu ডিফল্টগুলো শুরু থেকেই sshd পর্যবেক্ষণ করে, এবং জেলগুলো আসলে কী করে — এবং কী টিউন করতে হবে — তা Ubuntu 24.04-এ fail2ban গাইড-এ আলোচনা করা হয়েছে।
ধাপ 6: --check দিয়ে পরীক্ষামূলক চালান, তারপর আসলে চালান
ansible-playbook site.yml --checkCheck mode সংযোগ করে, হিসাব করে এটি কী করতে পারত, এবং কিছু পরিবর্তন করে না। নিচের PLAY RECAP-এ changed= সংখ্যাটি পড়ুন — এটি হলো প্রতিটি host-এ কতগুলো task পরিবর্তন আনতে পারে তার সংখ্যা। একটি সতরাং সতর্কতা: যেখানে একটি পরবর্তী task একটি পূর্ববর্তী task-এর পরিবর্তনের উপর নির্ভর করে, সেখানে check mode-এ একটি কাঠামোগত সীমাবদ্ধতা আছে। Ubuntu-র স্ট্যান্ডার্ড সার্ভার ইমেজ ufw আগে থেকেই ইনস্টল করে দেয়, তাই এই playbook-টি পরীক্ষামূলকভাবে পরিষ্কারভাবে চলে — কিন্তু এটি ছাড়া একটি ন্যূনতম ইমেজে, ufw task-গুলো check mode-এ ব্যর্থ হয়, কারণ check mode কখনোই package-টি আসলে ইনস্টল করে না এবং module-এর কাছে তখন ডাকার মতো কিছুই থাকে না। এটি পরীক্ষামূলক চালানোর একটি সীমাবদ্ধতা, আপনার playbook-এ কোনো বাগ নয়। যখন পরিকল্পনাটি সঠিক মনে হয়:
ansible-playbook site.ymlপ্রতিটি task প্রতি host-এ একটি করে লাইন প্রিন্ট করে — হলুদ changed, সবুজ ok — এবং সারাংশটি হওয়া উচিত:
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 হলো fact-gathering এবং আটটি task এবং handler-এর সমষ্টি। আপনার changed আমার থেকে এক বা দুই পর্যন্ত আলাদা হতে পারে: Ubuntu-র স্ট্যান্ডার্ড ইমেজে ufw এবং unattended-upgrades আগে থেকেই থাকে, এবং fail2ban যেই মুহূর্তে apt এটি ইনস্টল করে নিজে নিজে চালু হয়ে যায়, তাই একটি task এর প্রথম চালানোতেই বৈধভাবে ok রিপোর্ট করতে পারে — এটি যে অবস্থা ঘোষণা করে তা ইতিমধ্যেই বহাল আছে। যে সংখ্যাগুলো অবশ্যই শূন্য হতে হবে সেগুলো হলো unreachable এবং failed। become: true সম্পর্কে একটি কথা: আপনি root হিসেবে সংযুক্ত থাকা পর্যন্ত এটি একটি আনুষ্ঠানিকতা মাত্র, কিন্তু আপনি যেই মুহূর্তে ansible_user-কে deploy-এ পরিবর্তন করেন, sudo আসল হয়ে যায় — এবং এই playbook-টি যে NOPASSWD sudoers ফাইল ইনস্টল করে তা-ই ঠিক আপনার কমান্ড লাইন থেকে -K দূরে রাখে। এটি ছাড়া আপনি Missing sudo password পাবেন, যা নিচে আলোচনা করা হয়েছে।
ধাপ 7: দুবার চালান — আইডেম্পটেন্স দেখতে যেমন হয়
একই কমান্ড অবিলম্বে আবার চালান:
web1 : ok=9 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0changed=0, এবং ok এক কমেছে কারণ নোটিফাই না করা হ্যান্ডলারটি আসে নি। কিছু পুনরায় ইনস্টল হয়নি, sshd রিস্টার্ট হয়নি, ufw স্পর্শ করা হয়নি। এটিই প্লেবুকটিকে প্রোভিশনারের পাশাপাশি একটি অডিট করে তোলে: আগামী মাসে ইনভেন্টরিতে web3 যোগ করে আবার চালান — নতুন বক্সটি তৈরি হবে, পুরোনো বক্সগুলি যাচাই হবে। আপনি যে বক্সটি স্পর্শ করেননি সেখানে একটি ননজিরো changed হলো ড্রিফ্ট, এবং এটি জানায় যে কেউ হাতে সম্পাদনা করেছে যা প্লেবুকে সম্পাদনা করা উচিত ছিল।
এখান থেকে প্যাটার্নটি বৃদ্ধি পায়। লেখার মতো পরবর্তী প্লেবুকটি একই VPS-এ একটি WireGuard VPN স্থাপন করে এবং ufw নিয়ম কঠোর করে যাতে SSH শুধুমাত্র টানেলে সাড়া দেয়; এর পরে, এমন একটি যা প্রতিটি অ্যাপ সার্ভারে Docker এবং Compose ইনস্টল করে। যখন site.yml তিনটি স্ক্রিন অতিক্রম করবে, তখন এটিকে রোলে ভাগ করুন — কিন্তু তার আগে নয়।
ব্যর্থতার ধরন, আপনি যে স্ট্রিংগুলো দেখবেন
UNREACHABLE, 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
}SSH ট্রান্সপোর্ট যেকোনো মডিউল চলার আগেই ব্যর্থ হয়েছে: ansible_user ভুল, চাবিটি ওই হোস্টে কপি হয়নি, অথবা ভুল চাবি প্রস্তাব করা হচ্ছে। সাধারণ ssh root@10.0.0.10 দিয়ে পুনরুৎপাদন করুন, তারপর ssh -v দিয়ে দেখুন কোন চাবিগুলো প্রস্তাব করা হয়েছিল। পাসওয়ার্ড SSH কাজ করে কিন্তু Ansible করে না যদি, আপনি ssh-copy-id এড়িয়ে গেছেন।
sudo পাসওয়ার্ড অনুপস্থিত।
web1 | FAILED! => {
"msg": "Missing sudo password"
}আপনি become: true সেট করেছেন, নন-রুট ব্যবহারকারী হিসেবে সংযুক্ত হয়েছেন, এবং ওই ব্যবহারকারীর sudo-র জন্য একটি পাসওয়ার্ড দরকার। কমান্ড লাইনে হয় -K (--ask-become-pass) যোগ করুন, অথবা ব্যবহারকারীকে একটি NOPASSWD sudoers এন্ট্রি দিন — ঠিক এই কারণেই প্লেবুকটি আপনি এতে স্যুইচ করার আগে deploy-র জন্য একটি ইনস্টল করে।
error: externally-managed-environment. আপনি Ubuntu 24.04-এ সিস্টেম Python-এর বিরুদ্ধে pip চালিয়েছেন। ধাপ 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প্রায় সবসময়ই এটি ইন্ডেন্টেশন: ভুল গভীরতায় একটি কী, অথবা কোলনের পরে একটি স্পেস অনুপস্থিত। রিপোর্ট করা লাইন নম্বরটি ভুলের কাছাকাছি নির্দেশ করে, ঠিক ওটাতে নয় — উপরের লাইনটিও যাচাই করুন। এর আত্মীয় found character '\t' that cannot start any token মানে একটি ট্যাব ঢুকে গেছে; YAML সেগুলো নিষিদ্ধ করে। প্রতিটি রানের আগে ansible-playbook site.yml --syntax-check একটি অভ্যাসে পরিণত করুন, এবং YAML-এর জন্য আপনার এডিটরকে দুই-স্পেস ইন্ডেন্টেশনে সেট করুন।
/usr/bin/python3: not found. প্রমিত Ubuntu 24.04 ইমেজে বিরল, ন্যূনতম বা নেটবুট ইমেজে সাধারণ: লক্ষ্যে কোনো Python না থাকায় মডিউল সম্পাদন ব্যর্থ হয়। এটি raw মডিউল দিয়ে বুটস্ট্র্যাপ করুন, একমাত্র মডিউল যার দূরপ্রান্তে কিছুই দরকার নেই: ansible all -m raw -a "apt-get update && apt-get install -y python3" --become, তারপর প্লেবুকটি পুনরায় চালান।
FAQ
এটি পরিচালনা করা সার্ভারগুলিতে আমাকে কি Ansible ইনস্টল করতে হবে?
না। Ansible এজেন্টবিহীন: কন্ট্রোল মেশিন SSH-এর মাধ্যমে ছোট Python মডিউল পাঠায়, সেগুলি চালায় এবং তারপর মুছে দেয়। একটি টার্গেট মেশিনে শুধু python3 এবং SSH অ্যাক্সেস প্রয়োজন, যা স্টক Ubuntu ইমেজে আগে থেকেই থাকে। এই গাইডে একমাত্র ইনস্টলেশন আপনার কন্ট্রোল মেশিনেই হবে।
Ansible কেন "Permission denied (publickey)" বলে?
UNREACHABLE! ব্লকের সাথে Permission denied (publickey) মানে Ansible কিছু চালানোর আগেই SSH প্রমাণীকরণ ব্যর্থ হয়েছে। যাচাই করুন যে ইনভেন্টরিতে ansible_user আপনার সত্যিকারে সেট আপ করা অ্যাকাউন্টের সাথে মেলে, আপনি সেই হোস্টে ssh-copy-id চালিয়েছেন এবং সাধারণ ssh user@host পাসওয়ার্ড ছাড়াই লগইন করে। সাধারণ ssh কমান্ড যা ঠিক করে, তাই Ansible ঠিক করে, কারণ এরা একই ট্রান্সপোর্ট ব্যবহার করে।
Ansible-এ idempotent মানে কী?
একটি টাস্ক একটি কাঙ্ক্ষিত অবস্থা ঘোষণা করে — "এই প্যাকেজটি উপস্থিত আছে", "এই ফাইলে এই লাইনটি আছে" — সম্পাদন করার জন্য একটি ক্রিয়া নয়। অবস্থা আগে থেকেই মিলে গেলে, Ansible কিছু করে না এবং changed-এর বদলে ok রিপোর্ট করে। এই কারণেই একটি প্লেবুক দুবার চালালে দ্বিতীয়বার changed=0 দেখায় এবং পুনরায় চালানো একটি ঝুঁকিপূর্ণ পুনরায় ইনস্টলের বদলে একটি নিরাপদ অডিট।
Ubuntu 24.04-এ Ansible ইনস্টল করতে আমার কি pip বা pipx ব্যবহার করা উচিত?
pipx। Ubuntu 24.04 সিস্টেম Python-কে বাহ্যিকভাবে পরিচালিত হিসেবে চিহ্নিত করে, তাই ডিজাইন অনুসারে pip install ansible error: externally-managed-environment দিয়ে ব্যর্থ হয়। pipx install --include-deps ansible Ansible-কে একটি বিচ্ছিন্ন virtualenv-এ রাখে এবং ansible, ansible-playbook এবং বাকিগুলি আপনার PATH-এ পরিষ্কারভাবে উন্মুক্ত করে।
ansible এবং ansible-core প্যাকেজের মধ্যে পার্থক্য কী?
ansible-core হলো ইঞ্জিন এবং শুধু ansible.builtin মডিউল। ansible প্যাকেজটি কিউরেটেড কমিউনিটি কালেকশনগুলির সাথে কোর বান্ডেল করে — যার মধ্যে ansible.posix (authorized_key মডিউল) এবং community.general (ufw মডিউল) রয়েছে, উভয়ই এই গাইডে ব্যবহৃত হয়েছে। সম্পূর্ণ প্যাকেজ দিয়ে শুরু করুন; শুধু তখনই কোর এবং নির্বাচিত কালেকশনে সংকুচিত করুন যখন আপনার একটি কারণ থাকে।