OtterStack Usage Guide
Complete reference for using OtterStack - a deployment orchestration tool for Docker Compose applications with zero-downtime deployments via Traefik priority-based routing.
What is OtterStack?
OtterStack is a Git-driven deployment orchestrator for Docker Compose applications running on a single VPS. It provides:
- •Zero-downtime deployments using Traefik priority-based routing
- •Git worktree isolation - each deployment gets its own directory
- •Health check validation before traffic switching
- •Automatic rollback if deployments fail
- •Environment variable management with smart type detection
- •Deployment history and retention policies
Core Concepts
- •Projects: A project is a Docker Compose application tracked in git
- •Worktrees: Each deployment creates an isolated git worktree
- •Deployments: Deploy any git ref (commit, branch, tag)
- •Priority Routing: New containers start at priority 200, old at 100
- •Health Checks: Validates containers before traffic switch (5 min timeout)
Installation
go build ./cmd/otterstack ./otterstack version
Quick Start
1. Add Your First Project
Local repository:
otterstack project add myapp /srv/myapp
Remote repository:
otterstack project add myapp https://github.com/user/repo.git
With Traefik zero-downtime routing:
otterstack project add myapp https://github.com/user/repo.git --traefik-routing
Custom compose file:
otterstack project add myapp /srv/myapp --compose-file docker-compose.prod.yml
2. Configure Environment Variables
OtterStack now has smart environment variable management with auto-discovery!
Option 1: Auto-discovery during project add
# Create .env.<project-name> in current directory echo "DATABASE_URL=postgres://localhost/mydb" > .env.myapp echo "API_KEY=secret123" >> .env.myapp # Add project - OtterStack will auto-discover and load the file otterstack project add myapp /srv/myapp # Prompts interactively for any missing variables
Option 2: Set variables manually
otterstack env set myapp DATABASE_URL=postgres://localhost/mydb otterstack env set myapp API_KEY=secret DEBUG=false
Option 3: Load from file
otterstack env load myapp .env.production
Option 4: Interactive scan (for existing projects)
otterstack env scan myapp # Scans compose file, prompts for missing variables
List variables:
otterstack env list myapp otterstack env list myapp --show-values # Show actual values
Get specific variable:
otterstack env get myapp DATABASE_URL
Remove variables:
otterstack env unset myapp DEBUG
3. Deploy
Deploy default branch:
otterstack deploy myapp
Deploy specific ref:
otterstack deploy myapp --ref feature/new-ui otterstack deploy myapp --ref v1.2.3 otterstack deploy myapp --ref a1b2c3d4
Force deploy (skip validations - use carefully!):
otterstack deploy myapp --force
4. Check Status
List all projects:
otterstack project list
View project details:
otterstack status myapp
Check deployment history:
otterstack deployments myapp
5. Manage Projects
Remove project:
otterstack project remove myapp
Force remove (skip confirmation):
otterstack project remove myapp --force
Environment Variable Management
Smart Type Detection
OtterStack automatically detects variable types from names:
| Pattern | Type | Validation |
|---|---|---|
DATABASE_URL, API_ENDPOINT | URL | Must have scheme (https://) |
ADMIN_EMAIL, SUPPORT_EMAIL | Valid email format | |
HTTP_PORT, DB_PORT | Port | 1-65535 |
WORKER_COUNT, MAX_CONNECTIONS, TIMEOUT | Integer | Valid number |
DEBUG_ENABLED, FEATURE_FLAG, USE_SSL | Boolean | Yes/No dialog |
| Everything else | String | Basic validation |
Interactive Prompts
When you run env scan or project add, OtterStack:
- •Parses compose file to find all
${VAR}references - •Checks stored values to identify missing variables
- •Groups prompts: Required first, optional second
- •Type-aware UI: Booleans use Yes/No dialogs, others use validated text inputs
- •Shows context: "Used by: web, worker"
- •Generates
.env.examplefor documentation
Supported Variable Formats
OtterStack parses these Docker Compose formats:
services:
web:
environment:
- DATABASE_URL=${DATABASE_URL} # Required
- API_URL=${API_URL:-https://api.example.com} # Optional with default
- SECRET_KEY=${SECRET_KEY:?Secret key required} # Required with error message
- DEBUG=$DEBUG # Simple form
Zero-Downtime Deployments with Traefik
Prerequisites
- •Traefik running and connected to Docker
- •Compose file has Traefik labels:
services:
web:
image: myapp:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`myapp.example.com`)"
- •Project added with
--traefik-routingflag
How It Works
1. [Old Containers Serving] → Priority: 100 2. [Start New Containers] → No Traefik labels yet 3. [Health Check] → Wait up to 5 minutes 4. [Apply Priority Labels] → New: 200, Old: 100 5. [Traffic Switches] → Traefik routes to higher priority 6. [Stop Old Containers] → Deployment complete
If health checks fail at step 3, old containers keep serving traffic.
Deployment Flow
Without Traefik:
- •Start new containers
- •Stop old containers immediately
- •Brief downtime during switch
With Traefik:
- •Start new containers (no traffic)
- •Wait for healthy
- •Switch traffic priority
- •Stop old containers
- •Zero downtime!
Command Reference
Project Management
# Add project otterstack project add <name> <repo-path-or-url> [flags] --compose-file string Path to compose file (default: docker-compose.yml) --traefik-routing Enable zero-downtime Traefik routing # List projects otterstack project list # Remove project otterstack project remove <name> [--force] # View project status otterstack status <name>
Environment Variables
# Set variables otterstack env set <project> KEY=VALUE [KEY=VALUE...] # Get variable otterstack env get <project> [KEY] # List variables otterstack env list <project> [--show-values] # Load from file otterstack env load <project> <file> # Interactive scan otterstack env scan <project> # Remove variables otterstack env unset <project> KEY [KEY...]
Deployment
# Deploy otterstack deploy <project> [flags] --ref string Git ref to deploy (commit, branch, tag) --force Skip validation checks # View deployment history otterstack deployments <project>
Global Flags
--config string Config file (default: $HOME/.otterstack.yaml) --data-dir string Data directory (default: $HOME/.otterstack) --verbose Verbose output --help Show help --version Show version
Common Workflows
First-Time Project Setup
# 1. Create .env file cat > .env.myapp <<EOF DATABASE_URL=postgres://user:pass@localhost/mydb REDIS_URL=redis://localhost:6379 API_KEY=your-secret-key EOF # 2. Add project (auto-discovers .env.myapp) otterstack project add myapp https://github.com/user/repo.git --traefik-routing # 3. Verify configuration otterstack env list myapp # 4. Deploy otterstack deploy myapp
Adding Variables to Existing Project
# Option 1: Interactive scan otterstack env scan myapp # Option 2: Manual set otterstack env set myapp NEW_VAR=value # Option 3: Load from file otterstack env load myapp .env.new
Deploying a Feature Branch
# Deploy feature branch otterstack deploy myapp --ref feature/new-ui # Check status otterstack status myapp # If good, merge to main and deploy git checkout main git merge feature/new-ui git push otterstack deploy myapp --ref main
Rolling Back a Deployment
# Deploy previous commit otterstack deploy myapp --ref HEAD~1 # Or deploy specific commit otterstack deploy myapp --ref a1b2c3d
Updating Environment Variables
# Update variable otterstack env set myapp API_KEY=new-key # Redeploy for changes to take effect otterstack deploy myapp
Pre-Deployment Validation
OtterStack validates environment variables before starting deployment:
$ otterstack deploy myapp
Validating environment variables...
❌ ERROR: Missing required environment variables
The following variables are required but not set:
DATABASE_URL
• Required by: web, worker
• Error: Database connection required
API_KEY
• Required by: web
To fix this, you can:
1. Set variables individually:
otterstack env set myapp DATABASE_URL=<value>
otterstack env set myapp API_KEY=<value>
2. Use interactive scan:
otterstack env scan myapp
3. Load from file:
otterstack env load myapp .env.myapp
Error: missing required environment variables
This prevents wasted deployment attempts with incomplete configuration!
Troubleshooting
"Project not found"
# List all projects otterstack project list # Verify project name matches exactly
"Lock file exists"
Another deployment is in progress or a previous one failed:
# Wait for deployment to finish, or if stuck: rm ~/.otterstack/locks/<project>.lock # Then retry otterstack deploy myapp
"Missing required environment variables"
# Scan for missing variables otterstack env scan myapp # Or check what's missing otterstack env list myapp
"Health check failed"
Containers didn't become healthy within 5 minutes:
# Check container logs docker compose -f /path/to/worktree/docker-compose.yml logs # Check container status docker compose -f /path/to/worktree/docker-compose.yml ps # Fix issues, then redeploy otterstack deploy myapp
"Compose file not found"
# Verify compose file path cat ~/.otterstack/projects.db | grep compose_file # Update if wrong # (Currently requires manual DB edit - future feature)
Environment Variables Not Working
# Verify variables are set
otterstack env list myapp --show-values
# Check compose file syntax
grep -E '\$\{[A-Z_]+\}' docker-compose.yml
# Redeploy after setting variables
otterstack deploy myapp
Best Practices
1. Environment Variables
- •✅ Use
.env.<project-name>files during initial setup - •✅ Run
env scanto catch missing variables early - •✅ Use type-appropriate variable names (DATABASE_URL, HTTP_PORT)
- •✅ Store secrets securely, never commit to git
- •✅ Generate
.env.examplefor documentation - •❌ Don't hardcode values in compose files
- •❌ Don't skip the pre-deployment validation
2. Docker Compose Files
- •✅ Use
${VAR}syntax for environment variables - •✅ Provide defaults with
${VAR:-default}when possible - •✅ Include health checks for all services
- •✅ Use Traefik labels for zero-downtime deployments
- •❌ Don't use
container_name(breaks worktree isolation) - •❌ Don't use
env_file(OtterStack manages env vars)
3. Deployments
- •✅ Deploy to staging/testing first
- •✅ Use
--traefik-routingfor production apps - •✅ Tag important releases:
git tag v1.0.0 - •✅ Keep deployment history: check retention policy
- •✅ Monitor health checks during deployment
- •❌ Don't use
--forcein production unless necessary - •❌ Don't deploy without testing env vars first
4. Project Organization
- •✅ Use descriptive project names
- •✅ Document required env vars in README
- •✅ Keep compose files simple and standard
- •✅ Use semantic versioning for tags
- •❌ Don't mix projects in the same repo
- •❌ Don't commit environment-specific config
Advanced Topics
Worktree Management
OtterStack creates git worktrees for each deployment:
# Worktrees are stored at: ~/.otterstack/worktrees/<project>/<commit-hash>/ # Each worktree is isolated with its own: # - Git checkout # - Docker Compose state # - Environment file
Retention Policy
Old worktrees are cleaned up based on retention policy:
- •Failed deployments: Kept for debugging
- •Successful deployments: Configurable retention
Direct Compose Access
You can interact with deployed containers directly:
# Find worktree path WORKTREE=$(ls -t ~/.otterstack/worktrees/myapp | head -1) # Use docker compose directly docker compose -f ~/.otterstack/worktrees/myapp/$WORKTREE/docker-compose.yml logs docker compose -f ~/.otterstack/worktrees/myapp/$WORKTREE/docker-compose.yml exec web bash
Health Check Configuration
Compose file health check example:
services:
web:
image: myapp:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
Version History
v0.2.0 (2026-01-11)
- •✨ Enhanced environment variable management
- •✨ Auto-discovery of
.env.<project-name>files - •✨ Smart type detection and validation
- •✨ Interactive
env scancommand - •✨ Pre-deployment validation gate
- •✨ Automatic
.env.examplegeneration
Earlier Versions
- •v0.2.0-rc.4: Fixed double-locking bug
- •v0.2.0-rc.3: Fixed TOCTOU race condition
- •v0.2.0-rc.2: Real-time Docker output streaming
Getting Help
# General help otterstack --help # Command-specific help otterstack project --help otterstack env --help otterstack deploy --help # Version info otterstack version
Related Files
- •
README.md- Overview and quick start - •
IMPROVEMENTS.md- Proposed enhancements based on deployment experience - •
TROUBLESHOOTING.md- Common issues and solutions - •
.claude/plans/enhanced-env-var-management.md- Implementation plan for env var features
Summary
OtterStack makes Docker Compose deployments simple and safe:
- •Add project with
project add - •Configure env vars with
env scanor auto-discovery - •Deploy with
deploy - •Zero downtime with Traefik routing
- •Automatic rollback if things fail
The enhanced environment variable management ensures you never deploy with missing configuration, and the interactive prompts make setup a breeze!
Usage in Orchestration
This skill is referenced during Phase 4: Setup and Phase 5: Deployment of the /deploy-otterstack command.
Integration Points
The orchestration command uses this skill's documentation to execute OtterStack commands in three modes:
- •Project Setup Mode - Check if project exists and add if needed
- •Environment Variable Setup Mode - Load/scan/configure environment variables
- •Deployment Mode - Execute deployment with verbose monitoring
Project Setup Mode
When the orchestration command needs to set up a new project:
Check if project exists:
# Local
otterstack project list | grep -q "^${PROJECT_NAME}$"
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack project list | grep -q '^${PROJECT_NAME}$'"
Add project if missing (local):
otterstack project add ${PROJECT_NAME} /path/to/repo --traefik-routing
Add project if missing (remote/VPS):
# Get remote git URL
REPO_URL=$(git config --get remote.origin.url)
# Add to VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack project add ${PROJECT_NAME} ${REPO_URL} --traefik-routing"
Environment Variable Setup Mode
When the orchestration command configures environment variables:
Auto-load from .env file if exists:
if [ -f ".env.${PROJECT_NAME}" ]; then
# Local
otterstack env load ${PROJECT_NAME} .env.${PROJECT_NAME}
# VPS
scp .env.${PROJECT_NAME} archivist@194.163.189.144:/tmp/
ssh archivist@194.163.189.144 "~/OtterStack/otterstack env load ${PROJECT_NAME} /tmp/.env.${PROJECT_NAME}"
fi
Interactive scan for missing variables:
# Local
otterstack env scan ${PROJECT_NAME}
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack env scan ${PROJECT_NAME}"
Validate all required vars are set:
# Local
otterstack env list ${PROJECT_NAME}
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack env list ${PROJECT_NAME}"
Set individual variables:
# Local
otterstack env set ${PROJECT_NAME} DATABASE_URL="postgres://..."
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack env set ${PROJECT_NAME} DATABASE_URL='postgres://...'"
Deployment Mode
When the orchestration command executes deployment:
Deploy with verbose output for monitoring:
# Local
otterstack deploy ${PROJECT_NAME} -v
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deploy ${PROJECT_NAME} -v"
Monitor deployment stages: The orchestration command watches for these sequential stages:
- •"Fetching latest changes..." → Git operations (remote repos only)
- •"Validating compose file..." → Syntax and env var validation
- •"Pulling images..." → Docker image downloads
- •"Starting services..." → Container creation and startup
- •"Waiting for containers to be healthy..." → Health check polling
- •"Applying Traefik priority labels..." → Traffic routing setup
- •"Deployment successful!" → Completion
Check deployment status:
# Local
otterstack status ${PROJECT_NAME}
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack status ${PROJECT_NAME}"
View deployment history:
# Local
otterstack deployments ${PROJECT_NAME}
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deployments ${PROJECT_NAME}"
Quick Reference for Orchestration
Commands used by /deploy-otterstack:
Pre-flight checks:
# Verify OtterStack is installed which otterstack || command -v otterstack # VPS: Test SSH connection ssh -o ConnectTimeout=5 archivist@194.163.189.144 "echo 'SSH OK'" # VPS: Verify OtterStack on VPS ssh archivist@194.163.189.144 "~/OtterStack/otterstack --version"
Project existence check:
# Returns exit code 0 if exists, 1 if not
otterstack project list | grep -q "^${PROJECT_NAME}$" && echo "exists" || echo "missing"
Quick deployment status:
otterstack status ${PROJECT_NAME} 2>&1
Force redeploy if lock stuck:
# Local
rm ~/.otterstack/locks/${PROJECT_NAME}.lock
otterstack deploy ${PROJECT_NAME} -v
# VPS
ssh archivist@194.163.189.144 "rm ~/.otterstack/locks/${PROJECT_NAME}.lock"
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deploy ${PROJECT_NAME} -v"
Get previous deployment SHA (for rollback):
# Local
otterstack deployments ${PROJECT_NAME} | tail -2 | head -1 | awk '{print $2}'
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deployments ${PROJECT_NAME} | tail -2 | head -1 | awk '{print \$2}'"
Deploy specific ref (rollback):
# Local
otterstack deploy ${PROJECT_NAME} --ref ${PREVIOUS_SHA} -v
# VPS
ssh archivist@194.163.189.144 "~/OtterStack/otterstack deploy ${PROJECT_NAME} --ref ${PREVIOUS_SHA} -v"
Context Passing
The orchestration command maintains these variables that inform OtterStack commands:
- •
PROJECT_NAME- Name of the project being deployed - •
DEPLOYMENT_TARGET- "local" or "vps" - •
SSH_PREFIX- Empty for local, "ssh archivist@194.163.189.144" for VPS - •
OTTERSTACK_CMD- "otterstack" for local, "~/OtterStack/otterstack" for VPS - •
REPO_PATH- Local repository path - •
REPO_URL- Git repository URL (for VPS)
Commands are constructed as:
${SSH_PREFIX} ${OTTERSTACK_CMD} [subcommand] [args]
Error Handling
The orchestration command handles these OtterStack error scenarios:
| Error | OtterStack Message | Orchestration Action |
|---|---|---|
| Missing env vars | "variable X is not set" | Run env scan or prompt user |
| Project not found | "project not found" | Add project with project add |
| Lock held | "deployment in progress" | Wait or remove stale lock |
| Validation failed | "compose validation failed" | Invoke debug-vps-deployment |
| Health check failed | "container unhealthy" | Invoke debug-vps-deployment |
Related Commands
- •
/deploy-otterstack- Full orchestration command that uses this skill in Phases 4 and 5