Policy rollback¶
Every successful request policy reload takes a snapshot of /etc/enforcegate/rules.d/ before applying the new rule set. Snapshots live under [policy].backup_path (default /var/lib/enforcegate/policy-backups/) as timestamped subdirectories mirroring the rules.d/ layout. The engine retains the N most-recent snapshots — bounded by [policy].backup_depth (default 10) — and prunes older ones after every successful reload.
This page covers the operator path to undo a policy load. For the optional per-commit audit trail and per-rule blame that sit on top of the snapshot system, see policy audit and history.
When to roll back¶
- A
request policy reloadsucceeded but the live engine is matching URLs against rules you didn't intend (over-broad regex, wrong action, copy-paste of the wrong policy file). - An automated pipeline applied a
.policychange that turned out to be wrong. - An audit trail asks "what was the policy on date X?" — listing snapshots gives a quick answer.
A rollback is not the right tool for fixing engine internals, license issues, or non-policy bugs. It only swaps the .policy files in rules.d/ and re-runs the compile.
Step 1 — List available snapshots¶
eghost cli
> show policy backups
Gen Snapshot Files Note
1 20260528-1503.001 12 (currently applied)
2 20260528-1320.001 11
3 20260527-0945.001 10
4 20260526-1842.001 10
…
Generation 1 is whatever was applied by the most recent request policy reload. Generation 2 is the snapshot taken immediately before — i.e. the state that was current before generation 1 became current. Higher numbers are older.
Available at Monitoring privilege and above.
Step 2 — Preview the rollback¶
Always preview before applying. The dry-run reports which files would be removed (orphans added after the snapshot was taken) and which would be overwritten (operator-edited since the snapshot):
> request policy rollback 2 dry-run true
Rollback dry-run from gen 1 → gen 2:
- would remove orphan file: 75-temp-experiment.policy
- would overwrite operator-edited file: 50-deny-shorteners.policy
This rollback would discard 1 file you added since the snapshot and overwrite
1 file you edited. Re-run without dry-run to apply, or pass yes true to skip
the interactive confirmation.
The diff is your "are you sure?" gate. If the dry-run reports a clean delta (no orphans, no overwritten operator edits) the rollback is safe to apply.
Step 3 — Apply¶
Interactive — the client re-renders the diff and prompts for confirmation:
To skip the interactive confirmation (CI pipelines, automation):
The engine refuses to roll back over operator-added files unless yes true (or the nicli --yes flag) is present — the gate is intentional so a careless rollback doesn't wipe new policy work.
On success:
rules.d/is replaced with the contents of snapshot generation 2.- A new snapshot (the pre-rollback state, i.e. generation 1) is recorded as the new generation 2 — so the rollback itself is also undoable.
- The compiled policy in
engine.dbis regenerated from the rolled-back files. - The live in-memory policy graph is reloaded.
Step 4 — Verify¶
Confirm the rollback applied:
> show policy backups
Gen Snapshot Files Note
1 20260528-1503.002 11 (currently applied)
2 20260528-1503.001 12
3 20260528-1320.001 11
…
> show policy match https://some-test-url.example/
URI: https://some-test-url.example/
Matched: no (permit-by-default)
Code: 200 (permit)
The freshly-applied state appears as the new generation 1; the state that was current before the rollback drops to generation 2.
Retention¶
[policy].backup_depth (default 10) sets how many snapshots are kept. After every successful reload or rollback, snapshots beyond the depth are pruned. Older snapshots cannot be recovered after pruning — they're gone from disk.
To keep a longer history, bump the depth in engine.conf:
Restart or reload the engine to pick up the change.
Limitations¶
- Snapshots cover
rules.d/only. They do not includeengine.confschema changes (e.g. flipping a default-permit to default-deny via[policy]settings), license material, or operator config edits. Roll those back separately. - The snapshot directory is on the persistent
enforcegate-configvolume. Adocker compose down -v(factory reset) wipes the volume — and with it, all snapshots. Back up the volume before any reset. - Snapshots are taken pre-apply. If the engine crashes during
request policy reloadafter the snapshot is taken but before the in-memory graph is replaced, the on-diskengine.dbmay end up between states. The engine's boot-time rescue rebuildsengine.dbfromrules.d/if it detects an inconsistent state — but in practice, just re-runrequest policy reloadafter the restart.