generated from bisco/codex-bootstrap
Compare commits
5 Commits
1509c1e5fd
...
production
| Author | SHA1 | Date | |
|---|---|---|---|
| 34b68ae6e7 | |||
| 1470b49ed9 | |||
| 27b3b7624f | |||
| 741ed4764d | |||
| 86680f71f3 |
@@ -13,22 +13,46 @@ Docker Compose deployment for Traefik used as a TCP load balancer with TLS passt
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Edit SNI routes and backend targets in `config/dynamic/tcp-services.yml`:
|
Add or edit one file per site under `config/dynamic/`. For example, `config/dynamic/lab-younerd.yml` contains:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
http:
|
||||||
|
routers:
|
||||||
|
lab-yourdomain-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`lab.yourdomain.tld`)"
|
||||||
|
service: lab-yourdomain-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
lab-yourdomain-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "lab.yourdomain.tld"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:8080"
|
||||||
|
|
||||||
tcp:
|
tcp:
|
||||||
routers:
|
routers:
|
||||||
lab-younerd:
|
lab-yourdomain-tls:
|
||||||
rule: "HostSNI(`lab.younerd.org`)"
|
entryPoints:
|
||||||
service: lab-younerd
|
- tls
|
||||||
|
rule: "HostSNI(`lab.yourdomain.tld`)"
|
||||||
|
service: lab-yourdomain-tls
|
||||||
tls:
|
tls:
|
||||||
passthrough: true
|
passthrough: true
|
||||||
|
|
||||||
services:
|
services:
|
||||||
lab-younerd:
|
lab-yourdomain-tls:
|
||||||
loadBalancer:
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
servers:
|
servers:
|
||||||
- address: "host.docker.internal:8443"
|
- address: "127.0.0.1:8443"
|
||||||
```
|
```
|
||||||
|
|
||||||
`HostSNI(...)` matches the hostname sent by the client during the TLS handshake. This deployment uses host networking so Traefik can reach services bound to the Docker host loopback address, such as `127.0.0.1:8443`.
|
`HostSNI(...)` matches the hostname sent by the client during the TLS handshake. This deployment uses host networking so Traefik can reach services bound to the Docker host loopback address, such as `127.0.0.1:8443`.
|
||||||
@@ -36,13 +60,14 @@ tcp:
|
|||||||
HTTP-01 certificate challenges use normal HTTP routing on port `80`, not SNI. The included example forwards:
|
HTTP-01 certificate challenges use normal HTTP routing on port `80`, not SNI. The included example forwards:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
lab.younerd.org -> 127.0.0.1:8080
|
lab.yourdomain.tld -> 127.0.0.1:8080
|
||||||
azionelab.org -> 127.0.0.1:9080
|
www.yourdomain.tld -> 127.0.0.1:9080
|
||||||
www.azionelab.org -> 127.0.0.1:9080
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Adjust `8080` and `9080` to the local ports where the backend HTTP service is listening. The full HTTP request is forwarded so the backend can handle redirects and ACME challenge paths.
|
Adjust `8080` and `9080` to the local ports where the backend HTTP service is listening. The full HTTP request is forwarded so the backend can handle redirects and ACME challenge paths.
|
||||||
|
|
||||||
|
Each backend service includes health checks. TCP checks verify that the TLS port accepts connections; HTTP checks call `/` with the configured hostname and treat successful or redirect responses as healthy.
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
Validate the Compose file:
|
Validate the Compose file:
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
alfredodistasio-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`alfredodistasio.com`) || Host(`www.alfredodistasio.com`)"
|
||||||
|
service: alfredodistasio-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
alfredodistasio-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "alfredodistasio.com"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:10080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
alfredodistasio-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`alfredodistasio.com`) || HostSNI(`www.alfredodistasio.com`)"
|
||||||
|
service: alfredodistasio-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
alfredodistasio-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:10443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
avernum-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`avernum.org`) || Host(`www.avernum.org`)"
|
||||||
|
service: avernum-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
avernum-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "avernum.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:11080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
avernum-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`avernum.org`) || HostSNI(`www.avernum.org`)"
|
||||||
|
service: avernum-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
avernum-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:11443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
azionelab-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`azionelab.org`) || Host(`www.azionelab.org`)"
|
||||||
|
service: azionelab-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
azionelab-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "azionelab.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:9080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
azionelab-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`azionelab.org`) || HostSNI(`www.azionelab.org`)"
|
||||||
|
service: azionelab-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
azionelab-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:9443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
bc-younerd-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`bc.younerd.org`) || Host(`www.bc.younerd.org`)"
|
||||||
|
service: bc-younerd-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
bc-younerd-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "bc.younerd.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:12080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
bc-younerd-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`bc.younerd.org`) || HostSNI(`www.bc.younerd.org`)"
|
||||||
|
service: bc-younerd-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
bc-younerd-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:12443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
files-avernum-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`files.avernum.org`)"
|
||||||
|
service: files-avernum-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
files-avernum-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "files.avernum.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:13080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
files-avernum-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`files.avernum.org`)"
|
||||||
|
service: files-avernum-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
files-avernum-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:13443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
git-younerd-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`git.younerd.org`)"
|
||||||
|
service: git-younerd-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
git-younerd-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "git.younerd.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:14080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
git-younerd-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`git.younerd.org`)"
|
||||||
|
service: git-younerd-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
git-younerd-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:14443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
ignoranzartificiale-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`ignoranzartificiale.org`) || Host(`www.ignoranzartificiale.org`)"
|
||||||
|
service: ignoranzartificiale-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
ignoranzartificiale-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "ignoranzartificiale.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:15080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
ignoranzartificiale-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`ignoranzartificiale.org`) || HostSNI(`www.ignoranzartificiale.org`)"
|
||||||
|
service: ignoranzartificiale-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
ignoranzartificiale-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:15443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
lab-younerd-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`lab.younerd.org`)"
|
||||||
|
service: lab-younerd-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
lab-younerd-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "lab.younerd.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:8080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
lab-younerd-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`lab.younerd.org`)"
|
||||||
|
service: lab-younerd-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
lab-younerd-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:8443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
paste-younerd-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`paste.younerd.org`)"
|
||||||
|
service: paste-younerd-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
paste-younerd-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "paste.younerd.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:16080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
paste-younerd-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`paste.younerd.org`)"
|
||||||
|
service: paste-younerd-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
paste-younerd-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:16443"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
static-younerd-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`static.younerd.org`)"
|
||||||
|
service: static-younerd-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
static-younerd-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "static.younerd.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:17080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
static-younerd-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`static.younerd.org`)"
|
||||||
|
service: static-younerd-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
static-younerd-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:17443"
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
http:
|
|
||||||
routers:
|
|
||||||
lab-younerd-acme:
|
|
||||||
entryPoints:
|
|
||||||
- web
|
|
||||||
rule: "Host(`lab.younerd.org`)"
|
|
||||||
service: lab-younerd-acme
|
|
||||||
|
|
||||||
azionelab-acme:
|
|
||||||
entryPoints:
|
|
||||||
- web
|
|
||||||
rule: "Host(`azionelab.org`) || Host(`www.azionelab.org`)"
|
|
||||||
service: azionelab-acme
|
|
||||||
|
|
||||||
services:
|
|
||||||
lab-younerd-acme:
|
|
||||||
loadBalancer:
|
|
||||||
servers:
|
|
||||||
- url: "http://127.0.0.1:8080"
|
|
||||||
|
|
||||||
azionelab-acme:
|
|
||||||
loadBalancer:
|
|
||||||
servers:
|
|
||||||
- url: "http://127.0.0.1:9080"
|
|
||||||
|
|
||||||
tcp:
|
|
||||||
routers:
|
|
||||||
lab-younerd:
|
|
||||||
entryPoints:
|
|
||||||
- tls
|
|
||||||
rule: "HostSNI(`lab.younerd.org`)"
|
|
||||||
service: lab-younerd
|
|
||||||
tls:
|
|
||||||
passthrough: true
|
|
||||||
|
|
||||||
azionelab:
|
|
||||||
entryPoints:
|
|
||||||
- tls
|
|
||||||
rule: "HostSNI(`azionelab.org`) || HostSNI(`www.azionelab.org`)"
|
|
||||||
service: azionelab
|
|
||||||
tls:
|
|
||||||
passthrough: true
|
|
||||||
|
|
||||||
services:
|
|
||||||
lab-younerd:
|
|
||||||
loadBalancer:
|
|
||||||
servers:
|
|
||||||
- address: "127.0.0.1:8443"
|
|
||||||
|
|
||||||
azionelab:
|
|
||||||
loadBalancer:
|
|
||||||
servers:
|
|
||||||
- address: "127.0.0.1:9443"
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
thefiredodo-http:
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
rule: "Host(`thefiredodo.org`) || Host(`www.thefiredodo.org`)"
|
||||||
|
service: thefiredodo-http
|
||||||
|
|
||||||
|
services:
|
||||||
|
thefiredodo-http:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
path: "/"
|
||||||
|
hostname: "thefiredodo.org"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- url: "http://127.0.0.1:18080"
|
||||||
|
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
thefiredodo-tls:
|
||||||
|
entryPoints:
|
||||||
|
- tls
|
||||||
|
rule: "HostSNI(`thefiredodo.org`) || HostSNI(`www.thefiredodo.org`)"
|
||||||
|
service: thefiredodo-tls
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
thefiredodo-tls:
|
||||||
|
loadBalancer:
|
||||||
|
healthCheck:
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
|
servers:
|
||||||
|
- address: "127.0.0.1:18443"
|
||||||
@@ -20,7 +20,7 @@ Traefik routes incoming TLS connections with `HostSNI(...)` to the configured TC
|
|||||||
|
|
||||||
TLS certificates, private keys, and certificate renewal remain the responsibility of each backend. Traefik can route TLS traffic based on the TLS SNI value but cannot inspect HTTP headers or paths because TLS is passed through unchanged.
|
TLS certificates, private keys, and certificate renewal remain the responsibility of each backend. Traefik can route TLS traffic based on the TLS SNI value but cannot inspect HTTP headers or paths because TLS is passed through unchanged.
|
||||||
|
|
||||||
Backend health is limited to TCP reachability unless protocol-specific health checks are added later. Configuration changes in `config/dynamic/` are watched by Traefik and can be applied without recreating the container.
|
Backend health checks are configured per site. TCP health checks verify backend port reachability; HTTP health checks call `/` with the configured hostname. Configuration changes in `config/dynamic/` are watched by Traefik and can be applied without recreating the container.
|
||||||
|
|
||||||
## Alternatives considered
|
## Alternatives considered
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ The container does not mount the Docker socket, does not run privileged, drops L
|
|||||||
|
|
||||||
## Operational impact
|
## Operational impact
|
||||||
|
|
||||||
Operators update backend IP addresses and ports in `config/dynamic/tcp-services.yml`. Traefik listens directly on host `80/tcp` and `443/tcp`; the ping entrypoint is used by the healthcheck.
|
Operators update backend IP addresses and ports in per-site files under `config/dynamic/`. Traefik listens directly on host `80/tcp` and `443/tcp`; the ping entrypoint is used by the healthcheck.
|
||||||
|
|
||||||
## Rollback
|
## Rollback
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ This project runs Traefik Proxy as a Dockerized TCP load balancer.
|
|||||||
|
|
||||||
- `compose.yaml`: defines the Traefik container, host networking, host-based configuration volume, container hardening, and healthcheck.
|
- `compose.yaml`: defines the Traefik container, host networking, host-based configuration volume, container hardening, and healthcheck.
|
||||||
- `config/traefik.yml`: static Traefik configuration for HTTP, TCP TLS, ping, file provider, and logging.
|
- `config/traefik.yml`: static Traefik configuration for HTTP, TCP TLS, ping, file provider, and logging.
|
||||||
- `config/dynamic/tcp-services.yml`: dynamic HTTP challenge routers, TCP routers, and backend load-balancer services.
|
- `config/dynamic/*.yml`: dynamic per-site HTTP routers, TCP routers, and backend load-balancer services.
|
||||||
|
|
||||||
## Data flow
|
## Data flow
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Update `config/dynamic/tcp-services.yml` with the required SNI hostnames and backend addresses:
|
Add or update a per-site file under `config/dynamic/` with the required hostnames and backend addresses:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
tcp:
|
tcp:
|
||||||
@@ -28,7 +28,9 @@ tcp:
|
|||||||
|
|
||||||
This deployment uses host networking so Traefik can reach services bound to host loopback addresses such as `127.0.0.1:8443`.
|
This deployment uses host networking so Traefik can reach services bound to host loopback addresses such as `127.0.0.1:8443`.
|
||||||
|
|
||||||
HTTP traffic is routed separately with HTTP `Host(...)` rules on port `80`. Configure the HTTP services in `config/dynamic/tcp-services.yml` to point at the local backend port that should handle redirects and ACME challenge paths.
|
HTTP traffic is routed separately with HTTP `Host(...)` rules on port `80`. Configure the HTTP service in the same per-site file to point at the local backend port that should handle redirects and ACME challenge paths.
|
||||||
|
|
||||||
|
Keep each site's HTTP and TCP routers in the same dynamic file, for example `config/dynamic/lab-younerd.yml` or `config/dynamic/azionelab.yml`.
|
||||||
|
|
||||||
The `./config` directory is the host-based configuration volume. It is mounted read-only into the container:
|
The `./config` directory is the host-based configuration volume. It is mounted read-only into the container:
|
||||||
|
|
||||||
|
|||||||
+6
-3
@@ -24,7 +24,7 @@ Dynamic configuration changes under `config/dynamic/` are watched by Traefik and
|
|||||||
|
|
||||||
## Health checks
|
## Health checks
|
||||||
|
|
||||||
The container healthcheck runs:
|
The Traefik container healthcheck runs:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
traefik healthcheck --ping
|
traefik healthcheck --ping
|
||||||
@@ -36,6 +36,8 @@ Check health with:
|
|||||||
docker compose ps
|
docker compose ps
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Backend services also define Traefik load-balancer health checks in each file under `config/dynamic/`. HTTP checks call `/` with the configured hostname; TCP checks verify that the local TLS port accepts connections.
|
||||||
|
|
||||||
## Logs
|
## Logs
|
||||||
|
|
||||||
Traefik logs to container stdout:
|
Traefik logs to container stdout:
|
||||||
@@ -46,11 +48,11 @@ docker compose logs -f traefik
|
|||||||
|
|
||||||
## Backend maintenance
|
## Backend maintenance
|
||||||
|
|
||||||
To remove a backend from rotation, edit `config/dynamic/tcp-services.yml` and remove or comment out its `address` entry. Keep at least one reachable backend configured before applying the change.
|
To remove a backend from rotation, edit that site's file under `config/dynamic/` and remove or comment out its `address` entry. Keep at least one reachable backend configured before applying the change.
|
||||||
|
|
||||||
This deployment uses host networking. For backends running on the Docker host, use `127.0.0.1:PORT` when the service is bound to host loopback.
|
This deployment uses host networking. For backends running on the Docker host, use `127.0.0.1:PORT` when the service is bound to host loopback.
|
||||||
|
|
||||||
For HTTP on port `80`, update the HTTP services in `config/dynamic/tcp-services.yml` to match the local backend ports that handle redirects and ACME challenge paths.
|
For HTTP on port `80`, update the HTTP services in the relevant site file under `config/dynamic/` to match the local backend ports that handle redirects and ACME challenge paths.
|
||||||
|
|
||||||
## Known operational risks
|
## Known operational risks
|
||||||
|
|
||||||
@@ -58,3 +60,4 @@ For HTTP on port `80`, update the HTTP services in `config/dynamic/tcp-services.
|
|||||||
- Backend certificates and renewal jobs must be monitored on each backend.
|
- Backend certificates and renewal jobs must be monitored on each backend.
|
||||||
- SNI routing depends on clients sending the expected hostname during the TLS handshake. Clients that connect by IP address or omit SNI will not match hostname-specific routers.
|
- SNI routing depends on clients sending the expected hostname during the TLS handshake. Clients that connect by IP address or omit SNI will not match hostname-specific routers.
|
||||||
- Public port `80/tcp` forwards all HTTP paths for configured hostnames to the matching backend.
|
- Public port `80/tcp` forwards all HTTP paths for configured hostnames to the matching backend.
|
||||||
|
- TCP health checks verify reachability, not certificate validity or application-level correctness.
|
||||||
|
|||||||
+13
-2
@@ -16,7 +16,7 @@ docker compose down
|
|||||||
|
|
||||||
### Update backend targets
|
### Update backend targets
|
||||||
|
|
||||||
1. Edit `config/dynamic/tcp-services.yml`.
|
1. Edit the relevant site file under `config/dynamic/`.
|
||||||
2. Run `docker compose config` to catch Compose-level errors.
|
2. Run `docker compose config` to catch Compose-level errors.
|
||||||
3. Watch Traefik logs:
|
3. Watch Traefik logs:
|
||||||
|
|
||||||
@@ -39,6 +39,17 @@ docker compose logs traefik
|
|||||||
|
|
||||||
Confirm that `config/traefik.yml` is mounted and that the ping entrypoint is enabled.
|
Confirm that `config/traefik.yml` is mounted and that the ping entrypoint is enabled.
|
||||||
|
|
||||||
|
### Backend is unhealthy
|
||||||
|
|
||||||
|
Check Traefik logs and verify that the local backend ports respond from the host:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -H 'Host: lab.younerd.org' http://127.0.0.1:8080/
|
||||||
|
openssl s_client -connect 127.0.0.1:8443 -servername lab.younerd.org
|
||||||
|
```
|
||||||
|
|
||||||
|
Repeat with the hostname and ports from the relevant file under `config/dynamic/`.
|
||||||
|
|
||||||
### Clients cannot connect
|
### Clients cannot connect
|
||||||
|
|
||||||
Check that the host is listening on `80/tcp` and `443/tcp`, firewall rules allow inbound traffic, and backend IP addresses are reachable from Traefik. For services bound to host loopback, configure backends as `127.0.0.1:PORT`.
|
Check that the host is listening on `80/tcp` and `443/tcp`, firewall rules allow inbound traffic, and backend IP addresses are reachable from Traefik. For services bound to host loopback, configure backends as `127.0.0.1:PORT`.
|
||||||
@@ -49,7 +60,7 @@ Check that port `80/tcp` is reachable from the internet and that the matching HT
|
|||||||
|
|
||||||
### Wrong certificate is presented
|
### Wrong certificate is presented
|
||||||
|
|
||||||
Because TLS is passed through, the certificate comes from the selected backend. Check backend certificate configuration and SNI routing rules in `config/dynamic/tcp-services.yml`.
|
Because TLS is passed through, the certificate comes from the selected backend. Check backend certificate configuration and SNI routing rules in the relevant file under `config/dynamic/`.
|
||||||
|
|
||||||
## Rollback
|
## Rollback
|
||||||
|
|
||||||
|
|||||||
@@ -40,5 +40,6 @@ openssl s_client -connect LOAD_BALANCER_HOST:443 -servername www.azionelab.org
|
|||||||
|
|
||||||
- Docker/Compose validation: `docker compose config`.
|
- Docker/Compose validation: `docker compose config`.
|
||||||
- Runtime health: `docker compose ps`.
|
- Runtime health: `docker compose ps`.
|
||||||
|
- Backend health checks: Traefik load-balancer health checks configured per site.
|
||||||
- HTTP route smoke test: `curl`.
|
- HTTP route smoke test: `curl`.
|
||||||
- TLS passthrough smoke test: `openssl s_client`.
|
- TLS passthrough smoke test: `openssl s_client`.
|
||||||
|
|||||||
Reference in New Issue
Block a user