It’s October 2023 and we have Rails 7.1 released. The whole community is excited with the new release and countless people are awaiting to start new projects with Rails. I believe Rails has one of the best productivity oriented ecosystems. It’s not just a framework, it’s a complete ecosystem with tools, knowledge and communities supporting it.
Ruby on Rails is my default tech stack choice for my personal projects. I have some of them running online, but the usual problem is, I do not like to pay too much money for for-fun projects which do not generate any income. Previously, I was running my projects on Heroku, but with their pricing changes, I had to take them down as it became too expensive to run those projects where usually I was the only user.
With the introduction of Kamal and the great pricing of Hetzner Cloud, now there is an opportunity to actually run a rails project in under $5 per month. To make my life easier, I decided to write some automation scripts so that every time I setup a new application, I do not have to remember all the detailed steps I need to take. Let’s elaborate on this.
Typical rails setup
On my personal projects the typical setup 3 components:
- The rails app
- The postgresql database
- The redis db (used for cache and background jobs)
For projects that are under development, have no significant user base or the project is at the stage of idea trying, I just need a setup that works and is easily set up. So… this is the solution I use.
Setup of the cloud VM
The VM setup of my choice is named CAX11 on Hetzner cloud. It has 2 shared vCPUs, 4 GB of RAM and 40 GB of disc space. Good enough to run all those components in one server and at the time of writing it costs less than $5 per month
I wrote a terraform script which creates this server and a firewall rule to limit the open ports to ssh and http. Now I can easily provision the servers for my setups by just running this terraform script. More about it below.
Setup of deployment
With the introduction of Kamal, now we can easily have a Heroku like easy deployment process for containerized rails application. It takes care of not only rails application, but also of the necessary auxiliary infrastructure as database and redis. While playing with kamal, I realized, while it is very easy to use and makes deployment fun, I still had to spend a couple of hours to tweak the configuration details to make it work. These kind of tweaks are usually are not found in one documentation page as they are custom to your setup, but anyway I had to loose the time to google the info and make it work. So I decided to write a ruby scrip to automate this.
Here is what exactly this script does:
Phase 1: It collects input
- It asks for the root folder of the project
- Then it asks for your docker registry username
- Next it asks for the IP of the server, the DB and Redis (they can also all be the same IP)
Prepares the rails app
- It extracts the name of the rails app from database.yml
- it creates the kamal deployment file to setup all these components
- It creates/appends .env file to add two keys:
- RAILS_MASTER_KEY – reads it from config/master.key and copies here. Itused when running rails docker container
- POSTGRES_PASSWORD – used for postgres container
- Disable force_ssl so the application can be accessed using http
With the preparation, now your application is ready to be deployed using Kamal
What about previous versions of rails?
If you want to use the scripts with apps older than rails 7.1 you need to prepare them to be dockerized. The script expects to be able to dockerize the app and use the generated image for deployment. If you add a working docker file to your older rails app, the setup will work.
Where can you get the scripts?
I packaged the scripts and a readme file for each of them into one zip file and published them as a digital product. It is for free and can be accessible from here: https://ariancelina.lemonsqueezy.com
You can get the scripts and use for your own project. If you like them or if you have any feedback, please send it to me, I’d love to hear from you.