Deploy your apps on a Raspberry Pi using Kamal

()
Back to home

Setting up the Raspberry Pi

Use Raspberry Pi imager to flash the latest Raspberry Pi OS to a microSD card. Use the Lite version of the OS if you only intend to use the Pi as a server.
Don't forget to enable SSH in the "Services" tab and adding your computer's public key.

Once the OS is flashed and the Pi is booted, SSH into the Pi using the following command with the hostname and username you defined in Raspberry Pi Imager:

ssh <USERNAME>@<HOSTNAME>

The next steps will require you to be able to SSH into the Pi with the root user. To do so, copy your public key to the root user's authorized_keys file:

sudo cp ~/.ssh/authorized_keys /root/.ssh/

The raspberry Pi should now be ready, as Kamal will handle the rest of the setup.

Installing Kamal

On a Mac, install ruby.

brew install ruby
brew link --overwrite ruby --force

The second version allows to link brew to the latest version of ruby (cf this thread)

Add ruby to your PATH in your .bashrc or .zshrc:

export PATH=$(brew --prefix ruby)/bin:$PATH
export PATH=$(gem environment gemdir)/bin:$PATH

Setting up the Github container registry

On Github, create a personal access token with the read:packages and write:packages permissions. Kamal will use this token to push the Docker image to the Github container registry.

Set it as an environment variable:

export KAMAL_REGISTRY_PASSWORD=<YOUR-TOKEN>

You can now follow Kamal's setup instructions and get your site up and running!

Github actions

On the page of the Github package Kamal created, link the package to its related repository. You should also got to Package settings > Manage Actions access and allow the repository to write the package.

Then, add the following Github action to your repository:

name: Deploy

on:
  push:
    branches:
      - main

jobs:
  Deploy:
    runs-on: ubuntu-latest

    env:
      DOCKER_BUILDKIT: 1
      KAMAL_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.2.2
          bundler-cache: true

      - name: Install dependencies
        run: gem install kamal

      - uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - run: kamal version
      - run: kamal registry login --verbose

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      # Deploying two builds could cause locking issues when the first is cancelled.
      - run: kamal lock release --verbose
      - run: kamal redeploy --verbose

Using the gh cli, you can use the following command to generate an SSH key pair and set the private key as a secret in your repository:

REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner | sed 's/\//\-/g')
DATE=$(date '+%Y-%m-%d %H:%M:%S')
KEY=$TMPDIR$REPO
PUB_KEY=$KEY.pub

ssh-keygen -t rsa -b 4096 -f $KEY -P "" -C "$REPO $DATE"
ssh-copy-id -i $PUB_KEY root@<HOSTNAME>
gh secret set SSH_PRIVATE_KEY --body "$(cat -p $KEY)"
Back to home