134 lines
3.9 KiB
Caddyfile
134 lines
3.9 KiB
Caddyfile
{
|
|
email {$ACME_EMAIL}
|
|
admin off
|
|
|
|
# Reduce protocol/parser attack surface without interfering with Guacamole
|
|
# WebSockets. HTTP/3 can be enabled later if there is a concrete need.
|
|
servers {
|
|
protocols h1 h2
|
|
strict_sni_host on
|
|
max_header_size 64KB
|
|
timeouts {
|
|
read_header 10s
|
|
}
|
|
}
|
|
}
|
|
|
|
(edge_security_headers) {
|
|
header {
|
|
-Server
|
|
Strict-Transport-Security "max-age=31536000"
|
|
X-Content-Type-Options "nosniff"
|
|
Referrer-Policy "strict-origin-when-cross-origin"
|
|
Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=()"
|
|
}
|
|
}
|
|
|
|
(edgeguard_check) {
|
|
# EdgeGuard only listens on 127.0.0.1. These headers are overwritten by
|
|
# Caddy and therefore cannot be forged by an Internet client.
|
|
forward_auth 127.0.0.1:9081 {
|
|
uri /check
|
|
header_up X-Edge-Client-IP {client_ip}
|
|
header_up X-Edge-Original-Host {host}
|
|
header_up X-Edge-Original-Method {method}
|
|
header_up X-Edge-Original-URI {uri}
|
|
}
|
|
}
|
|
|
|
# Guacamole public endpoint + SessionGuard Access Auth
|
|
{$GUAC_HOST} {
|
|
encode zstd gzip
|
|
import edge_security_headers
|
|
|
|
route {
|
|
# Security pre-check occurs before OIDC/Auth and before any backend.
|
|
import edgeguard_check
|
|
|
|
# These endpoints belong to SessionGuard, but intentionally live on
|
|
# the Guacamole hostname so the Access-Auth cookie remains host-bound.
|
|
handle_path /_sessionguard/* {
|
|
reverse_proxy {$SESSIONGUARD_IP}:8080
|
|
}
|
|
|
|
handle {
|
|
route {
|
|
# Never trust identity headers supplied by an Internet client.
|
|
request_header -X-Guacamole-User
|
|
request_header -X-SessionGuard-User
|
|
request_header -X-SessionGuard-Email
|
|
request_header -X-SessionGuard-Groups
|
|
request_header -X-Forwarded-User
|
|
request_header -X-Authenticated-User
|
|
|
|
# SessionGuard is the single OIDC/ForwardAuth authority.
|
|
forward_auth {$SESSIONGUARD_IP}:8080 {
|
|
uri /auth/verify
|
|
copy_headers {
|
|
X-Guacamole-User
|
|
X-SessionGuard-User
|
|
X-SessionGuard-Email
|
|
X-SessionGuard-Groups
|
|
}
|
|
}
|
|
|
|
# Sticky sessions are important because Guacamole keeps runtime
|
|
# authentication/session state in the selected webapp process.
|
|
reverse_proxy {$GUAC01_IP}:8080 {$GUAC02_IP}:8080 {$GUAC03_IP}:8080 {
|
|
lb_policy cookie guac_node {$GUAC_LB_SECRET}
|
|
lb_try_duration 5s
|
|
lb_try_interval 250ms
|
|
health_uri /
|
|
health_interval 10s
|
|
health_timeout 3s
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
log {
|
|
output file /var/log/caddy/guacamole-access.log {
|
|
roll_size 100MiB
|
|
roll_keep 5
|
|
roll_keep_for 168h
|
|
}
|
|
format json
|
|
sampling {
|
|
interval 1s
|
|
first 200
|
|
thereafter 20
|
|
}
|
|
}
|
|
}
|
|
|
|
# SessionGuard administration UI, Agent endpoint and APIs.
|
|
{$SESSIONGUARD_HOST} {
|
|
encode zstd gzip
|
|
import edge_security_headers
|
|
|
|
route {
|
|
import edgeguard_check
|
|
|
|
# These endpoints are required internally only. Broker requests from
|
|
# Guacamole workers go directly over NetBird, never via public Caddy.
|
|
respond /metrics 404
|
|
respond /api/v1/broker/* 404
|
|
|
|
reverse_proxy {$SESSIONGUARD_IP}:8080
|
|
}
|
|
|
|
log {
|
|
output file /var/log/caddy/sessionguard-access.log {
|
|
roll_size 100MiB
|
|
roll_keep 5
|
|
roll_keep_for 168h
|
|
}
|
|
format json
|
|
sampling {
|
|
interval 1s
|
|
first 200
|
|
thereafter 20
|
|
}
|
|
}
|
|
}
|