Deploy Rails with Kamal on Hetzner
Kamal is the deployment tool Rails 8 ships with: it builds your app's Docker image, pushes it to a registry, and performs zero-downtime cutovers on any server you own. Paired with Hetzner Cloud (servers from ~€4/month), it's the cheapest way to run Rails in production without giving up push-to-deploy ergonomics. Here's the full path — and what each step looks like when LaunchPad does it for you.
Create a Hetzner Cloud server
Sign up at Hetzner (servers from ~€4/month), create a project, and provision a server — a CX22 comfortably runs a small Rails app, its worker, and PostgreSQL. Install Docker, set up a firewall (UFW), and harden SSH.
Make sure your app has a Dockerfile
Rails 7.1+ generates a production Dockerfile with bin/rails new. Kamal builds this image and ships it to your server — no buildpacks involved.
Pick a container registry
Kamal pushes your built image to a registry: Docker Hub or GitHub Container Registry (GHCR) both work. You'll need your registry username and an access token — for GHCR, a personal access token with the write:packages scope. Kamal reads it from the KAMAL_REGISTRY_PASSWORD secret.
Write config/deploy.yml
Tell Kamal your service name, image, server IP, registry, env secrets, and a health-check path (Rails ships /up). Kamal's proxy only promotes a new container once the health check passes — that's the zero-downtime part.
Run kamal setup, then kamal deploy
kamal setup bootstraps the server on first run; after that, every release is a single kamal deploy: build, push, pull on the server, health-check, and cut over with no dropped requests.
Set up PostgreSQL and backups
Run PostgreSQL on the same server (or a second one), then automate pg_dump backups to off-site object storage — and actually test your restores. This is the step most home-rolled setups skip.
The same steps, automated by LaunchPad
LaunchPad runs this exact playbook for you — it generates the Kamal config from your app's
settings and shells out to the real kamal CLI,
so there's no proprietary deploy magic to outgrow.
- Server: paste a Hetzner API token and LaunchPad provisions the server and hardens it — Docker, UFW firewall, fail2ban, swap.
- Deploy: point at a GitHub repo + branch, set your registry username and a
KAMAL_REGISTRY_PASSWORDenv var, and hit Deploy. Logs stream live; cutover is gated on a health check, with automatic rollback if it fails. - Database: LaunchPad provisions PostgreSQL on your server, snapshots it before every deploy, ships encrypted backups to Backblaze B2, runs restore drills, and supports point-in-time recovery via WAL archiving.
- Day 2: managed cron entries, server health checks, security-update scans, and a live Rails console from the browser.
Free tier during early access — you pay only Hetzner and Backblaze, billed directly.