{
	log {
		# Specify path and log level for Caddy logs
		output file /var/log/caddy/logfile.log
		level INFO
	}

	# replace `localhost` with an externally accessible IP address, e.g. a local LAN address or Tailscale IP. Take care not to use a publicly accessible IP address, as the Caddy API is not separately protected by API keys!
	admin localhost:2019

	servers {
		metrics
	}

	# Replace with your email address for SSL certificate registration
	email info@example.com
}

# This is a highly permissive CORS config. Dial it back as your use case allows.
(cors) {
	@cors_preflight method OPTIONS
	header {
		Access-Control-Allow-Origin "*"
		Access-Control-Expose-Headers "Authorization"
		Access-Control-Allow-Credentials "true"
		Access-Control-Allow-Headers "Authorization, Content-Type"
	}

	handle @cors_preflight {
		header {
			Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE"
			Access-Control-Max-Age "3600"
		}
		respond "" 204
	}
}

# Replace with the subdomain you want to expose your API over
api.example.com {
	import cors

	# Specify which endpoints do not require an API key
	@public {
		path /img/* /oauth /oauth/* /MS365 /MS365/* /ip /health /health* /health/* /id /identity
	}

	# Accept your GLOBAL_API_KEY (specified via environment variable in Caddy's context) via `Authorization: Bearer` header
	@apiKeyAuthHeader {
		header Authorization "Bearer {env.GLOBAL_API_KEY}"
	}

	# Optionally, accept your GLOBAL_API_KEY via query parameters
	@apiKeyAuthQuery {
		query api_key={env.GLOBAL_API_KEY}
	}

	handle @public {
		reverse_proxy {
			# Specify the local (or Tailscale) IPs & ports where the API service is running
			to  100.64.64.20:4444 100.64.64.11:4444 10.13.37.30:4444 localhost:4444
			lb_policy first
			health_uri /health
			health_interval 10s
			health_timeout 5s
			health_status 2xx
			header_up X-Forwarded-For {remote}
			header_up X-Forwarded-Proto {scheme}
		}
	}

	handle @apiKeyAuthHeader {
		reverse_proxy {
			# Specify the local (or Tailscale) IPs & ports where the API service is running
			to  100.64.64.20:4444 100.64.64.11:4444 10.13.37.30:4444 localhost:4444
			lb_policy first
			health_uri /health
			health_interval 10s
			health_timeout 5s
			health_status 2xx
		}
	}

	handle @apiKeyAuthQuery {
		reverse_proxy {
			# Specify the local (or Tailscale) IPs & ports where the API service is running
			to  100.64.64.20:4444 100.64.64.11:4444 10.13.37.30:4444 localhost:4444
			lb_policy first
			health_uri /health
			health_interval 10s
			health_timeout 5s
			health_status 2xx
		}
	}

	handle {
		respond "Unauthorized: Valid API key required" 401
	}

	# Assuming you use Cloudflare for DNS challenges and have configured a CLOUDFLARE_API_TOKEN environmental variable in Caddy's context
	tls {
		dns cloudflare {env.CLOUDFLARE_API_TOKEN}
	}

	log {
		output file /var/log/caddy/sijapi.log {
			roll_size 100mb
			roll_keep 5
			roll_keep_for 720h
		}
		format json {
			time_format "iso8601"
			message_key "message"
		}
	}
}

# Everything below here is ancillary to the primary API functionality
# If you have another domain you want to expose a particular endpoint on, try something like this -- e.g., here, https://sij.law/pgp as a short URL to share my public PGP key via.
sij.law {
	reverse_proxy /pgp 100.64.64.20:4444 100.64.64.30:4444 100.64.64.11:4444 localhost:4444 {
		lb_policy first
		health_uri /health
		health_interval 10s
		health_timeout 5s
		health_status 2xx
	}

	# Because I maintain a seperate service on this domain (a Ghost blog), I need fall back handling for everything besides `/pgp`.
	reverse_proxy localhost:2368
	tls {
		dns cloudflare {env.CLOUDFLARE_API_TOKEN}
	}
}

# Another special use case example: this provides handling for my URL shortener. 
sij.ai {
	
	# Any three-character alphanumeric URI is construed as a shortened URL.
	@shorturl {
		path_regexp ^/[a-zA-Z0-9]{3}$
	}

	# https://sij.ai/s points to the WebUI for my URL shortener
	@shortener_ui {
		path /s
	}

	@apiKeyAuthHeader {
        header Authorization "Bearer {env.GLOBAL_API_KEY}"
    }

    @apiKeyAuthQuery {
        query api_key={env.GLOBAL_API_KEY}
    }

	@analytics {
		path_regexp ^/analytics/[a-zA-Z0-9]{3}$
	}

	@pgp {
		path /pgp
	}

	handle @shortener_ui {
		reverse_proxy 100.64.64.20:4444 100.64.64.30:4444 100.64.64.11:4444 localhost:4444 {
			lb_policy first
			health_uri /health
			health_interval 10s
			health_timeout 5s
			health_status 2xx
		}
	}

	handle @shorturl {
		reverse_proxy 100.64.64.20:4444 100.64.64.30:4444 100.64.64.11:4444 localhost:4444 {
			lb_policy first
			health_uri /health
			health_interval 10s
			health_timeout 5s
			health_status 2xx
		}
	}

	handle @analytics {
		reverse_proxy 100.64.64.20:4444 100.64.64.30:4444 100.64.64.11:4444 localhost:4444 {
			lb_policy first
			health_uri /health
			health_interval 10s
			health_timeout 5s
			health_status 2xx
		}
	}

	# Handling for my public PGP key endpoint
	handle @pgp {
		reverse_proxy 100.64.64.20:4444 100.64.64.30:4444 100.64.64.11:4444 localhost:4444 {
			lb_policy first
			health_uri /health
			health_interval 10s
			health_timeout 5s
			health_status 2xx
		}
	}
	
	# Base domain redirects to my Ghost blog
	handle / {
		redir https://sij.law permanent
	}

	# All URIs that don't fit the patterns above redirect to the equivalent URI on my Ghost blog domain
	handle /* {
		redir https://sij.law{uri} permanent
	}

	tls {
		dns cloudflare {env.CLOUDFLARE_API_TOKEN}
	}
}