App Deployment·8 min read·

Zero-Downtime Application Deployments with Kamal 2 on Ubuntu

Deploy production web applications with 37signals Kamal 2 on Ubuntu 24.04, orchestrating zero-downtime container swaps and dynamic proxy routing.

NB

Netbay Engineering

Netbay Engineering

On this page

Deploying containerized web applications without introducing the sprawling operational complexity of Kubernetes has become a primary objective for modern development teams. Kamal 2, developed by 37signals (the creators of Ruby on Rails and Basecamp), delivers a minimal, robust approach: build standard Docker container images, push them to any registry, and roll them out across Linux VPS instances with true zero downtime.

Kamal 2 replaces the older Traefik proxy model with kamal-proxy, an ultra-fast, single-binary reverse proxy written in Go that manages live connection draining, health checking, and instant container swaps on port 80/443 without dropping a single TCP request.

The Philosophy of Kamal 2: Simplicity and Control

For over a decade, enterprise deployment models converged toward Kubernetes clusters, necessitating ingress controllers, custom resource definitions, overlay networks, and complex etcd state management. For 95% of web applications, this introduces unnecessary failure modes and significant maintenance overhead.

Kamal 2 strips deployment mechanics down to essential Linux and Docker primitives:

  • A deployment target requires only a standard Linux VPS with Docker installed and an SSH key.
  • Deployments are driven from your developer workstation or CI runner via SSH commands.
  • The state lives entirely in Docker containers and standard system files on High-Speed SSD storage, eliminating distributed coordination consensus engines.

Target Server Prerequisites on Ubuntu 24.04

Kamal operates remotely via SSH and the Docker daemon API. Prepare your Ubuntu VPS instance in Lucknow DC01 with Docker Engine and non-root deployment privileges:

bash
# Install Docker Engine on Ubuntu 24.04
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin

# Add deployer user to docker group
sudo usermod -aG docker deploy
sudo systemctl enable --now docker

Verify that your local workstation can authenticate to the server via SSH without password prompts.

Writing the config/deploy.yml Configuration

In your application repository, install Kamal 2 via Ruby gems (gem install kamal) or the standalone binary, and initialize the configuration:

bash
kamal init

Edit config/deploy.yml to define the service name, container registry, target server IP, environment variables, and proxy health check endpoint:

yaml
# config/deploy.yml
service: checkout-api
image: ghcr.io/netbay-org/checkout-api

servers:
  web:
    hosts:
      - 10.0.0.4

registry:
  server: ghcr.io
  username: netbay-deployer
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  clear:
    PORT: "3000"
    NODE_ENV: "production"
  secret:
    - DATABASE_URL
    - REDIS_URL

proxy:
  ssl: true
  host: api.example.com
  app_port: 3000
  healthcheck:
    path: /up
    interval: 2
    timeout: 3

builder:
  arch: amd64
  cache:
    type: registry

The proxy block automatically configures kamal-proxy on the target host to manage Let's Encrypt certificates and monitor the /up healthcheck route.

Expand
Kamal 2 Zero-Downtime Deployment
Kamal 2 Docker Container Deployment

Running Setup and Zero-Downtime Deploys

With configuration in place, run kamal setup to install kamal-proxy and deploy the initial version:

bash
# Initial boot: initializes kamal-proxy, pulls image, starts container
kamal setup

# Subsequent deploys: builds new image, boots container, verifies /up, switches traffic
kamal deploy

During kamal deploy, kamal-proxy launches the new container on an ephemeral host port, waits for consecutive successful 200 OK responses on /up, immediately routes incoming traffic to the new container, and allows existing connections on the previous container to drain gracefully before stopping it.

Kamal 2 Rolling Container Swap Sequence kamal-proxy Ingress - Port 80/443 (TLS) - High-Speed SSD host - Zero request drop - Active connection drain Container V1 (Old) - Draining in-flight requests - Stopped after drain period Container V2 (New) - Booted on ephemeral port - Passes health check /up Postgres / Valkey - Managed accessories - Docker internal network - Persistent volume storage - High-Speed SSD backed kamal-proxy ensures uninterrupted production traffic during rolling deployments
Kamal 2.0 Web Application Deployment Walkthrough
YouTube

Instant Rollback and Operational Controls

If a regression escapes staging into production, Kamal allows instantaneous rollbacks to the prior container image without rebuilding:

bash
# Inspect running container versions and proxy routes
kamal app details

# Roll back immediately to the previous image tag
kamal rollback

# Stream live production container logs
kamal app logs -f

Kamal 2 delivers the operational simplicity of single-tenant cloud servers with the continuous delivery velocity of modern containers.

Deploy your containerized applications with Kamal 2 on Netbay Linux VPS in under 60 seconds with High-Speed SSD in Lucknow DC01 — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance