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 Ubuntu • Ansible apt Module: Complete Package Management Guide • Ansible become: Privilege Escalation Complete Guide • Ansible UFW Firewall Module Guide • Ansible Systemd Module: Manage Services on LinuxCategory: installation