I recently wrote an article about how I do deployments with Kamal, which included setting up SSL for your domain and redirecting from non-ssl to ssl. In this article, I want to go further and show you how I redirect from www to non-www.
In the config
folder, I have 3 yaml files: deploy.yml
, deploy.development.yml
, and deploy.production.yml
.
deploy.yml
contains the shared configuration across environments. Then, in each deploy.*.yml
, I add the specifics for each environment, such as the server IP address, different domain names, etc.
# config/deploy.yml
# Name of your application.
service: my_app
image: username/image_name
registry:
# Specify the registry server
username: registry_username
password:
- KAMAL_REGISTRY_PASSWORD
env:
clear:
HOSTNAME: your_hostname
secret:
- KAMAL_REGISTRY_PASSWORD
- add_any_other_secrets_here
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: "your_email_address"
certificatesResolvers.letsencrypt.acme.storage: "/letsencrypt/acme.json"
certificatesResolvers.letsencrypt.acme.httpchallenge: true
certificatesResolvers.letsencrypt.acme.httpchallenge.entrypoint: web
# add this if you are using a different route and port than kamal's defaults
healthcheck:
path: /
port: 1234
Before you begin the deployment process for the first time, remember to create the necessary folders and Docker network:
Setup the directory for Let's encrypt
mkdir -p /letsencrypt && touch /letsencrypt/acme.json && chmod 600 /letsencrypt/acme.json
create a Docker network called
private
docker network create -d bridge private
The reason we're using a Docker private network is that when you open a port in Kamal, it becomes accessible to everyone. This happens because Docker automatically adds it to the iptables firewall.
Now let's see how config.development.yml
looks like:
servers:
web:
hosts:
- put_your_deployment_server_ip_address_here
labels:
traefik.http.routers.devproject_secure.entrypoints: websecure
traefik.http.routers.devproject.rule: Host(`your_domain.tld`) || Host(`www.your_domain.tld`)
traefik.http.routers.devproject_secure.rule: Host(`your_domain.tld`) || Host(`www.your_domain.tld`)
traefik.http.routers.devproject_secure.tls: true
traefik.http.routers.devproject_secure.tls.certresolver: letsencrypt
traefik.http.routers.devproject_secure.middlewares: redirect-to-non-www
traefik.http.middlewares.redirect-to-non-www.redirectregex.regex: ^https?://www.your_domain.tld/(.*)
traefik.http.middlewares.redirect-to-non-www.redirectregex.replacement: https://your_domain.tld/$1
traefik.http.middlewares.redirect-to-non-www.redirectregex.permanent: true
builder:
multiarch: false
Accepting traffic from domain and subdomain
To accept traffic from both the www subdomain and our main domain in our router, we can simply use ||
(OR) to include both hosts. By doing this, we'll accept incoming traffic from both and also obtain an SSL certificate for them.
Middlewares
traefik.http.routers.devproject_secure.middlewares: redirect-to-non-www
We hook up a new middleware caled: redirect-to-non-www
to our devproject_secure
router.
Regex middleware to redirect www to non-www
traefik.http.middlewares.redirect-to-non-www.redirectregex.regex: ^https?://www.your_domain.tld/(.*)
traefik.http.middlewares.redirect-to-non-www.redirectregex.replacement: https://your_domain.tld/$1
traefik.http.middlewares.redirect-to-non-www.redirectregex.permanent: true
This part is straightforward: we specify the regex expression, define the replacement, and enable 301 redirects by setting it to true
.
Now, you can deploy your app (or update your configuration), but don't forget to run kamal traefik reboot
every time you change Traefik settings.
I began using Traefik when I started deploying with kamal, and I'm currently learning about what it can do and how.