// Engineering Log

Deployment Platforms: Part 5 — Kamal: deploying Docker applications to your own server

Published on 2026-09-22

// Fast route

This article belongs to the topic Deploy and reliability.

Kamal — a command-line tool from 37signals (creators of Basecamp and Ruby on Rails) for deploying web applications in Docker containers on your own servers. It sits between platforms like Heroku or Vercel, where convenience is paid for with a markup and vendor lock-in, and Kubernetes, which offers flexibility at the cost of significant complexity. Kamal connects to servers via SSH, runs containers on them and switches traffic to the new version without downtime.

Kamal was originally made for Rails, but now it is language-agnostic: if an application can be built into a Docker image, it can be deployed. The active branch is Kamal 2 (the latest release at the time of writing is 2.12).

How deployment works

The kamal deploy command performs the following steps:

  1. builds the application’s Docker image;
  2. pushes it to a container registry;
  3. on each server downloads the new image and starts the container;
  4. waits until the new container responds to the health check;
  5. switches traffic to the new container and stops the old one.

Traffic switching is handled by kamal-proxy — Kamal’s own proxy, which replaced Traefik in the second version. During deployment it polls the healthcheck path once per second (by default /up) and routes requests to the new container only after a successful response. If the app doesn’t come up within the allotted time, traffic stays on the old version.

Installation and server preparation

Kamal is installed on the developer machine or in CI as a Ruby gem (gem install kamal); if Ruby is not available, it can be run from a Docker container. Servers only need SSH key access.

The initial deployment is performed with kamal setup. According to the documentation it connects to servers via SSH (by default as root), installs Docker where it’s missing using the get.docker.com script, starts kamal-proxy and performs the first deploy. Installing Docker requires root privileges.

Configuration

All configuration is a single file config/deploy.yml. A minimal example with one server and automatic HTTPS:

yaml
service: my-app
image: my-user/my-app

servers:
  web:
    hosts:
      - 192.0.2.10

proxy:
  host: app.example.ru
  app_port: 3000
  ssl: true
  healthcheck:
    path: /up

registry:
  server: registry.example.ru
  username: my-user
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  clear:
    LOG_LEVEL: info
  secret:
    - DATABASE_URL

builder:
  arch: amd64

With ssl: true kamal-proxy obtains a Let’s Encrypt certificate by itself. According to the documentation this works when the app is deployed on a single server, the domain points to it and port 443 is open. If there are multiple servers, a load balancer is required in front of them, and the certificate is issued on it.

Secrets

Secret values are not stored in deploy.yml. Kamal reads them from files in the .kamal/ directory: first .kamal/secrets-common, then .kamal/secrets (or a file for a specific environment). The format is like dotenv, and a value can be obtained with:

bash
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
DATABASE_URL=$(cat /secure/database_url)

For password managers there is the kamal secrets command, which pulls values from the store during deploy. The secret files themselves should not be committed to the repository, and variables from the secret section are delivered to the server in a separate environment file, not as container run parameters.

Auxiliary services

Kamal can run databases, Redis and other services alongside the application as accessories — separate containers on the specified server. For small projects this is convenient. For production systems with valuable data the database is usually moved to a separate server or a managed service: Kamal does not handle database backups, upgrades or database fault tolerance.

When Kamal is a good fit

  • Several servers or a single server, steady load, a small team without a dedicated infrastructure engineer.
  • You want to move away from a cloud platform that charges per resource to your own servers without switching to Kubernetes.
  • Servers can be in any data center — only SSH access and Docker matter. For a Russian company these can be VPS from Russian providers.

When it is not a good fit:

  • you need automatic scaling for sudden traffic spikes;
  • dozens of services with complex network connectivity where orchestrator capabilities are already required;
  • the team already lives in Kubernetes and knows how to operate it.

A general comparison of deployment platforms is in the first part of the series. A similar task is solved by Dokploy, but it has a web interface and its own panel, while Kamal is only a command-line tool and a single configuration file in the repository.

Common mistakes

  • No healthcheck path. If the application does not respond to /up (or the configured path), the deploy will not switch traffic.
  • The .kamal/secrets file was committed to the repository with real values.
  • Automatic HTTPS on multiple servers. Let’s Encrypt certificates via kamal-proxy are only issued when deploying on a single server.
  • Image architecture doesn’t match the server. An image built on an ARM Mac will not run on an x86-64 server without specifying builder.arch.
  • Database running as an accessory without backups.

// Similar task

If you are dealing with something similar

This article belongs to one of the main working topics. You can keep reading on the topic, go to the homepage to understand what I do, or open the service pages directly.

Article topic

Deploy and reliability

Docker, CI/CD, releases, monitoring, observability, and incident handling.

Typical tasks behind this topic

  • Set up deployment without manual chaos
  • Add monitoring, alerts, and baseline observability
  • Investigate incidents and stabilize production

// Next step

If you need help with this topic, not just another article, it is better to go straight to the service page. The homepage and topic collection stay available as secondary routes.

Open services

// Reviews

Related reviews

I came with an expensive request to configure a VPS server, but during the consultation Mikhail suggested a much simpler, more affordable solution. In the end I saved time and money. Mikhail — a true expert who works for the client's result, not for the fee. I recommend him!

I came with an expensive request to configure a VPS server, but during the consultation Mikhail suggested a much simpler and more cost-effective solution. In the end I saved budget and time. Mikhail — a true expert who …

kfhzasorin

VPS setup, server setup

2026-05-12 · ★ 5/5

// Contact

Need help?

Get in touch with me and I'll help solve the problem

I reply within one business day (03:00-13:00 GMT)

Или оставьте заявку здесь:

Confirm that you are not a bot.

Write and get a quick reply