npx claudepluginhub nityeshaga/claude-code-essentials --plugin basicsThis skill uses the workspace's default tool permissions.
Expert guidance for deploying applications with Kamal - DHH's zero-downtime deployment tool from 37signals.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Expert guidance for deploying applications with Kamal - DHH's zero-downtime deployment tool from 37signals.
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:
WebFetch(url: "https://kamal-deploy.org/docs/installation/", prompt: "Extract complete installation and setup guide")
WebFetch(url: "https://kamal-deploy.org/docs/configuration/overview/", prompt: "Extract all configuration options and deploy.yml structure")
WebFetch(url: "https://kamal-deploy.org/docs/commands/view-all-commands/", prompt: "Extract all Kamal commands and usage")
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:
https://kamal-deploy.org/docs/configuration/servers/https://kamal-deploy.org/docs/configuration/accessories/https://kamal-deploy.org/docs/configuration/environment-variables/https://kamal-deploy.org/docs/configuration/builders/https://kamal-deploy.org/docs/hooks/overview/https://kamal-deploy.org/docs/upgrading/overview/Only after fetching fresh docs, use the reference material below as supplementary context.
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:
Mental model: Hetzner/DigitalOcean = the computer, Kamal = deploys your app to it
Check these first to avoid common friction:
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).
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:
builder:
arch: amd64
remote: ssh://root@SERVER_IP
This builds on the target server and avoids local Docker entirely.
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.
Registry access - Confirm the user has a container registry (Docker Hub, GHCR) and knows their credentials before writing config.
# Install (or upgrade)
gem install kamal
# Initialize in project
kamal init
# First deploy (installs Docker, proxy, deploys app)
kamal setup
# Subsequent deploys
kamal deploy
| 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 |
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 live in .kamal/secrets:
# .kamal/secrets
KAMAL_REGISTRY_PASSWORD=ghp_xxxxxxxxxxxx
RAILS_MASTER_KEY=abc123def456
DATABASE_URL=postgres://user:pass@db:5432/app
Reference in deploy.yml:
env:
clear:
RAILS_ENV: production
secret:
- RAILS_MASTER_KEY
- DATABASE_URL
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:
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
Automatic (Let's Encrypt):
proxy:
ssl: true
host: myapp.com # Must point to server IP
Custom certificate:
proxy:
ssl:
certificate_pem:
- SSL_CERTIFICATE
private_key_pem:
- SSL_PRIVATE_KEY
proxy:
healthcheck:
interval: 3
path: /up
timeout: 3
App must return 200 on /up (Rails default) or configured path.
Create config/deploy.staging.yml:
servers:
- staging.myapp.com
proxy:
host: staging.myapp.com
Deploy: kamal deploy -d staging
Secrets: .kamal/secrets.staging
Place in .kamal/hooks/ (no file extension):
Available hooks:
pre-connect, pre-build, pre-deploy, post-deploypre-app-boot, post-app-bootpre-proxy-reboot, post-proxy-rebootExample .kamal/hooks/post-deploy:
#!/bin/bash
curl -X POST "https://api.honeybadger.io/v1/deploys" \
-d "deploy[revision]=$KAMAL_VERSION"
Kamal needs a Dockerfile. For Rails:
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).
"Container not healthy"
/up endpoint returns 200deploy_timeout if app boots slowlykamal app logs"Permission denied"
ssh-add ~/.ssh/id_rsaRegistry auth failed
KAMAL_REGISTRY_PASSWORD in .kamal/secretswrite:packages"Address already in use"
kamal proxy reboot or check docker ps on server| 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 |
docker build . && docker run -p 3000:80 <image>.kamal/secrets in .gitignoreasset_path: /app/public/assetsFor detailed configuration options, see: