I use asdf to manage my runtime versions (Ruby and Node). This makes life a lot easier when switching between multiple codebases and allows me to easily to switch machines due to the presence of a .tool-versions file in each of my repositories.

Where this gets a little complicated is creating a new Ruby on Rails project, as my local (in a directory) version of tools may be different to my global (laptop wide) versions.

To ensure I’m not getting versions mixed up, I like to setup my local versions before creating the application.

Setup using asdf

Create a folder from the terminal on your machine and navigate into it.

mkdir my_new_rails_project
cd my_new_rails_project

From here we will tell asdf which versions of Ruby and Node we want to use. I’ve previously tried to also specify the Postgres version too but that caused more issues than it solved.

asdf local ruby 3.4.1
asdf local nodejs 22.9.0

By default the yarn version is usually set to v1.x which is pretty old in comparison to the current v4.x that is available, so lets fix that.

yarn set version stable
yarn -v
# 4.6.0

I sometimes have issues where the above command fails with an error saying that the Node version is incorrect. This can usually be fixed with a asdf reshim nodejs command.

Add the node-modules linker to the newly created .yarnrc.yml. This tells yarn to use the old node modules folder structure, which Rails typically relies on

echo "nodeLinker: node-modules" >> .yarnrc.yml

Rails new

You should now be ready to run the rails new command. You may need to install the rails gem for the your version of Ruby - there’s nothing special for you to do here other than following the Rails documentation

When running the rails new command, be sure to run it from the directory that you have manually created. Instead of naming the project in the rails new command you’ll want to use the existing directory. This is achieved by running rails new . rather than something like rails new my_new_rails_project as described in the documentation - the . tells the Rails CLI tool to use the current directory

My go to is

rails new . --css tailwind -j esbuild --skip-spring --skip-system-test --asset-pipeline=propshaft --database=sqlite3

Prepare to deploy

Dockerfile

We’re using a different version of Node than the default Dockerfile expects, so we’ll make some updates

Remove npm install -g yarn@$YARN_VERSION && \ from the “# Install JavaScript dependancies” section.

Add the following after the “# Install JavaScript dependancies” section.

# Setup yarn  
RUN corepack enable  
RUN yarn set version stable

Change RUN yarn install --frozen-lockfile to RUN yarn install --immutable in the # Install node modules section.

Kamal

Update deploy.yml and .secrets

deploy.yml

Find and replace your-user with your GitHub handle i.e. dcyoung-dev

Update the servers section to specify hosts and options. Network allows for a private network to be established on your machine, useful for running multiple applications.

servers:  
  web:  
    hosts:  
      - 5.75.164.130  
    options:  
      network: your_project_name

Update proxy hostname to your domain name

Update registry server to use GitHub i.e. server: ghcr.io. Why use Docker when you’re already using GitHub 🤷‍♂️

.secrets

I use 1Password to manage my secrets. Update the GITHUB_TOKEN to read a personal access token from 1Password GITHUB_TOKEN=$(op read "op://VaultName/GitHub/personal_access_token") and then update the KAMAL_REGISTRY_PASSWORD to use the GITHUB_TOKEN i.e. KAMAL_REGISTRY_PASSWORD=$GITHUB_TOKEN

Server Setup

With the private network being used you’ll have to SSH into your machine and set this up in Docker manually. If this is your first application, run kamal setup first. It will fail but should have Docker installed on your server. You can then run the following:

ssh root@<server_ip_address> then docker network create your_project_name - your_project_name comes from servers:web:options:network in your deploy.yml

DNS

I usually use Cloudflare to manage my DNS. Where ever you manage your DNS jump in and create a new A record, I usually use a subdomain pointing to the IP address of my server. In Cloudflare you can leave the Proxy status set to “proxied”.

Deploy

Make sure you have committed and pushed your code to GitHub.

Make sure Docker is running on your local machine.

Then run

kamal setup

Once complete you can visit your new web application