Kamal Series Part 1: Deploy Rails application on Hetzner
Kamal is a new shiny way to deploy Rails applications announced by DHH back in February 2023 and also spoke about it in his RailsWorld Keynote. Now that Heroku has removed their free tier, Kamal has become excitingly popular since it also resonates with the idea of “leaving the cloud”. Most importantly, Kamal is free and open source and is developed by the folks from Basecamp who created Rails.
This means we need to purchase our own server for deploying our Rails application. There are several choices for purchasing like: Digital Ocean or AWS or Hetzner. We are going to use Hetzner which is one of the crowd favorites. It also gives you the best bang for buck! (We can run our entire Rails application for as little as 4 euros!!!)
This is Part 1 of the Kamal Rails series. In this article, I will cover a basic way of deploying a vanilla Rails application on Hetzner Cloud.
Pre-Requisites:
- Docker is installed on our local environment. (Make sure the version is according to our OS)
- Docker account is created on Docker hub.
- You have a Rails application “created” using Rails > 6.0
If you don’t have a Rails application created yet, you can do so using:
1
rails new kamal_demo -T -m https://raw.githubusercontent.com/joshio1/rails_application_template/main/application_template.rb
- Account on Hetzner Cloud such that we are ready to create Projects/Servers.
Normally, it takes around a day for the account to be verified after our details are entered.
Steps:
1. Create a VPS on Hetzer Cloud
- Login to Hetzner Cloud and create a new “Project”.
- After a project is created, add a server to that project by clicking the “Add Server” button below:
- Select the location for your server and also choose the operating system. In this example, we are going to choose Ubuntu.
- Selected
Shared vCPU(x86) and CPX11
(which is the first plan)
- Choose IPv6 and IPv4 both
- Add an SSH key to our server. Below command is how we can copy our public key to the clipboard. Use that to paste in the SSH section on Hetzner cloud while creating the server.
pbcopy < ~/.ssh/id_rsa.pub
- That’s it. We don’t need any more configurations on the server. Click on
Create and Buy Now
- It will take around 1 or 2 minutes to create the server. We also get an email from Hetzner. Make sure the server is green and has an IPv4 address next to it. Check if we can SSH to the created server by doing:
ssh root@
2. Getting our Rails repository ready for deployment
- Now navigate to the root directory of your Rails application and check if you have a
Dockerfile
already present.
If your Rails application was created on Rails version 7.1 or greater, Rails now by default ships with a Dockerfile.
- If not, we can use the dockerfile-rails gem for generating Dockerfile and related files.
Make sure you have a Dockerfile
present because Kamal uses a docker image for deployment.
Next thing is to make sure you have health check route. Again if your application was created on Rails version 7.1 or greater, you should have an /up
route which determines whether your application is up or not.- If you don’t have an /up
health check route, you can add this following code to your config/routes.rb
file:
get ‘/up’, to: ->(env) { [204, {}, [’’]] }
- Once we have these two things (Dockerfile and the health check route), we should be all set to start using Kamal.
3. Using Kamal for deployment
- Install Kamal using:
gem install kamal
- Now, navigate to the Rails application repository (
kamal_demo
) and initialize Kamal
cd kamal_demo kamal init
- This will create a bunch of files like
.env
,config/deploy.yml
and some hooks. Modify the.env
file to insert Docker Registry password and Rails master key.
Docker Registry Key can be found by logging in to your Docker account and going to Account Settings > Security > New Access Token
to create a new access token.
RAILS_MASTER_KEY
for production environment is located inconfig/credentials/production.key
of our Rails application which is used to decrypt Rails credentials.- The
.env
file should look something like this:
KAMAL_REGISTRY_PASSWORD=
- The
kamal init
command also creates aconfi
g/deploy.yml
file. This file is responsible for storing the configuration of our Rails application which is necessary to deploy on a remote server. Edit this file and change it to something like this:
1
2
3
4
5
6
7
8
9
10
11
service: kamal_demo
image: joshio1/kamal_demo
servers:
- <ipv4_address_of_Hetzner_server>
registry:
username: joshio1
password:
- KAMAL_REGISTRY_PASSWORD
env:
secret:
- RAILS_MASTER_KEY
- Some details about the above
config/deploy.yml
file:
Here joshio1
is the Docker
username and kamal_demo
is the name of the Rails application
- Kamal automatically references
KAMAL_REGISTRY_PASSWORD
andRAILS_MASTER_KEY
from the.env
file when they are mentioned like this in theconfig/deploy.yml
file. <ipv4_address_of_hetzer_server>
is pretty self-explanatory.
Set force_ssl=false
in config/production.rb
- This is because we haven’t yet configured SSL certificates and we will only use HTTP to connect with our server.
- Note that we will configure HTTPS in upcoming parts of this Kamal series.
After we have done making these changes, this is the final command required to deploy our Rails application to the Hetzer server:
kamal setup
- You should see output like this:
➜ kamal_demo git:(main) ✗ kamal setup INFO [ffc073f1] Running /usr/bin/env mkdir -p .kamal on 5.161.42.10 INFO [ffc073f1] Finished in 3.630 seconds with exit status 0 (successful). Acquiring the deploy lock… … Ensure Docker is installed… … Push env files… … Log into image registry… … Build and push app image… … … … INFO [57d640dd] Finished in 0.527 seconds with exit status 0 (successful). INFO Container is healthy! … … INFO [36025396] Finished in 1.358 seconds with exit status 0 (successful). Finished all in 288.2 seconds Releasing the deploy lock… Finished all in 301.2 seconds
- Since our container is healthy and all the steps have successfully completed, we can navigate to the URL of our server and see if it is up. Go to:
<SERVER_IP>/up
and we should see a green screen like this:
- If there are any errors during
kamal setup
command or this green is not visible, please refer to theImportant Points
section below for more information.
Next Part: Add Postgres to your Rails application
- So far we have only deployed a basic Rails application with SQLite. In Part 2 of this series, we will deploy a Rails application backed by Postgres.
- Click HERE to go to the next part in this Kamal series
NOTE:
- If this article is out of date, please don’t hesitate to contact me on Twitter from this page and I’ll be happy to update it.
- Listen to this podcast where DHH talks about Rails and Kamal.
- If you would like to search for specific terms or concepts or names in Ruby/Rails podcasts, check out rubypodcatcher.com