kamal
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 fileskamal setup- First-time setup (installs Docker, deploys everything)kamal deploy- Standard deploy with zero downtimekamal 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 containerkamal app exec -i --reuse "bash"- Interactive shellkamal app maintenance- Enable maintenance modekamal app live- Disable maintenance modekamal app containers- List all containers (for rollback)kamal app version- Show deployed version
Accessories
kamal accessory boot NAME- Start accessorykamal accessory logs NAME [-f]- View accessory logskamal accessory exec NAME "CMD"- Run command in accessory
Troubleshooting
kamal config- Show parsed configurationkamal lock status- Check deployment lockkamal lock release- Release stuck lockkamal server exec "CMD"- Run command on host
Multiple Environments
kamal deploy -d staging- Deploy to stagingkamal deploy -h 192.168.1.10- Deploy to specific hostkamal 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.