Deploy a web app with Kamal
Kamal is a Ruby gem that runs on your deployment machine (laptop or CI runner), not on the server. It orchestrates Docker containers on a VPS over SSH. This guide walks through installing Kamal, configuring a deploy, and running your first deployment.
Prerequisites
- A deployment machine (your laptop or CI runner) with Ruby installed (2.7+). This is where Kamal runs.
- A target VPS with SSH access (root or a user with sudo). No software needs to be pre-installed.
- A Docker registry account (Docker Hub, GHCR, or any private registry) with credentials.
- Your web app with a
Dockerfilein the repository root that builds a runnable image. - A domain name with an A/AAAA record pointing to your VPS IP.
Kamal is a client-side tool. It never runs on the server. The VPS is a blank machine that only needs SSH reachability and ports 80 and 443 open in the firewall.
Step 1: Install Kamal on your deployment machine
Install the Kamal Ruby gem:
gem install kamalVerify it is available:
kamal versionThat is all. Do not install Kamal on the VPS. The VPS will receive commands over SSH from this machine.
Step 2: Initialize Kamal in your application
Navigate to your application root and run:
cd /path/to/your-app
kamal initThis creates two things:
config/deploy.ymlโ the deployment configuration file.kamal/secretsโ a local file for sensitive values (do not commit this file)
Both files are meant to be edited by you in the next steps.
Step 3: Configure deploy.yml
Open config/deploy.yml and replace the template with values for your project. A minimal working configuration:
service: myapp
image: your-registry-user/myapp
servers:
web:
- your-domain.com
proxy:
ssl: true
host: your-domain.com
app_port: 3000
registry:
server: ghcr.io
username: your-registry-user
password: KAMAL_REGISTRY_PASSWORD
env:
clear:
RAILS_ENV: production
secret:
- RAILS_MASTER_KEY
- DATABASE_URLKey fields:
serviceโ a name for your app (used for container naming)imageโ the full registry image nameservers.webโ list of your VPS hostnames or IPsproxyโ kamal-proxy will terminate SSL with Let's Encrypt and forward traffic toapp_portregistryโ credentials for pushing and pulling imagesenvโ environment variables passed to the container
For accessories like PostgreSQL or Redis, you can add an accessories section, but start without them for the first deploy.
Step 4: Set secrets
Edit .kamal/secrets to define the values referenced in deploy.yml:
KAMAL_REGISTRY_PASSWORD=your-personal-access-token
RAILS_MASTER_KEY=your-rails-master-key
DATABASE_URL=postgres://user:pass@host/dbThe .kamal/secrets file is local only. On CI, inject these values through the CI secret store and pass them via environment variables that Kamal reads.
Never commit .kamal/secrets to version control. The .kamal directory is in .gitignore by default.
Step 5: Set up the VPS with kamal setup
This is the key command. It does everything in one shot:
kamal setupKamal will SSH into your VPS and:
- Install Docker if it is not already present
- Start the kamal-proxy container, which binds ports 80 and 443
- Obtain a Let's Encrypt SSL certificate for your domain automatically
- Pull your application image from the registry
- Start your application container behind the proxy
No manual Docker installation, no Nginx configuration, no certbot. The VPS goes from blank to running your app in one command.
Step 6: Deploy updates
After the initial setup, deploy new versions with:
kamal deployThis builds or pulls the new image, stops the old container gracefully, starts the new one, and verifies the health check. Kamal rolls back automatically if the health check fails.
Maintenance
- Upgrade Kamal:
gem update kamalon your deployment machine - Check logs:
kamal app logs - Run a command inside a container:
kamal app exec 'rails console' - Restart the app:
kamal app restart - Rollback:
kamal deploy --version=<previous-version> - Upgrade kamal-proxy on the server:
kamal proxy upgrade
Kamal does not manage databases. Back up persistent data separately and document how to recreate your server from the repository and secret store alone.
Tools mentioned
Kamal
โDeploy web applications to any VPS with zero infrastructure complexity using Docker.
Free and open source. No platform fees. Deploy to any server you control with only Docker as a dependency.