Tools
Tools: Fire Your DevOps Team: A Solo Dev’s Guide to Kamal 2
2026-02-09
0 views
admin
The Deployment Dilemma ## What is Kamal? ## The Hardware: The $5 Powerhouse ## The Guide: From Zero to SSL ## 1. Installation ## 2. Configuration (config/deploy.yml) ## 3. The Magic of Kamal 2: The Proxy ## 4. What about the Database? ## 5. The Launch ## Day 2 Operations: Sleep Easy ## Summary For the last decade, developers have been stuck between a rock and a hard place. Enter Kamal.
Created by Basecamp (the makers of Rails), Kamal bridges this gap. It gives you the ownership and low cost of raw VPS (Virtual Private Server) hardware, with the ease of a git push style deployment. With the release of Kamal 2, it is finally ready for the masses. Here is how I deployed a production-ready app to a $5 Hetzner server in under 10 minutes. Kamal is essentially "Capistrano for Containers." It runs locally on your laptop. When you type kamal deploy, it: There is no "Master Node." There is no Kubernetes cluster state to manage. If you lose your laptop, your server keeps running. Go to Hetzner (or DigitalOcean/Linode) and buy a cheap VPS.
For roughly $5/month, you can get an ARM server with 2 vCPUs and 4GB of RAM. On Heroku, a "Performance" dyno with similar specs would cost you $250+/month.
That is the math that makes Kamal a no-brainer for solo developers. Assuming you have Docker running locally: Kamal 2 simplified configuration massively. Here is all you need: In Kamal 1, you had to configure Traefik manually to handle SSL. It was confusing.
Kamal 2 includes kamal-proxy by default. It automatically handles: You just add this to your deploy.yml: For a true "One Person" setup, we don't want to pay for a Managed Database (RDS). We want the DB on the same $5 server. Kamal handles this via Accessories. You can tell Kamal to boot a Postgres container and manage it for you. This single command will: In about 3-5 minutes, your app is live at https://myapp.com. "But what if I deploy a bug?" Kamal keeps the old containers around (stopped). A rollback just switches the proxy pointer back to the old container. It takes 10 seconds. "What if I need to run a Rails console?" You are instantly dropped into a remote console session on your server. The "DevOps Guy" used to be a mandatory hire.
With Kamal 2, the barrier to entry for owning your own infrastructure has collapsed. You don't need Kubernetes. You don't need AWS Lambda. You need a Linux box, an SSH key, and Kamal. Fire your DevOps team (or rather, stop trying to be one). Get back to coding. Are you still paying the PaaS premium? Let me know why in the comments! 👇 Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse CODE_BLOCK:
gem install kamal
kamal init Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
gem install kamal
kamal init CODE_BLOCK:
gem install kamal
kamal init COMMAND_BLOCK:
service: my-app
image: your-username/my-app servers: web: - 123.45.67.89 # Your VPS IP address # The Registry where your Docker images live
registry: server: ghcr.io username: your-username password: - KAMAL_REGISTRY_PASSWORD # Inject environment variables
env: secret: - RAILS_MASTER_KEY - POSTGRES_PASSWORD Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
service: my-app
image: your-username/my-app servers: web: - 123.45.67.89 # Your VPS IP address # The Registry where your Docker images live
registry: server: ghcr.io username: your-username password: - KAMAL_REGISTRY_PASSWORD # Inject environment variables
env: secret: - RAILS_MASTER_KEY - POSTGRES_PASSWORD COMMAND_BLOCK:
service: my-app
image: your-username/my-app servers: web: - 123.45.67.89 # Your VPS IP address # The Registry where your Docker images live
registry: server: ghcr.io username: your-username password: - KAMAL_REGISTRY_PASSWORD # Inject environment variables
env: secret: - RAILS_MASTER_KEY - POSTGRES_PASSWORD CODE_BLOCK:
proxy: ssl: true host: myapp.com Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
proxy: ssl: true host: myapp.com CODE_BLOCK:
proxy: ssl: true host: myapp.com COMMAND_BLOCK:
accessories: db: image: postgres:15 host: 123.45.67.89 port: 5432 env: POSTGRES_DB: my_app_production POSTGRES_USER: my_app POSTGRES_PASSWORD: - POSTGRES_PASSWORD files: # Persist data to the host disk so it survives restarts! - db_data:/var/lib/postgresql/data Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
accessories: db: image: postgres:15 host: 123.45.67.89 port: 5432 env: POSTGRES_DB: my_app_production POSTGRES_USER: my_app POSTGRES_PASSWORD: - POSTGRES_PASSWORD files: # Persist data to the host disk so it survives restarts! - db_data:/var/lib/postgresql/data COMMAND_BLOCK:
accessories: db: image: postgres:15 host: 123.45.67.89 port: 5432 env: POSTGRES_DB: my_app_production POSTGRES_USER: my_app POSTGRES_PASSWORD: - POSTGRES_PASSWORD files: # Persist data to the host disk so it survives restarts! - db_data:/var/lib/postgresql/data CODE_BLOCK:
kamal setup Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
kamal setup CODE_BLOCK:
kamal setup CODE_BLOCK:
kamal rollback Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
kamal rollback CODE_BLOCK:
kamal rollback CODE_BLOCK:
kamal app exec -i 'bin/rails console' Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
kamal app exec -i 'bin/rails console' CODE_BLOCK:
kamal app exec -i 'bin/rails console' - The PaaS Trap (Heroku, Render, Fly): extremely easy to use, but the moment you need more than 512MB of RAM, the price jumps from $7 to $50 to $200. You pay a "convenience tax."
- The Cloud Maze (AWS, Kubernetes): Infinite power and cheaper raw resources, but you need a PhD in IAM roles, VPCs, and Load Balancers to serve a "Hello World" app. - Builds your Docker image locally (or on a builder).
- Pushes it to a registry (like Docker Hub or GitHub Packages).
- SSH's into your server(s).
- Pulls the new image.
- Boots it up alongside the old version.
- Switches traffic over (Blue/Green deployment) using its built-in Proxy.
- Kills the old version. - Zero-downtime deployments: It holds requests while your app restarts.
- Auto-SSL: It talks to Let's Encrypt automatically to give you HTTPS. - SSH into your VPS and install Docker.
- Start your Database accessory.
- Start the Kamal Proxy.
- Build your app.
- Start your app.
- Issue an SSL certificate.
how-totutorialguidedev.toaimllinuxserverswitchpostgresqldockernodessldatabasekubernetes