Ansible apt Module Tutorial + Examples


Percy Grunwald's Profile Picture

Written by Percy Grunwald

— Last Updated February 22, 2019

What does the Ansible apt module do?

Ansible’s apt module is used to manage packages with the apt package manager, which is the default on Debian based Linux distributions such as Debian and Ubuntu.

Most systems require root/superuser permissions to manage packages, which means that become: true is required.

I recommend always using the update_cache: true parameter when installing or updating packages, which forces apt to check if the package cache is out of date and it update it if needed.

- name: ensure php7.2 is installed
  apt:
    name: php7.2
    state: present
    update_cache: true
  become: true

If you need to manage apt repositories, use the apt_repository module.

If you need to manage packages on Red Hat based distributions like Red Hat Enterprise Linux or CentOS, use the yum module instead.

Ansible apt Module Video Tutorial

If you prefer watching to reading, here’s a full video tutorial from the TopTechSkills YouTube channel covering a many of the points and examples from this article. Feel free to comment on this article or the video if you have any questions.

▶️ Watch on YouTube

When to use the apt module vs yum module

Debian based Linux distributions such as Debian and Ubuntu use the apt package manager, so you should use the apt module for those distros. The yum module manages packages using the yum package manager, which is only available on Red Hat Enterprise Linux and CentOS.

When to use the apt module vs package module

The package module manages packages using whichever package manager is present on the remote host, such as apt, yum or dnf. This appears to be the most convenient way to manage packages, but I advise you to avoid using the package module in any situation.

The biggest reason to avoid it is because the same package may have different names on different distros.

For example: the server package for the popular in-memory database Redis is called redis-server on Debian based distros and redis on Red Hat based distros.

Unless you (and everyone on your team) is intimately familiar with the naming differences for packages across all distributions, using package drastically increases the chance of an error due to package naming. I highly recommend you manage packages using the module specific to the remote host.

The most common pattern for creating roles that can be run across all distributions is to run tasks conditionally based on the ansible_os_family variable:

- name: install redis on Debian based distros 
  apt:
    name: redis-server
    state: present
    update_cache: true
  become: true
  when: ansible_os_family == 'Debian'

- name: install redis on RHEL based distros
  yum:
    name: "{{ item }}"
    state: present
    update_cache: true
  become: true
  loop:
    - epel-release
    - redis
  when: ansible_os_family == 'RedHat'

Examples

How to install a package with the apt module

Set the name parameter to the package you wish to install and state: present to install a package. If the package is already installed on the remote host (with any version), Ansible will do nothing. If you need a specific version of a package, or to ensure the latest version of a package is installed, please see the following sections.

I recommend always using the update_cache: true parameter when installing or updating packages, which forces apt to check if the package cache is out of date and it update it if needed.

- name: ensure php7.2 is installed
  apt:
    name: php7.2
    state: present
    update_cache: true
  become: true

How to install a specific version of a package with the apt module

Add ={{ version }} to the name parameter to install a specific version of a package. The package must be available on the system. You can check which packages are available on the remote host by running apt list {{ package }} -a in the shell (-a lists all available package versions, not just the latest):

ubuntu@ip-10-1-11-72:~$ apt list php7.2 -a
Listing... Done
php7.2/bionic-updates,bionic-security 7.2.10-0ubuntu0.18.04.1 all
php7.2/bionic 7.2.3-1ubuntu1 all

Given that we would like to install version 7.2.10-0ubuntu0.18.04.1:

- name: ensure specific version of php7.2 is installed
  apt:
    name: php7.2=7.2.10-0ubuntu0.18.04.1
    state: present
    update_cache: true
  become: true

How to install multiple packages with the apt module

The best way to install multiple packages is by passing the list to the name parameter. This method is preferred over using loop because loop will install each package individually, which is very inefficient compared to passing all packages in name.

- name: ensure php7.2 and php7.2-mysql are installed
  apt:
    name: 
      - php7.2
      - php7.2-mysql
    state: present
    update_cache: true
  become: true

How to install a .deb package with the apt module

You can install .deb package directly with the apt module by setting the deb parameter to a local file path or internet URL.

- name: install php7.2 from a .deb on the internet
  apt:
    deb: http://security.ubuntu.com/ubuntu/pool/main/p/php7.2/php7.2_7.2.10-0ubuntu0.18.04.1_all.deb
    state: present
  become: true
  register: apt_output
  when: ansible_os_family == 'Debian'

How to uninstall a package with the apt module

Set state: absent to uninstall a package. I recommend also setting autoremove: true, which removes any dependencies that were installed originally but are no longer required.

- name: ensure nginx is not installed and autoremove unneeded deps
  apt:
    name: nginx
    state: absent
    autoremove: true
  become: true

How to update a package with the apt module

Set state: latest to ensure the latest available version of the package is installed. If the package is not installed at all, apt will install the latest version available.

- name: ensure latest version of php7.2 is installed
  apt:
    name: php7.2
    state: latest
    update_cache: true
  become: true

How to update multiple packages with the apt module

The process for updating multiple packages is essentially the same as installing multiple packages: simply pass a list of package names to the name parameter and set state: latest.

- name: ensure latest versions of php7.2 and php7.2-mysql are installed
  apt:
    name: 
      - php7.2
      - php7.2-mysql
    state: latest
    update_cache: true
  become: true

How to update all packages with the apt module

You can update all packages on the remote host by setting name: "*", state: latest and force_apt_get: true.

force_apt_get: true is generally required unless you have already installed aptitude.

- name: update all packages installed on the system
  apt:
    name: "*"
    state: latest
    force_apt_get: true
    update_cache: true
  become: true

How to downgrade a package with the apt module

There is no way I know of to downgrade a package with a single task using the apt module, but it’s simple enough to downgrade a package by first fully removing the package, then installing a specific previous version of the package.

I recommend setting autoremove: true in all cases when removing a package.

- name: ensure php7.2 is not installed
  apt:
    name: php7.2
    state: absent
    autoremove: true
  become: true

- name: ensure older version of php7.2 is installed
  apt:
    name: php7.2=7.2.3-1ubuntu1
    state: present
    update_cache: true
  become: true

How to clean up the apt cache

Set autoclean: true to clean up stale packages from the apt cache. It’s possible to run this as a standalone task.

- name: clean up the apt cache
  apt:
    autoclean: true
  become: true

How to remove package dependencies that are no longer required

Set autoremove: true to remove any dependencies that were installed along with other packages but are no longer required. I typically recommend setting this parameter any time you remove a package, but you can also run it as a standalone task:

- name: automatically remove any unused dependencies
  apt:
    autoremove: true
  become: true

How to capture apt module output

Use the register keyword to capture the output of the apt module.

- name: ensure php7.2 is installed
  apt:
    name: php7.2
    state: present
    update_cache: true
  become: true
  register: apt_output

- debug: var=apt_output

The debug task above will output the following:

ok: [123.123.123.123] => {
    "apt_output": {
        "changed": true,
        "diff": {},
        "failed": false,
        "stderr": "",
        "stderr_lines": [],
        "stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nThe following packages will be REMOVED:\n  php7.2\n0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.\nAfter this operation, 76.8 kB disk space will be freed.\n(Reading database ... \r(Reading database... 5%\r(Reading database ... 10%\r(Reading database ... 15%\r(Reading database ... 20%\r(Reading database ... 25%\r(Reading database ... 30%\r(Reading database ... 35%\r(Reading database ... 40%\r(Reading database ... 45%\r(Reading database ... 50%\r(Reading database ... 55%\r(Reading database ... 60%\r(Reading database ... 65%\r(Reading database ... 70%\r(Reading database ... 75%\r(Reading database ... 80%\r(Reading database ... 85%\r(Reading database ... 90%\r(Reading database ... 95%\r(Reading database ... 100%\r(Reading database ... 85816 files and directories currently installed.)\r\nRemoving php7.2 (7.2.3-1ubuntu1) ...\r\n",
        "stdout_lines": [
            "Reading package lists...",
            "Building dependency tree...",
            "Reading state information...",
            "The following packages will be REMOVED:",
            "  php7.2",
            "0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.",
            "After this operation, 76.8 kB disk space will be freed.",
            "(Reading database ... ",
            "(Reading database ... 5%",
            "(Reading database ... 10%",
            "(Reading database ... 15%",
            "(Reading database ... 20%",
            "(Reading database ... 25%",
            "(Reading database ... 30%",
            "(Reading database ... 35%",
            "(Reading database ... 40%",
            "(Reading database ... 45%",
            "(Reading database ... 50%",
            "(Reading database ... 55%",
            "(Reading database ... 60%",
            "(Reading database ... 65%",
            "(Reading database ... 70%",
            "(Reading database ... 75%",
            "(Reading database ... 80%",
            "(Reading database ... 85%",
            "(Reading database ... 90%",
            "(Reading database ... 95%",
            "(Reading database ... 100%",
            "(Reading database ... 85816 files and directories currently installed.)",
            "Removing php7.2 (7.2.3-1ubuntu1) ..."
        ]
    }
}

Further reading

Ansible apt Module on Ansible Docs

Comments