kamal
Deploy web applications to any server with Kamal — zero-downtime Docker deployments without Kubernetes. Use when someone asks to "deploy to a VPS", "deploy without Kubernetes", "Kamal deploy", "simple Docker deployment", "deploy Rails/Node/Python to a server", "zero-downtime deployment to bare metal", or "replace Heroku with a VPS". Covers Docker-based deployment, zero downtime with Traefik, multi-server, secrets, and accessory services.
Usage
Getting Started
- Install the skill using the command above
- Open your AI coding agent (Claude Code, Codex, Gemini CLI, or Cursor)
- Reference the skill in your prompt
- The AI will use the skill's capabilities automatically
Example Prompts
- "Deploy the latest build to the staging environment and run smoke tests"
- "Check the CI pipeline status and summarize any recent failures"
Documentation
Overview
Kamal (formerly MRSK) deploys containerized web apps to any server — VPS, bare metal, cloud VM — with zero downtime and no Kubernetes complexity. Created by 37signals (Basecamp/HEY), it uses Docker + Traefik to manage rolling deployments, SSL, and load balancing. Configure once in YAML, deploy with one command.
When to Use
- Deploying to VPS/bare metal servers (Hetzner, DigitalOcean, Linode)
- Want zero-downtime deployments without Kubernetes
- Migrating off Heroku/Railway to self-hosted
- Need SSL, rolling deploys, and health checks with minimal config
- Multi-server deployment (web + worker + cron on different machines)
Instructions
Setup
gem install kamal
# Or without Ruby:
docker run -it ghcr.io/basecamp/kamal:latest
# Initialize in your project
kamal init
Configuration
# config/deploy.yml — Main deployment config
service: my-app
image: myuser/my-app
servers:
web:
hosts:
- 167.235.1.100
- 167.235.1.101
labels:
traefik.http.routers.my-app.rule: Host(`myapp.com`)
traefik.http.routers.my-app-secure.entrypoints: websecure
traefik.http.routers.my-app-secure.rule: Host(`myapp.com`)
traefik.http.routers.my-app-secure.tls.certresolver: letsencrypt
worker:
hosts:
- 167.235.1.102
cmd: node worker.js
# Docker image registry
registry:
server: ghcr.io
username: myuser
password:
- KAMAL_REGISTRY_PASSWORD
# Environment variables
env:
clear:
NODE_ENV: production
PORT: 3000
secret:
- DATABASE_URL
- REDIS_URL
- SECRET_KEY
# Traefik for load balancing + SSL
traefik:
options:
publish:
- "443:443"
volume:
- "/letsencrypt:/letsencrypt"
args:
entryPoints.web.address: ":80"
entryPoints.websecure.address: ":443"
certificatesResolvers.letsencrypt.acme.email: admin@myapp.com
certificatesResolvers.letsencrypt.acme.storage: /letsencrypt/acme.json
certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint: web
# Accessories (databases, Redis, etc.)
accessories:
db:
image: postgres:16
host: 167.235.1.100
port: 5432
env:
secret:
- POSTGRES_PASSWORD
directories:
- data:/var/lib/postgresql/data
redis:
image: redis:7
host: 167.235.1.100
port: 6379
# Health check
healthcheck:
path: /health
port: 3000
max_attempts: 10
interval: 3
Deploy
# First deployment (sets up Docker, Traefik, accessories)
kamal setup
# Subsequent deployments (zero-downtime rolling)
kamal deploy
# Deploy with specific version/tag
kamal deploy --version=abc123
# Rollback to previous version
kamal rollback
# Check status
kamal details
# View logs
kamal app logs
kamal app logs -f # Follow
# Run one-off commands
kamal app exec "node scripts/migrate.js"
kamal app exec -i "node" # Interactive shell
Secrets Management
# .kamal/secrets — Environment file (NOT committed to git)
KAMAL_REGISTRY_PASSWORD=ghp_xxx
DATABASE_URL=postgresql://user:pass@db:5432/myapp
REDIS_URL=redis://redis:6379
SECRET_KEY=super-secret-key
# Secrets from 1Password, AWS SSM, etc.
kamal secrets extract --adapter=1password --account=myteam --from=MyApp/Production
Examples
Example 1: Deploy a Next.js app to Hetzner
User prompt: "Deploy my Next.js app to a Hetzner VPS with SSL and zero downtime."
The agent will create a Dockerfile, configure Kamal with Traefik for SSL via Let's Encrypt, set up health checks, and deploy with kamal setup.
Example 2: Multi-server deployment with worker
User prompt: "I have a web app and a background job worker. Deploy web to 2 servers and worker to 1."
The agent will configure Kamal with separate server roles (web × 2, worker × 1), shared environment, and rolling deployment for the web servers.
Guidelines
kamal setupfor first deploy — installs Docker, starts Traefik, deploys accessorieskamal deployfor updates — zero-downtime rolling deployment- Health check is critical — Kamal waits for
/healthto return 200 before switching traffic - Accessories for databases — Postgres, Redis managed alongside your app
- Secrets in
.kamal/secrets— never in deploy.yml or git - Traefik handles SSL — automatic Let's Encrypt certificates
- Rollback is instant —
kamal rollbackswitches to previous container - Works with any Docker image — not just Ruby/Rails
- Multi-server is built-in — add hosts, Kamal deploys to all
- No Kubernetes needed — for most apps, Kamal + VPS is simpler and cheaper
Information
- Version
- 1.0.0
- Author
- terminal-skills
- Category
- DevOps
- License
- Apache-2.0