Skip to Content
Course content

139: Deploying Rails with Kamal

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you're moving into a new house. In the old days of deployment, you'd move in with a giant list of instructions: "Buy this specific brand of lightbulbs, install the flooring exactly like this, and make sure the plumbing is exactly version 2.1." If the house had slightly different wiring than you expected, the whole thing would fall apart the moment you flipped a switch. That's how we used to deploy apps—hoping the server's environment perfectly matched our local machine.

Kamal changes that. Instead of giving the server a list of instructions, Kamal lets you build a "shipping container." You pack your Ruby version, your gems, your compiled assets, and your OS settings into one sealed box. When you deploy, you aren't installing software on the server; you're just dropping that container onto the plot of land and telling it to run. If it works on your machine, it works on the server, because the environment is inside the box.

Setting the Stage with Docker and SSH

Before we touch Kamal, you need two things: a place to store your "containers" (a Docker Registry) and a way to talk to your server (SSH). I usually recommend Docker Hub for the registry, though GitHub Packages works great too. You'll need a VPS—something like a DigitalOcean Droplet or a Hetzner instance—running Ubuntu.

The beauty here is that you don't need to install Ruby or Rails on the server itself. The server only needs Docker installed. That's it. I've spent way too many hours of my life debugging "missing shared library" errors on production servers; Kamal effectively kills that entire category of headache.

Mapping the BookWorm App to deploy.yml

Let's say we're deploying an app called BookWorm. To get Kamal working, we focus on the deploy.yml file. This is the brain of your deployment. Instead of a complex script, it's a declarative list of where the app goes and how it behaves.


service: bookworm
image: your-docker-hub-username/bookworm

servers:
  - 123.45.67.89 # Your VPS IP

registry:
  username: your-docker-hub-username
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  clear:
    PORT: 3000
  secret:
    - RAILS_MASTER_KEY
    - DATABASE_URL

Notice the distinction between clear and secret environments. I always tell my juniors: if it's a password or a key, it must be in secret. Kamal handles these by pulling them from your local .env file and securely injecting them into the container at runtime, so your secrets never actually live in your version control.

The Magic of Zero-Downtime Deploys

One of the things that makes Kamal feel like magic is how it handles updates. It doesn't just kill the old version of BookWorm and start the new one—that would leave your users staring at a 502 error for a few seconds.

Instead, Kamal starts the new container on a different port. Once that new container signals that it's healthy and ready to take traffic, Kamal tells Traefik (the load balancer it installs for you) to flip the switch. The traffic shifts to the new version instantly, and only then does the old container get shut down. It's a seamless handoff.

When you're ready, you just run kamal deploy. Kamal builds the image locally (or on a remote builder), pushes it to your registry, pulls it down to your servers, and performs that switch. If something goes sideways, kamal rollback is your best friend—it just flips the traffic back to the previous container that's still sitting there on the server.




📋 Practical Task

Configuring BookWorm for a Dual-Server High Availability Setup

You've successfully deployed BookWorm to a single server, but your user base is growing. You've just purchased a second VPS to ensure that if one server goes down, the app stays online.

Modify your deploy.yml to achieve the following:

  • Add a second server IP (use 98.76.54.32 as the second IP).
  • Configure the roles attribute for the servers so that the first server (123.45.67.89) handles both the web and job roles, but the second server (98.76.54.32) only handles the web role.
  • Add a new secret environment variable called STRIPE_API_KEY to the env: secret section.

Write out the updated deploy.yml content that reflects these changes.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.