Kamal Deployment
Kamal is a zero-downtime deployment tool for containerized applications, originally built by 37signals for deploying Rails apps but works with any containerized web application.
Core Concepts
Philosophy: Kamal uses an imperative "push" model where you explicitly tell servers what to do, unlike declarative tools like Kubernetes. It combines SSH, Docker, and Kamal Proxy to achieve zero-downtime deployments.
Components:
- •SSH/SSHKit: Remote command execution
- •Docker: Container runtime and image management
- •Kamal Proxy: Reverse proxy for zero-downtime deployments (routes traffic between container versions)
- •Accessories: Supporting services (PostgreSQL, MySQL, Redis, etc.)
When to Use This Skill
Use this skill when you need to:
- •Set up Kamal for a new project
- •Configure
config/deploy.ymlor understand configuration options - •Deploy applications or troubleshoot deployment failures
- •Manage multiple environments (staging, production)
- •Configure accessories (databases, Redis, etc.)
- •Debug deployment issues or container problems
- •Perform rollbacks or maintenance mode
- •Understand Kamal commands and workflows
- •Set up CI/CD pipelines with Kamal
Quick Start Workflow
Initial Setup
# 1. Install Kamal gem install kamal # 2. Initialize configuration cd your-app kamal init # 3. Edit config/deploy.yml # - Set service name and image # - Add server IP addresses # - Configure registry credentials # - Set environment variables # 4. Configure secrets in .kamal/secrets KAMAL_REGISTRY_PASSWORD=your-token RAILS_MASTER_KEY=your-key # 5. Run initial setup (installs Docker, deploys everything) kamal setup
Standard Deploy
kamal deploy # Build, push, deploy with zero downtime kamal deploy -d staging # Deploy to staging environment kamal app logs -f # Follow application logs
Common Operations
kamal app exec -i --reuse "bin/rails console" # Rails console kamal app logs -g "error" # Search logs kamal rollback <version> # Rollback kamal app maintenance # Maintenance mode kamal app live # Exit maintenance
Configuration Patterns
Basic deploy.yml Structure
service: myapp
image: username/myapp
servers:
web:
- 192.168.1.10
registry:
server: ghcr.io
username: myuser
password:
- KAMAL_REGISTRY_PASSWORD
env:
secret:
- RAILS_MASTER_KEY
clear:
RAILS_ENV: production
proxy:
ssl: true
host: example.com
Multi-Server with Roles
servers:
web:
hosts:
- 192.168.1.10
- 192.168.1.11
worker:
hosts:
- 192.168.1.12
cmd: bundle exec sidekiq
Accessories (Supporting Services)
accessories:
postgres:
image: postgres:15
host: 192.168.1.20
port: 5432
env:
secret:
- POSTGRES_PASSWORD
clear:
POSTGRES_DB: myapp_production
directories:
- data:/var/lib/postgresql/data
redis:
image: redis:7
host: 192.168.1.21
directories:
- data:/data
For comprehensive configuration options, see references/configuration.md.
Essential Commands
Deployment
- •
kamal init- Initialize configuration files - •
kamal setup- First-time setup (installs Docker, deploys everything) - •
kamal deploy- Standard deploy with zero downtime - •
kamal redeploy- Fast redeploy (skips proxy setup) - •
kamal rollback VERSION- Rollback to previous version
Application Management
- •
kamal app logs [-f]- View logs (follow with -f) - •
kamal app exec "COMMAND"- Run command in container - •
kamal app exec -i --reuse "bash"- Interactive shell - •
kamal app maintenance- Enable maintenance mode - •
kamal app live- Disable maintenance mode - •
kamal app containers- List all containers (for rollback) - •
kamal app version- Show deployed version
Accessories
- •
kamal accessory boot NAME- Start accessory - •
kamal accessory logs NAME [-f]- View accessory logs - •
kamal accessory exec NAME "CMD"- Run command in accessory
Troubleshooting
- •
kamal config- Show parsed configuration - •
kamal lock status- Check deployment lock - •
kamal lock release- Release stuck lock - •
kamal server exec "CMD"- Run command on host
Multiple Environments
- •
kamal deploy -d staging- Deploy to staging - •
kamal deploy -h 192.168.1.10- Deploy to specific host - •
kamal deploy -r web- Deploy to specific role
For complete command reference, see references/commands.md.
Common Workflows
Deploy with Database Migration
Using pre-deploy hook (recommended):
Create .kamal/hooks/pre-deploy:
#!/bin/bash kamal app exec -p -q "bin/rails db:migrate"
chmod +x .kamal/hooks/pre-deploy kamal deploy
Rollback Workflow
# Check what went wrong kamal app logs # List available versions kamal app containers # Rollback to previous version kamal rollback abc123def
Debugging Failed Deployments
- •Check logs:
kamal app logs -n 500 - •Check container status:
kamal server exec "docker ps -a" - •Test health endpoint:
kamal app exec "curl localhost:3000/up" - •Check configuration:
kamal config - •Release stuck locks:
kamal lock release
Multiple Environments Pattern
Create environment-specific configs:
- •
config/deploy.yml(production) - •
config/deploy.staging.yml
kamal setup -d staging kamal deploy -d staging kamal deploy # production
For detailed workflows, troubleshooting guides, and best practices, see references/workflows.md.
Database and Accessory Management
Running Commands in Accessories
# PostgreSQL kamal accessory exec postgres "psql -U myapp" kamal accessory exec postgres "pg_dump -U myapp myapp_production" > backup.sql # Redis kamal accessory exec redis "redis-cli" # MySQL kamal accessory exec mysql "mysql -u root -p myapp_production"
Litestream (SQLite Replication)
kamal accessory exec litestream "litestream generations /data/production.sqlite3" kamal accessory exec litestream "litestream restore /data/production.sqlite3"
Configuration for Common Scenarios
Custom SSH User/Port
ssh: user: deploy port: 2222
Custom Build Context
builder:
context: .
dockerfile: Dockerfile.production
args:
RUBY_VERSION: 3.2.0
Health Check Configuration
healthcheck: path: /up port: 3000 interval: 10 max_attempts: 7
Aliases for Common Commands
aliases: console: app exec --interactive --reuse "bin/rails console" shell: app exec --interactive --reuse "bash" logs: app logs -f
Use: kamal console instead of full command.
CI/CD Integration
GitHub Actions Example
- name: Deploy
env:
KAMAL_REGISTRY_PASSWORD: ${{ secrets.REGISTRY_TOKEN }}
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
run: |
gem install kamal
kamal deploy
Key Limitations
- •No automatic state reconciliation - Kamal won't automatically decommission containers if you remove them from config
- •No dynamic provisioning - Cannot auto-scale or provision servers on demand
- •Single-server load balancing only - Kamal Proxy balances containers on each server, not across servers (use external load balancer for that)
References
This skill includes comprehensive reference documentation:
- •configuration.md - Complete
config/deploy.ymlreference with all options, registry configurations, accessory setups, and example configurations - •commands.md - Detailed command reference for all Kamal CLI commands with options and examples
- •workflows.md - Common deployment workflows, troubleshooting patterns, CI/CD integration, security best practices, and production guidelines
Read these references when you need detailed information about specific configuration options, commands, or deployment patterns.