AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible apt Module: Install, Remove & Manage Packages on Debian/Ubuntu

By Luca Berton · Published 2024-01-01 · Category: installation

Complete guide to Ansible apt module (ansible.builtin.apt). Install, remove, upgrade packages on Debian and Ubuntu.

The ansible.builtin.apt module manages packages on Debian, Ubuntu, Linux Mint, and other APT-based distributions. It handles installation, removal, upgrades, cache management, and repository configuration.

Install a Package

- name: Install nginx
  ansible.builtin.apt:
    name: nginx
    state: present

See also: Install Docker in Debian-like systems - Ansible module apt_key, apt_repository and apt

Install Multiple Packages

- name: Install web stack
  ansible.builtin.apt:
    name:
      - nginx
      - postgresql
      - redis-server
      - python3-pip
    state: present

Remove a Package

# Remove package (keep config files)
- name: Remove nginx
  ansible.builtin.apt:
    name: nginx
    state: absent

# Purge package (remove config files too) - name: Purge nginx completely ansible.builtin.apt: name: nginx purge: true state: absent

See also: Install Google Chrome in Debian like systems - Ansible module apt_key, apt_repository and apt

Update Cache (apt update)

# Update cache before installing
- name: Install with fresh cache
  ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: true
    cache_valid_time: 3600    # Skip update if <1 hour old

# Just update cache - name: Update apt cache ansible.builtin.apt: update_cache: true

Best practice: Always use cache_valid_time with update_cache to avoid running apt update on every task.

Upgrade All Packages

# Safe upgrade (apt upgrade)
- name: Upgrade all packages
  ansible.builtin.apt:
    upgrade: safe
    update_cache: true

# Full upgrade (apt full-upgrade / apt dist-upgrade) - name: Full upgrade ansible.builtin.apt: upgrade: full update_cache: true

# Dist upgrade - name: Distribution upgrade ansible.builtin.apt: upgrade: dist

See also: Install Microsoft Edge on Debian with Ansible

Pin a Specific Version

- name: Install specific version
  ansible.builtin.apt:
    name: nginx=1.24.0-2ubuntu1
    state: present

# Find available versions: apt-cache policy nginx

Install from .deb File

- name: Download package
  ansible.builtin.get_url:
    url: https://example.com/app_1.2.3_amd64.deb
    dest: /tmp/app.deb

- name: Install .deb package ansible.builtin.apt: deb: /tmp/app.deb

Add a Repository

- name: Add signing key
  ansible.builtin.apt_key:
    url: https://packages.grafana.com/gpg.key
    state: present

- name: Add Grafana repository ansible.builtin.apt_repository: repo: "deb https://packages.grafana.com/oss/deb stable main" state: present filename: grafana

- name: Install Grafana ansible.builtin.apt: name: grafana state: present update_cache: true

Modern Approach (signed-by)

- name: Add key to keyrings
  ansible.builtin.get_url:
    url: https://packages.grafana.com/gpg.key
    dest: /usr/share/keyrings/grafana.asc

- name: Add repository with signed-by ansible.builtin.apt_repository: repo: "deb [signed-by=/usr/share/keyrings/grafana.asc] https://packages.grafana.com/oss/deb stable main" state: present

Autoremove Unused Dependencies

- name: Remove unnecessary packages
  ansible.builtin.apt:
    autoremove: true

# Autoremove and autoclean - name: Clean up ansible.builtin.apt: autoclean: true autoremove: true

Install Latest Version

# Ensure latest version (upgrade if newer available)
- name: Install latest nginx
  ansible.builtin.apt:
    name: nginx
    state: latest
    update_cache: true
    cache_valid_time: 3600

⚠️ state: latest runs upgrades on every play — use state: present in production to avoid unexpected upgrades.

Key Parameters

| Parameter | Default | Description | |-----------|---------|-------------| | name | — | Package name(s) | | state | present | present, absent, latest, fixed | | update_cache | false | Run apt update first | | cache_valid_time | 0 | Skip cache update if recent (seconds) | | upgrade | — | safe, full, dist | | purge | false | Remove config files with absent | | deb | — | Path to .deb file | | autoremove | false | Remove unused dependencies | | force_apt_get | false | Use apt-get instead of aptitude | | install_recommends | true | Install recommended packages |

apt vs package Module

# ansible.builtin.apt — Debian/Ubuntu only, full APT features
- ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: true

# ansible.builtin.package — cross-platform, limited features - ansible.builtin.package: name: nginx state: present

Use apt when you need APT-specific features (cache, repos, purge). Use package for cross-platform playbooks.

Practical Examples

Bootstrap a Server

- name: Bootstrap Ubuntu server
  hosts: new_servers
  become: true
  tasks:
    - name: Update cache and upgrade
      ansible.builtin.apt:
        update_cache: true
        upgrade: safe

- name: Install base packages ansible.builtin.apt: name: - curl - wget - git - vim - htop - unzip - jq - ca-certificates - gnupg - lsb-release state: present

- name: Remove unwanted packages ansible.builtin.apt: name: - telnet - rsh-client state: absent purge: true

- name: Autoremove ansible.builtin.apt: autoremove: true

Conditional Install by OS Version

- name: Install Python
  ansible.builtin.apt:
    name: "{{ python_pkg }}"
    state: present
  vars:
    python_pkg: "{{ (ansible_distribution_version is version('22.04', '>=')) | ternary('python3.11', 'python3.10') }}"

Hold/Unhold Package Version

- name: Hold kernel version
  ansible.builtin.dpkg_selections:
    name: linux-image-generic
    selection: hold

- name: Unhold later ansible.builtin.dpkg_selections: name: linux-image-generic selection: install

FAQ

What's the difference between state present and latest?

present installs the package if missing but doesn't upgrade it. latest always checks for newer versions and upgrades. Use present in production for stability; use latest only when you explicitly want automatic upgrades.

How do I avoid running apt update every time?

Use cache_valid_time: update_cache: true with cache_valid_time: 3600 skips the update if the cache was refreshed within the last hour (3600 seconds).

Why does apt fail with "could not get lock"?

Another process (unattended-upgrades, another apt instance) holds the lock. Either wait, disable unattended-upgrades during deployment, or add a pre-task that waits for the lock to release.

How do I install a package from a specific repository?

Add the repository first with apt_repository, then install with apt. Use default_release parameter to specify the release if needed: default_release: bullseye-backports.

Conclusion

The apt module is essential for managing Debian/Ubuntu servers. Use update_cache with cache_valid_time to avoid unnecessary updates, state: present for stability, and combine with apt_repository and apt_key for third-party packages. For cross-platform playbooks, consider the package module instead.

Related Articles

How to Install Ansible on Ubuntu 24.04Ansible copy Module GuideAnsible service Module Guide

See also

How to Install Multiple Packages in Ansible (One Task)

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home