Spacelift + ServiceNow = Self-Service IaC Without the Learning Curve

➡️ Register Now

Ansible

Using Ansible apt Module to Manage Packages

ansible apt module

🚀 Level Up Your Infrastructure Skills

You focus on building. We’ll keep you updated. Get curated infrastructure insights that help you make smarter decisions.

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:

  1. What is the Ansible apt module?
  2. When to use the Ansible apt module?
  3. How to use the Ansible apt module
  4. Troubleshooting package installation

What is the Ansible apt module?

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.

When to use the Ansible apt module?

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

How to use the Ansible apt module

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:

install latest package version ansible apt

Let’s check the status of the Nginx server.

latest nginx version ansible apt

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:

validate if package is installed ansible apt

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:

ansible apt package removed

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:

remove unused dependencies ansible apt

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:

ansible apt status

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:

Manage external apt repositories

The repository list will show the Docker repository:

docker repository ansible apt

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:

ansible apt remove repo

Troubleshooting apt package installation in Ansible

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. 

How can Spacelift help you with Ansible projects?

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:

ansible product video thumbnail

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.

Key points

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.

Learn more