How to deploy a rails app in under 30 mins and less than $5 per month

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

Screenshot from https://www.hetzner.com/cloud, accessed on 12 Oct 2023

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

  1. It asks for the root folder of the project
  2. Then it asks for your docker registry username
  3. 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

  1. It extracts the name of the rails app from database.yml
  2. it creates the kamal deployment file to setup all these components
  3. 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
  4. 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. You can grab them 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 write me, I’d love to hear from you.

Kubernetes basic questions answered

when getting started with Kubernetes, it can be a daunting task at first to get a grasp of the basic concepts which will allow you to move forward with it. I would like to try to answer some basic questions about Kubernetes, some of which I was having in my mind when I first started to learn and work with Kubernetes.

If you do not have any understanding of containers and containerised applications, it becomes even harder to realise where in the big picture does Kubernetes fit.

Explaining what containers are is out of the scope of this article. If you feel like you still need clarity in understanding what containers are and how do they help, I suggest to find that out first before moving forward. If you feel comfortable with containers, then off we go.

What is Kubernetes?

Kubernetes is a container orchestrator. And what would that be? Well, when we containerise an application, we package the application and its environment in an image, but we still need somehow to run it. We can execute a docker run command and run a docker container, but then when we have an update or a new image, we would manually need to kill the running container and run the new one. And what happens when the container crashes because of e.g. unhealthy state? Who would take care of restarting the container? This is where Kubernetes fits into the big picture.

Kubernetes orchestrates the lifecycle of a container. It can deploy containers together with their dependencies, restart them if they crash, update them if the image version changes, create new instances of the image without downtime, etc. Most of these can be fairly easily automated with the help of Kubernetes.

What is a Pod?

Well, in the previous paragraph I made a false statement. Kubernetes doesn’t actually focus a lot directly on the containers. Kubernetes works on a one level higher abstraction concept called Pods. Pods can be thought of as mini virtual machines which can run multiple containers inside. Usually, Docker is used as a container engine, but this can be configured differently if needed.

Ideally, a pod would run a main container (e.g. one application or a service), and it can run other side containers which would serve the main container. The reason behind this is that, if one of the containers signals to be unhealthy, Kubernetes will kill the whole Pod and try to create a new one. Therefore, it’s a good practice to have one main service running in a Pod, and if that service is not healthy, then the Pod is instatiated by the orchestration scheduler.

What applications can I run on Kubernetes?

Anything that can be containerised. Kubernetes supports stateless as well as stateful applications. Although, from experience I can say, running stateless applications is easier. That’s because managing the state requires more management work from our side.

Personally, I try to push stateful software outside Kubernetes and use them from PaaS providers. One example of such a scenario is the Database. This leaves me more room to focus on running the in-house developed applications and less attention on dependencies.

What is kubectl?

Kubectl is a CLI tool to query and manage kubernetes. Kubernetes has several types of resources. Those resources can be Pods, Services, Deployments, ConfigMaps, etc. Kubectl allows us easily to find information about those resource as well as change them. One example would be to read the deployment configuration of a pod, another would be scaling up a deployment.

One can get most (if not all) of these using a UI, but come on, who needs a UI nowadays ☺️.

I want to have a Kubernetes cluster, what are my options?

Starting from the most obvious option, you can get some bare metal servers and install your own Kubernetes cluster. Though, I would strongly not recommend this until you really know what you are doing. Kubernetes is a very complex system. It has several components and a good configuration would require several servers. Only keeping a safe, available and up to date configuration would be a challenge, let alone taking care of more complex topics like the security of the cluster.

Unless you are constrained here, I would strongly recommend you start with one of the cloud providers that provide Kubernetes as a service. It is offered by many providers, amongst them Azure, AWS, and DigitalOcean.

The cloud providers abstract away the management of the cluster itself and give you freedom to focus on actually building your application infrastructure.

When is Kubernetes good for me?

If you have only one or two applications running, you are better off without it. Kubernetes offers great functionality to orchestrate containers, but it also comes with an administration overhead. If you are not building many (3+) different applications or micro services that you deploy frequently (several times per month), in my opinion it would not be a good option.

Kubernetes is a great helper in an environment of multiple micro services where continuous delivery is the process. It is an overkill to run 2-3 applications which get deployed a couple of times per month. You get my point.

Start small and adjust as you grow!

Conclusion

Kubernetes is one of our time’s coolest tools. It has enabled many business solutions scale flexibly and shine. But at the same time, it can be a complex beast. Take it with a grain of salt and prepare well before adopting. Equipped with knowledge, it will take your DevOps processes and with it your possibility to reacting to changes to a whole new level.