Skip to content

feat(roles/duplicity): support Debian/Ubuntu and remove the build toolchain#282

Open
markuslf wants to merge 1 commit into
mainfrom
feat/duplicity-multi-distro
Open

feat(roles/duplicity): support Debian/Ubuntu and remove the build toolchain#282
markuslf wants to merge 1 commit into
mainfrom
feat/duplicity-multi-distro

Conversation

@markuslf

@markuslf markuslf commented Jun 17, 2026

Copy link
Copy Markdown
Member

Security win: no build toolchain on backup hosts

Until now the duplicity role installed gcc plus the Python -devel headers on every backup host. The cause sat deep in the dependency tree: duplicity unconditionally depends on pyrax (its Rackspace backend, which we never use), and that old stack pulled in netifaces - a package that is deprecated and unmaintained (last release 2021), ships no wheels for current Python, and therefore had to be compiled from source on the target.

Pinning a modern oslo.* stack (which no longer depends on netifaces) through a pip constraints file removes netifaces from the tree entirely. The role now installs no compiler and no development headers; package_requirements is reduced to the Python interpreter only. Taking the build toolchain off production backup machines is a significant reduction of the attack surface.

Verified across all supported distros that gcc is absent and netifaces is not installed, while Swift backups still work.

What else is in here

  • Debian and Ubuntu support. duplicity now runs on Debian 12/13 and Ubuntu 22.04/24.04/26.04 in addition to RHEL 8/9/10. All ten distros were validated in containers (manylinux wheel install, gpg present, Swift code path reached). Marked proven (x) in COMPATIBILITY.md.
  • Swift fixed on Python 3.10+. The same modern oslo.* pin fixes the long-standing collections.Mapping crash (AttributeError in oslo_config), so the manual oslo.config>=9 workaround documented in the README is no longer needed.
  • librsync-devel dropped. duplicity 3.1.0 ships manylinux wheels that bundle its _librsync extension, so that build dependency is obsolete.
  • gnupg is installed by the role, so backups also work on minimal installs that ship without gpg.

New generic feature in python_venv

To wire the constraints cleanly, python_venv gained an optional per-venv pip_constraints key: it writes a constraints file into the venv and passes pip --constraint. Backward compatible (no change without the key). This is reusable by any venv-based role that needs to pin a transitive dependency without listing it as a direct package.

CONTRIBUTING / example conformance

While in the role, aligned it with the guidelines and the example role:

  • Added meta/argument_specs.yml to both duplicity and python_venv (validates inputs at role entry; required GPG keys, choices for backend/loglevel).
  • Load platform variables under the always tag.
  • Removed a duplicate gpg --import task; set owner/group on all template tasks.
  • Tag vocabulary: dropped the non-standard duplicity:script (the script deploys under duplicity:configure), added duplicity:dump for the backup schedule.

Testing

  • Container runs (podman) on RHEL 8/9/10, Debian 12/13, Ubuntu 22.04/24.04/26.04: wheel install, no gcc, no netifaces, duplicity --version, and the Swift code path reaching a real auth/network error (not the import crash).
  • Real python_venv role run against a Rocky 8 container via the containers.podman connection: constraints file deployed, gcc not installed, netifaces avoided, duplicity runnable via the exposed-binary symlink.
  • argument_specs validated with ansible-playbook (required-var, type, and choices enforcement; Swift and SFTP paths both pass).
  • yamllint clean on all changed files.

🤖 Generated with Claude Code

…lchain

Security win: backup hosts no longer get a C compiler. duplicity's Swift
backend pulled the deprecated, source-only netifaces (via the unused pyrax
stack), which forced gcc and the Python -devel headers onto every backup
host. Pinning a modern oslo.* stack drops netifaces, so the role now installs
no build toolchain at all - a significant reduction of the attack surface on
production machines.

* python_venv: add an optional per-venv pip_constraints key (writes a
  constraints file and passes pip --constraint), plus meta/argument_specs.yml.
* duplicity: pin a modern oslo.* stack via pip_constraints. This also fixes
  the collections.Mapping crash on Python 3.10+, so the manual oslo.config
  workaround is gone. package_requirements is now interpreter-only (no gcc,
  no -devel, no librsync-devel).
* duplicity: add Debian 12/13 and Ubuntu 22.04/24.04/26.04 support, proven on
  all of them plus RHEL 8/9/10 via containers. Install gnupg from the role.
* duplicity: add meta/argument_specs.yml, load platform vars under the always
  tag, drop a duplicate gpg --import task, set owner/group on all templates,
  and align the tags with the LFOps vocabulary (duplicity:script folded into
  duplicity:configure, new duplicity:dump for the backup schedule).
* Mark Debian and Ubuntu proven for duplicity in COMPATIBILITY.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant