Deploying with Kamal

deploying to the cloud

Running your own VPS is no mean feat when you consider how easy digital ocean or netlify make it deploy your website.

But it’s not as difficult as it used to be, there are some great open source tools to make it easier like coolify and kamal.

Coolify and Kamal take slightly different approaches, coolify is an app you install on your server, has a nice gui you can use to install from git or docker images.

Kamal on the other hand is a command line tool that you run and configure your deployment locally, it accesses your server and installs docker, builds your app into a docker image and deploys it to your server.

Sounds simple enough that your probably thinking I could just write a script to do that, but kamal also setups a proxy allowing you to run multiple apps on a server (new in kamal v2), gracefully pushes a new version of your app without downtime and configures certificates. It is very easy to configure and can be easily integrated into your CI/CD pipeline.

Kamal assumes you already have a dockerfile for your application and you will need a container registry as kamal will build your dockerfile locally, push it to your registry then on the server pull it from the registry. Kamal also requires root access and assumes you have an ssh token setup on the machine you are deploying from.

Kamal is a ruby gem and can be installed locally or via docker.

gem install kamal

Initialise

kamal init

this creates a few things

a config folder with a deploy.yml file that contains your deployment settings.

a .kamal folder with some samples for hooks that are scripts that can be run at certain stages of deployment like pre-deploy if you need it and a secrets file which is like a .env file and has a few ways of loading your secrets in.

The meat is in your deploy.yml file where you configre your deployement.

service: appname

# Name of the container image.
image: yourns/appname

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

proxy:
  ssl: true
  host: example.com
  app_port: 8080

# Credentials for your image host.
registry:
  # Specify the registry server, if you're not using Docker Hub
  server: 1234456789kr.ecr.eu-west-1.amazonaws.com
  username: AWS

  # Always use an access token rather than real password (pulled from .kamal/secrets).
  password:
    - KAMAL_REGISTRY_PASSWORD

# Configure builder setup.
builder:
  arch: amd64

env:
  secret:
    - NEXT_PUBLIC_SUPABASE_URL

The env var KAMAL_REGISTRY_PASSWORD is pulled from the secrets file.

This is all that is needed.

Initially i ran into a few issues when using digital ocean container registry which can only contain one namespace or image tag, although after switching to use AWS ECR which is the same, so you will need one repo per app.

As you can see there is not a lot of configuration here, but it is also very configurable if you need to, even being able to an accessory to push a database or other service.

Other things to consider when running your own VPS:

© 2024 Timney.