Skip to main content

ansible-rehearse

CI PyPI Python License: MIT

Rehearse your Ansible playbook in a throwaway container and see the real state diff — packages, files, services, ports, users — before you touch production.

Think terraform plan, but for Ansible: instead of predicting what a playbook might do, rehearse actually runs it inside an ephemeral container matched to your target distro, snapshots the system before and after, and shows you exactly what changed.

rehearse demo

Why not just --check?

ansible-playbook --check lies by omission:

  • Modules without check-mode support are silently skipped — shell, command, script, raw tasks are never executed, so their effects are invisible.
  • Registered variables stay undefined, so when: conditionals silently take the wrong branch and dependent tasks are mis-simulated or explode.
  • Some modules simply behave differently under --check (a task that works in a real run can fail in check mode, and vice versa).

rehearse takes the opposite approach: run everything for real, in a sandbox, and measure what actually happened. Your shell tasks run. Your register + when chains take the same branches they would take on a real host. Then you get a terraform-plan-style diff of observed state — not a simulation.

Quick start

pip install ansible-rehearse

You need Docker (or Podman) running. Ansible itself is not required on your machine — it runs inside the container, so rehearse works from Linux, macOS and Windows hosts alike.

# Rehearse against a plain Ubuntu 22.04 container
rehearse run site.yml

# Service state too? Use a systemd-enabled container
rehearse run site.yml --systemd

# Match your target distro
rehearse run site.yml --distro rocky9

# Machine-readable output for CI
rehearse run site.yml --json result.json

The first run per distro prepares the container (installs a pinned ansible-core into an isolated venv) and caches it as an image; later runs start in seconds.

What you get

  • Packages — installed / removed / upgraded, with versions
  • Files — created / deleted / modified under watched directories (/etc, /usr/local, /opt, /srv, /root, /home, /var/spool/cron, /var/www, plus --watch DIR), including mode / owner / content changes
  • Services — enabled / started / stopped (in --systemd mode)
  • Listening ports — opened / closed, with the owning process
  • Users & groups — added / removed / modified
  • A per-task fidelity table — how much to trust each result (see below)

The fidelity model

A container is not your production host, and pretending otherwise is how preview tools lose your trust. Every task gets an explicit fidelity label:

Label Meaning
exact The state change happens for real in the container and is fully observable.
real-exec Arbitrary code (shell, command…) executed for real — the thing --check can never show you.
needs-systemd Service state needs a service manager; rerun with --systemd.
approximate Runs, but a container's shared kernel / missing subsystems may differ from a real host (sysctl, firewall, SELinux).
not-rehearsable No meaningful container equivalent (reboot, kernel modules, partitioning).
external Would touch systems outside the container — refused by default.

Run rehearse modules to see the full matrix.

Safety model

  • External-effect gate. Before anything runs, the playbook is statically scanned. Tasks that would touch real infrastructure — cloud collections (amazon.aws.*, azure.*, kubernetes.core.*…), notification modules, mutating uri calls — cause rehearse to refuse to run (exit code 3) unless you pass --allow-external. Both modern FQCN and legacy action:/local_action: syntax are scanned.
  • No tampering window. The state collector is piped into the container over stdin for each snapshot; there is no on-disk script a playbook could rewrite between snapshots.
  • --systemd is privileged. Systemd-in-docker requires a privileged container sharing host cgroups: kernel-level operations can leak to the docker host. rehearse labels those tasks accordingly and warns loudly — only rehearse playbooks you trust, especially in --systemd mode.
  • Third-party content. Roles/collections from requirements.yml are installed at runtime inside the container and are not covered by the static gate — review them yourself.

A rehearsal is not your production host

Honest limitations, so you can decide what to trust:

  • The container starts clean: the diff shows what the playbook does to a fresh OS-matched system, not to your drifted production host with its years of accumulated state.
  • Kernel, hardware, network topology and cross-host orchestration are not reproduced. Cloud/network modules cannot be rehearsed at all (they are blocked by default precisely because they would run for real).
  • Facts differ (hostname, IPs, memory), so playbooks branching on them may take different paths than in production.

What it is great at: catching broken task logic, missing packages, wrong paths, template errors, misbehaving conditionals, unintended file/permission changes, and services that do not come up — before any real host is involved.

How it compares

executes tasks real state diff needs test code target
ansible-playbook --check no (simulates, skips) no no your real hosts
check-mode formatters no (same skips, prettier) no no your real hosts
Molecule yes no (you write assertions) yes fresh test instance
rehearse yes yes (packages/files/services/ports/users) no throwaway container

Molecule is the right tool for testing roles with assertions in CI over time; rehearse answers a different question — "what exactly will this playbook do, right now, before I run it for real?" — with zero test code.

Supported targets

profile plain image --systemd image
ubuntu22 (default) ubuntu:22.04 geerlingguy/docker-ubuntu2204-ansible
ubuntu24 ubuntu:24.04 geerlingguy/docker-ubuntu2404-ansible
debian12 debian:12 geerlingguy/docker-debian12-ansible
rocky9 rockylinux:9 geerlingguy/docker-rockylinux9-ansible
fedora44 fedora:44 geerlingguy/docker-fedora44-ansible

Or bring your own image with --image.

Exit codes

code meaning
0 rehearsal completed, playbook succeeded
1 rehearsal completed, playbook failed (partial diff shown)
2 usage / playbook / internal error
3 refused: playbook contains external-effect tasks
4 container engine unavailable

Contributing

See CONTRIBUTING.md. Bug reports with a failing playbook snippet are gold; so are fidelity-matrix corrections from people who know a module better than we do.

License

MIT

Metadata

Release files for ansible-rehearse 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ansible-rehearse 0.1.1
File Size Uploaded
ansible_rehearse-0.1.1.tar.gz 71.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ansible-rehearse 0.1.1
File Interpreter ABI Platform
ansible_rehearse-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 108.6 kB

Release files / ansible_rehearse-0.1.1.tar.gz

Download URL ansible_rehearse-0.1.1.tar.gz
Size 71.2 kB
Tags Source
SHA-256 checksum
How to use checksums
a270a6e36a641c0c008d1c92d25ec0845251e22c4b252b2a547451fbd7403243
BLAKE2b-256 checksum
How to use checksums
2e001cd9ec867596b0efb4dfe11bc9c802a093cc9ca41ad6b6b5d4dbd287ac15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release files / ansible_rehearse-0.1.1-py3-none-any.whl

Download URL ansible_rehearse-0.1.1-py3-none-any.whl
Size 37.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5215a5285329c1087923726879c189fc6b7c295d494e9744266a89eb82ad9401
BLAKE2b-256 checksum
How to use checksums
9ae52e565a11d5163c033e5e44f2a83b61a13b0f42737c9c3716d916fffdc1a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page