Skip to main content

Securing Traefik with Let's Encrypt


Building on the previous Traefik setup with an internal domain and applications, this tutorial guides you through using a public domain with trusted certificates.


The core objectives of this tutorial are to:
  1. Deploy Traefik with Automatic SSL using Docker: This step covers installing the latest Traefik with Let's Encrypt integration and exposing the container to the internet.
  2. Configure DNS for Secure Access: Set up an A record in your domain provider (e.g., Cloudflare) pointing to your pfSense firewall's public IP address for external access and pfsense's DNS server for internal access.
  3. Access Applications with HTTPS: Access your applications using their fully qualified domain names with trusted certificates externally and internally


Lets walk through our topology:


This is our firewall which is directly connected to the Internet and doing the following:

  1. NATs all traffic from the internal LAN network ( to the WAN (internet).
  2. Runs a DNS Resolver to resolve hostnames for your applications. This is needed to access the application internally.
  3. We have permitted inbound ports TCP 80 and 443 on the pfSense firewall to our Ubuntu server ( running docker

Ubuntu Server

Our PC is running Ubuntu 22.04 release. Docker and docker compose have been installed. This is where we will run traefik and all the apps

  • Windows PC

  • This PC is used to install and configure Traefik (SSH in to the Ubuntu server) and for testing.

  • Access Flow

From a Windows PC, we'll open a browser and navigate to Since pfSense is our DNS server, this URL will resolve to the Ubuntu server's IP address. Traefik, exposed on ports 80 and 443, will handle the requests. It will automatically route them to the appropriate containers based on the domain name
Note: You will need to replace with your publicly registered domain.


  1. You have a public domain registered.
  2. An installation of docker and docker-compose. We will be running docker on Ubuntu 22.04

DNS Configuration

pfsense Configuration

We need our DNS server to resolve * to our Ubuntu server. So will resolve to our Ubuntu server IP address

In pfsense navigate to:
  1. Services --> DNS Resolver --> General Settings
  2. Enable DNS Resolver
  3. Scroll down and Display Customer Options and past the following config
 local-zone: "" redirect
 local-data: " 3600 IN A"
The windows PC and ubuntu server are configured to use pfsense ( as the DNS server. If we ping it should resolve to our Ubuntu server and ping successfully
 PING ( 56(84) bytes of data.
 64 bytes from pserver ( icmp_seq=1 ttl=64 time=0.032 ms
 64 bytes from pserver ( icmp_seq=2 ttl=64 time=0.089 ms
 64 bytes from pserver ( icmp_seq=3 ttl=64 time=0.109 ms

Cloudflare Configuration

If you are using a different provider, please follow their instructions
  • Navigate to you domain in Cloudflare
  • Navigate to DNS --> Records and Click on Add Record
  • Enter the following
    • Type: A
    • Name: *
    • IPv4: Public IP of your Internet provider at home
    • Proxied: Disable it
Note: While at home, go to to get your public IP

Configure and Install Traefik

Create a directory to store the docker files and traefik config files 

 mkdir traefik
 cd traefik

Create a docker-compose.yml file using an editor of your choice

 vim docker-compose.yml
Paste the following config in docker-compose.yml
version: "3.3"
    container_name: traefik
    image: traefik:latest # Download traefik
    restart: always # Restart the container if stops
      - 443:443 # Expose port 443 on the host machine
      - 80:80 # Expose port 80 on the host machine
    command: # Static file is not required if using commands
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entryPoint.scheme=https
      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.forwardedheaders.insecure=true
      - --serverstransport.insecureskipverify=true 
      - --log.level=DEBUG
      - --api=true
      - --api.insecure=true
      - --api.dashboard=true
      - --api.debug=true
      - --entrypoints.websecure.http.tls.certResolver=letsencrypt
      # It is recommended you uncomment the next line and try out if you get the trusted certs. Once verifed, you can comment it and restart the container
      #- --certificatesresolvers.letsencrypt.acme.caserver=
      - --certificatesresolvers.letsencrypt.acme.dnschallenge=true
      - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare
      - --certificatesResolvers.cfresolver.acme.dnsChallenge.resolvers=,
      - cf_email
      - cf_api
      # you may choose to use secrets instead of environment variables like this
      CF_API_EMAIL_FILE: /run/secrets/cf_email
      CF_API_KEY_FILE: /run/secrets/cf_api 
      - /var/run/docker.sock:/var/run/docker.sock # Allow Traefik access to docker API's to dynamically learn applications
      - ./certs:/letsencrypt
      # Traefik uses lables to learn about containers and dynamically configures itself. Expose the traefik dashboard on port 443
      traefik.enable: true
      traefik.http.routers.traefik.tls: true
      traefik.http.routers.traefik.rule: Host(``)
      traefik.http.routers.traefik.entrypoints: websecure
      traefik.http.routers.traefik.service: api@internal
      traefik.http.routers.traefik.tls.certresolver: letsencrypt
        # Use the custom network web that is defined below
      - web
    file: ./secrets/cf_email.secret
    file: ./secrets/cf_api.secret

Create a secrets folder with secret files within the traefik folder

Replace your_cloudflare_email with the email used to sign in to Cloudflare and your_cloudflare_api with the API key can be obtained by:
  • Navigating to your Cloudflare account
  • Click on your profile
  • Select API tokens from the left navigation pane
  • Get the Global API Key
 mkdir secrets
 cd secrets
 echo "your_cloudflare_email" >> cf_email.secret
 echo "your_cloudflare_api" >> cf_api.secret

Start Traefik

docker-compose up -d
The aforementioned command will pull the traefik image and start the container. The traefik dashboard should be reachable via 

Configure and Install Homer

Create a folder called homer your home path
 mkdir homer
 cd homer

Create a docker-compose.yml file using an editor of your choice

 vim docker-compose.yml
Paste the following config in docker-compose.yml
version: "3.5"
    image: b4bz/homer
    container_name: homer1
      - ./assets/:/www/assets
    restart: unless-stopped
    labels: # auto-detects port 80 in next line
      traefik.enable: true
      traefik.http.routers.homer1.tls: true
      traefik.http.routers.homer1.rule: Host(``)
      traefik.http.routers.homer1.tls.certresolver: letsencrypt
      traefik.http.routers.homer1.entrypoints: websecure
      traefik.http.routers.homer1.service: homer1-svc 8080      
      - traefik_web
    external: true


Success! Traefik is deployed with secure Let's Encrypt certificates. This allows you to enjoy secure access to your applications from anywhere, whether on the internet or your home network.


Popular posts from this blog

Traefik Install and configuration - Part 1

Introduction In this tutorial we are going to install and configure Traefik Proxy . As quoted on their website "Traefik is a leading modern reverse proxy and load balancer that makes deploying microservices easy. Traefik integrates with your existing infrastructure components and configures itself automatically and dynamically." All our applications will be front-ended by traefik. Objective The core objective for this tutorial is to: Configure an A record in our DNS server (pfsesne firewall) to point to our traefik proxy Configure and install Traefik in docker Configure and install two http based applications ( homer and heimdall ) in docker that will be accessed via traefik Topology The above image represents our topology. Our pfsense firewall is connected directly to the Internet and is NAT'ing all traffic from the internal network to the outside world. We have a single LAN segment ( defined on pfsense and we have the following two PC's connected d

Run your Meteor App on a Production Ubuntu 16.04 Server with Nginx

Introduction Meteor enables developers to create apps and quickly test them on a development webserver. Once you have created your app the big question is how to run it on a production server. In this tutorial we will demostrate how to run your Meteor app on Ubuntu 16.04 using Nginx Credits and Acknowledgements This entire post is based off this Digital Ocean article. The article was modified for issues we encountered and adapted for Ubuntu 16.04. The entire credit goes to Daniel Speichert Objective In this tutorial we will: Install and Configure Nginx with HTTPS enabled Install MongoDB Install NodeJS Bundle your Meteor App Create a startup script to automatically start your app on reboot Assumptions We assumue the following: You already have a fresh install of Ubuntu 16.04 Server SSH enabled on your fresh install You have root privelages on your server You have a different server where you can insall meteor and budle your app

Installing Zurmo on Ubuntu Sever 14.10

Introduction Zurmo is an Open Source Customer Relationship Management (CRM) application that is mobile, social, and gamified. It can be used to: Create and Track Project progress Create Customer Accounts Tasks - Associate Tasks to Accounts and/or Projects Customize fields of Tasks, Accounts etc. Generate Reports etc. Objective The final objective is to install Zurmo 2.8.5 on Ubuntu Server 14.10 Assumptions Fresh Install of Ubuntu Server 14.10 SSH enabled (sudo apt-get install ssh-server) User has sudo or root privileges Step 1: Install the Apache Webserver sudo apt-get install apache2 -y Step 2: Install MySQL Server sudo apt-get install mysql-server -y Step 3: Install PHP5 sudo apt-get install php5 -y sudo apt-get install php5-mysql -y sudo apt-get install php5-memcache -y sudo apt-get install php5-curl -y sudo apt-get install php-apc -y sudo apt-get install php-soap -y sudo apt-get install php5-imap -