Introduction
Kamal 2 is Rails 8's built-in deployment tool. It deploys containerized applications to any Linux server with zero downtime. Kamal 2 replaces the generic Traefik proxy from Kamal 1 with its own purpose-built Kamal Proxy.
Key Concepts
- Kamal Proxy: Kamal 2's built-in reverse proxy that handles SSL, health checks, and zero-downtime container swaps. Replaces Traefik from Kamal 1.
- Accessories: Supporting services (databases, Redis) managed by Kamal alongside your application.
- Destinations: Named deployment targets (staging, production) allowing different configurations for each environment.
Real World Context
With Kamal 2, you can go from a fresh Ubuntu server to a fully deployed Rails application with SSL, zero-downtime deploys, and database services in under 10 minutes with a single kamal setup command.
Deep Dive
Installation
bashgem install kamal kamal init
This creates config/deploy.yml and .kamal/secrets.
Kamal 2 Configuration
yaml# config/deploy.yml service: myapp image: ghcr.io/myuser/myapp servers: web: hosts: - 192.168.1.1 - 192.168.1.2 job: hosts: - 192.168.1.3 cmd: bundle exec rake solid_queue:start proxy: ssl: true host: myapp.com app_port: 3000 registry: server: ghcr.io username: myuser password: - KAMAL_REGISTRY_PASSWORD env: clear: RAILS_ENV: production SOLID_QUEUE_IN_PUMA: true secret: - RAILS_MASTER_KEY - DATABASE_URL accessories: db: image: postgres:17 host: 192.168.1.4 port: 5432 env: secret: - POSTGRES_PASSWORD volumes: - /data/postgres:/var/lib/postgresql/data
Secrets File
bash# .kamal/secrets KAMAL_REGISTRY_PASSWORD=ghp_xxx RAILS_MASTER_KEY=abc123 DATABASE_URL=postgres://user:pass@db:5432/app POSTGRES_PASSWORD=secure_password
Deployment Commands
bashkamal setup # First-time setup (installs Docker, deploys everything) kamal deploy # Deploy new version with zero downtime kamal rollback # Roll back to previous version kamal app logs # View application logs kamal app exec 'bin/rails console' # Open Rails console
Common Pitfalls
- Using Traefik configuration from Kamal 1 — Kamal 2 uses
proxy:instead oftraefik:. The proxy section is simpler and handles SSL automatically. - Forgetting to set secrets — Missing secrets in
.kamal/secretswill cause deployment failures. Always verify withkamal env pushbefore deploying.
Best Practices
- Use
proxy: ssl: true— Kamal Proxy handles Let's Encrypt certificates automatically. No manual SSL configuration needed. - Run Solid Queue in Puma for simple apps — Set
SOLID_QUEUE_IN_PUMA: trueto avoid needing a separate job server.
Summary
- Kamal 2 uses Kamal Proxy instead of Traefik for routing and SSL.
- Configuration lives in
config/deploy.ymlwith secrets in.kamal/secrets. kamal setuphandles first-time deployment from a fresh server.kamal deployperforms zero-downtime rolling updates.- Accessories manage supporting services like databases.
Code Examples
yaml
# Kamal 2 deploy.yml — note proxy: instead of traefik:
service: myapp
image: ghcr.io/myuser/myapp
servers:
web:
hosts:
- 192.168.1.1
proxy:
ssl: true
host: myapp.com
env:
clear:
SOLID_QUEUE_IN_PUMA: true
secret:
- RAILS_MASTER_KEY
- DATABASE_URL