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)
- Ruby, Ruby on Rails, SQLite and Docker are already installed
- A server running Ubuntu version 22.04 (or later), or Debian 11 (or later)
- SSH access to that server
- Access to the root user
- Basic knowledge of Ruby on Rails and Kamal
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
Then visit
rails server -d
http://localhost:3000
to view the default home page.
- On public interface
Then visit
rails server -d -b 0.0.0.0
http://<public_ip_of_local_device>:3000
to view the default home page.
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
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
toDOCKER_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
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.