Securing your blog with Traefik and LetsEncrypt
This post demonstrates how to use Traefik and LetsEncrypt to obtain a free TLS certificate. Traefik enables us to make the blog accessible securely on the public internet, even if it is running on a private network.
I recently launched my blog, which is powered by Ghost and Docker. I wrote a post about it; you can read it here:
If you have not set it up then make sure you read the post first and set up your blog. Today I will be extending that post to add two new features to the blog.
- To make the blog visible on the public internet
- To make sure the blog is secure with a TLS certificate
We need a domain name for our blog where we want our blog to be accessible. We can purchase one from a provider such as Name.com or NameCheap.com. Alternatively, we can sign up for a free dynamic DNS provider such as NoIP.com. Any of these services will work, as long as we know how to set it up.
We will be using Traefik as a reverse proxy for the blog. Traefik can also help us get a free LetsEncrypt TLS certificate, which will help create an encrypted connection between our website and the reader's browser. This ensures that the communication between the two is secure and private. A secure connection is indicated by a lock icon next to the address bar in the browser, giving readers the assurance that their data is safe and secure. This is especially important in today's digital landscape, and having a trusted certificate is a great way to be sure our readers have the best possible experience.
To achieve this, let's extend the docker-compose.yaml
file to add these features.
version: "3"
services:
ghost_database:
image: mysql:8-debian
container_name: ghost_database
restart: unless-stopped
volumes:
- type: bind
source: /path/to/database
target: /var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=password
ghost:
image: ghost:5-alpine
container_name: ghost
restart: unless-stopped
depends_on:
- ghost_database
volumes:
- type: bind
source: /path/to/content
target: /var/lib/ghost/content
environment:
database__client: mysql
database__connection__host: ghost_database
database__connection__user: root
database__connection__password: password
database__connection__database: ghost
url: https://your.domain.com
labels:
- "traefik.enable=true"
- "traefik.http.routers.blog.rule=Host(`your.domain.com`)"
- "traefik.http.routers.blog.entrypoints=websecure"
- "traefik.http.routers.blog.tls.certresolver=myresolver"
- "traefik.http.services.blog.loadbalancer.server.port=2368"
traefik:
image: "traefik:v2.9"
container_name: "traefik"
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
- "[email protected]"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "443:443"
- "80:80"
volumes:
- type: bind
source: /path/to/letsencrypt
target: /letsencrypt
- type: bind
source: /var/run/docker.sock
target: /var/run/docker.sock
read_only: true
This is the complete docker-compose.yaml
file you will need. As you can see, we have added another service in our configuration file that uses Traefik. Traefik is exposing two ports: 443
and 80
. Port 80
is used by the HTTP protocol, which is not secure. Port 443
is used by HTTPS, which is secure. To use HTTPS, we need a TLS certificate. To store the certificate, create a new directory named letsencrypt
and add it to the volumes in docker-compose.yaml
under the new service we created.
To configure the domain name, find the IP address of the computer where you want to host your blog. If you have a dynamic IP, you can use a dynamic DNS service, which I mentioned before. Set the IP address of the computer in your DNS provider with the domain name that will be used to access your blog. For example, if your domain is your.domain.com, set the IP address against your domain name. For more information, contact your domain name provider or your dynamic DNS service provider.
To configure the domain and TLS certificate for your domain name, add the following labels to the Ghost service.
...
labels:
- "traefik.enable=true"
- "traefik.http.routers.blog.rule=Host(`your.domain.com`)"
- "traefik.http.routers.blog.entrypoints=websecure"
- "traefik.http.routers.blog.tls.certresolver=myresolver"
- "traefik.http.services.blog.loadbalancer.server.port=2368"
...
Make sure you replace the domain (your.domain.com
) with a working one in both the ghost service url
environment variable and in labels for Traefik service.
Run docker-compose up -d
in your terminal to start all three services. If there are no errors, Traefik will get a TLS certificate for your domain name and make your blog accessible securely when you browse it.
Navigate to https://your.domain.com
(note the https
) in your browser. You will see a lock icon next to your address bar, confirming your connection is secure.
Now your ghost blog is running securely and is publicly available. You can share it with your friends and family and invite them to sign up and read your blog.