Skip to content

Instantly share code, notes, and snippets.

@DanielVolz
Last active April 25, 2025 14:45
Show Gist options
  • Save DanielVolz/fb2da03618748679132aa70cee6f1a5c to your computer and use it in GitHub Desktop.
Save DanielVolz/fb2da03618748679132aa70cee6f1a5c to your computer and use it in GitHub Desktop.
Dockerfile, Caddyfile
ARG CADDY_VERSION=2.9.1
FROM caddy:${CADDY_VERSION}-builder-alpine AS builder
RUN xcaddy build \
--with github.com/lucaslorentz/caddy-docker-proxy/[email protected] \
--with github.com/caddy-dns/porkbun \
--with github.com/greenpau/[email protected]
FROM caddy:${CADDY_VERSION}-alpine
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
CMD ["caddy", "docker-proxy"]
----------------------------------------------------------------------
{
email [email protected]
acme_dns porkbun {
api_key {$PORKBUN_API_KEY}
api_secret_key {$PORKBUN_API_PASSWORD}
}
# admin 2019
# OAuth security configuration
security {
oauth identity provider generic_oauth {
realm generic
driver generic
delay_start 10
client_id
client_secret
scopes openid email profile
base_auth_url http://auth.{$MY_DOMAIN}
metadata_url http://auth.{$MY_DOMAIN}/.well-known/openid-configuration
}
authentication portal myportal {
enable identity provider generic_oauth
crypto default token lifetime 7200
cookie domain {$MY_DOMAIN}
ui {
links {
"Home" "/"
}
}
transform user {
match realm generic
action add role authp/user
}
}
authorization policy mypolicy {
set auth url /auth
allow roles authp/user
validate source address
inject headers with claims
}
}
}
(tls_internal) {
tls /certs/_wildcard.rbpi.lan+4.pem /certs/_wildcard.rbpi.lan+4-key.pem
}
# Base settings for all sites
(base_settings) {
encode gzip {
minimum_length 512
}
log {
output file /var/log/caddy/access.log {
roll_size 10MB
roll_keep 10
}
format console
level INFO
}
handle_errors {
respond "{http.error.status_code} {http.error.status_text}"
}
}
# Common security headers
(common_headers) {
import base_settings
header {
-Server
X-Content-Type-Options "nosniff"
Referrer-Policy "no-referrer-when-downgrade"
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Xss-Protection "1; mode=block"
}
}
(strict_headers) {
import common_headers
header {
# Additional strict security headers
X-Frame-Options "SAMEORIGIN"
X-Robots-Tag "noindex, nofollow"
Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()"
Content-Security-Policy "upgrade-insecure-requests; default-src 'self'; script-src 'self' 'unsafe-inline'"
X-Permitted-Cross-Domain-Policies "none"
Cache-Control "no-store, no-cache, must-revalidate"
}
}
(nextcloud_headers) {
import base_settings
header {
# Remove Server header
-Server
# Basic security headers
X-Content-Type-Options "nosniff"
Referrer-Policy "no-referrer"
X-XSS-Protection "1; mode=block"
X-Robots-Tag "noindex, nofollow"
X-Download-Options "noopen"
X-Permitted-Cross-Domain-Policies "none"
# HSTS
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Nextcloud requires a more permissive Content-Security-Policy
Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; img-src * data: blob:; media-src *; connect-src *"
# More appropriate cache control for Nextcloud
Cache-Control "public, max-age=15778463"
# Permissions that Nextcloud might need
Permissions-Policy "interest-cohort=()"
}
}
# Define a reusable snippet with common auth logic
(auth_common) {
@oauth {
path /auth/oauth2/generic
path /auth/oauth2/generic/authorization-code-callback
}
route @oauth {
authenticate with myportal
}
route /* {
authorize with mypolicy
}
}
(site_tls) {
tls {
issuer acme {
dns porkbun {
api_key {$PORKBUN_API_KEY}
api_secret_key {$PORKBUN_API_PASSWORD}
}
}
}
}
auth.domain.org {
reverse_proxy /api/* http://pocketid:8080 {
trusted_proxies 0.0.0.0/0
trusted_proxies ::/0
}
reverse_proxy /.well-known/* http://pocketid:8080 {
trusted_proxies 0.0.0.0/0
trusted_proxies ::/0
}
reverse_proxy /* http://pocketid:3000 {
trusted_proxies 0.0.0.0/0
trusted_proxies ::/0
}
}
local.{$MY_DOMAIN} *.local.{$MY_DOMAIN} {
import site_tls
}
wg.domain.org {
reverse_proxy rbpi:51821
}
----------------------------------------
compose.yml for example container:
labels:
caddy_0: ${CADDY_DOMAIN_DOZZLE_LOCAL}
caddy_0.import: common_headers
caddy_0.reverse_proxy: dozzle-rbpi:8080
This generates with ucaslorentz/caddy-docker-proxy/[email protected] in Caddyfile the following:
rbpi-log.local.domain.org {
import common_headers
reverse_proxy dozzle-rbpi:8080
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment