Skip to content

Deploy Rollback

Griffen Fargo edited this page Aug 1, 2026 · 3 revisions

Deploy Rollback

strut automatically saves a snapshot of your container images before each deploy. If something goes wrong, you can roll back to the previous state with a single command.

Quick Reference

strut my-stack rollback --env prod              # Restore previous deploy
strut my-stack rollback --env prod --list       # List available rollback points
strut my-stack rollback --env prod --dry-run    # Preview what would be restored
strut my-stack rollback diff HEAD~1 HEAD        # Diff images across snapshots
strut my-stack rollback diff HEAD~1 HEAD --json

How It Works

  1. Before each deploy, strut captures the current image digest for every running service
  2. The snapshot is saved as JSON in stacks/<stack>/.rollback/
  3. On rollback, strut pulls those exact image versions and redeploys
  4. Old snapshots are automatically pruned (default: keep last 5)

Snapshot Format

{
  "timestamp": "2025-01-15T14:30:00Z",
  "stack": "my-stack",
  "env": "prod",
  "service_count": 3,
  "services": {
    "app": { "image": "ghcr.io/org/app:sha-abc123" },
    "worker": { "image": "ghcr.io/org/worker:sha-def456" },
    "nginx": { "image": "nginx:1.25" }
  }
}

Listing Rollback Points

strut my-stack rollback --env prod --list
# Available rollback points for my-stack:
#   20250115-143000  (3 services, env: prod, 2h ago)
#   20250114-100000  (3 services, env: prod, 1d ago)

Performing a Rollback

strut my-stack rollback --env prod
# Rolling back to snapshot: 20250115-143000
#   Pulling app → ghcr.io/org/app:sha-abc123
#   Pulling worker → ghcr.io/org/worker:sha-def456
#   Pulling nginx → nginx:1.25
# Stopping current containers...
# Starting services with restored images...
# ✓ Rollback complete

Dry Run

Preview what would be restored without making changes:

strut my-stack rollback --env prod --dry-run

Rollback Diff (since v0.16.0)

Compare the images captured by two snapshots — useful for post-incident forensics or for knowing exactly what moved in a release window.

strut my-stack rollback diff HEAD~1 HEAD                  # previous vs latest
strut my-stack rollback diff 20260420-091500 HEAD         # named vs latest
strut my-stack rollback diff HEAD~1 HEAD --json           # machine-readable

Refs accept:

Ref Resolves to
HEAD newest snapshot
HEAD~N Nth-older snapshot (HEAD~1 = previous)
<basename> file at stacks/<stack>/.rollback/<basename>.json
<path> absolute path that exists

Exit codes:

Code Meaning
0 snapshots reference the same images
1 snapshots differ
2 ref could not be resolved

The output reads "from A → to B", so HEAD~1 HEAD shows what moved from old to new.

Prune Protection (since v0.16.0)

strut <stack> prune now protects images referenced by rollback snapshots from docker image prune -a so a prune never strands a rollback target. Protection is automatic when invoked per-stack.

strut my-stack prune --all --env prod                 # protects rollback images
strut my-stack prune --all --no-protect --env prod    # old behavior (prunes everything)

The protection window follows ROLLBACK_RETENTION_DAYS (default 30). Set PRUNE_PROTECT_ROLLBACK_IMAGES=false in strut.conf to opt out globally.

Configuration

Set ROLLBACK_RETENTION in strut.conf to control how many snapshots to keep:

# strut.conf
ROLLBACK_RETENTION=10           # Keep last 10 snapshots (default: 5)
ROLLBACK_RETENTION_DAYS=30      # Prune-protection window (default: 30)
PRUNE_PROTECT_ROLLBACK_IMAGES=true  # Opt out with false

Typical Workflow

# Deploy new version
strut my-stack deploy --env prod

# Something is broken — check logs
strut my-stack logs api --env prod --follow

# Roll back immediately
strut my-stack rollback --env prod

# Investigate the issue, fix, and redeploy
strut my-stack deploy --env prod

Related

Clone this wiki locally