π Deploy Docker Stacks. No Drama.
Strut is an open-source CLI for managing Docker Compose stacks across any VPS that speaks SSH. One command to release, one config tree per project, zero Kubernetes.
What is Strut?
Strut started as a single helper script for managing one client’s VPS. It grew into a full CLI toolkit when I realized the same patterns kept repeating across projects: SSH in, pull the repo, run migrations, restart containers, verify health, backup the database, rotate a key. Same dance, different stack, every time.
It now powers two of my personal stacks and 10+ client stacks across multiple VPSes. Every command is config-driven (no hardcoded service names), every destructive action supports --dry-run, and every release is reproducible. If your infrastructure has SSH and Docker, Strut can ship to it.
β¨ Key Capabilities
π§± Multi-Stack Management
Run as many Docker Compose stacks as you want on a single VPS. Each one gets its own config, secrets, and lifecycle, and they don’t step on each other.
π One-Command Releases
strut my-app release --env prod syncs the repo, runs migrations, deploys containers, and verifies health checks. If anything fails, it tells you exactly where.
ποΈ Two-Tree Architecture
The engine lives at ~/.strut/ and is shared across every project. Your config – strut.conf, stack definitions, env files – lives in the project root. Zero hardcoded values in the engine means you can upgrade across all your machines without touching a single project, and scaffold a new one with strut init in under a minute.
πΎ Database Backup & Restore
Native support for Postgres, MySQL, and SQLite. Backup from prod, restore to staging, pull live data down to local for debugging – all from the same CLI.
π Drift Detection
Compare your local config to what’s actually running on the VPS. See exactly what’s different and decide whether to fix it locally or push the change up.
π Secret Rotation
Rotate SSH keys, API tokens, database passwords, and GitHub deploy keys with one command. Strut updates the right .env files and restarts the right services.
π§ͺ Dry-Run Everywhere
Every destructive command supports --dry-run. See exactly what would happen before it does. Especially useful when you’re rotating credentials at 11pm.
πΊοΈ VPS Audit & Migration
Already have Docker containers running on a VPS without Strut? strut audit scans the box and helps you convert what’s there into managed stacks, no rip-and-replace required.
π€ Agent-First by Design
Strut ships with agent steering files and a skills library so AI agents like Claude, Cursor, or any MCP-compatible assistant can run deployments, backups, and rollbacks for you.
I built it this way because that’s how I work now. I describe what I want, the agent reads strut.conf and services.conf to figure out what’s deployed, and runs the right commands. The agent gets context, I get back hours.
- Agent steering: prompt files that guide an agent through Strut commands
- Skills library: pre-built skills for deploy, backup, rollback, scale, logs, and more
- Context-aware: agents read your config and current stack state before acting
- MCP-compatible: works with Claude, Cursor, Windsurf, and any other MCP-compatible agent
π― Who It’s For
Solo developers
You have a VPS, a Docker Compose file, and zero interest in learning Kubernetes. Strut gives you a real deployment workflow without the YAML sprawl.
Small teams
Everyone gets the same commands, same configs, same process. New devs can deploy on day one without learning a custom toolchain.
Agencies and consultancies
Same pattern across every client, different configs per project. Stacks stay isolated, the workflow stays consistent, and onboarding a new project takes minutes.
β‘ Quick Start
Install Strut with a single curl:
curl -fsSL https://raw.githubusercontent.com/gfargo/strut/main/install.sh | bashThen initialize a project, scaffold a stack, and ship it:
strut init --registry ghcr --org my-org # Initialize project
strut scaffold my-app # Create a stack
nano stacks/my-app/.env.template # Configure (copy to .prod.env)
strut my-app release --env prod # Deploy to VPSFull walkthrough in the Quick Start guide.
Common day-to-day commands once you’re set up:
strut my-app drift --env prod # what's different from local?
strut my-app db:pull --env prod # pull prod db down to local
strut my-app keys db:rotate postgres --env prod # rotate db credentials
strut my-app logs api --follow --env prod # tail logs from one service
strut my-app health --env prod --json # health check, machine-readableπ Real-World Usage
- 2 personal stacks running production workloads on my own VPSes
- 10+ client stacks deployed across multiple VPS providers
- 21 releases shipped as of v0.20.1, with v1.0 still in active development
- 33 wiki pages covering installation, architecture, deployment workflows, and contribution
π How It Compares
- vs Kubernetes: minutes to first deploy instead of days; no YAML sprawl, no control plane to maintain
- vs Kamal: built-in multi-stack support, drift detection, secret rotation, and database backup workflows
- vs manual SSH: same low learning curve, but with health checks, dry-runs, and a real release pipeline
If your infrastructure runs on a Linux box you can SSH into, Strut probably fits. No proprietary agents, no cloud lock-in, just SSH + Bash + Docker.
π§° Technology Stack
- Language: Bash (99.7% of the codebase)
- Architecture: Two-tree design – engine at
~/.strut/, your config at project root - Container runtime: Docker + Docker Compose
- Transport: SSH (no daemons, no agents)
- Registries supported: GitHub Container Registry, Docker Hub, Amazon ECR, or none
- Testing: Bats (Bash Automated Testing System)
- License: MIT
π Links
- Website: strut.griffen.codes
- GitHub: github.com/gfargo/strut
- Wiki / Full Documentation: github.com/gfargo/strut/wiki
- Releases: 21 releases and counting
- Discord: Join the community
Try it on a fresh VPS in five minutes, or point an agent at it and let the agent take the first deploy. Either way, no Kubernetes required.
Like what you saw?
There's more where that came from.

