traefik: harden websecure defaults (crowdsec, headers, tls12)

This commit is contained in:
2026-02-07 02:15:13 +08:00
parent 2d7c788202
commit dc2c7f46ae
10 changed files with 90 additions and 1 deletions

3
.gitignore vendored
View File

@@ -25,5 +25,8 @@ node_modules/
# Ignore generated secrets # Ignore generated secrets
dynamic.d/middlewares/crowdsec.yml dynamic.d/middlewares/crowdsec.yml
# Local secrets directory (htpasswd, etc.)
secrets/
# Ignore backup files # Ignore backup files
*.~* *.~*

View File

@@ -53,7 +53,7 @@ labels:
- traefik.http.routers.myapp.rule=Host(`app.example.com`) - traefik.http.routers.myapp.rule=Host(`app.example.com`)
- traefik.http.routers.myapp.entrypoints=websecure - traefik.http.routers.myapp.entrypoints=websecure
- traefik.http.routers.myapp.tls.certresolver=letsencrypt - traefik.http.routers.myapp.tls.certresolver=letsencrypt
- traefik.http.routers.myapp.middlewares=crowdsec@file,retry-fast@file,compress-middleware@file - traefik.http.routers.myapp.middlewares=myapp-custom@docker
- traefik.http.services.myapp.loadbalancer.serversTransport=fast-upstreams@file - traefik.http.services.myapp.loadbalancer.serversTransport=fast-upstreams@file
- traefik.http.services.myapp.loadbalancer.server.port=3000 - traefik.http.services.myapp.loadbalancer.server.port=3000
- traefik.docker.network=traefik_default - traefik.docker.network=traefik_default

View File

@@ -16,6 +16,7 @@ services:
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- ./certs:/letsencrypt - ./certs:/letsencrypt
- ./secrets:/secrets:ro
#- ./dashboard_authfile:/dashboard_authfile:ro #- ./dashboard_authfile:/dashboard_authfile:ro
- ./dynamic.d:/dynamic.d - ./dynamic.d:/dynamic.d
- ./traefik.yml:/traefik.yml - ./traefik.yml:/traefik.yml
@@ -30,6 +31,11 @@ services:
- "traefik.http.routers.traefik.entrypoints=internal_websecure" - "traefik.http.routers.traefik.entrypoints=internal_websecure"
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt" - "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik.service=api@internal" - "traefik.http.routers.traefik.service=api@internal"
# CrowdSec bouncer middleware (defined via Docker provider so the LAPI key isn't stored in git-tracked files).
- "traefik.http.middlewares.crowdsec.plugin.bouncer.enabled=true"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecMode=stream"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiHost=localhost:8080"
- "traefik.http.middlewares.crowdsec.plugin.bouncer.crowdsecLapiKey=${CROWDSEC_LAPI_KEY}"
- "com.centurylinklabs.watchtower.enable=true" # Added label for Watchtower - "com.centurylinklabs.watchtower.enable=true" # Added label for Watchtower
# "traefik.http.middlewares.auth.basicauth.usersfile=/dashboard_authfile" # "traefik.http.middlewares.auth.basicauth.usersfile=/dashboard_authfile"
- "traefik.http.services.traefik.loadbalancer.server.port=9090" - "traefik.http.services.traefik.loadbalancer.server.port=9090"

View File

@@ -0,0 +1,6 @@
http:
middlewares:
label-auth:
basicAuth:
# Keep actual user hashes out of git.
usersFile: /secrets/label.htpasswd

View File

@@ -0,0 +1,12 @@
http:
middlewares:
secure-headers:
headers:
contentTypeNosniff: true
frameDeny: true
referrerPolicy: "strict-origin-when-cross-origin"
# Intentionally no HSTS (per requirement).
customResponseHeaders:
server: ""
x-powered-by: ""

View File

@@ -0,0 +1,18 @@
http:
routers:
label:
rule: Host(`label.gbanyan.net`)
entryPoints:
- websecure
tls:
certResolver: letsencrypt
middlewares:
- label-auth
service: label
services:
label:
loadBalancer:
passHostHeader: true
servers:
- url: "http://127.0.0.1:5004"

View File

@@ -0,0 +1,16 @@
http:
routers:
usher:
rule: Host(`member.usher.org.tw`)
entryPoints:
- websecure
tls:
certResolver: letsencrypt
service: usher
services:
usher:
loadBalancer:
passHostHeader: true
servers:
- url: "http://10.0.0.225:8000"

View File

@@ -0,0 +1,5 @@
tls:
options:
default:
minVersion: VersionTLS12

View File

@@ -5,3 +5,8 @@ http:
forwardingTimeouts: forwardingTimeouts:
idleConnTimeout: 30s idleConnTimeout: 30s
responseHeaderTimeout: 15s responseHeaderTimeout: 15s
gitea-upstreams:
maxIdleConnsPerHost: 64
forwardingTimeouts:
idleConnTimeout: 10m
responseHeaderTimeout: 10m

View File

@@ -59,8 +59,14 @@ entryPoints:
entryPoint: entryPoint:
to: "websecure" # The target element to: "websecure" # The target element
scheme: "https" scheme: "https"
permanent: true
websecure: websecure:
address: "10.0.0.225:443" address: "10.0.0.225:443"
transport:
respondingTimeouts:
readTimeout: 10m
writeTimeout: 10m
idleTimeout: 10m
forwardedHeaders: forwardedHeaders:
trustedIPs: trustedIPs:
- "173.245.48.0/20" - "173.245.48.0/20"
@@ -85,6 +91,12 @@ entryPoints:
- "2405:8100::/32" - "2405:8100::/32"
- "2a06:98c0::/29" - "2a06:98c0::/29"
- "2c0f:f248::/32" - "2c0f:f248::/32"
http:
middlewares:
- crowdsec@docker
- secure-headers@file
- compress-middleware@file
- retry-fast@file
internal_web: internal_web:
address: "192.168.50.4:80" address: "192.168.50.4:80"
http: http:
@@ -92,8 +104,14 @@ entryPoints:
entryPoint: entryPoint:
to: "internal_websecure" # The target element to: "internal_websecure" # The target element
scheme: "https" scheme: "https"
permanent: true
internal_websecure: internal_websecure:
address: "192.168.50.4:443" address: "192.168.50.4:443"
transport:
respondingTimeouts:
readTimeout: 10m
writeTimeout: 10m
idleTimeout: 10m
metrics: metrics:
address: ":8082" address: ":8082"
dashboard: dashboard: