Skip to main content

Securing Traefik with Let's Encrypt

Introduction

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

Objective

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

Topology


Lets walk through our topology:

pfsense

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

  1. NATs all traffic from the internal LAN network (192.168.11.0/24) 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 (192.168.11.2) 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 https://homer.mydomain.com. 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 mydomain.com with your publicly registered domain.

Assumptions

  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 *.mydomain.com to our Ubuntu server. So homer.mydomain.com will resolve to our Ubuntu server IP address 192.168.11.2

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
 server:
 local-zone: "mydomain.com" redirect
 local-data: "mydomain.com 3600 IN A 192.168.11.2"
The windows PC and ubuntu server are configured to use pfsense (192.168.11.1) as the DNS server. If we ping homer.mydomain.com it should resolve to our Ubuntu server and ping successfully
 ping homer.mydomain.com
 PING homer.mydomain.com (192.168.11.2) 56(84) bytes of data.
 64 bytes from pserver (192.168.11.2): icmp_seq=1 ttl=64 time=0.032 ms
 64 bytes from pserver (192.168.11.2): icmp_seq=2 ttl=64 time=0.089 ms
 64 bytes from pserver (192.168.11.2): 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 https://www.whatismyip.com/ 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"
services:
  traefik:
    container_name: traefik
    image: traefik:latest # Download traefik
    restart: always # Restart the container if stops
    ports:
      - 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.to=websecure
      - --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
      - --entrypoints.websecure.http.tls.domains[0].main=mydomain.com
      - --entrypoints.websecure.http.tls.domains[0].sans=*.mydomain.com
      # 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=https://acme-staging-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.letsencrypt.acme.email=your_cloudflare_email
      - --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.letsencrypt.acme.dnschallenge=true
      - --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare
      - --certificatesResolvers.cfresolver.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53
    secrets:
      - cf_email
      - cf_api
    environment:
      # 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 
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock # Allow Traefik access to docker API's to dynamically learn applications
      - ./certs:/letsencrypt
    labels:
      # 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.mydomain.com`)
      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
    networks:
      - web
networks:
  web:
secrets:
  cf_email:
    file: ./secrets/cf_email.secret
  cf_api:
    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 https://traefik.mydomain.com 

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"
 
services:
  homer1:
    image: b4bz/homer
    container_name: homer1
    volumes:
      - ./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(`homer1.mydomain.com`)
      traefik.http.routers.homer1.tls.certresolver: letsencrypt
      traefik.http.routers.homer1.entrypoints: websecure
      traefik.http.routers.homer1.service: homer1-svc
      traefik.http.services.homer1-svc.loadBalancer.server.port: 8080      
    networks:
      - traefik_web
networks:
  traefik_web:
    external: true

Conclusion

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.

Comments

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 (192.168.11.0/24) 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

Part 1- Install Django using Virtualenv, Apache and MySQL on Ubuntu Server 14.10

Introduction I have been using Microsoft Excel to do my Personal Budget. Excel is extremely powerful and has fulfilled my needs. But I always wanted to build a web application which is accessible via a browser and in order to do so we need the following: An admin interface (website) to plug in my expenses A database to store all the entries Code to parse the database and calculate the expenses per month A public interface (website) to display expense charts After browsing the web I stumbled across Django. Django (as copied from the project page) is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. It focuses on automating as much as possible and adhering to the DRY principle. In the first part of this tutorial we will walk through the installation of Django using Virtualenv. In the following series we will build our Personal Budget application using Django. What is virtualenv and why use it? Virtualenv (as copied from th