Every image request was round-tripping through a gunicorn worker for what is just a static file on disk. Caddy now serves /media/* straight off the shared media_data volume (mounted read-only) and only falls through to Django for anything else — Django's own /media/* route stays as a fallback for compose.behind-proxy.yaml and runserver, where there is no bundled Caddy container.
34 lines
1.0 KiB
Caddyfile
34 lines
1.0 KiB
Caddyfile
{
|
|
email {$ACME_EMAIL}
|
|
}
|
|
|
|
# The bare domain (control panel, admin, auth) and every club subdomain, on one certificate.
|
|
{$ROSTERCHIEF_BASE_DOMAIN}, *.{$ROSTERCHIEF_BASE_DOMAIN} {
|
|
tls {
|
|
dns cloudflare {$CLOUDFLARE_API_TOKEN}
|
|
}
|
|
|
|
encode zstd gzip
|
|
|
|
# Club logos, served straight off the shared volume — no gunicorn worker involved. Only
|
|
# matters while storage is local disk; once AWS_STORAGE_BUCKET_NAME is set, club.logo.url
|
|
# points at the bucket directly and this block simply never matches. A missing file 404s
|
|
# here exactly as django.views.static.serve would, so there is no need to fall through.
|
|
handle_path /media/* {
|
|
root * /srv/media
|
|
file_server
|
|
}
|
|
|
|
# X-Forwarded-Proto is what SECURE_PROXY_SSL_HEADER reads. Without it Django believes every
|
|
# request is plain HTTP: request.is_secure() goes false, WebAuthn disagrees with the browser
|
|
# about the origin, and the SSL redirect becomes a loop.
|
|
reverse_proxy web:8000 {
|
|
header_up X-Forwarded-Proto {scheme}
|
|
header_up X-Real-IP {remote_host}
|
|
}
|
|
|
|
log {
|
|
output stdout
|
|
}
|
|
}
|