smithery.ai

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 infrastruc…

First seen Mar 30, 2026

Installation

$ npx skills add https://smithery.ai

Summary

  • 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.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,341 B
  • docs SUMMARY.md 524 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

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")
  1. WebFetch(url: "https://kamal-deploy.org/docs/configuration/overview/";, prompt: "Extract all configuration options and deploy.yml structure")
  1. WebFetch(url: "https://kamal-deploy.org/docs/commands/view-all-commands/";, prompt: "Extract all Kamal commands and usage")
  1. 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).
  1. 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.

  1. 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.
  1. Registry access - Confirm the user has a container registry (Docker Hub, GHCR) and knows their credentials before writing config.

Quick Start

# 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

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:

# .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

Multi-Server with Roles

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)

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):

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

Health Checks

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:

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:

#!/bin/bash
curl -X POST "https://api.honeybadger.io/v1/deploys" \
  -d "deploy[revision]=$KAMAL_VERSION"

Dockerfile Requirements

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).

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 KAMALREGISTRYPASSWORD 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 solutions