Configuring Subdomains Made Easy with Kamal

Nicolás Galdámez
Unagi
Published in
3 min readApr 12, 2024
Configuring Subdomains Made Easy with Kamal — freepik Illustration

Until recently, deploying a dockerized application seemed like a daunting task. Fortunately, this has changed thanks to Kamal, a tool specifically designed to streamline the deployment of web applications through a simple yet efficient workflow.

At Unagi, we’ve been “Kamalizing” some of our developments for a couple of months now, and so far, we’ve had a great experience.

But even with recent improvements, the official docs are still not clear. So, we have to rely on articles or content shared by the community.

To contribute our two cents, today I’m going to share something I haven’t found much information about: how to serve the application from a specific domain (e.g., example.com) and with the subdomain www (e.g., www.example.com).

Disclaimer: I assume you know what Kamal is and are familiar with the basics of its configuration.

Let’s assume we have a system built with Ruby on Rails that is already deployed on Hetzner/Digital Ocean or any preferred server. It’s likely that we have a configuration like this in the deploy.yml file:

service: messi

image: messigoat/web

servers:
web:
hosts:
- <%= ENV['WEB_IP'] %>
labels:
traefik.http.routers.messi-web.rule: Host(`messigoat.com`)
traefik.http.routers.messi-web.tls: true
traefik.http.routers.messi-web.tls.certresolver: letsencrypt

# Other configurations like builder, volumes, etc
# ...

traefik:
options:
publish:
- "443:443"
volume:
- "/letsencrypt/acme.json:/letsencrypt/acme.json"
args:
entryPoints.web.address: ":80"
entryPoints.websecure.address: ":443"
entryPoints.web.http.redirections.entryPoint.to: websecure
entryPoints.web.http.redirections.entryPoint.scheme: https
entryPoints.web.http.redirections.entrypoint.permanent: true
certificatesResolvers.letsencrypt.acme.email: "you@mail.com"
certificatesResolvers.letsencrypt.acme.storage: "/letsencrypt/acme.json"
certificatesResolvers.letsencrypt.acme.httpchallenge: true
certificatesResolvers.letsencrypt.acme.httpchallenge.entrypoint: web

With this configuration, we establish a web role where we specify the application’s domain and designate Let’s Encrypt to serve the certificate. In the Traefik configuration, we set up a redirection to ensure the application is consistently accessed via HTTPS, along with the necessary parameters to generate the certificate.

When we deploy and access messigoat.com, the application runs smoothly. However, the challenge arises when attempting to access www.messigoat.com because we’ve solely defined messigoat.com as the domain for the application.

To fix this, we just need to adjust the Traefik setup to handle requests for both messigoat.com and www.messigoat.com. This usually means setting up a rule to handle requests for both the main domain and the www subdomain, making sure that both are covered by the SSL certificate.

To achieve this, two very simple actions are necessary:

  1. Create a DNS record that points to the same IP as the main domain. This can be done from the platform where you manage DNS records.
  2. Add the subdomain configuration to Traefik configuration inside the deploy.yml file.

Here, we’re just gonna talk about the second item because for the first one you can easily find hundred of resources on how to do it. You’ll see that the changes are pretty simple. But because there isn’t much documentation, it took a lot of trial and error to make the changes I'm showing.

The first thing we need to do is add our subdomain as a rule of the web role. To do this, we replace the value of the key traefik.http.routers.messi-web.rule with the following:

traefik.http.routers.messi-web.rule: Host(`messigoat.com`) || Host(`www.messigoat.com`)

And then we must define a primary and secondary domain in the Traefik configuration:

traefik:
...
args:
...
entrypoints.websecure.http.tls.domains[0].main: "messigoat.com"
entrypoints.websecure.http.tls.domains[0].sans: "www.messigoat.com"
...

Done! With these changes, the next deployment will create the corresponding certificate, and the application will be accessible with or without the www subdomain.

I hope you found this information useful and that it saved you time on your Kamal configuration. Please let me know if you have any alternatives or suggestions.

Unagi is a software boutique that offers software development services in Ruby on Rails, a stack we still choose after +12 years. Check out more on our social media.

--

--

Nicolás Galdámez
Unagi
Editor for

Co-fundador de @unagi. Me gusta el cine, la lectura, y la ensalada de frutas.