GyaaniGuy

- self made πŸ’» 😎

Linux Automation with ansible - Part 1: Basics

I used to struggle with linux automation, fixing the same thing again and again. Coming back to old servers and not remembering how I had fixed something.

Same issue with deploying websites. It used to take like 20 commands changing permissions, making users, configuring services just to get some site running.

Not anymore.

Ansible - The last linux automation tool I’ll use.

Battle tested, used by millions, ansible is gold. Joy to configure, especially with ai. LLMs are great at making ansible scripts. We’ll do everything with ansible, adding users, editing config files, deploying websites, everything. 0 manual commands on the server. If we have to do something more, we improve the ansible script.

First I’ll show the anatomy of ansible, then how to install and use it, finally I’ll share my ansible scripts

What can Ansible do

Everything ! Setup a server from scratch - setup ssh, new users, permissions, deploy websites, install, and configure services. The same scripts can also be used on localhost!

Instead of manual commands, try to do everything with ansible. Do once, use again and again.

Anatomy of Ansible

  • hosts file: has info about servers on which commands will be run
  • playbooks: yml scripts. Have commands to run
  • execution: Run a playbook on a specified host, with specified user -
    ansible-playbook ./playbooks/zsh.yml -i ./inventory/hosts -l serverNameInHostsFile --user serverUserName

That’s it.

Install Ansible

  1. Local (debian) - sudo apt install ansible
  2. Remote Server - Make sure python is installed

That’s it !

Setup Ansible

I suggest making a dedicated ansibleDir to keep all your playbooks, hosts and configuration files in one place. Here is my Ansible Dir on github: https://github.com/gyaaniguy/ansible-guide

ansiblDir
β”œβ”€β”€ inventory
β”‚   └── hosts
β”œβ”€β”€ playbooks
β”‚   β”œβ”€β”€ caddy.yml
β”‚   β”œβ”€β”€ configs
β”‚   β”‚   β”œβ”€β”€ Caddyfile.j2
β”‚   β”‚   └── upload_settings.ini
β”‚   └── ssh
β”‚       └── some-ssh-key.pub
└── Readme.md

Running Ansible


# Test Command
ansible -i ./inventory/hosts servers -m ping --user root

# Regular command
ansible-playbook ./playbooks/zsh.yml -l serverNameInHostsFile -i ./inventory/hosts  --user serverUserName

# ssh login pass -> This is required if ssh uses password to login
ansible-playbook ... --ask-pass

# Run in localhost
ansible-playbook ... -l local 

# If playbook commands need elevated privileges on the server, give Ansible that password.
ansible-playbook ... --ask-become-pass

# Pass extra vars to the playbook
ansible-playbook ... --extra-vars "bare_repo=/home/user/repo.git"

# Verbose mode - Use when getting errors -> pass error to AI
ansible-playbook ... -vv

Hosts file

Straightforward

[serverNameInHostsFile]
servername.com

[local]
localhost ansible_connection=local

Playbooks

Playbooks are the scripts containing list of commands that ansible executes on your server. I won’t go into too much detail, explaining its syntax. But here are some pointers -

  • AI is really good at making, fixing and even adding more commands to the playbooks. Since ansible scripts are simple and has detailed logging in verbose mode -vv , AI is able to fix errors easily.
  • Ansible has a large selection of built in commands to handle everything -
    • make user
    • file operations
    • package manager commands
    • lots more..
  • Custom variable are supported. ansible-playbook --extra-vars="var=value" . This makes ansible really powerful - create different users, deploy different websites etc.
  • become: true - run some task or whole script as sudo
  • See handlers - simple functions that can be run when called with the β€˜notify’ command

Use my playbooks as a base, then use ai to imrpove upon them.

Example playbooks

  • Simple: apps.yml
    Playbook to install packages. Performs 2 tasks. updates repo, then installs packages using apt-get.
- name: Install required packages
  hosts: all
  become: true

  tasks:
    - name: Update package cache
     #become: true
      apt:
        update_cache: yes
        upgrade: dist

    - name: Install packages
     #become: true
      apt:
        name:
          - sudo
          - zsh
          - git
          - curl
          - unzip
          - zip
          - software-properties-common
          - build-essential
          - rsync
          - htop
          - neovim
        state: present
        install_recommends: no
  • Complex: user.yml
    Add a User
    I really like this one. Not only does it create a user, it does so with a custom password + configures the user - copies a ssh pub key and a zsh config file to the server.

Just one simple script and user creation has never been better !


- name: Create a login username
  hosts: all
  vars:
    username: "{{ u | default('user') }}"
    password: "{{ p | password_hash('sha512') }}"
  tasks:
    - name: Add a username
      ansible.builtin.user:
        name: "{{ username }}"
        password: "{{ password }}"
        groups:
          - sudo
          - www-data
        state: present
        shell: /bin/zsh
        system: no
        create_home: yes
        home: "/home/{{ username }}"

    - name: Add SSH key
      ansible.builtin.authorized_key:
        user: "{{ username }}"
        state: present
        key: "{{ lookup('file', './ssh/somepubkey.pub') }}"

    - name: Copy .zshrc file
      ansible.builtin.copy:
        src: ./configs/.zshrc
        dest: "/home/{{ username }}/.zshrc"
        owner: "{{ username }}"
        group: "{{ username }}"
        mode: '0644'

Of course on localhost you will first need to create a ssh/public_key.pub key, which will be copied. Or you can remove the β€˜Add SSH key’ task.

Execute above script:


ansible-playbook ./playbooks/user.yml \ 
--user root \
-i ./inventory/hosts \
-l serverName \
--extra-vars="u=aUsername p=aSentenceIsAGoodPasswordNotThisThough"

Next steps:

Explore my ansible setup. I’ll write an article on deploying laravel with ansible soon.


dated July 2025