Imagine an organization with ten Ubuntu servers that need security updates and Nginx installed on each one. The system administrator logs into each server manually, runs updates, and installs packages individually. This process is not only time-consuming but also prone to errors.
Managing packages is crucial for maintaining system security and stability, but doing it manually across multiple systems can be inefficient. Ansible simplifies this by automating package installations and updates, ensuring efficiency, consistency, and scalability.
In this article, we’ll show how to use the apt module in Ansible to automate package management. By the end, you’ll understand how automation improves system administration and how to implement it in various scenarios.
What we’ll cover:
The Ansible apt
module is used to manage packages on Debian-based Linux systems using the Advanced Packaging Tool (APT).
It allows you to install, remove, or update software packages directly from APT repositories. You can also specify whether a package should be in a certain state (e.g., present
, latest
, or absent
).
One standout feature of the apt
module is idempotency. Before making changes, it checks the system’s current package state. Instead of running every time like a manual sudo apt-get install command, the apt module only executes changes when necessary.
Ansible apt module parameters
The Ansible apt
module includes several parameters to control package management. The following are a few of them:
name
(required): Specifies the package name to install, update, or remove.state
(optional): Defines the package state (present, absent, latest). Default is present.update_cache
(optional): Updates the package list before installation.cache_valid_time
(optional): Defines how long (in seconds) before the package list is updated again.allow_unauthenticated
(optional): Installs packages from untrusted sources (use with caution).autoclean
(optional): Removes outdated package files.- purge (optional): Removes configuration files along with the package.
force
(optional): Forces installation or removal, even if dependencies are broken.install_recommends
(optional): Specifies whether to install recommended packages when installing a package via APT. This mirrors the APT configuration setting APT::Install-Recommends.
For a complete and up-to-date list of parameters, please refer to the official Ansible documentation.
You can use the Ansible apt
module to manage packages on multiple servers within your organization. Unlike yum
(for RHEL-based systems) and other modules, the apt
module is for managing packages on Debian-based systems like Ubuntu.
Popular derivatives such as Linux Mint and Pop_OS also use apt for package management. Its straightforward syntax makes it easy to use in Ansible playbooks.
Ansible apt is especially useful in these cases:
- Installing packages: Deploying software like Nginx, MySQL, or Docker across multiple servers
- Updating packages: Keeping software up to date without manual intervention.
- Removing packages: Uninstalling software that’s no longer needed
- Ensuring system consistency: Standardizing package versions across servers
- Automating server setup: Preloading necessary software on new servers
This section will show how to use the Ansible apt module for installations, updates, and deletions.
We’ll use Nginx as an example for this guide because it’s a popular web server and easy to demonstrate. However, you can use the same steps for any other package you need.
Demo environment
For this guide, we’ll use an AWS EC2 Ubuntu instance. However, you can follow along on any Debian system with Ansible installed.
1. Install a single package
To install a single package using Ansible, you must include the apt module within the tasks section in your playbook.
For example, to install an Nginx package, this is how your playbook will look:
---
- name: Install Nginx on Debian-based systems
hosts: all
become: yes # Run as sudo
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
update_cache: yes
From the playbook above, the apt
module updates the package list before installing the Nginx package using the update_cache
option. The state:present
command ensures that the Ansible apt module installs the Nginx package.
Once you run this playbook, you will see the following output:
2. Install the latest package version
To install the latest package version with the apt
module, append the state: latest option to your tasks in the Ansible playbook.
For example, to install the latest version of Nginx on your server, you’ll write your playbook like this:
---
- name: Install the latest version of Nginx
hosts: all
become: yes # Run as sudo
tasks:
- name: Ensure Nginx is installed and up-to-date
apt:
name: nginx
state: latest
update_cache: yes
You should see the following output once you run this playbook on your server:
Let’s check the status of the Nginx server.
3. Install multiple packages
To install multiple packages on your servers, the Ansible apt
module allows you to list packages under the name parameter in the playbook.
For example, if you need to install Nginx, curl, unzip, and git, each item will be listed on your playbook using the name parameter, and this playbook setup will look like this:
---
- name: Install multiple packages
hosts: localhost
become: yes # Run as sudo
tasks:
- name: Install required packages
apt:
name:
- nodejs
- mysql-server
- curl
- tree
- unzip
state: present
update_cache: yes
Here, the playbook lists multiple packages using the name parameter, updates the package list before installation, installs them, and ensures they are all installed.
Upon running this playbook on your server, you should see the following output:
4. Validate whether a package is installed
You can use the apt
module to validate the installation of a package on the system.
For example, after installing Nginx on your servers, you can determine whether the Nginx installation was successful by using the following configuration on your playbook:
---
- name: Validate whether a package is installed
hosts: localhost
become: yes # Run as sudo
tasks:
- name: Ensure Nginx is installed
apt:
name: nginx
state: present
From the playbook above, the state: present
option will check if Nginx is installed on the machine. If it isn’t, it will install it.
Once you run this playbook, you’ll see the following output:
5. Update all packages
The apt
module allows you to run updates on all packages on the system. This command is similar to running the everyday sudo apt update on an Ubuntu server.
On Ansible, the playbook commands will look like this:
---
- name: Update all packages on Debian-based systems
hosts: all
become: yes # Run as sudo
tasks:
- name: Update package cache
apt:
update_cache: yes
- name: Upgrade all packages to the latest version
apt:
upgrade: dist
This playbook command first updates the package cache using the update_cache
option on the server and then upgrades: dist
upgrades all installed packages to the latest version and resolves all dependencies.
After running this playbook, you should see a similar output:
6. Remove a package
You can remove an installed package on your server using the state: absent
command on your playbook.
For example, if you need to remove the Nginx package, you specify the package with the name command and set the state to absent to remove it. Your playbook will look like this:
---
- name: Remove Nginx from Debian-based systems
hosts: all
become: yes # Run as sudo
tasks:
- name: Uninstall Nginx
apt:
name: nginx
state: absent
You should see the following output once you run this playbook:
7. Remove unused dependencies
To remove unused dependencies on your server, use the auto-remove command in the apt
module. As with running the sudo apt-get autoremove
command, it removes previously installed packages not in use.
For instance, once you delete a Nginx package and other packages within the server, run the following Ansible playbook to eliminate unused dependencies:
---
- name: Remove unused dependencies on Debian-based systems
hosts: all
become: yes # Run as sudo
tasks:
- name: Clean up unused dependencies
apt:
autoremove: yes
Here, this playbook uses the autoremove: yes option to clean up unused dependencies within the server.
After running the playbook, you should see the following output:
8. Clean up the package cache
The apt
module comes with the autoclean:yes
option to clean up the package cache on the server. It removes the outdated package file from the local cache, freeing up disk space.
For instance, after previously removing the curl package on your server, you can clean up the cache by running the following playbook:
---
- name: Clean up package cache on Debian-based systems
hosts: all
become: yes # Run as sudo
tasks:
- name: Remove obsolete package files
apt:
autoclean: yes
After running the playbook, the output will be as follows:
9. Capture the output of the apt module
The register keyword allows you to capture the output of the apt
module. This command lets you store and display the task output in debug mode.
For example, after installing or deleting the Nginx or curl package, the register keyword captures the operation’s output and uses the debug mode to show whether the output was successful.
This is what your Ansible file will look like:
---
- name: Capture apt module output
hosts: all
become: yes # Run as sudo
tasks:
- name: Install or update Nginx
apt:
name: nginx
state: latest
update_cache: yes
register: apt_output # Captures the output
- name: Display apt output
debug:
var: apt_output
The register keyword in the playbook stores the result of the apt
module execution, and the debug printout shows the captured output, including whether the package was installed or updated, with error or success messages. It also indicates whether the package cache was updated.
After running the playbook, you should see the following output:
Status shows a successful playbook run:
10. Manage external apt repositories
The apt_repository
option on the playbook allows you to manage external apt repositories in Ansible. This option allows you to add, remove, or update third-party modules.
For example, installing Docker on your Ubuntu server requires external repositories. To add these repositories, you use the apt_repository
option on your playbook, and it will look like this:
- name: Add Docker APT repository
hosts: all
become: yes # Run as sudo
tasks:
- name: Add Docker GPG key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker repository
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
filename: docker
- name: Update package cache
apt:
update_cache: yes
This playbook adds the external repository using the apt_repository
option to install Docker on the server. It creates a file called docker, where the server will install the external repository.
Once you run the playbook, you should see the following output:
The repository list will show the Docker repository:
11. Remove a repository
You can also use the apt_repository
option in the apt
module to remove an external repository. To do so, you must set the state command to be absent.
For example, to remove the Docker repository stored in the previous example, you change the state command to absent, which shows that the Docker local repository has been removed.
The playbook will look like this:
---
- name: Remove Docker repository
hosts: all
become: yes
tasks:
- name: Remove Docker APT repository
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: absent
filename: docker
After running the playbook, you should see the following output:
When installing packages on your server, you may encounter errors like repository issues, locked package managers, or missing dependencies.
In this section, we’ll discuss the troubleshooting steps you can take on your Ansible playbook to mitigate errors successfully and ensure that the apt module works properly.
Capture errors using the installation process
While troubleshooting, you need to capture any errors that may occur during the package installation. This will help identify the root cause of the problem.
You can view the installation process output using the register
option and debug
mode:
- name: Capture errors while installing a package
hosts: all
become: yes # Run as sudo
tasks:
- name: Attempt to install Nginx
apt:
name: nginx
state: present
register: apt_output # Store the output for debugging
ignore_errors: yes # Prevents the Playbook from stopping on failure
- name: Show installation output
debug:
var: apt_output
The debug
mode will provide specific details like error messages and package state.
Install packages with recommended dependencies
While installing a package, several other packages may need to be installed to make the main package work. Once these packages are absent, the installation may fail.
The following playbook tells the Ansible apt
module to install all recommended and required packages:
---
- name: Install a package with dependencies
hosts: all
become: yes
tasks:
- name: Ensure dependencies are installed
apt:
name: nginx
state: present
install_recommends: yes # Installs suggested dependencies
This playbook features an install_recommends
option that installs suggested dependencies alongside the package, ensuring the Ansible execution doesn’t fail.
Fix broken dependencies
When installing a package using the apt
module, some dependencies may appear broken, causing issues in the installation process. To fix that, use the state: fixed option to attempt an automatic repair of the dependencies before installation.
The following playbook allows you to fix broken dependencies before installing:
---
- name: Fix broken dependencies before installation
hosts: all
become: yes
tasks:
- name: Fix broken dependencies
apt:
name: "*"
state: fixed
- name: Install Nginx after fixing dependencies
apt:
name: nginx
state: present
Handle all locked apt processes within the server
When installing a package on your server, other processes may be running that lock the current apt process. If you try to install a package while this package manager is locked, the installation will fail.
The example playbook below handles all locked apt processes within the server and installs the Nginx package with zero errors:
- name: Handle locked apt process
hosts: all
become: yes
tasks:
- name: Wait for the apt lock to be released
command: "while sudo lsof /var/lib/dpkg/lock; do sleep 5; done"
changed_when: false
- name: Install Nginx after lock is released
apt:
name: nginx
state: present
From the playbook, the lsof /var/lib/dpkg/lock
command checks if another process uses apt and loops continuously until the package-lock is free, at which point it proceeds to install the package.
Remove all corrupt or partially installed packages
When installing or modifying a file using Ansible, previous attempts at installing that file may have corrupted or partially installed the dependencies or configuration files.
With the apt
module, you can remove all corrupt files with the following playbook:
- name: Remove broken packages before reinstallation
hosts: all
become: yes
tasks:
- name: Remove problematic package
apt:
name: nginx
state: absent
purge: yes # Completely removes config files
- name: Clean up package cache
apt:
autoclean: yes
- name: Reinstall package
apt:
name: nginx
state: present
This playbook removes the package from the server, deletes the configuration files, and cleans up the cache, ensuring a clean installation with no remaining issues.
Spacelift’s vibrant ecosystem and excellent GitOps flow are helpful for managing and orchestrating Ansible. By introducing Spacelift on top of Ansible, you can easily create custom workflows based on pull requests and apply any necessary compliance checks for your organization.
Another advantage of using Spacelift is that you can manage infrastructure tools like Ansible, Terraform, Pulumi, AWS CloudFormation, and even Kubernetes from the same place and combine their stacks with building workflows across tools.
Our latest Ansible enhancements solve three of the biggest challenges engineers face when they are using Ansible:
- Having a centralized place in which you can run your playbooks
- Combining IaC with configuration management to create a single workflow
- Getting insights into what ran and where
Provisioning, configuring, governing, and even orchestrating your containers can be performed with a single workflow, separating the elements into smaller chunks to identify issues more easily.
Would you like to see this in action, or just get a tl;dr? Check out this video showing you Spacelift’s Ansible functionality:
If you want to learn more about using Spacelift with Ansible, check our documentation, read our Ansible guide, or book a demo with one of our engineers.
In this article, we covered the apt module in Ansible and explained how to use it. We started by showing you how to install packages, validate whether a package is installed, remove unused dependencies, and clean the package cache.
We also walked you through the different ways to troubleshoot package installation issues on the server. These include capturing errors during installation, installing the package with recommended dependencies, fixing broken dependencies, handling all locked apt processes, and removing all corrupt packages.
The apt module is the recommended way to install, update, and manage packages efficiently on Debian-based systems. The module ensures consistency and helps maintain a well-optimized package management process.
Manage Ansible better with Spacelift
Managing large-scale playbook execution is hard. Spacelift enables you to automate Ansible playbook execution with visibility and control over resources, and seamlessly link provisioning and configuration workflows.