This is the docker-compose.yml file from the LXC 103
version: "3.9"
networks:
t2_proxy:
name: t2_proxy
driver: bridge
ipam:
config:
- subnet: 192.168.90.0/24
default:
driver: bridge
socket_proxy:
name: socket_proxy
driver: bridge
ipam:
config:
- subnet: 192.168.91.0/24
########################### SECRETS
secrets:
htpasswd:
file: $DOCKERDIR/secrets/htpasswd
cf_email:
file: $DOCKERDIR/secrets/cf_email
cf_api_key:
file: $DOCKERDIR/secrets/cf_api_key
cf_token:
file: $DOCKERDIR/secrets/cf_token
traefik_forward_auth:
file: $DOCKERDIR/secrets/traefik_forward_auth
mysql_root_password:
file: $DOCKERDIR/secrets/mysql_root_password
smtp_password:
file: $DOCKERDIR/secrets/smtp_password
guac_db_name:
file: $DOCKERDIR/secrets/guac_db_name
guac_mysql_user:
file: $DOCKERDIR/secrets/guac_mysql_user
guac_mysql_password:
file: $DOCKERDIR/secrets/guac_mysql_password
# Authentik Postgres
authentik_postgresql_db:
file: $DOCKERDIR/secrets/authentik_postgresql_db
authentik_postgresql_user:
file: $DOCKERDIR/secrets/authentik_postgresql_user
authentik_postgresql_password:
file: $DOCKERDIR/secrets/authentik_postgresql_password
# Authentik
authentik_secret_key:
file: $DOCKERDIR/secrets/authentik_secret_key
# GMail Auth Account
NORDVPN_USER:
file: $DOCKERDIR/secrets/NORDVPN_USER
NORDVPN_PASSWD:
file: $DOCKERDIR/secrets/NORDVPN_PASSWD
#traefik_hub_agent_token:
# file: $DOCKERDIR/secrets/traefik_hub_agent_token
########################### EXTENSION FIELDS
# Helps eliminate repetition of sections
# More Info on how to use this: https://github.com/htpcBeginner/docker-traefik/pull/228
# Common environment values
x-environment: &default-tz-puid-pgid
TZ: $TZ
PUID: $PUID
PGID: $PGID
tty: true
# Keys common to some of the services in basic-services.txt
x-common-keys-core: &common-keys-core
networks:
- t2_proxy
security_opt:
- no-new-privileges:true
restart: always
tty: true
# profiles:
# - core
# Keys common to some of the services in basic-services.txt
x-common-keys-monitoring: &common-keys-monitoring
networks:
- t2_proxy
security_opt:
- no-new-privileges:true
restart: always
tty: true
# profiles:
# - monitoring
# Keys common to some of the dependent services/apps
x-common-keys-apps: &common-keys-apps
networks:
- t2_proxy
security_opt:
- no-new-privileges:true
restart: unless-stopped
tty: true
# profiles:
# - apps
# Keys common to some of the services in media-services.txt
x-common-keys-media: &common-keys-media
networks:
- t2_proxy
security_opt:
- no-new-privileges:true
restart: "no"
tty: true
# profiles:
# - media
########################### SERVICES
services:
############################# FRONTENDS
# Traefik 2 - Reverse Proxy
# Touch (create empty files) traefik.log and acme/acme.json. Set acme.json permissions to 600.
# touch $DOCKERDIR/appdata/traefik2/acme/acme.json
# chmod 600 $DOCKERDIR/appdata/traefik2/acme/acme.json
# touch $DOCKERDIR/logs/cloudserver/traefik.log
# touch $DOCKERDIR/logs/cloudserver/access.log
traefik:
<<: *common-keys-core # See EXTENSION FIELDS at the top
container_name: traefik
image: traefik:2.9
command: # CLI arguments
- --global.checkNewVersion=true
- --global.sendAnonymousUsage=true
- --entryPoints.http.address=:80
- --entryPoints.https.address=:443
# Allow these IPs to set the X-Forwarded-* headers - Cloudflare IPs: https://www.cloudflare.com/ips/
- --entrypoints.https.forwardedHeaders.trustedIPs=$CLOUDFLARE_IPS,$LOCAL_IPS
- --entryPoints.traefik.address=:8080
# - --entryPoints.ping.address=:8081
- --api=true
# - --api.insecure=true
- --api.dashboard=true
#- --ping=true
# - --serversTransport.insecureSkipVerify=true
- --log=true
- --log.filePath=/logs/traefik.log
- --log.level=INFO # (Default: error) DEBUG, INFO, WARN, ERROR, FATAL, PANIC
- --accessLog=true
- --accessLog.filePath=/logs/access.log
- --accessLog.bufferingSize=100 # Configuring a buffer of 100 lines
- --accessLog.filters.statusCodes=204-299,400-499,500-599
- --providers.docker=true
# - --providers.docker.endpoint=unix:///var/run/docker.sock # Use Docker Socket Proxy instead for improved security
- --providers.docker.endpoint=tcp://socket-proxy:2375
# Automatically set Host rule for services
# - --providers.docker.defaultrule=Host(`{{ index .Labels "com.docker.compose.service" }}.$DOMAINNAME`)
- --providers.docker.exposedByDefault=false
# - --entrypoints.https.http.middlewares=chain-oauth@file
- --entrypoints.https.http.tls.options=tls-opts@file
# Add dns-cloudflare as default certresolver for all services. Also enables TLS and no need to specify on individual services
- --entrypoints.https.http.tls.certresolver=dns-cloudflare
- --entrypoints.https.http.tls.domains[0].main=$DOMAINNAME
- --entrypoints.https.http.tls.domains[0].sans=*.$DOMAINNAME
# - --entrypoints.https.http.tls.domains[1].main=$DOMAINNAME2 # Pulls main cert for second domain
# - --entrypoints.https.http.tls.domains[1].sans=*.$DOMAINNAME2 # Pulls wildcard cert for second domain
- --providers.docker.network=t2_proxy
- --providers.docker.swarmMode=false
- --providers.file.directory=/rules # Load dynamic configuration from one or more .toml or .yml files in a directory
# - --providers.file.filename=/path/to/file # Load dynamic configuration from a file
- --providers.file.watch=true # Only works on top level files in the rules folder
# - --certificatesResolvers.dns-cloudflare.acme.caServer=https://acme-staging-v02.api.letsencrypt.org/directory # LetsEncrypt Staging Server - uncomment when testing
- --certificatesResolvers.dns-cloudflare.acme.email=$CLOUDFLARE_EMAIL
- --certificatesResolvers.dns-cloudflare.acme.storage=/acme.json
- --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.provider=cloudflare
- --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.resolvers=1.1.1.1:53,1.0.0.1:53
- --certificatesResolvers.dns-cloudflare.acme.dnsChallenge.delayBeforeCheck=90 # To delay DNS check and reduce LE hitrate
# - --metrics.prometheus=true
# - --metrics.prometheus.buckets=0.1,0.3,1.2,5.0
networks:
t2_proxy:
ipv4_address: 192.168.90.254
socket_proxy:
#healthcheck:
# test: ["CMD", "traefik", "healthcheck", "--ping"]
# interval: 5s
# retries: 3
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
# - target: 8080 # insecure api wont work
# published: 8080
# protocol: tcp
# mode: host
volumes:
- $DOCKERDIR/appdata/traefik2/rules:/rules # file provider directory
# - /var/run/docker.sock:/var/run/docker.sock:ro # Use Docker Socket Proxy instead for improved security
- $DOCKERDIR/appdata/traefik2/acme/acme.json:/acme.json # cert location - you must create this emtpy file and change permissions to 600
- $DOCKERDIR/logs:/logs
environment:
- TZ=$TZ
- CF_API_EMAIL_FILE=/run/secrets/cf_email
- CF_API_KEY_FILE=/run/secrets/cf_api_key
- HTPASSWD_FILE=/run/secrets/htpasswd # HTPASSWD_FILE can be whatever as it is not used/called anywhere.
- DOMAINNAME # Passing the domain name to traefik container to be able to use the variable in rules.
secrets:
- cf_email
- cf_api_key
- htpasswd
labels:
#- "autoheal=true"
- "traefik.enable=true"
# HTTP-to-HTTPS Redirect
- "traefik.http.routers.http-catchall.entrypoints=http"
- "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
# HTTP Routers
- "traefik.http.routers.traefik-rtr.entrypoints=https"
- "traefik.http.routers.traefik-rtr.rule=Host(`traefik.$DOMAINNAME`)"
- "traefik.http.routers.traefik-rtr.tls=true" # Some people had 404s without this
- "traefik.http.routers.traefik-rtr.tls.certresolver=dns-cloudflare" # Comment out this line after first run of traefik to force the use of wildcard certs
- "traefik.http.routers.traefik-rtr.tls.domains[0].main=$DOMAINNAME"
- "traefik.http.routers.traefik-rtr.tls.domains[0].sans=*.$DOMAINNAME"
# - "traefik.http.routers.traefik-rtr.tls.domains[1].main=$DOMAINNAME2" # Pulls main cert for second domain
# - "traefik.http.routers.traefik-rtr.tls.domains[1].sans=*.$DOMAINNAME2" # Pulls wildcard cert for second domain
## Services - API
- "traefik.http.routers.traefik-rtr.service=api@internal"
## Healthcheck/ping
#- "traefik.http.routers.ping.rule=Host(`traefik.$DOMAINNAME`) && Path(`/ping`)"
#- "traefik.http.routers.ping.tls=true"
#- "traefik.http.routers.ping.service=ping@internal"
## Middlewares
- "traefik.http.routers.traefik-rtr.middlewares=chain-no-auth@file" # For No Authentication
#- "traefik.http.routers.traefik-rtr.middlewares=middlewares-rate-limit@file,middlewares-https-redirectscheme@file,middlewares-secure-headers@file,middlewares-basic-auth@file"
#- "traefik.http.routers.traefik-rtr.middlewares=chain-basic-auth@file" # For Basic HTTP Authentication
#- "traefik.http.routers.traefik-rtr.middlewares=chain-oauth@file" # For Google OAuth
#- "traefik.http.routers.traefik-rtr.middlewares=chain-authelia@file" # For Authelia Authentication
# Docker Socket Proxy - Security Enchanced Proxy for Docker Socket
socket-proxy:
<<: *common-keys-core # See EXTENSION FIELDS at the top
container_name: socket-proxy
image: tecnativa/docker-socket-proxy
networks:
socket_proxy:
ipv4_address: 192.168.91.254 # You can specify a static IP
# privileged: true # true for VM. False for unprivileged LXC container.
ports:
# - "127.0.0.1:2375:2375" # Port 2375 should only ever get exposed to the internal network. When possible use this line.
# I use the next line instead, as I want portainer to manage multiple docker endpoints within my home network.
- "2375:2375"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
environment:
- LOG_LEVEL=info # debug,info,notice,warning,err,crit,alert,emerg
## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* parts of the API, etc.).
# 0 to revoke access.
# 1 to grant access.
## Granted by Default
- EVENTS=1
- PING=1
- VERSION=1
## Revoked by Default
# Security critical
- AUTH=0
- SECRETS=0
- POST=1 # Watchtower
# Not always needed
- BUILD=0
- COMMIT=0
- CONFIGS=0
- CONTAINERS=1 # Traefik, portainer, etc.
- DISTRIBUTION=0
- EXEC=0
- IMAGES=1 # Portainer
- INFO=1 # Portainer
- NETWORKS=1 # Portainer
- NODES=0
- PLUGINS=0
- SERVICES=1 # Portainer
- SESSION=0
- SWARM=0
- SYSTEM=0
- TASKS=1 # Portainer
- VOLUMES=1 # Portainer
# Portainer - WebUI for Containers
portainer:
<<: *common-keys-core # See EXTENSION FIELDS at the top
container_name: portainer
image: portainer/portainer-ce:2.16.1
# command: -H unix:///var/run/docker.sock # # Use Docker Socket Proxy instead for improved security
command: -H tcp://socket-proxy:2375
--log-level DEBUG
networks:
t2_proxy:
socket_proxy:
ipv4_address: 192.168.91.5
ports:
#- "$PORTAINER_PORT:9000"
- 9900:9900
volumes:
# - /var/run/docker.sock:/var/run/docker.sock:ro # # Use Docker Socket Proxy instead for improved security
- $DOCKERDIR/appdata/portainer/data:/data # Change to local directory if you want to save/transfer config locally
environment:
- TZ=$TZ
labels:
- "traefik.enable=true"
## HTTP Routers
- "traefik.http.routers.portainer-rtr.entrypoints=https"
- "traefik.http.routers.portainer-rtr.rule=Host(`portainer.$DOMAINNAME`)"
- "traefik.http.routers.portainer-rtr.tls=true"
## Middlewares
- "traefik.http.routers.portainer-rtr.middlewares=chain-no-auth@file"
#- "traefik.http.routers.portainer-rtr.middlewares=chain-oauth@file"
#- "traefik.http.routers.portainer-rtr.middlewares=middlewares-basic-auth@file"
#- "traefik.http.routers.portainer-rtr.middlewares=chain-basic-auth@file"
#- "traefik.http.routers.portainer-rtr.middlewares=chain-authelia@file"
#- "traefik.http.routers.portainer-rtr.middlewares=chain-authentik@file"
## HTTP Services
- "traefik.http.routers.portainer-rtr.service=portainer-svc"
- "traefik.http.services.portainer-svc.loadbalancer.server.port=9000"
postgresql:
image: postgres:12-alpine
container_name: authentik_postgres
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 20s
interval: 30s
retries: 5
timeout: 5s
networks:
- t2_proxy
volumes:
- "$DOCKERDIR/appdata/authentik/postgresql/data:/var/lib/postgresql/data"
environment:
- POSTGRES_DB
- POSTGRES_USER
- POSTGRES_PASSWORD
secrets:
- authentik_postgresql_db
- authentik_postgresql_user
- authentik_postgresql_password
# - POSTGRES_PASSWORD=${PG_PASS:?database password required}
# - POSTGRES_USER=${PG_USER:-authentik}
# - POSTGRES_DB=${PG_DB:-authentik}
# env_file:
# - .env
redis:
image: docker.io/library/redis:alpine
container_name: authentik_redis
command: --save 60 1 --loglevel warning
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
retries: 5
timeout: 3s
networks:
- t2_proxy
# volumes:
# - redis:/data produces error
authentik:
container_name: authentik_server
hostname: authentik_server
image: ghcr.io/goauthentik/server:latest
restart: unless-stopped
command: server
networks:
- t2_proxy
environment:
- AUTHENTIK_REDIS__HOST
- AUTHENTIK_POSTGRESQL__HOST
- AUTHENTIK_POSTGRESQL__NAME
- AUTHENTIK_POSTGRESQL__USER
- AUTHENTIK_POSTGRESQL__PASSWORD
- AUTHENTIK_EMAIL__PASSWORD
- AUTHENTIK_ERROR_REPORTING__ENABLED
- AUTHENTIK_SECRET_KEY
- AUTHENTIK_COOKIE_DOMAIN
# - WORKERS
volumes:
- "$DOCKERDIR/appdata/authentik/media:/media"
- "$DOCKERDIR/appdata/authentik/custom-templates:/templates"
- "$DOCKERDIR/appdata/authentik/geoip/data:/geoip"
secrets:
- authentik_postgresql_db
- authentik_postgresql_user
- authentik_postgresql_password
- smtp_password
- authentik_secret_key
ports:
- "${COMPOSE_PORT_HTTP:-9000}:9000"
- "${COMPOSE_PORT_HTTPS:-9443}:9443"
depends_on:
- postgresql
- redis
labels:
- "traefik.enable=true"
## HTTP Routers
#- traefik.http.routers.authentik-rtr.rule: Host(`authentik.$DOMAINNAME`)
- "traefik.http.routers.authentik-rtr.rule=Host(`authentik.$DOMAINNAME`)|| HostRegexp(`{subdomain:[A-Za-z0-9]+}.$DOMAINNAME`) && PathPrefix(`/outpost.goauthentik.io/`)"
- "traefik.http.routers.authentik-rtr.entrypoints=https"
- "traefik.http.routers.authentik-rtr.priority=1"
- "traefik.http.routers.authentik-rtr.tls=true"
- "traefik.http.routers.authentik-rtr.tls.certresolver=dns-cloudflare"
authentik-worker:
container_name: authentik_worker
hostname: authentik_worker
image: ghcr.io/goauthentik/server:latest
restart: unless-stopped
command: worker
networks:
- t2_proxy
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- $DOCKERDIR/appdata/authentik/media:/media
- $DOCKERDIR/appdata/authentik/templates:/templates
- $DOCKERDIR/appdata/authentik/geoip/data:/geoip
environment:
- AUTHENTIK_REDIS__HOST
- AUTHENTIK_POSTGRESQL__HOST
- AUTHENTIK_POSTGRESQL__NAME
- AUTHENTIK_POSTGRESQL__USER
- AUTHENTIK_POSTGRESQL__PASSWORD
- AUTHENTIK_EMAIL__PASSWORD
- AUTHENTIK_ERROR_REPORTING__ENABLED
- AUTHENTIK_SECRET_KEY
- AUTHENTIK_COOKIE_DOMAIN
secrets:
- authentik_postgresql_db
- authentik_postgresql_user
- authentik_postgresql_password
- smtp_password
- authentik_secret_key
#env_file:
# - .env
geoipupdate:
image: maxmindinc/geoipupdate:latest
container_name: geoipupdate
restart: unless-stopped
volumes:
- "$DOCKERDIR/appdata/authentik/geoip/data:/usr/share/GeoIP"
environment:
- GEOIPUPDATE_EDITION_IDS
- GEOIPUPDATE_FREQUENCY
- GEOIPUPDATE_ACCOUNT_ID
- GEOIPUPDATE_LICENSE_KEY
whoami-test:
image: traefik/whoami
container_name: whoami-test
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- t2_proxy
environment:
- TZ
labels:
- "traefik.enable=true"
## HTTP Routers
- "traefik.http.routers.whoami-test-rtr.rule=Host(`whoami-test.$DOMAINNAME`)"
- "traefik.http.routers.whoami-test-rtr.entrypoints=https"
- "traefik.http.routers.whoami-test-rtr.tls=true"
- "traefik.http.routers.whoami-test-rtr.tls.certresolver=dns-cloudflare"
## Middlewares
- "traefik.http.routers.whoami-test-rtr.middlewares=chain-authentik@file"
In traefik Dashboard I see the http router and everything is green
In traefik Dashboard I see the service status green and pointing to http://192.168.1.181:9990
This traefik normal log
time="2023-09-05T15:58:16+02:00" level=info msg="Traefik version 2.9.10 built on 2023-04-06T16:15:08Z"
time="2023-09-05T15:58:16+02:00" level=info msg="Stats collection is enabled."
time="2023-09-05T15:58:16+02:00" level=info msg="Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration."
time="2023-09-05T15:58:16+02:00" level=info msg="Help us improve Traefik by leaving this feature on :)"
time="2023-09-05T15:58:16+02:00" level=info msg="More details on: Traefik Data Collection Documentation - Traefik"
time="2023-09-05T15:58:16+02:00" level=info msg="Starting provider aggregator aggregator.ProviderAggregator"
time="2023-09-05T15:58:16+02:00" level=info msg="Starting provider *file.Provider"
time="2023-09-05T15:58:16+02:00" level=info msg="Starting provider *traefik.Provider"
time="2023-09-05T15:58:16+02:00" level=info msg="Starting provider *docker.Provider"
time="2023-09-05T15:58:16+02:00" level=info msg="Starting provider *acme.ChallengeTLSALPN"
time="2023-09-05T15:58:16+02:00" level=info msg="Starting provider *acme.Provider"
time="2023-09-05T15:58:16+02:00" level=info msg="Testing certificate renew..." providerName=dns-cloudflare.acme ACME CA="https://acme-v02.api.letsencrypt.org/directory"
logs from traefik
192.168.1.70 - - [05/Sep/2023:14:04:27 +0000] "GET / HTTP/2.0" 499 21 "-" "-" 6 "portainerapps-rpi-rtr@file" "http://192.168.1.181:9990" 2502ms
192.168.1.70 - - [05/Sep/2023:14:04:30 +0000] "POST /signalr/messages/negotiate?access_token=d26348e2ce7fbed73895e2&negotiateVersion=1 HTTP/2.0" 502 45 "-" "-" 9 "prowlarr-rpi-rtr@file" "-" 31ms
GNU nano 6.2 /home/guyf/docker/logs/traefik.log
time="2023-09-05T16:08:04+02:00" level=info msg="Traefik version 2.9.10 built on 2023-04-06T16:15:08Z"
time="2023-09-05T16:08:04+02:00" level=info msg="Stats collection is enabled."
time="2023-09-05T16:08:04+02:00" level=info msg="Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration."
time="2023-09-05T16:08:04+02:00" level=info msg="Help us improve Traefik by leaving this feature on :)"
time="2023-09-05T16:08:04+02:00" level=info msg="More details on: https://doc.traefik.io/traefik/contributing/data-collection/"
time="2023-09-05T16:08:04+02:00" level=info msg="Starting provider aggregator aggregator.ProviderAggregator"
time="2023-09-05T16:08:04+02:00" level=info msg="Starting provider *file.Provider"
time="2023-09-05T16:08:04+02:00" level=info msg="Starting provider *traefik.Provider"
time="2023-09-05T16:08:04+02:00" level=info msg="Starting provider *acme.Provider"
time="2023-09-05T16:08:04+02:00" level=info msg="Testing certificate renew..." ACME CA="https://acme-v02.api.letsencrypt.org/directory" providerName=dns-cloudflare.acme
time="2023-09-05T16:08:04+02:00" level=info msg="Starting provider *acme.ChallengeTLSALPN"
time="2023-09-05T16:08:04+02:00" level=info msg="Starting provider *docker.Provider"