Automating Linux updates

Photo by Xu Haiwei on Unsplash

Photo by Xu Haiwei on Unsplash

Updating Ubuntu servers with Ansible
Updated 1. March 2025

Updating a bunch of Linux servers is not hard, but it can be time-consuming, and tedious. Thankfully Ansible is an excellent tool for automating the job.

In this article, I will guide you through the process of getting started with automated updating all your Ubuntu or any other Debian-based servers running on Virtual Private Servers (VPS) or bare-metal hosts, including fun projects like a cluster of Raspberry Pis.

Setup

What to do before you can run start automating.

A good place to start is with all your VPSes updated and healthy. You should also ensure that Python3 is installed and available through the terminal on all servers.

Once they are updated, you should install Ansible on your local computer. Since Ansible is an agentless automation tool, you don't need to install any kind of agent software related to Ansible on the servers. To install Ansible, follow the installation guide found in the Ansible docs.

 If you are on a Windows host, it's probably a good idea to run Ansible through WSL to make your life simpler.

Inventory

List all your servers

To make it possible to run the Ansible automation on several hosts, you must create an inventory file that lists all your hosts, with aliases, and other configurations, and then group them into groups.

inventory
www1 ansible_host=www1.haxor.no ansible_python_interpreter=auto_legacy_silent
www2 ansible_host=www2.haxor.no ansible_python_interpreter=auto_legacy_silent
www3 ansible_host=www3.haxor.no ansible_python_interpreter=auto_legacy_silent
deploy ansible_host=deploy.haxor.no ansible_python_interpreter=auto_legacy_silent
ipa ansible_host=ipa.haxor.no ansible_python_interpreter=auto_legacy_silent

[ubuntu_hosts]
www1
www2
www3
deploy

[redhat_hosts]
ipa

[all_hosts:children]
ubuntu_hosts
redhat_hosts

In the inventory file above, I have listed five servers. After the hostnames, the "ansible_python_interpreter" variable indicates that I don't want any error related to an old Python version installed on the hosts.

Four servers are running Ubuntu and are placed in the ubuntu_hosts group, and one is running Red Hat and is placed in the redhat_hosts group. 

To run any automation on all hosts, I use the all_hosts group, which includes all the children of the ubuntu_hosts, and the redhat_hosts groups.

Test connectivity

Before you can run any automation with Ansible, you should ensure that you can authenticate all the servers using an SSH key without being prompted for a password. 

Generate a new ssh-key using this command:

ssh-keygen

To copy your private key to each server, run this command:

ssh-copy-id <hostname>

Verify that you can connect to the servers without providing your password.

ssh <hostname>

Now that you can connect to all the servers passwordless using an SSH key, you can create the following connection_testing playbook:

ping_all_hosts.yaml
- hosts: all_hosts
  name: Ping all hosts
  tasks:
    - name: Check connectivity
      ping:

The playbook above connects to all the servers in the all_hosts group in your inventory file, and runs a "ping-pong" script to verify that everything is working as expected.

To run the playbook run this command:

ansible-playbook -i inventory ping_all_hosts.yaml

PLAY [Ping all hosts] **************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [www1]
ok: [www2]
ok: [www3]
ok: [deploy]
ok: [ipa]

TASK [Check connectivity] **********************************************************************************************
ok: [www1]
ok: [www2]
ok: [www3]
ok: [deploy]
ok: [ipa]

PLAY RECAP *************************************************************************************************************
www1                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
www2                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
www3                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
deploy                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
ipa                        : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

If you don't get any errors, you have successfully configured your inventory, and can proceed with writing Ansible playbooks for automating your sysadmin tasks.

Updating the servers

Saving hours each month!

Now, after all that setup and testing, you can start writing your playbook to automate the OS update process, potentially saving you hours of manual work each month.

Create the following playbook:

ubuntu_update.yaml
- hosts: ubuntu_hosts
  name: Update all Ubuntu hosts
  tasks:
    - name: Update OS
      become: true
      apt: 
        upgrade: yes
        update_cache: yes

To dry-run the playbook, run this command:

ansible-playbook -i inventory ubuntu_update.yaml --ask-become-pass --check

If you did not get any errors, you can run the playbook without the --check option:

ansible-playbook -i inventory ubuntu_update.yaml --ask-become-pass
BECOME password:

PLAY [Update all Ubuntu hosts] *****************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [www1]
ok: [www2]
ok: [www3]
ok: [deploy]

TASK [Update OS] *******************************************************************************************************
ok: [www1]
ok: [www2]
ok: [www3]
ok: [deploy]

PLAY RECAP *************************************************************************************************************
www1                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
www2                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
www3                     : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
deploy                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Congratulations! You have now automated OS updates on your Ubuntu servers! 🎉