Easy_solution/frankenphp/Caddyfile.prod

105 lines
2.4 KiB
Caddyfile

{
# Global options
frankenphp {
# Number of workers for better performance
num_threads {$NUM_THREADS:4}
}
# Order directives properly
order mercure after encode
order php_server before file_server
}
# HTTP - redirect to HTTPS
http://{$SERVER_NAME:localhost} {
redir https://{host}{uri} permanent
}
# HTTPS server
https://{$SERVER_NAME:localhost} {
# Root directory
root * /app/public
# TLS configuration - Caddy will automatically obtain and renew Let's Encrypt certificates
tls {
protocols tls1.2 tls1.3
}
# Enable compression
encode zstd gzip
# Mercure hub configuration (built-in)
mercure {
# Publisher JWT key
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {
algorithm hs256
}
# Subscriber JWT key
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {
algorithm hs256
}
# Allow anonymous subscribers
anonymous
# Enable subscriptions
subscriptions
# CORS configuration
cors_origins *
}
# Client max body size (for uploads)
request_body {
max_size 20MB
}
# Security: Deny access to sensitive directories
@forbidden {
path /bin/* /config/* /src/* /templates/* /tests/* /translations/* /var/* /vendor/*
}
handle @forbidden {
respond "Access Denied" 404
}
# Security: Deny access to dot files (except .well-known for Mercure)
@dotfiles {
path */.*
not path /.well-known/*
}
handle @dotfiles {
respond "Access Denied" 404
}
# Cache static assets (30 days)
@static {
path *.jpg *.jpeg *.png *.gif *.ico *.css *.js *.svg *.woff *.woff2 *.ttf *.eot *.xlsx *.pdf
file
}
handle @static {
header Cache-Control "public, max-age=2592000, no-transform"
file_server
}
# Serve files from /assets directory
handle /assets/* {
root * /app/public
file_server
}
# PHP FrankenPHP handler
php_server {
# Resolve symlinks
resolve_root_symlink
}
# Logging
log {
output file /app/var/log/access.log
format json
# Redact sensitive data
format filter {
request>uri query {
replace authorization REDACTED
}
}
}
}