Skip to content
yisusvii Blog
Go back

Kamal: Deploy Web Apps Anywhere with Zero Downtime

Suggest Changes

In 2023, DHH (creator of Ruby on Rails and co-founder of 37signals) introduced Kamal — a deployment tool born from 37signals’ decision to leave the cloud and run their own servers. Kamal (originally called MRSK) is designed to deploy Docker containers to any server — cloud VM, bare metal, or Raspberry Pi — with zero-downtime rolling deploys.

Kamal is not a PaaS. It is a deployment tool — think of it as a modern Capistrano for the Docker era. You own the servers, Kamal handles the deployment.

Table of Contents

Open Table of Contents

What Is Kamal?

Kamal is an open-source deployment tool that uses Docker to deploy web applications to any server with SSH access. It handles building Docker images, pushing them to a registry, pulling them on your servers, and performing zero-downtime rolling deployments using Kamal Proxy (a custom reverse proxy built by 37signals).

Official page: https://kamal-deploy.org

GitHub: https://github.com/basecamp/kamal

Key Features

Getting Started — How to Install

Prerequisites

Installation

# Option 1: Install as a Ruby gem
gem install kamal

# Option 2: Via Docker (no Ruby required)
alias kamal='docker run -it --rm \
  -v "${PWD}:/workdir" \
  -v "${SSH_AUTH_SOCK}:/ssh-agent" \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e "SSH_AUTH_SOCK=/ssh-agent" \
  ghcr.io/basecamp/kamal:latest'

Initialize a Project

kamal init

This creates a config/deploy.yml file — the heart of Kamal configuration.

Configuration: config/deploy.yml

service: my-saas-api
image: myorg/my-saas-api

servers:
  web:
    hosts:
      - 203.0.113.1
      - 203.0.113.2
    labels:
      role: web
  worker:
    hosts:
      - 203.0.113.3
    cmd: bundle exec sidekiq

proxy:
  ssl: true
  host: api.mycompany.com

registry:
  server: ghcr.io
  username: myorg
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  clear:
    RAILS_ENV: production
    DB_HOST: 203.0.113.4
  secret:
    - RAILS_MASTER_KEY
    - DATABASE_URL
    - REDIS_URL

accessories:
  db:
    image: postgres:16
    host: 203.0.113.4
    port: 5432
    env:
      clear:
        POSTGRES_DB: myapp_production
      secret:
        - POSTGRES_PASSWORD
    directories:
      - data:/var/lib/postgresql/data

  redis:
    image: redis:7
    host: 203.0.113.4
    port: 6379
    directories:
      - data:/data

Deploy

# First-time setup (installs Docker, Kamal Proxy, and deploys)
kamal setup

# Subsequent deploys
kamal deploy

Common Commands

# View app logs
kamal app logs

# Run a command in the container
kamal app exec "bin/rails console"

# Rollback to the previous version
kamal rollback

# View deployment details
kamal details

# Restart the app without rebuilding
kamal app boot

# Manage accessories
kamal accessory boot db
kamal accessory logs db

Adoption Level (2025–2026)

Kamal has gained significant traction thanks to DHH’s influence and the broader “leave the cloud” movement:

MetricValue (as of early 2026)
GitHub Stars~12,000+
CreatorDHH / 37signals
First release2023 (as MRSK)
Used in productionHEY, Basecamp, ONCE
Built into RailsDefault in Rails 8
CommunityActive GitHub, Ruby community

Why Kamal is gaining momentum:

Where Kamal falls short:

Best Examples for Implementing

1. Rails 8 Application (Default Setup)

Rails 8 includes Kamal out of the box:

rails new my-app
cd my-app
# config/deploy.yml is already generated
kamal setup

2. Node.js API

# config/deploy.yml
service: node-api
image: myorg/node-api

servers:
  web:
    hosts:
      - 203.0.113.1

proxy:
  ssl: true
  host: api.mycompany.com

registry:
  server: ghcr.io
  username: myorg
  password:
    - KAMAL_REGISTRY_PASSWORD

builder:
  dockerfile: Dockerfile

env:
  clear:
    NODE_ENV: production
    PORT: 3000
  secret:
    - DATABASE_URL
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

3. Multi-Server Production Setup

servers:
  web:
    hosts:
      - 203.0.113.1  # Web server 1
      - 203.0.113.2  # Web server 2
      - 203.0.113.3  # Web server 3
  worker:
    hosts:
      - 203.0.113.4  # Worker server
    cmd: node worker.js

accessories:
  db:
    image: postgres:16
    host: 203.0.113.5  # Dedicated DB server
    port: 5432
    directories:
      - data:/var/lib/postgresql/data

  redis:
    image: redis:7
    host: 203.0.113.5
    port: 6379

Kamal deploys to all servers in parallel with zero-downtime rolling updates.

4. Python Django + Celery

service: django-app
image: myorg/django-app

servers:
  web:
    hosts:
      - 203.0.113.1
    cmd: gunicorn myproject.wsgi --bind 0.0.0.0:8000
  worker:
    hosts:
      - 203.0.113.2
    cmd: celery -A myproject worker --loglevel=info
  beat:
    hosts:
      - 203.0.113.2
    cmd: celery -A myproject beat --loglevel=info

proxy:
  ssl: true
  host: app.mycompany.com

accessories:
  db:
    image: postgres:16
    host: 203.0.113.3
    port: 5432
  redis:
    image: redis:7
    host: 203.0.113.3
    port: 6379

5. Go Microservice

service: go-service
image: myorg/go-service

servers:
  web:
    hosts:
      - 203.0.113.1

builder:
  dockerfile: Dockerfile

proxy:
  ssl: true
  host: service.mycompany.com
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /service .

FROM alpine:3.19
COPY --from=builder /service /service
EXPOSE 8080
CMD ["/service"]

Cost Analysis

Kamal is completely free and open-source. Your costs are servers and a Docker registry.

Server Costs (Bare Metal / VPS)

Provider2 vCPU / 4 GB4 vCPU / 8 GBDedicated (8 core / 32 GB)
Hetzner€4.50/month€8.50/month€39/month
DigitalOcean$12/month$24/month
OVH€6/month€12/month€30/month
Vultr Bare Metal$120/month

Docker Registry

RegistryFree TierPaid
Docker Hub1 private repo free$5/month (unlimited)
GitHub Container RegistryFree for public reposIncluded in GitHub plans
Self-hosted (Harbor)FreeYour server cost

Real-World Estimate for a Startup

A production setup with:

Total: ~$24/month — for a production-grade, multi-server deployment with zero downtime.

37signals’ Cost Savings

37signals (the company behind Kamal) reported saving over $1 million per year by leaving AWS and moving to their own hardware managed with Kamal. While most startups will not see savings at that scale, the principle applies: owning your servers is cheaper at scale.

When Kamal Makes Sense

When Kamal Is Overkill

Verdict

Kamal is the best deployment tool for teams that own their servers. It brings the sophistication of container orchestration (rolling deploys, health checks, zero downtime) without the complexity of Kubernetes. If you are running Docker containers on VPS or bare-metal servers and want a battle-tested deployment workflow, Kamal — the tool that powers Basecamp and HEY — is the gold standard.

TL;DR: Kamal is what happens when 37signals gets frustrated with cloud costs and builds a deployment tool. It is opinionated, practical, and production-proven. If you own your servers and want zero-downtime Docker deploys, Kamal is the answer.


Follow my blog for more reviews of modern deployment platforms for startups.


Suggest Changes
Share this post on:

Previous Post
TensorFlow in 2026: Key Applications and the Best Alternatives
Next Post
Dokku: The Smallest PaaS Implementation You'll Ever See