Epidemiology & Technology

Traefik Reverse Proxy 2.10.3

Running the traffic reverse proxy led to some issues with iFrames. Further there were issues due to depreciated settings in configuration..yml. There I have updated the configurations as follows

traefik docker-compose.yml

version: "3.3"

services:
  traefik5:
    image: "traefik:2.10.3"
    container_name: "traefik5"
    restart: "always"
    command:
      - "--global.sendAnonymousUsage"
        #- "--log.level=DEBUG"
      - "--log.filePath=/var/log/traefik.log"
      - "--accesslog=true"
      - "--accesslog.filePath=/var/log/access.log"
      - "--accesslog.bufferingsize=100"
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.file.directory=/configuration"
      - "--providers.file.filename=dynamic_conf.toml"
      - "--providers.file.watch=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
        #- "--certificatesresolvers.mytlschallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.mytlschallenge.acme.email=xxx@yahoo.com"
      - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
    volumes:
      - logs:/var/log
      - "./letsencrypt:/letsencrypt"
      - "./configuration:/configuration"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    networks:
      - web
    ports:
      - 80:80
      - 443:443

networks:
  web:
    external: true

volumes:
  logs: {}
Code language: PHP (php)

Dynamic Configuration TOML

[http]

  [http.routers.my-api]
    entryPoints = ["websecure"]
    rule = "Host(`monitor.epidemiology.tech`)"
    service = "api@internal"
    middlewares = ["secured"]
    [http.routers.my-api.tls]
      options = "default"
      certResolver = "mytlschallenge"

  [http.middlewares]

    [http.middlewares.secured.chain]
      middlewares = ["safe-ipwhitelist", "auth"]

    [http.middlewares.secureHeader]
      [http.middlewares.secureHeader.headers]
        frameDeny = true
        stsSeconds = 31536000
        stsPreload = true
        stsIncludeSubdomains = true
        browserXssFilter = true
        contentTypeNosniff = true
        forceSTSHeader = true
        contentSecurityPolicy = "frame-ancestors 'self'"
        isDevelopment = false
        customFrameOptionsValue = "SAMEORIGIN"

    [http.middlewares.httpsRedirect]
      [http.middlewares.httpsRedirect.redirectScheme]
        scheme = "https"
        permanent = true

    [http.middlewares.compression]
      [http.middlewares.compression.compress]
        excludedContentTypes = ["text/event-stream"]
        minResponseBodyBytes = 1200

    [http.middlewares.auth.basicAuth]
      users = [
        "Ssssssss:$XXXXXxxxxxxxxxxxxx"
      ]

    [http.middlewares.safe-ipwhitelist.ipWhiteList]
      sourceRange = ["XX.XX.XX.XX/24", "YYY.YYY.YYY.YYY/24", "ZZZ.ZZZ.ZZZ.ZZZ/24"]


[tls]
  [tls.options]
    [tls.options.default]
      minVersion = "VersionTLS12"
      cipherSuites = [
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
        "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
      ]

Code language: PHP (php)

The Key changes

  • SSLredirect has been removed from secureHeader.headers as it is depreciated
  • added a new http middleware called httpsRedirect
  • Added a new  http middleware called compression which enables gZip compress on response
  • Added following to headers middleware
    •  contentSecurityPolicy = “frame-ancestors ‘self'”
      • based on MDN . The HTTP Content-Security-Policy (CSP)  frame-ancestors allows use to specify what parent source may embed a page using <frame><iframe><object>, or <embed>.
      • This enables page-preview in page builders to work where iFrame is being used.
      • 'self' refers to the origin from which the protected document is being served, including the same URL scheme and port number.
    •   isDevelopment = false
    •   customFrameOptionsValue = “SAMEORIGIN”
      • The customFrameOptionsValue allows the X-Frame-Options header value to be set with a custom value.
      • SAMEORIGIN ensures that the page can only be displayed if all ancestor frames are same origin to the page itself.
      •  The Content-Security-Policy HTTP header has a frame-ancestors directive which obsoletes this header for supporting browsers. We are adding the CSP header but this one is being added also for older browsers

Using the middleware in a WordPress container


version: "3"

services:
  newDomain:
    image: wordpress:6.2.2-php8.2-apache
    environment:
      WORDPRESS_DB_HOST: dbWP
      WORDPRESS_DB_USER: XXXXXXXX
      WORDPRESS_DB_PASSWORD: XXXXXXXXXXX
      WORDPRESS_DB_NAME: XXXXXXXXX
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.middlewares.newDomain-https.redirectscheme.scheme=https"
      - "traefik.http.routers.newDomain-http.entrypoints=web"
      - "traefik.http.routers.newDomain-http.rule=Host(`newDomain.com`, `www.newDomain.com`)"
      - "traefik.http.routers.newDomain-http.middlewares=newDomain-https@docker"
      - "traefik.http.routers.newDomain.middlewares=secureHeader@file, compression@file, httpsRedirect@file"
      - "traefik.http.routers.newDomain.entrypoints=websecure"
      - "traefik.http.routers.newDomain.rule=Host(`newDomain.com`, `www.newDomain.com`)"
      - "traefik.http.routers.newDomain.tls=true"
      - "traefik.http.routers.newDomain.tls.options=default"
      - "traefik.http.routers.newDomain.tls.certresolver=mytlschallenge"

#      Create a middleware named `customCors` for CORS headers
#      - "traefik.http.middlewares.customCors.headers.accesscontrolalloworiginlist=https://newDomain.com, https://www.newDomain.com"
#      Apply the  middleware named `customCors` to the router named `newDomain`      
#      - "traefik.http.routers.newDomain.middlewares=customCors"

#     Apply the common TRAEFIC2 configuration file  middleware named `dataCompress` for gZip to the router named `newDomain`
#      - "traefik.http.routers.newDomain.middlewares=test-compress@file"


    volumes:
      - ./newDomain/wordpress_files:/var/www/html
      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    networks:
      - internal
      - web

networks:
  web:
    external: true
  internal:
    external: true

Code language: PHP (php)

Folder structure for WordPress container

├── docker-compose.yml
├── newDomain
│   └── wordpress_files
└── uploads.iniCode language: CSS (css)

uploads.ini

file_uploads = On
memory_limit = 512M
upload_max_filesize = 2M
post_max_size = 2M
max_execution_time = 60

Database Container

version: "3"

services:
  dbWP:
    image: mariadb:10.5
    environment:
#      MYSQL_USER: XXXXXXXXXXXXXXXXXXXXXXXX 
#      MYSQL_PASSWORD: XXXXXXXXXXXXXXXXXXXX
#      MYSQL_DATABASE: XXXXXXXXXXXXXXXX
       MYSQL_RANDOM_ROOT_PASSWORD: '1'
    networks:
      - internal
    labels:
      - traefik.enable=false
    volumes:
      - ./datadir:/var/lib/mysql

networks:
  web:
    external: true
  internal:
    external: trueCode language: PHP (php)

Refer to steps in my first post about how to know your mySQL root password the first time the container is created, and how to create databases and users for WordPress sites using terminal.

docker ps -a
docker logs dbContainerName | grep password

# CREATE DATABASE AND USER FOR WORDPRESS
docker inspect logs dbContainerName | grep  IPA
# Note the IP address
mysql -u root -h XXX.XXX.XX.XX -p
# Enter the root password to reach the database shell >
CREATE USER 'MariaDbUser'@'%' IDENTIFIED BY 'MariaDbUserPassword';
GRANT ALL ON blog1.* TO 'username'@'%';  
flush privileges;
Code language: PHP (php)

Adminer Container

This is a GUI web interface which can be used to manage the database. It is working as a subdomain which needs to be created in the DNS settings of the hosting provider. Normally, the container must be switched off. Switch it on only when needed. A few minutes of effort are well worth the safety gained.

version: '3'

services:
  adminer:
    image: adminer:latest
    container_name: adminer2023
    security_opt:
      - no-new-privileges:true
    environment:
      ADMINER_DEFAULT_SERVER: dbWP
      ADMINER_PLUGINS: 'tables-filter tinymce'
      ADMINER_DESIGN: galkaev
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=web"
      - "traefik.http.middlewares.adminer-https.redirectscheme.scheme=https"
      - "traefik.http.routers.adminer-http.entrypoints=web"
      - "traefik.http.routers.adminer-http.rule=Host(`adminer.newDomain.com`)"
      - "traefik.http.routers.adminer-http.middlewares=adminer-https@docker"
      - "traefik.http.routers.adminer.middlewares=secureHeader@file"
      - "traefik.http.routers.adminer.entrypoints=websecure"
      - "traefik.http.routers.adminer.rule=Host(`adminer.newDomain.com`)"
      - "traefik.http.routers.adminer.tls=true"
      - "traefik.http.routers.adminer.tls.options=default"
      - "traefik.http.routers.adminer.tls.certresolver=mytlschallenge"
      - "traefik.http.services.adminer.loadbalancer.server.port=8080"
    networks:
      - internal
      - web

networks:
  web:
    external: true
  internal:
    external: trueCode language: JavaScript (javascript)

Container recreation when testing the Traefik/wordpress/adminer containers

docker-compose down
docker-compose pull
docker-compose up --build -d
docker-compose up -d

Working with containers using terminals

executing bash commands inside containers

docker exec -it dbContainerName bash

 View the enabled Modules
apache2ctl -M
# View the prefork module settings
cat /etc/apache2/mods-enabled/mpm_prefork.conf
# https://www.jeffgeerling.com/blog/3-small-tweaks-make-apache-fly
# Apache thread memory consumption
ps aux | grep 'httpd' | awk '{print $6/1024 " MB";}'
ps aux | grep 'httpd' | awk '{print $6/1024;}' | awk '{avg += ($1 - avg) / NR;} END {print avg " MB";}'Code language: PHP (php)

Copying and editing files inside containers

# From container to Host and Edit
docker cp dbContainerName:/etc/apache2/apache2.conf .
cp apache2.conf apache2.conf.default
nano apache2.conf 

# From host to container
docker cp apache2.conf dbContainerName:/etc/apache2/apache2.conf

# From container to Host and Edit
docker cp dbContainerName:/etc/apache2/mods-available/mpm_prefork.conf .
cp mpm_prefork.conf mpm_prefork.conf.default
nano mpm_prefork.conf  
cp mpm_prefork.conf dbContainerName:/etc/apache2/mods-available/mpm_prefork.confCode language: PHP (php)

Related posts