Skip to main content
RunBook Academy

AnsibleL · Automation Disaster RecoveryWhat the controller actually held

The controller is permanently lost

Advanced⏱ ~26 minbashgit

What you'll learn

  • State the automation DR scenario precisely enough to test a recovery plan against it
  • Enumerate what lived only on the controller and would be lost with it
  • Separate the recoverable set from the unrecoverable set before an incident forces the question
  • Recognise the single dependency that turns a recoverable repository into noise

Prerequisites

Verified against ansible-core 2.21.x · ansible (community package) 14.x · Python (controller) 3.12+ · ansible-lint 26.x · Molecule 26.x · Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL / Rocky / AlmaLinux 9.x · 2026-08-11

Not yet marked complete on this device.

The controller is a single host. Everything this course has taught you to do — targeting, batching, check runs, vault, rolling deployments — runs from it, and in most organisations there is exactly one of it.

That makes it the least redundant machine in an estate whose entire purpose is to make other machines redundant. Nobody plans it that way. It happens because the controller starts as somebody’s shell account with a playbooks/ directory in it, and by the time it is managing four hundred servers it has never once been treated as production.

This part asks one question and spends six lessons answering it: the controller is permanently lost — can you rebuild it?

The scenario, stated precisely

Vagueness is what lets a recovery plan pass review without working. So the scenario is fixed, and every later lesson is tested against it:

  • The controller host is destroyed. Not powered off, not corrupted, not recoverable by a filesystem check. The disk is gone, the hypervisor is gone, or the region is gone.
  • There is no backup of the host itself. If there is one, that is a bonus, not the plan — a plan that depends on a backup you have not restored in eighteen months is a plan you have not tested.
  • The fleet is fine. Four hundred managed nodes are up and serving traffic. Nothing about them has changed.
  • Tomorrow morning there is work to do on that fleet: a security patch, a certificate rotation, or an incident. Something that needs automation, and needs it in hours rather than weeks.

Note what is deliberately not in the scenario. This is not a site-wide disaster. No managed node needs restoring. The question is narrow and uncomfortable: your ability to act on the estate is gone, while the estate itself is untouched.

The inventory of what was on that host

Before you can plan a rebuild, you have to enumerate what you are rebuilding. The list below is what a real controller carries. Read it against your own, and be honest about which column each item falls into.

What was on the controllerWhere else does it exist?
Playbooks and rolesGit, if they were committed and pushed
Inventory filesGit, if static; the source system, if dynamic
Dynamic-inventory plugin configGit — and the credentials it uses are not
ansible.cfgGit, if it was the project one and not ~/.ansible.cfg
requirements.ymlGit, if it exists at all
Installed collections and rolesReinstallable from requirements.yml, if pinned
The ansible-core versionReinstallable, if pinned somewhere
Vault-encrypted variable filesGit — safely, because they are encrypted
The vault passwordNowhere, unless you deliberately made it exist elsewhere
The automation SSH private keyNowhere, unless escrowed
~/.ssh/known_hostsRebuildable, and see the warning below
Sudo/become passwordsA secret manager, if you used one
Cron or timer schedules for runsGit, if managed; the crontab, if not
Fact cacheRegenerable; it is a cache
Run logs and artefactsWherever they were shipped, if they were shipped

Two rows are in bold because they are categorically different from the rest. Everything else on that list is either in Git or reconstructible from something in Git. Those two are secrets, and secrets are the one thing you are specifically not allowed to put in Git.

Two questions that separate a plan from a hope

Ask these of your own environment. They take about ten minutes and the answers are usually unwelcome.

1. What is on the controller that is not in the repository?

The honest way to find out is not to think about it — it is to look.

Read-only / Safewhat is untracked or unpushed on the controller
cd /srv/ansible

# Files git does not know about at all.
git status --short --untracked-files=all

# Commits that exist locally and nowhere else.
git log --branches --not --remotes --oneline

# Collections installed on this host, and where from.
ansible-galaxy collection list

# Which config file is actually in effect.
ansible --version | grep 'config file'

Each of those four commands answers a different failure. Untracked files are the hand-edited ansible.cfg and the one-off fix-it.yml somebody wrote during an incident. Unpushed commits are three weeks of work on a branch. The collection list is the collection somebody installed by hand in March that no requirements.yml records. And the config file line tells you whether the settings the fleet depends on live in the repository or in ~/.ansible.cfg, which nobody will think to recreate.

2. Which of your secrets exists in exactly one place?

  1. The vault password: is there a copy outside the controller, and has anyone verified it decrypts the current repository this year?
  2. The automation SSH private key: is there a copy, and would using it require a passphrase that also exists in one place?
  3. The become/sudo password, if you use one: is it in a secret manager, or in somebody head?
  4. Dynamic-inventory credentials: the API token the cloud inventory plugin uses is a secret too, and it is usually the one nobody counted.
  5. CI credentials: if the pipeline can decrypt the vault, then the pipeline is also a copy - which is either your escrow or an unmanaged second copy, and you should know which.

The uncomfortable pattern is that item five is often the accidental answer to item one. Many teams discover during the drill that their only surviving copy of the vault password is a CI secret variable nobody documented as an escrow — which works, right up until the CI system is the thing being migrated.

Recovery time is a number, and you probably do not know it

The DR vocabulary from Proxmox Part XIV applies unchanged here. RTO is how long you can tolerate being unable to act on the fleet. RPO is how much automation work you can afford to lose.

For a controller, RPO is usually easy: it is the age of your last push, because Git is the state store. If people push daily, RPO is a day.

RTO is the number that surprises people. It is not “how long does pip install ansible-core take” — it is the sum of finding a host, getting network access to the fleet from it, restoring credentials, reinstalling a pinned toolchain, and getting a read-only run to succeed. Teams estimate two hours. Teams that have run the drill in lesson 6 usually report a day, and the difference is always the same three things: an undocumented manual step, a credential nobody could locate, and a collection installed by hand.

The recoverable set, named

The rest of this part builds the answer, and it has four parts. Naming them now makes the following five lessons a checklist rather than a tour.

LayerWhat it coversLesson
In GitPlaybooks, roles, inventory sources, ansible.cfg, requirements.yml, encrypted vars2
Reproducible from pinsansible-core, Python, collections, roles, Python dependencies3
In escrowVault passwords, automation private keys, break-glass procedure4
ContainerisedThe whole toolchain as an image, as one legitimate answer to layer two5
ProvedA timed rebuild on a fresh host, with a read-only run at the end6

A plan that covers the first three and has never executed the last one is the industry norm and is not sufficient. The drill is where the undocumented step is found, and there is always an undocumented step.

Knowledge check

Knowledge check · 5 questions

  1. Q1. A team has every playbook, role, inventory file and vault-encrypted variable file committed and pushed to a well-protected Git remote. The controller is destroyed. What is most likely to make the rebuild fail?

  2. Q2. Which items would typically be lost permanently when a controller is destroyed, assuming a disciplined team that commits and pushes daily? Select all that apply.

  3. Q3. Because Ansible is agentless, nothing in the managed fleet records which host was its controller.

  4. Q4. Why does this part define the scenario as "the fleet is fine, only the controller is gone" rather than a full site disaster?

  5. Q5. A team runs two controllers so that losing one is survivable. What does this arrangement specifically fail to address?

Passing score: 75%. Answers are checked in this browser.