Restore
The restore command pushes the desired state from your Git repository back to Consul KV. It compares Git (source of truth) against the current Consul state and generates a plan of SET and DELETE operations. All writes use CAS (Check-And-Set) to prevent overwriting concurrent changes.
When to restore
- A bad config change is causing production issues and you need to revert.
- Consul data was accidentally deleted.
- You're setting up a new Consul cluster and need to seed it from a backup.
- Drift detection found differences you want to correct.
Dry-run preview
Always start with --dry-run:
consul-guardian restore \
--consul-addr http://localhost:8500 \
--prefix "config/" \
--git-repo ./consul-backup \
--dry-run
Output:
Restore plan for prefix "config/" (source: git):
+ CREATE config/cache/ttl (3 bytes)
~ UPDATE config/database/host (15 bytes, CAS index: 847)
~ UPDATE config/database/max-connections (4 bytes, CAS index: 923)
- DELETE config/temp/debug-mode (CAS index: 1052)
Summary: 3 sets, 1 delete, 4 total operations
The plan shows exactly what will happen:
- CREATE -- Key exists in Git but not in Consul (CAS index 0).
- UPDATE -- Key exists in both but values differ. The CAS index ensures Guardian only writes if the key hasn't been modified since the plan was generated.
- DELETE -- Key exists in Consul but not in Git.
Executing the restore
Once you've reviewed the plan, run without --dry-run:
consul-guardian restore \
--consul-addr http://localhost:8500 \
--prefix "config/" \
--git-repo ./consul-backup
Output:
Restore plan for prefix "config/" (source: git):
+ CREATE config/cache/ttl (3 bytes)
~ UPDATE config/database/host (15 bytes, CAS index: 847)
Summary: 2 sets, 0 deletes, 2 total operations
Restore complete: 2 succeeded, 0 failed (12ms)
Selective restore
Prefix-based
Restore only keys under a specific prefix:
consul-guardian restore --prefix "config/database/"
This only touches keys under config/database/ and leaves everything else alone.
Single key
To restore a single key, use a prefix that matches exactly one key:
consul-guardian restore --prefix "config/database/host"
CAS safety
Every restore operation uses Consul's Check-And-Set mechanism. Here's why this matters:
- Guardian reads the current
ModifyIndexfor each key in Consul. - When writing, it includes this index in the CAS operation.
- If another process modified the key between Guardian's read and write, the CAS check fails.
- A failed CAS means "someone else changed this key since you last looked at it" -- Guardian reports the conflict rather than silently overwriting.
This prevents a common disaster scenario: you start a restore while a deployment is also updating Consul. Without CAS, the restore would overwrite the deployment's changes.
Full disaster recovery scenario
Your Consul cluster lost its data. Here's how to recover:
# 1. Start a fresh Consul cluster
docker run -d --name consul -p 8500:8500 hashicorp/consul:1.18 agent -dev
# 2. Clone the backup repo (if not already local)
git clone git@github.com:yourorg/consul-backup.git
# 3. Preview the restore
consul-guardian restore \
--consul-addr http://localhost:8500 \
--prefix "config/" \
--git-repo ./consul-backup \
--dry-run
# 4. Execute the restore
consul-guardian restore \
--consul-addr http://localhost:8500 \
--prefix "config/" \
--git-repo ./consul-backup
# 5. Verify
consul kv get -recurse config/
For a full cluster restore (including ACLs and sessions), use snapshot restore instead. See Snapshots.
Real-world example
At 3am, an automated deploy script sets config/rate-limit/max-rps to 10 instead of 10000. API requests start getting throttled. The on-call engineer runs:
# See the Git history for that key
cd consul-backup
git log --oneline -- config/rate-limit/max-rps
# a1b2c3d consul-guardian: 1 keys changed (5 minutes ago)
# x9y8z7w consul-guardian: 1 keys changed (2 weeks ago)
# Restore the previous state of the prefix
consul-guardian restore --prefix "config/rate-limit/" --dry-run
consul-guardian restore --prefix "config/rate-limit/"
Service restored in under 2 minutes.