The quickstart ran one step against one host. This runs a real change across two hosts, through every control Opafra has: drafted, reviewed, previewed, approved, executed, recorded.
About thirty minutes. Nothing here is a toy: at the end you have a plan worth keeping.
Before you begin#
- Two Linux hosts registered and passing their connection check
- The connecting user able to
sudo -n - nginx installed on both, or willing to be
1. Put the hosts in an environment#
Create an environment called tutorial, set its tier to Production, and add both
hosts.
Creating it as Production turns on requires approval by default. Leave it on. That is the gate you will meet in step 5.
You should see the environment listed with both hosts and the gate on:
tutorial Production requires approval 2 servers2. Draft a plan#
Open the composer and describe the outcome rather than the commands:
Deploy a new nginx config to the tutorial environment.
Back up the existing config first, validate the new one
before reloading, and stop if validation fails.What comes back should be roughly four steps: a backup, a config write, a validation, and a reload. It is a draft. Nothing has run and it is not yet in your plan list.
3. Review it before anything else#
Read it in the order that catches the most, from reviewing a draft:
Targets first. Every step should target tutorial. A step that picked up a single
hostname is the mistake worth catching now.
Then order. The backup must come before the write, and the validation before the reload. Both read fine in the wrong order and are useless there.
Then anything raw. If the validation is an ssh.cmd running nginx -t, consider
whether nginx.reload already does it. It validates first and refuses to reload a broken
config, which is the behaviour the plan is trying to construct by hand.
Fix what you find, then Keep the draft. It is a real plan now.
4. Dry run it#
Run it in dry-run mode against both hosts. You should see:
Step 1 Back up the config file.backup
host-a would change /etc/nginx/nginx.conf.bak exists, would overwrite
host-b would create /etc/nginx/nginx.conf.bak
Step 2 Write the config template.deploy
host-a no change
host-b would change /etc/nginx/nginx.conf +6 -2Read what that says. The hosts are not in the same state: host-a already has the
config and host-b does not. That is the finding, and in a real estate it is usually the
first sign that someone changed a machine by hand.
Check the bottom of the report for unresolved variables. Any {{ vars.x }} listed there
will be empty at run time.
5. Run it, and meet the gate#
Start a normal run. It does not execute. It pauses immediately with status Paused and appears in the approvals inbox, because the environment requires approval.
You should see:
Status Paused
Waiting for approval
Steps run 0Notice what did not happen: no step ran, and the gate applied without the plan mentioning approval anywhere. The rule belongs to the environment.
6. Approve it#
Open the approvals inbox and approve the run. You will see the plan, the environments it touches, the mode it will proceed in, and the plan revision being approved.
Try this first, though: edit the plan while the run is waiting, then approve. The record will show the requested revision and the approved revision differing. Opafra reports the change rather than blocking it, and the discrepancy is in the audit trail permanently.
Once approved, the run resumes from the beginning and executes. You should see the revision mismatch recorded rather than hidden:
Requested revision 3
Approved revision 4
Revision changed yes7. Read the record#
Open the completed run. It holds what was asked for, who started it, who approved it and against which revision, and what each step did on each host, including the output.
You should see:
execution.start [email protected] 2026-09-08 14:20
approval.continue [email protected] 2026-09-08 14:22 requested 3, approved 4Both revision numbers are on the record permanently, which is what makes "what exactly was approved" answerable months later.
Clean up#
Delete the plan, then remove both hosts from the tutorial environment and delete it. The
config you deployed stays on the hosts: Opafra does not assume every step has an inverse,
so undoing a change is a plan you write, not a button.
Run records and audit entries remain by design.
What you built#
A plan that is written down, reviewable, previewable per host, gated by a policy attached to the environment rather than to the plan, and permanently recorded.
That is the whole product. Everything else is more tools, more hosts, and running it on a schedule.
Next steps#
- Scheduling to run this nightly, including as a drift check
- Modules to extract the sequence once it appears in a third plan
- Safety model for the controls you just used, in full