Reverse Proxy Server

Back  
 Next

Reverse Proxy Server

I seem to have gotten the Traefik reverse proxy working according to Techno Tim Put Wildcard Certificates and SSL on EVERYTHING (github reference_files for traefik-portainer-ssl). Also see Jim's Garage Your Traefik Isn't Secure (JimsGarage/Traefik-Secure/

Below is a basic description of the process that aligns with my configuration files. I do this for 2 reasons, both allowing me independence.

  1. Sometimes the source information or link are; changed, lost or removed.
  2. These note reference my current specific installation.

Proxy network to connect them all

These containers all talk via a docker bridge network named proxy, docker network create proxy

Traefik

  1. cd /home/docker_store
  2. sudo mkdir traefik
  3. sudo chown baumkp:baumkp traefik
  4. cd traefik
  5. mkdir data
  6. cd data
  7. touch acme.json
  8. chmod 600 acme.json
  9. touch traefik.yml
  10. cd ..

My traefik.yml locatation: /home/docker_store/traefik/data/traefik.yml. The current TechnoTim one here.

create docker network

  1. docker network create proxy
  1. touch docker-compose.yml
  2. touch provider.env

My docker-compose.yml location: /home/docker_store/traefik/docker-compose.yml. The current TechnoTim one here.
Note my docker compose file has some changes from the TechnoTim one, in particular the use of the Godaddy DNS chanlenge API instead of the the Cloudflare one used by TechnoTim.

Generate and Install Godaddy DNS Challenge Data

Godaddy changed their policies circa April 2024 that basically does not give small users access to their developers API system. Sadly and unprofessionally they did this without informing users of the policy. I only found out when my proxy server issued messages of certificate update failure, as the API DNS challenge stopped working. I checked the internet and it was indicated that Godaddy had changed their policies, however I found it difficult to believe that Godaddy would change their policy without contacting me, after all I am a paying customer! After raising a ticket on the matter, I was sent an email explaining the policy change. I immediately moved my domain DNS server to Hurricane Electronics. I needed to change the DNS verification process to suit that used by Hurricane Electronics.

My domain is still registered via Godaddy, I expect that I will look at moving to another registry when the registration comes due. I do not wish to support Godaddy going forward with my business. Godaddy SUCKS!

Old, tl;dr;

Generate and install Basic Authentication Password

  1. sudo apt update
  2. sudo apt install apache2-utils
  1. echo $(htpasswd -nb "<USER>" "<PASSWORD>") | sed -e s/\\$/\\$\\$/g

NOTE: Replace <USER> with your username and <PASSWORD> with your password to be hashed.

Paste the output in your docker-compose.yml in line (traefik.http.middlewares.traefik-auth.basicauth.users=<USER>:<HASHED-PASSWORD>)

  1. cd data
  2. touch config.yml
  1. docker-compose up -d

Portainer

  1. cd /home/docker_store
  2. sudo mkdir portainer
  3. sudo chown baumkp:baumkp portainer
  4. cd portainer
  5. touch docker-compose.yml
  6. mkdir data

My docker-compose.yml location: /home/docker_store/portainer/docker-compose.yml. The current TechnoTim one here.

  1. docker-compose up -d

Traefik Routes Config

Using labels in docker config files

Typical labels in Docker Compose

labels:
      # Enable Traefik for this service
      - "traefik.enable=true"
      # Tell Traefik to specifically use the network "proxy", specifically declared
      - "traefik.docker.network=proxy"
      # Make Traefik use this domain in HTTP
      - "traefik.http.routers.container_name.entrypoints=http"
      - "traefik.http.routers.container_name.rule=Host(`linkwarden.local.kptree.net`)"
      - "traefik.http.middlewares.container_name-https-redirect.redirectscheme.scheme=https"
      # Middleware to redirect HTTP to HTTPS
      - "traefik.http.routers.container_name.middlewares=linkwarden-https-redirect"
      # Make Traefik use this domain in HTTPS
      - "traefik.http.routers.container_name-secure.entrypoints=https"
      - "traefik.http.routers.container_name-secure.rule=Host(`linkwarden.local.kptree.net`)"
      - "traefik.http.routers.container_name-secure.tls=true"
      # Specify the specific resolver to use 
      #- "traefik.http.routers.container_name-secure.tls.certresolver=hurricane"
      - "traefik.http.routers.container_name-secure.service=linkwarden"
      - "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
      # Define the port inside of the Docker service to use
      - "traefik.http.services.container_name.loadbalancer.server.port=3000" # make sure the loadbalancer is the last line!! 

Using config.yml

  1. cd /home/docker_store/traefik/data
  2. nvim config.yml

I have broken down the Traefik router dynamic configuration file, My config.yml into 2 configuration files. One for the http/https specific router configuration and the other for the tcp router configuration, I do not use any UDP router configurations to date. I placed these files in the sub-directory: /home/docker_store/traefik/data/config. Traefik has been setup to look at all configuration files in this sub-directory and to dynamically update changes on the run. The current TechnoTim one here., also look at Portainer's instructions here: Deploying Portainer behind Traefik Proxy

  1. docker-compose up -d --force-recreate


Folder Structure:

./traefik
├── data
│   ├── acme.json         | This is the Lets Encrypt RSA key file downloaded by Traefik
│   ├── config
|   |   ├── http.yml      | This is the dynamic configuration file for http (want to separate into 2 smaller files, basic and main services)
|   |   └── tcp.yml       | This is the dynamic configuration file for tcp (not using at the moment, starttls is not supported by Traefik at this time)
│   ├── provider.env      | This has the key file for DNS wildcard challenge on LetsEncrypt 
│   ├── traefik.yml       | This is the main traefik static configuration file 
│   └── traefik.log       | This is the main traefik log file (permanent, but does not show up on the Docker error log)
└── docker-compose.yml

whitelisting

The Traefik middleware ipWhitelist only allows the define ip address(es) to be forwarded. All other address will have 403 forbidden returned.

ipWhitelist

BasicAuth

For any internal service I expose to the public internet that are either not full services with own password, e.g. dokuwiki, nextcloud and mail server, but I do not want general public access I would like to add basic password protection. This is built into the web server applications such as Apache and presumably Nginx, but Traefik also has some functionality.

The middleware BasicAuth seems to define this functionality. If I setup Gotify, that does not have an iOS client I can then use a public access webpage with password protection to check notifications. Unfortunately this is not active, in that it does not actively alert of new messages that presumably an app would do, but would probably meet my needs.

SSL Services

For TCP and HTTPS services behind the Traefik router that require TLS the Traefik router must be specified to pass through the TLS, that is not terminate the SSL connection.

Entrypoints

The Standard entry point port normally defined are HTTP (port 80 and perhaps 8080) and HTTPS (port 443). If you are using other services then additional entry points need to be defined, as required for each service / port. Mail servers are an example that requires use of specialised TCP entrypoints. Often these entry points also needed to be passed to the server without handling (termination) of SSL connections. Do not forget to expose the used ports in the Docker / Docker Compose file.

References

References

ssl certificates / openssl

Export Traefik certificates

#!/bin/bash
 
# Requirements: you will need to install jq and maybe openssl
 
# creates a directory for all of your certificates
mkdir -p certificates/
 
# reads the acme.json file, please put this file in the same directory as your script
json=$(cat acme.json)
 
export_cer_key () {
    echo $json | jq -r '.[].Certificates[] | select(.domain.main == "'$1'") | .certificate' | base64 -d > certificates/$1.cer
    echo $json | jq -r '.[].Certificates[] | select(.domain.main == "'$1'") | .key' | base64 -d > certificates/$1.key
}
 
export_pfx () {
        openssl pkcs12 -export -out certificates/$domain.pfx -inkey certificates/$domain.key -in certificates/$domain.cer -passout pass: 
}
 
read -p "Do you want to export as .pfx file as well [y]?" REPLY
 
# iterates through all of your domains
for domain in $(echo $json | jq -r '.[].Certificates[].domain.main')
do
    if [[ $REPLY =~ ^[Yy]$ ]]
    then
        export_cer_key "$domain"
        export_pfx "$domain"
    else
        export_cer_key "$domain"
    fi
done

There is also How to export certificates from Traefik certificate store in python.

Cloudsec

/app/www/public/data/pages/docker_notes/docker-reverse-proxy.txt · Last modified: 2024-12-22 Sun wk51 09:36
CC Attribution-Share Alike 4.0 International Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International