// 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:
- builds the application’s Docker image;
- pushes it to a container registry;
- on each server downloads the new image and starts the container;
- waits until the new container responds to the health check;
- 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:
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: amd64With 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:
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/secretsfile 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 …
VPS setup, server setup
2026-05-12 · ★ 5/5
Excellent work! Set up the server very quickly, installed the control panel, and configured the IP. Definitely recommend!
Excellent work! Very quickly set up the server, installed the panel, configured the IP I can definitely recommend it!
Everything was excellent; helped promptly and professionally. Thank you — I recommend them to the community.
Everything's great, helped promptly and professionally, thank you, I recommend it to the community
VPS setup, server setup
2026-04-16 · ★ 5/5
There were several issues concerning both the technical side and overall understanding. Mikhail responded quickly, resolved the technical problems, and helped me understand them — many thanks. I'm satisfied with the result.
There were several issues concerning both the technical side and overall understanding. Mikhail responded quickly to the request, helped sort things out and resolved the technical problems and helped clarify …
VPS setup, server setup
2026-02-18 · ★ 5/5
Everything was done quickly and efficiently. I recommend.
Everything was done quickly and efficiently. I recommend.
VPS setup, server setup
2026-01-17 · ★ 5/5
Everything went well; the contractor responded quickly to questions and helped resolve the issue. Thanks!
Everything went well, the contractor responded quickly to questions and helped resolve the issue. Thank you!
VPS setup, server setup
2025-12-16 · ★ 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)
Или оставьте заявку здесь:
// Related