Перейти до вмісту
📘 Ansible Learning Journey – From Manual SSH to Automation Thinking
Source: Dev.to | Jan 14, 2026 (UTC)
CloudWithHorla | Cloud & DevOps Engineer (Learning in Progress 🚀)
Automation looks simple from the outside — until you try to build it yourself.
Recently, I worked on an Ansible hands-on project as part of my continuous learning in Cloud and DevOps engineering. The goal was simple on paper:
set up a controller node and manage multiple target nodes using Ansible.

In reality, the journey taught me far more than just commands.
🏗️ Project Overview
I built a small but realistic infrastructure on AWS consisting of:
- * 1 EC2 Controller (Ansible Master)
- * 3 EC2 Target Nodes
- * Ubuntu-based servers
- * SSH key-based authentication
- * Ansible ad-hoc commands and playbooks

This setup mirrors what actually happens in real-world environments — not just labs.
🔧 What I Implemented (Step-by-Step)
- Provisioned EC2 instances
- 1 controller
- 3 managed nodes
- Installed core dependencies
- Python3
- Pip
- Ansible on the controller
- Created Ansible configuration
- Custom
ansible.cfg
- Inventory file defining all target nodes
- SSH Key-Based Authentication
You are adding a new line of Public Key which is safe.
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCppACFB47TRDuT8YXSSxL+T9jxirz0yC04avxRB8nAOnVcz5xXpyT0mhYbhcLCbI2D4pcWkSb1NqGyUwF3OeHGtur+0MkDq7/9jhPG0amrFbk+RBQM+WZ7UaEzopiK7ZB8MUKwtMGVhR9wgtIiSK6+fgmzNaCpfj13B9aH7iiMRn4sHCwr81zCAskb79DnhCmB8Y7NU2VAqlMnW5NIFEujv3aixmPSZbIKomNotGT2ljtOV5EoMuFFqq3DqA/kZVM1WJjBMEAlWtdQTn2UM5dTAi5BNvPMYJcdzEfc4fXvkp11rFYLiEc9ZUFkYi6APg1Ju5bPgh0Yp+9YOhlCMEuEPlAdxUIHE4Ih3HoNhLOB622c+a6lNK5SF7Y76gB5cdK8Rar/tRQqF6kxqy852SLfZbLnXkfIOuktF4XGemMMt13F7yw1k980vwcwCgfAK4zOZ2hmaDypmG0Rd/lhsIpC+4i6s4T8a+AB3BSKt9KH/Dn9cxUM0BVgxgM1hWyk7Hs= ubuntu@ip-10-0-8-231" >> .ssh/authorized_keys
Enter fullscreen mode
Exit fullscreen mode
Caveat: Best practise
You are removing an existing “Public Key” which is not safe.
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCppACFB47TRDuT8YXSSxL+T9jxirz0yC04avxRB8nAOnVcz5xXpyT0mhYbhcLCbI2D4pcWkSb1NqGyUwF3OeHGtur+0MkDq7/9jhPG0amrFbk+RBQM+WZ7UaEzopiK7ZB8MUKwtMGVhR9wgtIiSK6+fgmzNaCpfj13B9aH7iiMRn4sHCwr81zCAskb79DnhCmB8Y7NU2VAqlMnW5NIFEujv3aixmPSZbIKomNotGT2ljtOV5EoMuFFqq3DqA/kZVM1WJjBMEAlWtdQTn2UM5dTAi5BNvPMYJcdzEfc4fXvkp11rFYLiEc9ZUFkYi6APg1Ju5bPgh0Yp+9YOhlCMEuEPlAdxUIHE4Ih3HoNhLOB622c+a6lNK5SF7Y76gB5cdK8Rar/tRQqF6kxqy852SLfZbLnXkfIOuktF4XGemMMt13F7yw1k980vwcwCgfAK4zOZ2hmaDypmG0Rd/lhsIpC+4i6s4T8a+AB3BSKt9KH/Dn9cxUM0BVgxgM1hWyk7Hs= ubuntu@ip-10-0-8-231" > .ssh/authorized_keys
Enter fullscreen mode
Exit fullscreen mode
Caveat: Not a best practise
Sample
- Privilege Escalation
- Used
become: true for system-level tasks
- Ensured sudo access without breaking security
- Ansible Ad-Hoc Commands
ansible -m apt -a "name=git state=present" all -b
Enter fullscreen mode
Exit fullscreen mode
- Ansible Playbook Execution
- Installed and removed packages
- Copied files to remote nodes
- Managed services across multiple machines in parallel
📄 Sample Playbook used in my project:
--- - name: Installing nginx playbook hosts: all become: true tasks: - name: First Task apt: name: nginx state: absent - name: Second Task apt: name: nginx state: present - name: Copy file with owner and permissions ansible.builtin.copy: src: ./index.html dest: /var/www/html/index.html owner: root group: root mode: '0777' - name: Third Task apt: name: apache2 state: present
Enter fullscreen mode
Exit fullscreen mode
⚠️ Challenges I Faced (and What I Learned)
1️⃣ “Permission denied (publickey)”
I initially thought Ansible could manage nodes without SSH access.
Through research and troubleshooting, I learned a critical truth:
Ansible always uses SSH. There is no automation without an initial trust path.
Key-based authentication must be established at least once — either at instance creation or manually.
2️⃣ PasswordAuthentication Confusion
I tried disabling password authentication before confirming key-based access.
That was a big lesson:
❌ Disabling PasswordAuthentication does NOT give access
✅ It only removes password login after SSH keys already work
Correct order matters:
- Establish SSH key access
- Test connectivity
- Then disable password authentication
3️⃣ APT Lock Errors (unattended-upgrades)
One node failed while others succeeded.
Cause:
- Ubuntu auto-updates were running in the background
Lesson:
Infrastructure is not deterministic — nodes behave independently.
Solution:
- Wait and retry
- Or design playbooks with retries and checks
Screenshot Output

This is when I ping of the node

This is when I ping all the node

This is the first page output of my Playbook

This is the second page output of my Playbook

Node 01

Node 02

Node 03
4️⃣ Wrong Package Names
I attempted to install apache instead of apache2.
Lesson:
Automation does exactly what you tell it — not what you mean.
Small naming errors can break entire workflows.
🧠 Key Takeaways I Want Others to Learn
- 🔑 SSH is foundational — Ansible cannot bypass it
- 🔁 Automation is about idempotency and retries
- 🧪 Always test with
--syntax-check and ping yourself (localhost) for test.

- 🔐 Never overwrite
authorized_keys
- 🛠️ Real learning happens when things break
🌱 Growth Mindset
This project reinforced my core belief:
Never stop learning.
Every error I faced forced me to:
- Research deeper
- Read documentation
- Understand why things work — not just how
I’m still learning.
I’m still breaking things.
And I’m still getting better — one tool at a time.
📌 Final Thought
Automation isn’t about avoiding work —
it’s about doing the work once, correctly and at scale.
CloudWithHorla ☁️
Cloud & DevOps Engineer | Always Learning
For further actions, you may consider blocking this person and/or reporting abuse
Залишити відповідь