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 on Ubuntu 26.04 LTS: sudo-rs, APT Rollback, and Automating Resolute Raccoon

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

Install and configure Ansible on Ubuntu 26.04 LTS Resolute Raccoon. Automate sudo-rs (Rust-based sudo), APT 3.2 transaction rollback, Wayland-only desktops.

Ubuntu 26.04 LTS Changes That Affect Your Ansible Playbooks

Ubuntu 26.04 LTS "Resolute Raccoon" ships changes that matter to anyone managing Linux infrastructure with Ansible. Most posts about this release will focus on desktop polish. This one focuses on what changes for automation engineers.

The headline: sudo-rs is now the default sudo provider. Your become: true tasks still work, but the binary handling privilege escalation on every managed host is fundamentally different. Here's what you need to know and how to automate it.

See also: Ansible on Ubuntu 26.04 LTS Automation Complete Guide

Install Ansible on Ubuntu 26.04

# Update package index
sudo apt update

# Install Ansible from Ubuntu repos sudo apt install -y ansible

# Or install latest from PPA sudo add-apt-repository --yes ppa:ansible/ansible sudo apt update sudo apt install -y ansible

# Or install via pip (recommended for control nodes) sudo apt install -y python3-pip python3-venv python3 -m venv ~/ansible-venv source ~/ansible-venv/bin/activate pip install ansible

# Verify ansible --version

Automate Control Node Setup

---
- name: Set up Ansible control node on Ubuntu 26.04
  hosts: localhost
  become: true

tasks: - name: Install Python and pip ansible.builtin.apt: name: - python3 - python3-pip - python3-venv - sshpass - git state: present update_cache: true

- name: Install Ansible in virtualenv ansible.builtin.pip: name: - ansible - ansible-lint - molecule virtualenv: /opt/ansible-venv virtualenv_command: python3 -m venv

- name: Create symlink for ansible commands ansible.builtin.file: src: "/opt/ansible-venv/bin/{{ item }}" dest: "/usr/local/bin/{{ item }}" state: link loop: - ansible - ansible-playbook - ansible-galaxy - ansible-vault - ansible-lint

sudo-rs: The Change That Actually Matters

sudo is the binary that runs as root on every Linux machine you manage. It's been written in C since 1980. In the last few years it's had CVEs that allowed local privilege escalation — Baron Samedit (CVE-2021-3156) being the memorable one, with 10 years of unpatched exposure across most Linux distros.

sudo-rs is a full rewrite in Rust. Same /etc/sudoers config format. Same CLI interface. Drop-in replacement. The memory safety guarantees Rust provides matter specifically here — on the binary that handles privilege escalation.

This isn't experimental. sudo-rs passed a full security audit by Radically Open Security in 2023. The sudo-rs team (developed by Prossimo/ISRG, the people behind Let's Encrypt) worked directly with Todd C. Miller, the original sudo maintainer. Ubuntu 26.04 making it the default is the signal that it's production-ready.

What Changes for Ansible

The good news: nothing breaks. Ansible's become method calls sudo as a binary. sudo-rs provides the same binary interface. Your existing playbooks work without modification.

What you should validate:

- name: Verify sudo-rs on Ubuntu 26.04 hosts
  hosts: ubuntu_26_04
  become: true

tasks: - name: Check which sudo binary is installed ansible.builtin.command: cmd: dpkg -l sudo-rs register: sudo_rs_check changed_when: false failed_when: false

- name: Confirm sudo-rs is active ansible.builtin.command: cmd: sudo --version register: sudo_version changed_when: false become: false

- name: Report sudo implementation ansible.builtin.debug: msg: > Host {{ inventory_hostname }} running: {{ sudo_version.stdout_lines[0] | default('unknown') }} {% if 'sudo-rs' in (sudo_version.stdout | default('')) %} (Rust implementation - memory safe) {% else %} (Traditional C implementation) {% endif %}

Enforce sudo-rs Across Your Fleet

If you're managing a mixed fleet of Ubuntu versions and want to standardize on sudo-rs where available:

- name: Enforce sudo-rs on supported Ubuntu hosts
  hosts: ubuntu
  become: true

tasks: - name: Install sudo-rs on Ubuntu 24.04+ ansible.builtin.apt: name: sudo-rs state: present when: - ansible_distribution == "Ubuntu" - ansible_distribution_version is version('24.04', '>=') register: sudo_rs_install

- name: Verify sudo still works after switch ansible.builtin.command: cmd: sudo -n true become: false changed_when: false when: sudo_rs_install.changed

- name: Validate sudoers syntax ansible.builtin.command: cmd: visudo -c changed_when: false

Harden sudoers Configuration

sudo-rs uses the same /etc/sudoers format, so your existing Ansible sudoers management works identically:

- name: Harden sudoers on Ubuntu 26.04
  hosts: ubuntu_26_04
  become: true

tasks: - name: Configure secure sudoers defaults ansible.builtin.lineinfile: path: /etc/sudoers regexp: "^Defaults\\s+{{ item.key }}" line: "Defaults {{ item.key }}={{ item.value }}" validate: "visudo -cf %s" loop: - { key: "passwd_timeout", value: "1" } - { key: "timestamp_timeout", value: "5" } - { key: "logfile", value: '"/var/log/sudo.log"' }

- name: Ensure Defaults use_pty is set ansible.builtin.lineinfile: path: /etc/sudoers regexp: "^Defaults\\s+use_pty" line: "Defaults use_pty" validate: "visudo -cf %s"

- name: Create Ansible service account sudoers ansible.builtin.copy: content: | # Ansible automation account - managed by Ansible ansible ALL=(ALL) NOPASSWD: ALL Defaults:ansible !requiretty dest: /etc/sudoers.d/ansible mode: '0440' validate: "visudo -cf %s"

See also: Ansible on Ubuntu 20.04 LTS: Unattended Security Updates Complete Guide

APT 3.2: Transaction Rollback

APT 3.2 in Ubuntu 26.04 introduces a transaction log with full rollback support. apt history-rollback undoes any package operation. This changes how you handle failed deployments and package management with Ansible.

Automate APT Rollback

- name: Safe package deployment with APT rollback
  hosts: ubuntu_26_04
  become: true

tasks: - name: Record APT transaction ID before changes ansible.builtin.command: cmd: apt history --format=json register: apt_history_before changed_when: false

- name: Store last transaction ID ansible.builtin.set_fact: pre_deploy_transaction: "{{ (apt_history_before.stdout | from_json)[-1].id | default('0') }}"

- name: Deploy application packages ansible.builtin.apt: name: - nginx - php8.4-fpm - php8.4-mysql - redis-server state: present update_cache: true register: pkg_install

- name: Validate application health ansible.builtin.uri: url: "http://localhost/health" return_content: true status_code: 200 register: health_check failed_when: false when: pkg_install.changed

- name: Rollback if health check fails ansible.builtin.command: cmd: "apt history-rollback -y {{ pre_deploy_transaction | int + 1 }}" when: - pkg_install.changed - health_check.status is defined - health_check.status != 200 register: rollback_result

- name: Alert on rollback ansible.builtin.debug: msg: "ROLLBACK EXECUTED on {{ inventory_hostname }} - deployment failed health check" when: rollback_result is changed

APT Rollback for Kernel Updates

- name: Safe kernel update with rollback capability
  hosts: ubuntu_26_04
  become: true

tasks: - name: Record current kernel ansible.builtin.command: cmd: uname -r register: kernel_before changed_when: false

- name: Apply kernel update ansible.builtin.apt: name: linux-generic state: latest update_cache: true register: kernel_update

- name: Schedule rollback check after reboot ansible.builtin.copy: content: | #!/bin/bash # Auto-rollback if system doesn't come up healthy sleep 300 if ! curl -sf http://localhost/health > /dev/null 2>&1; then apt history-rollback -y last reboot fi dest: /usr/local/bin/kernel-rollback-check.sh mode: '0755' when: kernel_update.changed

- name: Reboot with watchdog ansible.builtin.reboot: reboot_timeout: 600 test_command: uptime when: kernel_update.changed

Kernel 7.0: What Matters for Automation

Ubuntu 26.04 ships Linux Kernel 7.0 with Intel TDX (Trust Domain Extensions) for confidential computing and broader hardware support.

- name: Validate and configure Kernel 7.0 features
  hosts: ubuntu_26_04
  become: true

tasks: - name: Check kernel version ansible.builtin.command: cmd: uname -r register: kernel_version changed_when: false

- name: Verify kernel is 7.x ansible.builtin.assert: that: kernel_version.stdout is version('7.0', '>=') fail_msg: "Expected kernel 7.x, got {{ kernel_version.stdout }}"

- name: Check Intel TDX support ansible.builtin.command: cmd: grep -c tdx /proc/cpuinfo register: tdx_check changed_when: false failed_when: false

- name: Enable TDX if supported ansible.builtin.copy: content: | # Intel TDX confidential computing options kvm_intel tdx=1 dest: /etc/modprobe.d/tdx.conf mode: '0644' when: tdx_check.stdout | int > 0 notify: update initramfs

- name: Configure kernel parameters for production ansible.posix.sysctl: name: "{{ item.key }}" value: "{{ item.value }}" sysctl_set: true reload: true loop: - { key: "vm.swappiness", value: "10" } - { key: "net.core.somaxconn", value: "65535" } - { key: "net.ipv4.tcp_max_syn_backlog", value: "65535" } - { key: "fs.file-max", value: "2097152" } - { key: "kernel.pid_max", value: "4194304" }

handlers: - name: update initramfs ansible.builtin.command: cmd: update-initramfs -u

See also: Ansible on Ubuntu 22.04 LTS: Unattended Security Updates Complete Guide

Wayland-Only: X11 Is Gone

Ubuntu 26.04 removes X11 entirely. No more Xorg fallback session in GDM. If your Ansible playbooks install or configure X11 packages, they'll fail.

- name: Configure Wayland desktop on Ubuntu 26.04
  hosts: ubuntu_26_04_desktop
  become: true

tasks: - name: Remove any X11 references from old playbooks ansible.builtin.apt: name: - xorg - xserver-xorg - xinit state: absent failed_when: false

- name: Install Wayland desktop components ansible.builtin.apt: name: - ubuntu-desktop - mutter - xdg-desktop-portal-gnome - xwayland # For legacy X11 apps that need compatibility state: present

- name: Configure GDM for Wayland ansible.builtin.copy: content: | [daemon] WaylandEnable=true AutomaticLoginEnable=false

[security]

[xdmcp]

[chooser]

[debug] dest: /etc/gdm3/custom.conf mode: '0644' notify: restart gdm

- name: Set environment for Wayland ansible.builtin.copy: content: | # Wayland environment variables MOZ_ENABLE_WAYLAND=1 QT_QPA_PLATFORM=wayland GDK_BACKEND=wayland ELECTRON_OZONE_PLATFORM_HINT=wayland dest: /etc/environment.d/wayland.conf mode: '0644'

handlers: - name: restart gdm ansible.builtin.systemd: name: gdm3 state: restarted

Update Display Testing in CI

If your Ansible molecule tests or CI pipelines use virtual displays:

# Old approach (broken on 26.04)
# - name: Start Xvfb
#   command: Xvfb :99 -screen 0 1024x768x24

# New approach for Wayland - name: Install headless Wayland compositor for testing ansible.builtin.apt: name: weston state: present

- name: Start headless Wayland for testing ansible.builtin.shell: | weston --backend=headless --width=1024 --height=768 & export WAYLAND_DISPLAY=wayland-0 async: 3600 poll: 0

ROCm: AMD GPU Compute as a One-Liner

Ubuntu 26.04 includes ROCm in the official repositories. No more third-party repo configuration.

- name: Install AMD ROCm GPU compute
  hosts: gpu_workers
  become: true

tasks: - name: Install ROCm from official repos ansible.builtin.apt: name: - rocm state: present update_cache: true when: ansible_distribution_version is version('26.04', '>=')

- name: Add user to render and video groups ansible.builtin.user: name: "{{ item }}" groups: - render - video append: true loop: "{{ gpu_users }}"

- name: Verify ROCm installation ansible.builtin.command: cmd: rocm-smi register: rocm_status changed_when: false

- name: Display GPU info ansible.builtin.debug: msg: "{{ rocm_status.stdout }}"

ROCm vs Pre-26.04 Comparison

# Before Ubuntu 26.04 (manual repo setup)
# - name: Add ROCm GPG key
#   apt_key:
#     url: https://repo.radeon.com/rocm/rocm.gpg.key
# - name: Add ROCm repository
#   apt_repository:
#     repo: "deb [arch=amd64] https://repo.radeon.com/rocm/apt/6.0 jammy main"
# - name: Install ROCm
#   apt:
#     name: rocm-hip-sdk

# Ubuntu 26.04 - it's in the default repos - name: Install ROCm ansible.builtin.apt: name: rocm state: present

Ptyxis Terminal

Ubuntu 26.04 replaces GNOME Terminal with Ptyxis — GPU-accelerated, GTK4-native, with tabs that hold state. If your playbooks install or configure gnome-terminal, update them:

- name: Configure terminal on Ubuntu 26.04
  hosts: ubuntu_26_04_desktop
  become: true

tasks: - name: Ensure Ptyxis is installed (default on 26.04) ansible.builtin.apt: name: ptyxis state: present

- name: Remove old gnome-terminal references ansible.builtin.apt: name: gnome-terminal state: absent failed_when: false

Complete Ubuntu 26.04 Base Image Playbook

For building hardened base images, sudo-rs and the APT rollback flow are the two things to validate first:

---
- name: Ubuntu 26.04 LTS hardened base image
  hosts: ubuntu_26_04
  become: true

tasks: # 1. Validate sudo-rs is active - name: Confirm sudo-rs is the default ansible.builtin.shell: cmd: "sudo --version 2>&1 | head -1" register: sudo_impl changed_when: false become: false

- name: Assert sudo-rs ansible.builtin.assert: that: "'sudo-rs' in sudo_impl.stdout or 'rustc' in sudo_impl.stdout" fail_msg: "sudo-rs is not the default sudo on this host"

# 2. Full system update - name: Update all packages ansible.builtin.apt: upgrade: dist update_cache: true cache_valid_time: 3600

# 3. Install baseline packages - name: Install standard tooling ansible.builtin.apt: name: - curl - wget - git - vim - htop - unattended-upgrades - apt-listchanges - needrestart - ufw - fail2ban - chrony - jq state: present

# 4. Configure unattended security updates - name: Enable automatic security updates ansible.builtin.copy: content: | APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; APT::Periodic::AutocleanInterval "7"; dest: /etc/apt/apt.conf.d/20auto-upgrades mode: '0644'

# 5. Harden SSH - name: Harden SSH configuration ansible.builtin.lineinfile: path: /etc/ssh/sshd_config regexp: "^{{ item.key }}" line: "{{ item.key }} {{ item.value }}" validate: "sshd -t -f %s" loop: - { key: "PermitRootLogin", value: "no" } - { key: "PasswordAuthentication", value: "no" } - { key: "X11Forwarding", value: "no" } - { key: "MaxAuthTries", value: "3" } - { key: "ClientAliveInterval", value: "300" } - { key: "ClientAliveCountMax", value: "2" } notify: restart sshd

# 6. Configure UFW firewall - name: Enable UFW with default deny community.general.ufw: state: enabled default: deny direction: incoming

- name: Allow SSH community.general.ufw: rule: allow port: '22' proto: tcp

# 7. Configure fail2ban - name: Configure fail2ban for SSH ansible.builtin.copy: content: | [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 3600 findtime = 600 dest: /etc/fail2ban/jail.d/sshd.conf mode: '0644' notify: restart fail2ban

# 8. Configure chrony NTP - name: Configure NTP ansible.builtin.template: src: chrony.conf.j2 dest: /etc/chrony/chrony.conf mode: '0644' notify: restart chrony

# 9. Kernel hardening - name: Apply kernel hardening parameters ansible.posix.sysctl: name: "{{ item.key }}" value: "{{ item.value }}" sysctl_set: true reload: true loop: - { key: "net.ipv4.conf.all.rp_filter", value: "1" } - { key: "net.ipv4.conf.default.rp_filter", value: "1" } - { key: "net.ipv4.icmp_echo_ignore_broadcasts", value: "1" } - { key: "net.ipv4.conf.all.accept_redirects", value: "0" } - { key: "net.ipv6.conf.all.accept_redirects", value: "0" } - { key: "net.ipv4.conf.all.send_redirects", value: "0" } - { key: "kernel.randomize_va_space", value: "2" } - { key: "kernel.kptr_restrict", value: "2" }

# 10. Cleanup - name: Remove unnecessary packages ansible.builtin.apt: autoremove: true purge: true

handlers: - name: restart sshd ansible.builtin.systemd: name: ssh state: restarted

- name: restart fail2ban ansible.builtin.systemd: name: fail2ban state: restarted

- name: restart chrony ansible.builtin.systemd: name: chrony state: restarted

Ubuntu 26.04 Quick Reference

| Feature | What Changed | Ansible Impact | |---------|-------------|----------------| | sudo-rs | Rust-based sudo is default | become: true works unchanged; validate on fleet | | APT 3.2 | Transaction rollback via apt history-rollback | New rollback capability for safe deployments | | Kernel 7.0 | Intel TDX, broader hardware | New sysctl params, TDX module options | | Wayland-only | X11 completely removed | Remove Xorg tasks; update CI virtual displays | | ROCm in repos | apt install rocm | Remove manual repo configuration tasks | | Ptyxis | Replaces GNOME Terminal | Update desktop provisioning playbooks | | LTS until 2031 | 5 years standard, 10 with Pro | Long-term automation target |

FAQ

Does Ansible's become method work with sudo-rs?

Yes. Ansible calls sudo as a binary, and sudo-rs is a drop-in replacement with the same CLI interface. No changes to become: true, become_method: sudo, or ansible_become_password are needed. Your existing playbooks work without modification.

Should I switch existing Ubuntu 24.04 hosts to sudo-rs?

sudo-rs is available as a package on Ubuntu 24.04 and later. For security-sensitive environments, it's worth the switch. Test your sudoers configuration first — sudo-rs intentionally doesn't implement some rarely-used sudoers features that are common sources of security issues.

How do I use APT rollback in Ansible error handling?

Use Ansible's block/rescue pattern combined with apt history-rollback. Record the transaction ID before your package block, then call rollback in the rescue section if any task fails. See the safe deployment playbook above for the full pattern.

Will my X11-dependent Ansible roles break on Ubuntu 26.04?

If your roles install xorg, xserver-xorg, or configure X11 settings, they'll fail or produce warnings on Ubuntu 26.04. Audit roles for X11 dependencies and create Wayland alternatives. The xwayland package provides compatibility for legacy X11 applications that run under Wayland.

Is Ubuntu 26.04 safe for production Ansible managed nodes?

Yes. As an LTS release with 5 years of standard support (10 with Ubuntu Pro until 2036), Ubuntu 26.04 is designed for production. The sudo-rs change actually improves security posture. Test your playbooks in staging first, particularly around any X11 or custom sudo configurations.

Conclusion

Ubuntu 26.04 LTS "Resolute Raccoon" brings meaningful changes for automation engineers. sudo-rs eliminates an entire class of privilege escalation vulnerabilities in the most critical binary on your systems. APT 3.2 rollback gives you a safety net for package operations. The Wayland-only shift requires updating desktop provisioning playbooks. And ROCm in default repos simplifies GPU compute automation from a multi-step process to a single apt install. Validate sudo-rs and APT rollback first — they're the changes that impact every host you manage.

Related Articles

How to Install Ansible on UbuntuAnsible apt Module: Complete Package Management GuideAnsible become: Privilege Escalation Complete GuideAnsible UFW Firewall Module GuideAnsible Systemd Module: Manage Services on Linux

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home