+91 80401 38000[email protected]24/7 Expert Support
[email protected]Client Portal →
ServerGurus
← All posts
DevOpsTutorialsDeploymentDockerKamal

Kamal: The Zero-Downtime Deploy Tool That Replaces Kubernetes for Most Teams

By ServerGurus Team26 July 20265 min read
Kamal: The Zero-Downtime Deploy Tool That Replaces Kubernetes for Most Teams

What Is Kamal

Kamal (formerly MRSK) is a deployment tool built by 37signals - the same team behind Rails, Basecamp, and HEY. It deploys Docker containers to any Linux server with zero-downtime rolling restarts, built-in SSL, and a dead-simple YAML config file. No Kubernetes. No PaaS lock-in. Just SSH + Docker.

In 2026, Kamal has replaced Capistrano as the default Rails deployment tool, but it works with any containerized web app - Node.js, Python, Go, PHP, you name it.

Why Replace Kubernetes with Kamal

Kubernetes is brilliant at what it does. It is also the most over-adopted technology of the decade. Most teams running 1-3 apps on 1-3 servers do not need a multi-node container orchestrator with 14 control plane components. They need: push code, containers deploy, nothing drops.

Kamal gives you precisely that:

  • Zero-downtime deploys. Old containers keep serving until new ones are healthy.
  • Rolling restarts. One server at a time, never two offline simultaneously.
  • Built-in SSL. Let's Encrypt certificates provisioned and renewed automatically.
  • Accessory services. PostgreSQL, Redis, and other dependencies as managed containers.
  • Remote builds. Build images on the target server or locally - your choice.
  • CI/CD friendly. One command: kamal deploy. Add it to GitHub Actions and you are done.

The Architecture

Kamal uses a companion proxy called kamal-proxy that sits in front of your app containers. During a deploy, Kamal starts the new container, health-checks it, switches the proxy to point at the new container, and only then stops the old one. Requests never hit a dead container.

 Request
    │
    ▼
kamal-proxy (port 80/443)
    │
    ├── app:v3 (serving, healthy)
    │       ▲
    │       │ switch happens atomically
    │       ▼
    └── app:v4 (just booted, health check passed)

No load balancer. No ingress controller. No service mesh. Just a 6 MB Go binary routing traffic to healthy containers.

Getting Started

Install:

gem install kamal
# or if you use mise/rbenv:
gem install kamal --user-install

Initialize in your project:

cd myapp
kamal init

This creates:

  • .kamal/config/deploy.yml - the deployment configuration
  • .kamal/hooks/ - optional pre/post-deploy scripts

The Config File

# .kamal/config/deploy.yml
service: myapp
image: myapp

# Servers - same role on multiple hosts
servers:
  web:
    hosts:
      - 165.140.164.156
      - 165.140.164.157
    options:
      port: 3000

# Accessory services (PostgreSQL, Redis, etc.)
accessories:
  postgres:
    image: postgres:16
    host: 165.140.164.156
    port: 5432
    env:
      POSTGRES_PASSWORD: <%= ENV["PG_PASSWORD"] %>
    volumes:
      - /data/postgres:/var/lib/postgresql/data

  redis:
    image: valkey/valkey:7
    host: 165.140.164.156
    port: 6379

# Environment variables
env:
  clear:
    DATABASE_URL: postgres://...
    REDIS_URL: redis://...
  secret:
    - MASTER_KEY

# Proxy configuration
proxy:
  ssl: true
  host: myapp.com

# Builder
builder:
  local: false
  remote:
    arch: amd64
    host: 165.140.164.156

# Health check
healthcheck:
  path: /up
  port: 3000

Key Commands

kamal setup          # First-time: install Docker + proxy on servers
kamal deploy         # Build → push → pull → start → health check → proxy switch
kamal rollback       # Atomically switch back to previous container
kamal app logs       # Tail logs from all containers on all servers
kamal app exec bash  # Open a bash shell on a running container
kamal accessory logs postgres  # View database logs
kamal server exec    # Run a command directly on a server

Zero-Downtime Deploy Walkthrough

$ kamal deploy
  INFO [abc123] Running docker build on 165.140.164.156
  INFO [abc123] Built image myapp:v4 (sha256:d4e5...)
  INFO [abc123] Pushing image to registry...
  INFO [def456] Pulling myapp:v4 on 165.140.164.156
  INFO [def456] Pulling myapp:v4 on 165.140.164.157
  INFO [ghi789] Starting new container on 165.140.164.156
  INFO [ghi789] Health check passed (200 OK)
  INFO [ghi789] Switching proxy to new container
  INFO [ghi789] Stopping old container
  INFO [jkl012] Repeating on 165.140.164.157...
  INFO [jkl012] Deploy complete. 2 servers updated.

What happens under the hood:

  1. Build - Docker image built (locally or on remote builder)
  2. Push - Image pushed to a registry (Docker Hub, GHCR, or private)
  3. Pull - All target servers pull the new image
  4. Start - New container starts alongside old one
  5. Health check - Kamal polls /up (or your custom path) until 200
  6. Proxy switch - kamal-proxy atomically points to the new container
  7. Stop old - Old container is stopped and removed
  8. Repeat - Steps 4-7 repeat for each server (rolling)

Multi-Server Deployments

Kamal handles multi-server deployments natively. It uses SSHKit to execute commands in parallel across all servers, with a rolling strategy: it updates one server at a time, verifies the health check, then moves to the next. Two servers are never offline simultaneously.

servers:
  web:
    hosts:
      - 165.140.164.156
      - 165.140.164.157
      - 165.140.164.158
    options:
      port: 3000

With three servers, kamal deploy updates them one at a time. During the deploy, two servers are always serving traffic. Total downtime: zero.

When Kamal Is NOT Enough

Kamal is not a Kubernetes replacement for every team. Consider Kubernetes when you need:

  • Auto-scaling based on CPU/memory metrics
  • Service discovery across 20+ microservices
  • Multi-tenancy with namespace isolation
  • GPU scheduling for ML workloads
  • Policy enforcement (OPA, Kyverno)

If your answer to all five is "no," Kamal is probably the right tool.

How ServerGurus Runs Kamal

Every ServerGurus VPS and bare metal server ships with Docker pre-installed and SSH keys configured - the two prerequisites for Kamal. Our Ubuntu 24.04 images include gem install kamal out of the box. Pair a $12/mo VPS for the app server and a second $12/mo VPS for the database, and you have a production deployment for $24/mo. No Kubernetes tax. No PaaS lock-in. Just SSH and Docker.

For teams that want managed deploys, we offer a Kamal-on-ServerGurus setup service: we write your deploy.yml, configure your servers, and hand you a one-command pipeline.

Quick Start

gem install kamal
cd your-project
kamal init
# edit .kamal/config/deploy.yml with your server IPs
kamal setup
kamal deploy

Your app is live. With zero-downtime deploys, automatic SSL, and rolling restarts - on whatever hardware you own.

Ready to build your infrastructure?

Get a quote from our Hyderabad-based team - Tier IV datacenter, real support, INR or USD billing.

View pricingRequest a quoteWhatsApp sales