kamal-deploy
Expert-level Kamal deployment guidance for deploying containerized applications to any server. Use this skill when users ask about Kamal, container deployment, zero-downtime deployments, deploying Rails/web apps to VPS/cloud servers, kamal setup, kamal deploy, Docker deployment without Kubernetes, or deploying to Hetzner/DigitalOcean/AWS with Kamal. Also use when users mention DHH's deployment tool, 37signals deployment, or want an alternative to Heroku/Render/Vercel with self-hosted infrastructure.
Best use case
kamal-deploy is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Expert-level Kamal deployment guidance for deploying containerized applications to any server. Use this skill when users ask about Kamal, container deployment, zero-downtime deployments, deploying Rails/web apps to VPS/cloud servers, kamal setup, kamal deploy, Docker deployment without Kubernetes, or deploying to Hetzner/DigitalOcean/AWS with Kamal. Also use when users mention DHH's deployment tool, 37signals deployment, or want an alternative to Heroku/Render/Vercel with self-hosted infrastructure.
Teams using kamal-deploy should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/kamal-deploy/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How kamal-deploy Compares
| Feature / Agent | kamal-deploy | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Expert-level Kamal deployment guidance for deploying containerized applications to any server. Use this skill when users ask about Kamal, container deployment, zero-downtime deployments, deploying Rails/web apps to VPS/cloud servers, kamal setup, kamal deploy, Docker deployment without Kubernetes, or deploying to Hetzner/DigitalOcean/AWS with Kamal. Also use when users mention DHH's deployment tool, 37signals deployment, or want an alternative to Heroku/Render/Vercel with self-hosted infrastructure.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Kamal Deploy Expert
Expert guidance for deploying applications with Kamal - DHH's zero-downtime deployment tool from 37signals.
## Step 1: Fetch Latest Documentation (MANDATORY)
**BEFORE answering ANY Kamal question, you MUST use the WebFetch tool to get current documentation.** The docs below may be outdated - always fetch fresh docs first.
Execute these WebFetch calls in parallel:
1. `WebFetch(url: "https://kamal-deploy.org/docs/installation/", prompt: "Extract complete installation and setup guide")`
2. `WebFetch(url: "https://kamal-deploy.org/docs/configuration/overview/", prompt: "Extract all configuration options and deploy.yml structure")`
3. `WebFetch(url: "https://kamal-deploy.org/docs/commands/view-all-commands/", prompt: "Extract all Kamal commands and usage")`
4. `WebFetch(url: "https://kamal-deploy.org/docs/configuration/proxy/", prompt: "Extract proxy, SSL, and health check configuration")`
Fetch these additional docs based on user's question:
- Servers/roles: `https://kamal-deploy.org/docs/configuration/servers/`
- Accessories (DB, Redis): `https://kamal-deploy.org/docs/configuration/accessories/`
- Environment variables: `https://kamal-deploy.org/docs/configuration/environment-variables/`
- Docker build options: `https://kamal-deploy.org/docs/configuration/builders/`
- Deployment hooks: `https://kamal-deploy.org/docs/hooks/overview/`
- Upgrading v1→v2: `https://kamal-deploy.org/docs/upgrading/overview/`
**Only after fetching fresh docs, use the reference material below as supplementary context.**
## What is Kamal?
Kamal deploys containerized apps to any server via SSH + Docker. Created by 37signals (DHH's company) to deploy Basecamp, HEY, and other apps.
**Core architecture:**
- SSHs into servers, installs Docker automatically
- Builds app into Docker container
- Pushes to registry (Docker Hub, GHCR, etc.)
- Pulls and runs on target servers
- kamal-proxy handles routing, SSL (Let's Encrypt), zero-downtime
**Mental model:** Hetzner/DigitalOcean = the computer, Kamal = deploys your app to it
## Before You Start
**Check these first to avoid common friction:**
1. **Kamal version** - Run `kamal version`. If on 1.x, upgrade with `gem install kamal`. Config syntax changed significantly (1.x uses `traefik`, 2.x uses `proxy`).
2. **Local Docker situation** - Ask the user if they have Docker working locally. If not (or if Docker Desktop is problematic on macOS), configure a remote builder:
```yaml
builder:
arch: amd64
remote: ssh://root@SERVER_IP
```
This builds on the target server and avoids local Docker entirely.
3. **37signals open-source repos** - If deploying Campfire, HEY, or other 37signals apps, immediately delete `.env.erb` - it uses their internal 1Password setup and will fail with `op: command not found`.
4. **Registry access** - Confirm the user has a container registry (Docker Hub, GHCR) and knows their credentials before writing config.
## Quick Start
```bash
# Install (or upgrade)
gem install kamal
# Initialize in project
kamal init
# First deploy (installs Docker, proxy, deploys app)
kamal setup
# Subsequent deploys
kamal deploy
```
## Essential Commands
| Command | Purpose |
|---------|---------|
| `kamal setup` | First deploy - installs Docker, proxy, deploys |
| `kamal deploy` | Deploy new version |
| `kamal rollback` | Revert to previous version |
| `kamal app logs` | View application logs |
| `kamal app exec -i bash` | SSH into running container |
| `kamal accessory boot <name>` | Start accessory (db, redis) |
| `kamal proxy reboot` | Restart kamal-proxy |
| `kamal remove` | Remove everything from servers |
## Minimal config/deploy.yml
```yaml
service: my-app
image: username/my-app
servers:
- 123.45.67.89
registry:
username: username
password:
- KAMAL_REGISTRY_PASSWORD
proxy:
ssl: true
host: myapp.com
env:
secret:
- RAILS_MASTER_KEY
- DATABASE_URL
```
## Secrets Management
Secrets live in `.kamal/secrets`:
```bash
# .kamal/secrets
KAMAL_REGISTRY_PASSWORD=ghp_xxxxxxxxxxxx
RAILS_MASTER_KEY=abc123def456
DATABASE_URL=postgres://user:pass@db:5432/app
```
Reference in deploy.yml:
```yaml
env:
clear:
RAILS_ENV: production
secret:
- RAILS_MASTER_KEY
- DATABASE_URL
```
## Multi-Server with Roles
```yaml
servers:
web:
hosts:
- 123.45.67.89
- 123.45.67.90
workers:
hosts:
- 123.45.67.91
cmd: bin/jobs
proxy: false # Workers don't need proxy
```
## Accessories (Databases, Redis)
```yaml
accessories:
db:
image: postgres:16
host: 123.45.67.89
port: 5432
env:
clear:
POSTGRES_DB: app_production
secret:
- POSTGRES_PASSWORD
directories:
- data:/var/lib/postgresql/data
redis:
image: redis:7
host: 123.45.67.89
port: 6379
directories:
- data:/data
```
## SSL Configuration
**Automatic (Let's Encrypt):**
```yaml
proxy:
ssl: true
host: myapp.com # Must point to server IP
```
**Custom certificate:**
```yaml
proxy:
ssl:
certificate_pem:
- SSL_CERTIFICATE
private_key_pem:
- SSL_PRIVATE_KEY
```
## Health Checks
```yaml
proxy:
healthcheck:
interval: 3
path: /up
timeout: 3
```
App must return 200 on `/up` (Rails default) or configured path.
## Destinations (Staging/Production)
Create `config/deploy.staging.yml`:
```yaml
servers:
- staging.myapp.com
proxy:
host: staging.myapp.com
```
Deploy: `kamal deploy -d staging`
Secrets: `.kamal/secrets.staging`
## Hooks
Place in `.kamal/hooks/` (no file extension):
Available hooks:
- `pre-connect`, `pre-build`, `pre-deploy`, `post-deploy`
- `pre-app-boot`, `post-app-boot`
- `pre-proxy-reboot`, `post-proxy-reboot`
Example `.kamal/hooks/post-deploy`:
```bash
#!/bin/bash
curl -X POST "https://api.honeybadger.io/v1/deploys" \
-d "deploy[revision]=$KAMAL_VERSION"
```
## Dockerfile Requirements
Kamal needs a Dockerfile. For Rails:
```dockerfile
FROM ruby:3.3-slim
WORKDIR /app
# Install dependencies
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
COPY Gemfile* ./
RUN bundle install
COPY . .
RUN bundle exec rails assets:precompile
EXPOSE 80
CMD ["bin/rails", "server", "-b", "0.0.0.0", "-p", "80"]
```
Note: Kamal 2.x defaults to port 80 (not 3000).
## Common Issues
**"Container not healthy"**
- Check `/up` endpoint returns 200
- Increase `deploy_timeout` if app boots slowly
- Check logs: `kamal app logs`
**"Permission denied"**
- Ensure SSH key is added: `ssh-add ~/.ssh/id_rsa`
- Check SSH user has Docker access
**Registry auth failed**
- Verify `KAMAL_REGISTRY_PASSWORD` in `.kamal/secrets`
- For GHCR: use personal access token with `write:packages`
**"Address already in use"**
- Another service on port 80/443
- Run `kamal proxy reboot` or check `docker ps` on server
## Kamal vs Alternatives
| | Kamal | Kubernetes | Heroku |
|---|---|---|---|
| Complexity | Low | High | None |
| Cost | VPS only | VPS + overhead | $$$ |
| Control | Full | Full | Limited |
| Zero-downtime | Yes | Yes | Yes |
| SSL | Auto | Manual | Auto |
| Learning curve | Hours | Weeks | Minutes |
## Best Practices
1. **Always test locally first**: `docker build . && docker run -p 3000:80 <image>`
2. **Use staging destination** before production
3. **Keep secrets out of git**: `.kamal/secrets` in `.gitignore`
4. **Set up monitoring**: Use hooks to notify on deploy
5. **Regular backups**: Especially accessory volumes
6. **Use asset bridging** for Rails: `asset_path: /app/public/assets`
## Reference Files
For detailed configuration options, see:
- [references/configuration.md](references/configuration.md) - Complete deploy.yml reference
- [references/troubleshooting.md](references/troubleshooting.md) - Common issues and solutionsRelated Skills
NestJS Deployment
Docker builds, Memory tuning, and Graceful shutdown.
Multi-Platform Deployment
This skill should be used when the user asks to "deploy application", "deploy to production", "release app", "deploy to AWS", "deploy to Vercel", "deploy to Kubernetes", "iOS deployment", "Android deployment", "deploy smart contract", "web3 deployment", "deploy to multiple platforms", or needs guidance on deployment strategies across web, mobile, and blockchain platforms.
managing-astro-deployments
Manage Astronomer production deployments with Astro CLI. Use when the user wants to authenticate, switch workspaces, create/update/delete deployments, or deploy code to production.
kubernetes-deployment
Deploy, manage, and scale applications on Kubernetes clusters using manifests, Helm charts, and autoscaling configurations.
kubernetes-deployer
Package and deploy applications to Kubernetes with Dockerfiles, Helm charts, and local Minikube deployment. Use when containerizing applications, creating Kubernetes manifests, setting up Helm charts, deploying to Minikube, or preparing cloud-ready configurations. Focuses on local-first deployment with stateless services.
konto-deploy
Deploy and run Konto (personal finance dashboard) locally. Use when setting up a new Konto instance, troubleshooting installation, or helping users get started with Konto.
kagenti:deploy
Deploy or redeploy the Kagenti Kind cluster using the Python installer - quick redeploy, manual steps, and troubleshooting
k8s-simple-deploy
Assists with deploying simple apps to Kubernetes consisting of a deployment and a service.
k8s-deploy-auto
Kubernetes deployment automation workflows for CI/CD pipelines, GitOps, and scripted deployments. Use when automating k8s deployments, creating deployment scripts, integrating with GitHub Actions/GitLab CI, implementing rollout strategies, or setting up ArgoCD/Flux workflows.
gke-deployment
Deploy, configure, and manage Kubernetes workloads on GKE with Deployments, Services, Ingress, HPA, health probes, ConfigMaps, and Secrets. Use when deploying containers to GKE, configuring load balancers, setting up autoscaling, writing health checks, managing environment configs, or troubleshooting pod issues.
frontend-deployment
Deploy frontend applications from aramb.toml. Creates frontend service, resolves backend references from deployment outputs, builds static files, and deploys with environment variables. Returns deployment URL. Use for all frontend deployments.
featbit-deployment-kubernetes
Deploys FeatBit to Kubernetes using Helm Charts. Use when user mentions "Kubernetes", "Helm", "K8s", "kubectl", works with values.yaml files, asks about "cloud deployment", "AKS", "EKS", "GKE", "ingress", or needs production-grade container orchestration setup.