Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Deploying a Rails 8 app with Kamal

profile picture
Author
Aestimo Kirina
Published
2025-02-28
Time to read
8 minutes reading time

About the author- Full-stack developer. Building apps and learning.

Introduction

Ruby on Rails is a popular Ruby-based web framework for building fullstack applications. Rails (as it's popularly known) is well known for it's model-view-controller (MVC) architecture, ability to scaffold features, and large user community.

In this tutorial, we shall learn how to build a simple Ruby on Rails 8 web application and deploy it to a virtual private server using Kamal, a nifty, zero-downtime deploy tool for deploying applications to the cloud using Docker containers.

On the local device, we will use the following files:

my_blog_app
├──  config/deploy.yml        Kamal deploy configuration file
└── .kamal/secrets            Secret credentials used in config/deploy.yml

When you deploy config/deploy.yml, Kamal will connect to the virtual private server, install Docker, and start a container with the image that we will create on the local device beforehand.

Prerequisites

  • A local device
    • Ruby, Ruby on Rails, SQLite and Docker are already installed
      Make sure your user is added to the Docker group
    • An SSH key pair (public key has to be on the server)

  • A server running Ubuntu version 22.04 (or later), or Debian 11 (or later)
    • SSH access to that server
    • Access to the root user

Step 1 - Initiate a new Ruby on Rails app

On the local device, initialize a new Ruby on Rails application with the following command:

rails new my_blog_app

This command will setup a new Rails application with an SQLite database and some default boilerplate code which includes a Dockerfile and the Kamal configuration which we'll work with later on.

Next, cd into the app directory and run the command below to spin up a server to run the app:

  • On private interface
    rails server -d
    Then visit http://localhost:3000 to view the default home page.

  • On public interface
    rails server -d -b 0.0.0.0
    Then visit http://<public_ip_of_local_device>:3000 to view the default home page.

running-the-default-app

Now we are ready to create the blog functionality.

Step 2 - Building the blog posting feature

We'll use one of Rails' notable features to build this functionality — scaffolding.

Start by running the command below:

rails generate scaffold Post title:string body:text

This command generates a bunch of files including:

  • A migration file to create the database table for posts.

  • A model that will give us an intuitive way to interact with this table and the database.

  • A controller to hold all post-related business logic.

  • Adding routes for handling post creation, editing, updating and deleting to the app's route configuration.

  • Post views for handling create, read, edit and delete actions.

Then, run the newly generated database migration file using the command below to create the posts table in the database:

rails db:migrate
rails db:migrate:status

Finally, add /posts at the and of the URL and play around with the app by creating a few posts:

http://localhost:3000/posts

posts-index

create-new-post

Step 3 - Create a server that will host the blog

If you haven't already, create a server (e.g. with Hetzner on Cloud Console). Select Ubuntu 24.04 as the operating system and add your SSH key.

You can read the documentation here for steps on how to generate an SSH key.

It is important that your local device can access the root user of the server via an SSH key, as Kamal relies on this to connect to the server.

Step 4 - Prepare the server for the Kamal deployment (Optional)

  • Go to the server list in Cloud Console and copy your server's IP address (e.g. 203.0.113.1)
  • Connect to your server:
    ssh root@203.0.113.1
  • Update your server:
    apt update && apt upgrade -y
  • Double-check if the public key of your local device is on the server
    cat  ~/.ssh/authorized_keys
  • Reboot the server:
    reboot

Note: We could manually install Docker on the server, but since Kamal can handle this for us, there's no need to go through the manual process.

Step 5 - Make your app ready for the Kamal deployment

Follow this step on your local device.

Since we are working with a simple Ruby on Rails application, our main job will be on the Kamal deploy configuration file config/deploy.yml.

Start by opening up the file and editing it to resemble the example with a registry shown below:

Replace the following variables with your information:

  • <name_of_your_app>
  • <username/repository_name>
  • <your_app_domain_name>
  • <docker_registry>
  • <your_docker_username>

Also change KAMAL_REGISTRY_PASSWORD to DOCKER_REGISTRY_PASSWORD

# Name of your application. Used to uniquely configure containers.
service: <name_of_your_app>

# Name of the container image.
image: <username/repository_name>

# Deploy to these servers.
servers:
  web:
    - 203.0.113.1

# Enable SSL auto certification via Let's Encrypt
proxy:
  ssl: true
  host: <your_app_domain_name>

# Credentials for your image host.
registry:
  # Specify the registry server, if you're not using Docker Hub
  server: <docker_registry>
  username: <your_docker_username>

  # Always use an access token rather than real password when possible.
  password:
    - DOCKER_REGISTRY_PASSWORD

# Inject ENV variables into containers (secrets come from .kamal/secrets).
env:
  secret:
    - RAILS_MASTER_KEY
    - DOCKER_REGISTRY_PASSWORD
  clear:
    SOLID_QUEUE_IN_PUMA: true

aliases:
  console: app exec --interactive --reuse "bin/rails console"
  shell: app exec --interactive --reuse "bash"
  logs: app logs -f
  dbc: app exec --interactive --reuse "bin/rails dbconsole"

volumes:
  - "my_blog_app_storage:/rails/storage"

asset_path: /rails/public/assets

# Configure the image builder.
builder:
  arch: amd64

Kamal will connect to the root user of the server (in this example 203.0.113.1). For this to work, the public SSH key of your local device needs to be in the authorized_keys on your server.

You can get more details on configuring the Kamal deploy configuration file from the documentation.

Step 5.1 - Setup Kamal secrets

It's never a good idea to commit secrets like the repository tokens, database passwords and other sensitive data to your Git repository, so we make use of the secrets file .kamal/secrets.

First, ensure this file is never committed to your Git repository by adding it to the .gitignore file:

[...]

/.kamal/secrets

Now edit .kamal/secrets and add the following variable:

DOCKER_REGISTRY_PASSWORD=<your_access-token_or_password>

Finally, with the deploy configuration done, commit your changes to Git.

git config --global user.name "Your Name"
git config --global user.email "your-email@example.com"
git add .
git commit -a -m "Initial commit"
git log

Step 6 - Deploy the app

Deploy the Rails 8 app with the command below:

kamal setup

But just in case you get an error like the one shown below:

ERROR: failed to solve: process "/bin/sh -c bundle install &&     rm -rf ~/.bundle/ \"${BUNDLE_PATH}\"/ruby/*/cache \"${BUNDLE_PATH}\"/ruby/*/bundler/gems/*/.git &&     bundle exec bootsnap precompile --gemfile" did not complete successfully

Edit the Dockerfile and add an additional step that installs the libyaml-dev package like so:

...

# Install application gems
COPY Gemfile Gemfile.lock ./
RUN apt-get update && apt-get install -y libyaml-dev
RUN bundle install && \
    rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
    bundle exec bootsnap precompile --gemfile
...

Then commit the changes and retry the Kamal setup once more:

git add . && git commit -a -m "Update Dockerfile"
kamal setup

In a nutshell, the kamal setup command will:

  • Log into your server
  • Install any server prerequisites, for example, Linux packages, database packages etc.
  • Fetch and install Docker if it is not installed
  • Fetch your app from the Git repository and push it to the image registry you specified
  • Fetch your app's image from the image registry and deploy it to the server
  • Create and assign an SSL certificate for the domain name you specified
  • Make your app availalbe on the domain you specified

Once everything is setup, you should be able to access the web application on your server. Remember to add /posts at the end of the URL again:

https://example.com/posts

rails-app-deployed-to-production

Conclusion

In this tutorial, you've learned how to build a simple Ruby on Rails 8 web application and deploy the app using Kamal. This is an introductory tutorial to give you an idea of what's possible. Explore the Rails and Kamal documentation for more information on how to deploy more advanced apps.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get €20/$20 free credit!

Valid until: 31 December 2025 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more