Skip to content

Instantly share code, notes, and snippets.

@Fastidious
Forked from jmadden91/Caddyfile
Created April 24, 2025 00:12
Show Gist options
  • Save Fastidious/72568416f368f2ec2ed6c74c19a96d9f to your computer and use it in GitHub Desktop.
Save Fastidious/72568416f368f2ec2ed6c74c19a96d9f to your computer and use it in GitHub Desktop.
Caddyfile
# GLOBAL SETTINGS
{
#debug logs
#debug
dynamic_dns {
provider cloudflare {env.CLOUDFLARE_API_TOKEN}
domains {
example.com
example2.com
}
check_interval 10m
versions ipv4
}
#### caddy-security ####
order authenticate before respond
order authorize before basicauth
security {
oauth identity provider pocket-id {
realm pocket-id
driver generic
client_id <removed
client_secret <removed>
scopes openid email profile groups
enable id_token_cookie pocket-id_token
base_auth_url http://pocket-id:80
metadata_url http://pocket-id:80/.well-known/openid-configuration
delay_start 3
}
authentication portal pocket-id {
crypto default token lifetime 86400
enable identity provider pocket-id
transform user {
match realm pocket-id
action add caddy_username all-users as string
}
transform user {
match email [email protected]
action add caddy_username testing as string
}
}
authorization policy private_access {
bypass uri prefix /api
set auth url /caddy-security/oauth2/pocket-id
allow roles private
inject headers with claims
inject header "X-Token-Username" from caddy_username
}
authorization policy public_access {
set auth url /caddy-security/oauth2/pocket-id
allow roles user
inject headers with claims
inject header "X-Token-Username" from caddy_username
}
}
}
# SNIPPETS
## Use this private_access to skip auth on local network ##
# (private_access) {
# @notLocal not remote_ip private_ranges
# @auth path /caddy-security/*
# handle @notLocal {
# route @auth {
# authenticate with pocket-id
# }
# route {
# authorize with private_access
# }
# }
# }
(authentik) {
reverse_proxy /outpost.goauthentik.io/* authentik-server:9000 {
header_up Host {http.reverse_proxy.upstream.hostport}
}
forward_auth authentik-server: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
}
}
(oauth2) {
handle /oauth2/* {
reverse_proxy oauth2-proxy:4180 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Uri {uri}
}
}
handle {
forward_auth oauth2-proxy:4180 {
uri /oauth2/auth
header_up X-Real-IP {remote_host}
copy_headers Authorization X-Auth-Request-User X-Auth-Request-Email X-Auth-Request-Preferred-Username X-Auth-Request-Groups
@error status 401
handle_response @error {
redir * /oauth2/sign_in?rd={scheme}://{host}{uri}
}
}
}
}
(private_access) {
@auth {
path /caddy-security/*
}
route @auth {
authenticate with pocket-id
}
route /* {
authorize with private_access
}
}
(public_access) {
@auth {
path /caddy-security/*
}
route @auth {
authenticate with pocket-id
}
route /* {
authorize with public_access
}
}
(localNetwork) {
@localNetwork remote_ip private_ranges
@notLocal not remote_ip private_ranges
handle @notLocal {
respond "This service is not accessible remotely" 403
}
}
### Blog ##
example.com, www.example.com {
encode gzip
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
resolvers 1.1.1.1 8.8.8.8
}
reverse_proxy http://192.168.20.2:2368
}
# WILDCARD Cert for all sites
*.{env.DOMAIN} {
encode gzip
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
resolvers 1.1.1.1 8.8.8.8
}
# actual
@actual host actual.{env.DOMAIN}
handle @actual {
import localNetwork
reverse_proxy @localNetwork actual_server:5006
}
# audiobookshelf
@audiobooks host audiobooks.{env.DOMAIN}
handle @audiobooks {
reverse_proxy http://192.168.1.21:8585
}
# authentik
@authentik host auth.{env.DOMAIN}
handle @authentik {
reverse_proxy http://authentik-server:9000
}
# bitwarden
@bitwarden host bitwarden.{env.DOMAIN}
handle @bitwarden {
#import private_access
#extra security header modifications
header {
X-XSS-Protection "1; mode=block"
X-Frame-Options "DENY"
X-Robots-Tag "none"
-Server
}
reverse_proxy bitwarden:80
}
# blinko
@blinko host blinko.{env.DOMAIN}
handle @blinko {
import private_access
reverse_proxy blinko-website:1111
}
# calibre
@calibre host calibre.{env.DOMAIN}
handle @calibre {
import public_access
reverse_proxy http://192.168.1.21:8083
}
# calibre downloader
@books host books.{env.DOMAIN}
handle @books {
import public_access
reverse_proxy http://192.168.1.21:8084
}
# # cards
@cards host cards.{env.DOMAIN}
handle @cards {
basic_auth {
admin $2a$12$removed
}
reverse_proxy http://192.168.20.2:8080
}
# dockge
@dockge host dockge.{env.DOMAIN}
handle @dockge {
import private_access
reverse_proxy dockge:5001
}
# dozzle
@dozzle host dozzle.{env.DOMAIN}
handle @dozzle {
import localNetwork
reverse_proxy @localNetwork dozzle:8080
}
# frigate
@frigate host frigate.{env.DOMAIN}
handle @frigate {
import private_access
#reverse_proxy http://192.168.1.60:8971
reverse_proxy http://192.168.10.10:8971
}
# homeassistant
@hass host hass.{env.DOMAIN}
handle @hass {
# import private_access
reverse_proxy http://192.168.10.10:8123
}
# homepage
@home host home.{env.DOMAIN}
handle @home {
import localNetwork
reverse_proxy @localNetwork homepage:3000
}
# immich
@immich host immich.{env.DOMAIN}
handle @immich {
import private_access
reverse_proxy immich-server:2283
}
# jellyfin
@jellyfin host jellyfin.{env.DOMAIN}
handle @jellyfin {
import private_access
reverse_proxy 192.168.1.21:8096
}
# mealie
@mealie host mealie.{env.DOMAIN}
handle @mealie {
reverse_proxy mealie:9000
}
# NAS
@nas host nas.{env.DOMAIN}
handle @nas {
import private_access
reverse_proxy http://192.168.1.9:5000
}
# obsidian
@obsidian host obsidian.{env.DOMAIN}
handle @obsidian {
import private_access
reverse_proxy http://obsidian:3000
}
# obsidian sync
@sync host sync.{env.DOMAIN}
handle @sync {
reverse_proxy http://obsidian-livesync:5984
}
# outline
@notes host notes.{env.DOMAIN}
handle @notes {
reverse_proxy http://outline:3000
}
# ollama
@chat host chat.{env.DOMAIN}
handle @chat {
import private_access
reverse_proxy http://open-webui:8080
}
# overseerr
@overseerr host overseerr.{env.DOMAIN}
handle @overseerr {
reverse_proxy http://192.168.1.21:5055
}
#paperless
@paperless host paperless.{env.DOMAIN}
handle @paperless {
#import private_access
reverse_proxy http://paperless:8000
}
# #paperlessai
# @paperlessai host paperlessai.{env.DOMAIN}
# handle @paperlessai {
# import private_access
# reverse_proxy http://paperless-ai:3000
#paperlessgpt
@paperlessgpt host paperlessgpt.{env.DOMAIN}
handle @paperlessgpt {
import private_access
reverse_proxy http://paperless-gpt:8080
}
# pingvin
@pingvin host pingvin.{env.DOMAIN}
handle @pingvin {
import private_access
reverse_proxy http://pingvin:3000
}
# plex
@plex host plex.{env.DOMAIN}
handle @plex {
reverse_proxy http://192.168.1.21:32400
}
# pocket-id
@pocket-id host pocket-id.{env.DOMAIN}
handle @pocket-id {
reverse_proxy pocket-id:80
}
# prowlarr
@prowlarr host prowlarr.{env.DOMAIN}
handle @prowlarr {
import private_access
reverse_proxy http://192.168.1.21:9696
}
# proxmox
@proxmox host proxmox.{env.DOMAIN}
handle @proxmox {
import localNetwork
reverse_proxy @localNetwork https://192.168.0.50:8006 {
transport http {
tls_insecure_skip_verify
}
}
}
# proxmox backup server
@pbs host pbs.{env.DOMAIN}
handle @pbs {
import localNetwork
reverse_proxy @localNetwork https://192.168.0.52:8007 {
transport http {
tls_insecure_skip_verify
}
}
}
# radarr
@radarr host radarr.{env.DOMAIN}
handle @radarr {
import private_access
reverse_proxy http://192.168.1.21:7878
}
# readarr
@readarr host readarr.{env.DOMAIN}
handle @readarr {
import private_access
reverse_proxy http://192.168.1.21:8787
}
# remote access
@remote host remote.{env.DOMAIN}
handle @remote {
#rewrite * /guacamole{uri}
import private_access
reverse_proxy http://guacamole:8080 {
header_up X-Token-Username username
}
}
# sabnzbd
@sabnzbd host sabnzbd.{env.DOMAIN}
handle @sabnzbd {
import localNetwork
reverse_proxy @localNetwork http://192.168.1.21:8085
}
# scrypted
@scrypted host scrypted.{env.DOMAIN}
handle @scrypted {
import localNetwork
reverse_proxy @localNetwork https://192.168.0.51:10443 {
transport http {
tls_insecure_skip_verify
}
}
}
# sonarr
@sonarr host sonarr.{env.DOMAIN}
handle @sonarr {
import private_access
reverse_proxy http://192.168.1.21:8989 {
}
}
# # speaches
# @speaches host speaches.{env.DOMAIN}
# handle @speaches {
# import private_access
# reverse_proxy http://192.168.1.60:8000 {
# }
# }
# stirling-pdf
@pdf host pdf.{env.DOMAIN}
handle @pdf {
import private_access
reverse_proxy stirling-pdf:8080
}
# switchwire
@switchwire host switchwire.{env.DOMAIN}
handle @switchwire {
import private_access
reverse_proxy http://192.168.10.111:80
}
# tautulli (has plex login)
@tautulli host tautulli.{env.DOMAIN}
handle @tautulli {
reverse_proxy http://192.168.1.21:8181
}
# transmission
@transmission host transmission.{env.DOMAIN}
handle @transmission {
import private_access
reverse_proxy http://192.168.1.21:9091
}
# unifi
@unifi host unifi.{env.DOMAIN}
handle @unifi {
import private_access
reverse_proxy https://192.168.1.1 {
transport http {
tls_insecure_skip_verify
}
header_up X-Real-IP {remote_host}
}
}
# vacuum
@vacuum host vacuum.{env.DOMAIN}
handle @vacuum {
import private_access
reverse_proxy http://192.168.10.15:80
}
# voron
@voron host voron.{env.DOMAIN}
handle @voron {
import private_access
reverse_proxy http://192.168.10.110:80
}
# vscode
@vscode host vscode.{env.DOMAIN}
handle @vscode {
import private_access
reverse_proxy http://192.168.0.100:8443
}
# For whoami protected with oauth2-proxy
@whoami host whoami.{env.DOMAIN}
handle @whoami {
import oauth2
reverse_proxy whoami:80
}
# whats up docker
@wud host wud.{env.DOMAIN}
handle @wud {
import localNetwork
reverse_proxy @localNetwork whatsupdocker:3000
}
# Handle unlisted subdomains
handle {
respond "This service is not available" 404
#abort
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment