1. The problem I’m having:
I am trying to segregate logs between different containers. Ideally the log
directive could be used inside the handle
directive, however that is not possible.
I understand if it were possible to sub in {host} to the log filename, it would create an inode attack vector. If log could be defined within handle, then it would only create a new file for domains that are defined in the config, then fall back on default for everything else.
I could define each subdomain explicitly, but then I lose the privacy of using a wildcard cert as then my subdomains are vulnerable to being scraped by would-be attackers, shodan, and the like.
So, I’m at an impasse.
2. Error messages and/or full log output:
not relevant
3. Caddy version:
v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=
4. How I installed and ran Caddy:
xcaddy build \
--with github.com/caddyserver/transform-encoder \
--with github.com/hslatman/caddy-crowdsec-bouncer/http \
--with github.com/caddy-dns/cloudflare \
--with github.com/mholt/caddy-webdav \
--with github.com/greenpau/caddy-security \
--with github.com/porech/caddy-maxmind-geolocation
a. System environment:
lxc, debian.
b. Command:
ExecStart=/usr/local/bin/caddy run --environ --watch --config /etc/caddy/Caddyfile
c. Service/unit/compose file:
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
User=caddy
Group=caddy
Environment="HOME=/var/lib/caddy"
Environment="XDG_HOME=/var/lib/caddy"
ExecStart=/usr/local/bin/caddy run --environ --watch --config /etc/caddy/Caddyfile
ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateDevices=yes
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
d. My complete Caddy config:
(auth) {
reverse_proxy /outpost.goauthentik.io/* http://172.16.1.0:9000 {
header_up host id.example.com
header_up Connection keep-alive, Upgrade
# header_up Upgrade websockets
}
forward_auth http://172.16.1.0:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
trusted_proxies private_ranges
header_up host id.example.com
header_up Connection keep-alive, Upgrade
# header_up Upgrade websockets
}
# # always forward outpost path to actual outpost
}
(tls_data) {
tls {
dns cloudflare [redacted]
resolvers 1.1.1.1
}
log {
output file /var/log/caddy/access.log {
roll_size 1gb
roll_keep 5
roll_keep_for 720h
}
format console
level INFO
}
#tls /gordo/proxmox/deploy_scripts/caddy/certs/-.example.com/fullchain.pem /gordo/proxmox/deploy_scripts/caddy/certs/-.example.com/key.pem
}
(subdomain-auth) {
@sub-{args.0} {
host {args.0}.example.com
not remote_ip 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12
}
@sub-{args.0}-lan {
host {args.0}.example.com
remote_ip 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12
}
handle @sub-{args.0} {
import proxy {args.1}
import auth
}
handle @sub-{args.0}-lan {
import proxy {args.1}
}
}
(subdomain-auth-tls) {
@sub-{args.0} {
host {args.0}.example.com
not remote_ip 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12
}
@sub-{args.0}-lan {
host {args.0}.example.com
remote_ip 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12
}
handle @sub-{args.0} {
import proxy-tls {args.1}
import auth
}
handle @sub-{args.0}-lan {
import proxy-tls {args.1}
}
}
*.example.com {
import tls_data
encode gzip
@blocked {
path *service-worker.js
}
@wan {
not remote_ip 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12
}
respond @blocked 404
import subdomain ha http://172.16.0.4:8123 # https://ha.example.com
import subdomain id http://172.16.1.0:9000 # https://id.example.com
import subdomain bw http://172.16.1.0:8081 # https://bw.example.com
import subdomain plex http://172.16.1.0:32400 # https://plex.example.com
import subdomain-auth invoke http://172.16.0.2:7861 # https://invoke.example.com
import subdomain-auth-tls proxmox https://172.16.0.222:8006 # https://proxmox.example.com
import subdomain-auth-tls prox https://172.16.0.7:8006 # https://prox.example.com
import subdomain-auth radarr http://172.16.1.0:7878 # https://radarr.example.com
import subdomain-auth sonarr http://172.16.1.0:8989 # https://sonarr.example.com
import subdomain-auth overseerr http://172.16.1.0:5055 # https://overseerr.example.com
import subdomain-auth tautulli http://172.16.1.0:8181 # https://tautulli.example.com
import subdomain-auth nzbget http://172.16.1.0:6789 # https://nzbget.example.com
import subdomain-auth flaresolverr http://172.16.1.0:8191 # https://flaresolverr.example.com
import subdomain-auth prowlarr http://172.16.1.0:9696 # https://prowlarr.example.com
import subdomain-auth lidarr http://172.16.1.0:8686 # https://lidarr.example.com
import subdomain-auth stash http://172.16.1.0:9999 # https://stash.example.com
import subdomain-auth qbittorrent http://172.16.1.0:8080 # https://qbittorrent.example.com
import subdomain-auth frigate http://172.16.1.0:5000 # https://frigate.example.com
import subdomain-auth webrtc http://172.16.1.0:8083 # https://frigate.example.com
import subdomain-auth grafana http://172.16.1.0:3000 # https://grafana.example.com
import subdomain-auth-tls opnsense https://172.16.0.254:8443 # https://opnsense.example.com
import subdomain-auth wg http://172.16.1.0:51821 # https://wg.example.com
import subdomain-auth home http://172.16.1.0:3001 # https://home.example.com
import subdomain-auth cadvisor http://172.16.1.0:9081 # https://cadvisor.example.com
import subdomain-auth kerberos http://172.16.1.0:8082 # https://kerberos.example.com
file_server {
hide .git
root /gordo/Public/www/
}
root * /gordo/Public/www/
@webDav host files.example.com
handle @webDav {
@get {
method GET
not path /.*
}
route {
basicauth * bcrypt {
alice [redacted]
}
file_server @get browse {
root /gordo
hide *~ *Zone.Identifier .git *.filebot*
}
webdav
}
}
@static host static.example.com
handle @static {
@get {
method GET
not path /.*
}
file_server @get browse {
root /gordo/Public
}
}