A backup that has never been restored does not guarantee recovery. Regular drills confirm that snapshots are usable, keys are available, the procedure is documented, and recovery time meets targets.
Goal
Regularly test two recovery scenarios:
- restoring a Raft snapshot into an isolated cluster;
- failing over to a DR secondary (Stronghold EE);
and record the actual recovery time (RTO) and data loss (RPO).
Frequency
Run the checks with the following frequency:
| Check | Frequency |
|---|---|
snapshot inspect -validate for a fresh snapshot | After each snapshot or daily |
| Restoring a snapshot into an isolated cluster | Quarterly and after a Stronghold version upgrade |
| Planned failover to a DR secondary (Stronghold EE) | Every six months |
| Checking availability of unseal or recovery key share holders | Quarterly |
| Break-glass access drills | Every six months |
Prerequisites
To follow this example, you need:
- A Stronghold cluster with integrated Raft storage.
- An isolated restore environment: a separate network with no access to production databases, LDAP, and other systems managed by secrets engines.
- The unseal or recovery key share holders of the production cluster. After a snapshot restore, the original keys are required.
- For part 2: Stronghold EE and configured DR replication.
Part 1. Restoring a snapshot into an isolated cluster
Restore a production snapshot into an isolated test cluster and measure the recovery time.
The restored cluster contains production secrets and secrets engine configuration. If it gets network access to production systems, it starts revoking expired leases and rotating passwords in real databases and LDAP. Isolate the environment at the network level.
Get a snapshot. Use the latest automated snapshot (Stronghold EE):
d8 stronghold read sys/storage/raft/snapshot-auto/status/<CONFIG_NAME><CONFIG_NAME>is the name of the automated snapshot configuration.The
last_snapshot_urlfield points to the latest successful snapshot. Alternatively, save a snapshot manually:d8 stronghold operator raft snapshot save drill.snapCheck the snapshot integrity:
d8 stronghold operator raft snapshot inspect -validate drill.snapIn the isolated environment, deploy a Stronghold cluster of the same or a newer version with integrated Raft storage (see Installing Stronghold on Linux). Initialize and unseal it, and log in with the temporary root token:
d8 stronghold operator init d8 stronghold operator unseal d8 stronghold login <TEMPORARY_ROOT_TOKEN><TEMPORARY_ROOT_TOKEN>is the initial root token printed byoperator init.If the production cluster uses auto-unseal (KMS, HSM or another seal), configure the same
sealstanza on the test cluster and give it access to the same key. The snapshot contains the barrier keys encrypted by the production seal (core/hsm/barrier-unseal-keys), and after the restore the test cluster decrypts them through its own seal. With a different key the unseal fails, andsnapshot restorewithout-forcerefuses such a snapshot. With auto-unseal, the cluster unseals itself after the restore, and the step with the manualunsealbelow is not needed.Record the restore start time and restore the snapshot:
d8 stronghold operator raft snapshot restore -force drill.snapWith a Shamir seal, unseal the cluster with the original keys of the production cluster:
d8 stronghold operator unsealLog in to the restored cluster. The restore replaced the token store with the data from the snapshot, so the temporary root token is no longer valid. Log in with a token from the production cluster that has permissions to read the checked data:
d8 stronghold loginIf no such token is available, generate a root token on the test cluster. The holders of the production unseal key shares (recovery key shares with auto-unseal) take part in the generation:
d8 stronghold operator generate-root -init d8 stronghold operator generate-root d8 stronghold operator generate-root -decode=<ENCODED_TOKEN> -otp=<OTP> d8 stronghold loginThe first command starts the generation and prints the OTP. Run the second command once for each key share holder: it asks for a key share. After the last share, the command prints the encoded token,
<ENCODED_TOKEN>. The third command decodes it with<OTP>and prints the root token. Enter it whend8 stronghold loginasks for a token.Check the data and record the end time:
d8 stronghold status d8 stronghold secrets list d8 stronghold auth list d8 stronghold policy list d8 stronghold kv get -mount=secret <CONTROL_SECRET_PATH><CONTROL_SECRET_PATH>is the path to a control secret with a timestamp. Create the control secret in the production cluster in advance and update its timestamp regularly. Use it to determine the RPO: the RPO is the difference between the restore start time and the timestamp in the restored secret.Destroy the environment and all snapshot copies in it.
Part 2. Planned failover to a DR secondary
Switch clients to the DR secondary and return the former primary to the secondary role.
DR replication is available only in Stronghold EE.
Perform the failover in an agreed maintenance window. Do not promote the DR secondary while the primary is active: you would end up with two primaries.
Make sure the secondary has caught up with the primary. Read
last_walfrom the replication status of the primary andlast_remote_walfrom the replication status of the secondary:d8 stronghold read -address="${PRIMARY_ADDR}" -field=last_wal sys/replication/dr/status d8 stronghold read -address="${SECONDARY_ADDR}" -field=last_remote_wal sys/replication/dr/statusThe secondary has caught up when the two values are equal.
PRIMARY_ADDRandSECONDARY_ADDRare the addresses of the primary and the secondary.Demote the current primary:
d8 stronghold write -address="${PRIMARY_ADDR}" -force sys/replication/dr/primary/demoteGenerate a DR operation token on the secondary using the key share procedure and promote the secondary. The commands are given in Promote a DR secondary.
Switch clients to the new primary (DNS record or load balancer) and record the time.
Check operation: OIDC login, reading secrets, issuing dynamic credentials and certificates.
Return the former primary to the secondary role. On the new primary, issue an activation token:
d8 stronghold write -address="${SECONDARY_ADDR}" sys/replication/dr/primary/secondary-token id=dr-old-primaryThe command prints the activation token,
<ACTIVATION_TOKEN>.On the former primary, which is now a DR secondary, generate a DR operation token. The
update-primarycall on a DR secondary requires this token. The commands use thesys/replication/dr/secondary/generate-operation-token/attemptandsys/replication/dr/secondary/generate-operation-token/updateendpoints:d8 stronghold operator generate-root -address="${PRIMARY_ADDR}" -dr-token -init d8 stronghold operator generate-root -address="${PRIMARY_ADDR}" -dr-token d8 stronghold operator generate-root -address="${PRIMARY_ADDR}" -dr-token -decode=<ENCODED_TOKEN> -otp=<OTP>The first command starts the generation and prints the OTP. Run the second command once for each holder of an unseal key share (a recovery key share with auto-unseal): it asks for a key share. After the last share, the command prints the encoded token,
<ENCODED_TOKEN>. The third command decodes it with<OTP>and prints the DR operation token,<DR_OPERATION_TOKEN>.By default, the endpoints for generating a DR operation token require authentication. To call them without a token, add
generate-operation-tokento theenable_unauthenticated_accessparameter of the server configuration.Connect the former primary to the new primary:
d8 stronghold write -address="${PRIMARY_ADDR}" sys/replication/dr/secondary/update-primary token=<ACTIVATION_TOKEN> dr_operation_token=<DR_OPERATION_TOKEN>If needed, fail back with the same steps.
Drill checklist
After the drill, check the following items:
- The snapshot passed
inspect -validate. - Key share holders are available, and the quorum was gathered in acceptable time.
- The restored cluster was unsealed with the original keys.
- The control secret was read, and the RPO was measured.
- Auth methods, policies, and mounts are present as expected.
- For DR: the secondary was promoted, clients were switched, and the former primary was connected as a secondary.
- The recovery time (RTO) was measured and compared with the target.
- The isolated environment and snapshot copies were destroyed.
- Issues found were added to the recovery runbook.
Verification
A drill is successful if the actual RTO and RPO do not exceed the targets and all checklist items are done. Keep a drill record: date, participants, Stronghold version, snapshot used, measured RTO and RPO, and issues found.
Cleanup
After the drill, delete the test environment and the data copies:
- Delete the isolated cluster and its storage.
- Delete local snapshot copies:
shred -u drill.snap. - Revoke tokens issued for the drill on the production cluster.