1. The problem I’m having:
I want to configure Caddy in such a way that will allow me to activate CORS on multiple domains. I’ve been successful in adding the direct CORS config. And apply it to 1 domain/per line at a time. My problem is that sometimes I have a lot of servers that are trying to access my app on caddy, and many of them are with different domains. I find it really inefficient to add multiple lines every time I need to add a new domain. So I thought I’d ask my question here
2. Error messages and/or full log output:
There are no specific errors, but I'm looking for a convenient way to add multiple domains to apply CORS on
3. Caddy version:
I’m using: caddy:2.7.4-alpine
4. How I installed and ran Caddy:
a. System environment:
I am using Caddy Docker container with this version/tag: caddy:2.7.4-alpine
b. Command:
docker-compose up -d
c. Service/unit/compose file:
caddy:
image: ghcr.io/myrepo/my-caddy-build:latest
container_name: caddy-reverse-proxy
restart: unless-stopped
networks:
- giveth
ports:
- 80:80
- 443:443
env_file:
- ../.env
environment:
MY_APP_URL: ${MY_APP_URL:-}
RESTRICTED_PATHS: ${RESTRICTED_PATHS:-}
IP_WHITELIST: ${IP_WHITELIST:-}
WHITELIST_RATE_EVENTS: ${IG_WHITELIST_RATE_EVENTS:-}
WHITELIST_RATE_INTERVAL: ${IG_WHITELIST_RATE_INTERVAL:-}
PUBLIC_RATE_EVENTS: ${IG_PUBLIC_RATE_EVENTS:-}
PUBLIC_RATE_INTERVAL: ${IG_PUBLIC_RATE_INTERVAL:-}
DOMAIN_WHITELIST: ${DOMAIN_WHITELIST:-}
volumes:
- caddy_data:/data
- caddy_config:/config
- ./Caddyfile:/etc/caddy/Caddyfile
- ../logs/caddy:/usr/src/app/
depends_on:
- postgres
AND… I’m using a .env file to load ENV Variables into the configuration
#################### Public URLs configuration ####################
MY_APP_URL=https://myappdomain.com
IP_WHITELIST="IP1 IP2 IP3"
RESTRICTED_PATHS="/critical /restricted"
## Events(Number)/Interval(s,m,h,d) For Whitelisted IP Addresses Specified above
WHITELIST_RATE_EVENTS=1000000
WHITELIST_RATE_INTERVAL=1m
## Events(Number)/Interval(s,m,h,d) allowed for public Connections
PUBLIC_RATE_EVENTS=100
PUBLIC_RATE_INTERVAL=1m
####################################################################
DOMAIN_WHITELIST="https://domain1.com https://domain2.com" [NOT WORKING]
NOT that the last line of config is what is not working. I can’t specify multiple domains for CORS origin
d. My complete Caddy config:
# Global Options
{
order rate_limit before basicauth
log global {
output file /usr/src/app/global.log
format json
level debug
}
}
# CORS Config Block Directive
(cors) {
@cors_preflight{args[0]} {
method OPTIONS
header Origin {args[0]}
}
@cors{args[0]} header Origin {args[0]}
handle @cors_preflight{args[0]} {
header {
Access-Control-Allow-Origin "{args[0]}"
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers "Authorization, Cache-Control, Content-Type"
Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE"
Access-Control-Max-Age "3600"
Vary Origin
defer
}
respond "" 204
}
handle @cors{args[0]} {
header {
Access-Control-Allow-Origin "{args[0]}"
Access-Control-Allow-Credentials true
Access-Control-Expose-Headers *
Vary Origin
defer
}
}
}
#--------------------------------------------------------------------------
# My App site block
#--------------------------------------------------------------------------
{$APP_URL} {
# Call the cors for whitelisted domains
import cors {$DOMAIN_WHITELIST}
# Configure Logging
log {
output file /usr/src/app/access.log
format json
}
# Identify Config Keys for accesses
@privateIPAccess remote_ip {$IP_WHITELIST} # Whitelisted IP Addresses
@publicIPAccess not remote_ip {$IP_WHITELIST} # Unwhitelisted IP Addresses
@restrictedPaths path {$RESTRICTED_PATHS} # Restricted Paths
@unRestrictedPaths not path {$RESTRICTED_PATHS} # Unrestricted Paths
# Handling Restricted Paths Routes
route @restrictedPaths {
respond @publicIPAccess 403
reverse_proxy my-app:3000 {
transport http {
response_header_timeout 300s
dial_timeout 300s
}
}
}
# Handling Unrestricted Paths Route
route @unRestrictedPaths {
reverse_proxy my-app:3000 {
transport http {
response_header_timeout 300s
dial_timeout 300s
}
}
rate_limit @privateIPAccess {
zone myzone {
key {remote_host}
events {$WHITELIST_RATE_EVENTS}
window {$WHITELIST_RATE_INTERVAL}
}
sweep_interval 1m
}
}
# Apply Global rate limiting to all public Requests
rate_limit @publicIPAccess {
zone myzone {
key {remote_host}
events {$PUBLIC_RATE_EVENTS}
window {$PUBLIC_RATE_INTERVAL}
}
sweep_interval 1m
}
## Extra Header Configs
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
X-Frame-Options "DENY"
}
## Request Body Size
request_body {
max_size 30MB
}
}