Migrating From Dokku to Kamal: Setting up the Servers
This is the second post of the series "Migrating From Dokku to Kamal" and today I am gonna show you how I've set up my servers with Kamal, click here to read the first post of the series in case you've missed it.
Below you can find part of my final deploy.yml
:
It does a couple of things:
- reads the env vars
KAMAL_WEB_IP
,KAMAL_WORKER_IP
andPOSTGRES_HOST
from the.env
file that were defined with Terraform (as shown on the other post) - defines three servers:
web
,worker
anddb
(which is underaccessories
) - sets Let's Encrypt as certificate resolver for the
web
server - overrides the command to be executed on the Docker container for the
worker
server, it'll runbin/run-worker.sh
instead - sets GitHub as image registry, it's for free
- sets env vars.
PIDFILE=/dev/null
tells Rails to not save pid files as you might receive the errorA server is already running. Check /rails/tmp/pids/server.pid
in case docker gets killed abruptly. This will be the default behaviour as of Rails 8. Check this post for more info. - speeds up the build time by disabling
multiarch
since both my local machine and the servers run on the arm64 architecture - sets up a container on the
db
server to backup the Postgres database once a day using postgres-backup-s3
Resolving Let's Encrypt ACME v2 challenge
As my domain has Cloudflare as DNS resolver and I wanted to support wildcard certificates - so I could test my app at kamal.domain.com
before switching from Digital Ocean to Hetzner on domain.com
, the web server is solving Let's Encrypt ACME v2 challenge through DNS (thanks Nick for sharing it), that's why I had to define the extra args for traefik
(including CLOUDFLARE_EMAIL
and CLOUDFLARE_API_KEY
).
Note we are storing the certificate on the file we created with Terraform: /letsencrypt/acme.json
. This way we don't need to regenerate a new certificate every time a new web
container is run.
That's it for today, in the last post of the series I share how I've set up cron to run scheduled tasks.