Fix CORS handling and real IP logging

This commit is contained in:
2025-10-30 10:49:54 -06:00
parent f28b82db3f
commit 2b13ee7163
2 changed files with 228 additions and 28 deletions

240
start.sh
View File

@@ -50,14 +50,61 @@ fi
touch "$STARTUP_FLAG"
trap 'rm -f "$STARTUP_FLAG"' EXIT
BASE_URL="${CLOUDRON_APP_ORIGIN:-https://$CLOUDRON_APP_FQDN}"
APP_FQDN="${CLOUDRON_APP_DOMAIN:-${CLOUDRON_APP_FQDN:-localhost}}"
BASE_URL="${CLOUDRON_APP_ORIGIN:-https://$APP_FQDN}"
BASE_URL="${BASE_URL%/}"
RP_ID="${CLOUDRON_APP_FQDN:-${CLOUDRON_APP_DOMAIN:-localhost}}"
API_ORIGIN="${BASE_URL}/api"
ROOT_DOMAIN="$APP_FQDN"
if [ "$APP_FQDN" != "localhost" ] && expr "$APP_FQDN" : '.*\..*' >/dev/null; then
ROOT_DOMAIN="${APP_FQDN#*.}"
fi
PHOTOS_HOST="$APP_FQDN"
ACCOUNTS_HOST="$APP_FQDN"
AUTH_HOST="$APP_FQDN"
CAST_HOST="$APP_FQDN"
ALBUMS_HOST="$APP_FQDN"
FAMILY_HOST="$APP_FQDN"
USE_SUBDOMAIN_ROUTING=false
if [ "$APP_FQDN" != "localhost" ] && [ "$ROOT_DOMAIN" != "$APP_FQDN" ]; then
ACCOUNTS_HOST="accounts.${ROOT_DOMAIN}"
AUTH_HOST="auth.${ROOT_DOMAIN}"
CAST_HOST="cast.${ROOT_DOMAIN}"
ALBUMS_HOST="albums.${ROOT_DOMAIN}"
FAMILY_HOST="family.${ROOT_DOMAIN}"
USE_SUBDOMAIN_ROUTING=true
fi
PHOTOS_URL="https://${PHOTOS_HOST}"
if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
ACCOUNTS_URL="https://${ACCOUNTS_HOST}"
AUTH_URL="https://${AUTH_HOST}"
CAST_URL="https://${CAST_HOST}"
FAMILY_URL="https://${FAMILY_HOST}"
ALBUMS_URL="https://${ALBUMS_HOST}"
else
ACCOUNTS_URL="${BASE_URL}/accounts"
AUTH_URL="${BASE_URL}/auth"
CAST_URL="${BASE_URL}/cast"
FAMILY_URL="${BASE_URL}/family"
ALBUMS_URL="${BASE_URL}/albums"
fi
if [ "$APP_FQDN" != "localhost" ]; then
API_BASE="https://${APP_FQDN}"
else
API_BASE="$BASE_URL"
fi
API_ORIGIN="${API_BASE}/api"
RP_ID="$PHOTOS_HOST"
log INFO "Application base URL: $BASE_URL"
log INFO "Relying party ID: $RP_ID"
log INFO "API origin: $API_ORIGIN"
if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
log INFO "Serving frontend hosts: photos=${PHOTOS_HOST}, accounts=${ACCOUNTS_HOST}, auth=${AUTH_HOST}, cast=${CAST_HOST}"
fi
S3_CONFIG_FILE="$CONFIG_DIR/s3.env"
if [ ! -f "$S3_CONFIG_FILE" ]; then
@@ -299,13 +346,13 @@ http:
use-tls: false
apps:
public-albums: "$BASE_URL/albums"
public-locker: "$BASE_URL/photos"
accounts: "$BASE_URL/accounts"
cast: "$BASE_URL/cast"
family: "$BASE_URL/family"
public-albums: "$ALBUMS_URL"
public-locker: "$PHOTOS_URL"
accounts: "$ACCOUNTS_URL"
cast: "$CAST_URL"
family: "$FAMILY_URL"
custom-domain:
cname: "${CLOUDRON_APP_DOMAIN:-localhost}"
cname: "${APP_FQDN}"
db:
host: ${CLOUDRON_POSTGRESQL_HOST}
@@ -356,7 +403,7 @@ internal:
webauthn:
rpid: "$RP_ID"
rporigins:
- "$BASE_URL"
- "$PHOTOS_URL"
key:
encryption: $MASTER_KEY
@@ -377,7 +424,7 @@ oidc:
issuer: "${CLOUDRON_OIDC_IDENTIFIER}"
client_id: "${CLOUDRON_OIDC_CLIENT_ID}"
client_secret: "${CLOUDRON_OIDC_CLIENT_SECRET}"
redirect_url: "$BASE_URL/api/v1/session/callback"
redirect_url: "$API_BASE/api/v1/session/callback"
EOF_CFG
fi
@@ -453,14 +500,14 @@ if [ -d "$WEB_RUNTIME_DIR" ]; then
FRONTEND_REPLACEMENTS=(
"ENTE_API_ORIGIN_PLACEHOLDER|$API_ORIGIN"
"https://api.ente.io|$API_ORIGIN"
"https://accounts.ente.io|$BASE_URL/accounts"
"https://auth.ente.io|$BASE_URL/auth"
"https://cast.ente.io|$BASE_URL/cast"
"https://photos.ente.io|$BASE_URL/photos"
"https://web.ente.io|$BASE_URL/photos"
"https://albums.ente.io|$BASE_URL/albums"
"https://family.ente.io|$BASE_URL/family"
"https://ente.io|$BASE_URL"
"https://accounts.ente.io|$ACCOUNTS_URL"
"https://auth.ente.io|$AUTH_URL"
"https://cast.ente.io|$CAST_URL"
"https://photos.ente.io|$PHOTOS_URL"
"https://web.ente.io|$PHOTOS_URL"
"https://albums.ente.io|$ALBUMS_URL"
"https://family.ente.io|$FAMILY_URL"
"https://ente.io|$PHOTOS_URL"
)
OLD_IFS="$IFS"
for entry in "${FRONTEND_REPLACEMENTS[@]}"; do
@@ -483,10 +530,14 @@ chown -R cloudron:cloudron "$DATA_DIR/home"
chmod 700 "$DATA_DIR/home"
log INFO "Rendering Caddy configuration"
if [ "$USE_SUBDOMAIN_ROUTING" = true ]; then
cat > "$CADDY_CONFIG" <<EOF_CADDY
{
admin off
auto_https off
servers {
trusted_proxies static private_ranges
}
}
:3080 {
@@ -499,33 +550,44 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
@options {
method OPTIONS
header Origin *
}
handle @options {
header Access-Control-Allow-Origin "*"
header Access-Control-Allow-Origin "{http.request.header.Origin}"
header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
header Access-Control-Allow-Headers "*"
header Access-Control-Allow-Credentials "true"
header Access-Control-Max-Age "3600"
header Vary "Origin"
respond 204
}
handle_path /api/* {
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Real-IP}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
header Access-Control-Allow-Origin "*"
header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
header Access-Control-Allow-Headers "*"
header Access-Control-Allow-Credentials "true"
@api_cors {
header Origin *
}
header -Access-Control-Allow-Origin
header -Access-Control-Allow-Credentials
header @api_cors {
Access-Control-Allow-Origin {http.request.header.Origin}
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "*"
Access-Control-Allow-Credentials "true"
Vary "Origin"
}
}
handle /health {
rewrite * /ping
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Real-IP}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
@@ -534,7 +596,130 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
handle /ping {
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Real-IP}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
}
handle /public/* {
reverse_proxy localhost:8080
}
@photos_host host ${PHOTOS_HOST}
handle @photos_host {
root * $WEB_RUNTIME_DIR/photos
try_files {path} {path}/index.html /photos/index.html
file_server
}
@accounts_host host ${ACCOUNTS_HOST}
handle @accounts_host {
root * $WEB_RUNTIME_DIR/accounts
try_files {path} {path}/index.html /accounts/index.html
file_server
}
@auth_host host ${AUTH_HOST}
handle @auth_host {
root * $WEB_RUNTIME_DIR/auth
try_files {path} {path}/index.html /auth/index.html
file_server
}
@cast_host host ${CAST_HOST}
handle @cast_host {
root * $WEB_RUNTIME_DIR/cast
try_files {path} {path}/index.html /cast/index.html
file_server
}
@albums_host host ${ALBUMS_HOST}
handle @albums_host {
root * $WEB_RUNTIME_DIR/albums
try_files {path} {path}/index.html /albums/index.html
file_server
}
@family_host host ${FAMILY_HOST}
handle @family_host {
root * $WEB_RUNTIME_DIR/family
try_files {path} {path}/index.html /family/index.html
file_server
}
handle {
respond "Not Found" 404
}
}
EOF_CADDY
else
cat > "$CADDY_CONFIG" <<EOF_CADDY
{
admin off
auto_https off
servers {
trusted_proxies static private_ranges
}
}
:3080 {
log {
level INFO
output stdout
}
encode gzip
@options {
method OPTIONS
header Origin *
}
handle @options {
header Access-Control-Allow-Origin "{http.request.header.Origin}"
header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
header Access-Control-Allow-Headers "*"
header Access-Control-Allow-Credentials "true"
header Access-Control-Max-Age "3600"
header Vary "Origin"
respond 204
}
handle_path /api/* {
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
@api_cors {
header Origin *
}
header -Access-Control-Allow-Origin
header -Access-Control-Allow-Credentials
header @api_cors {
Access-Control-Allow-Origin {http.request.header.Origin}
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "*"
Access-Control-Allow-Credentials "true"
Vary "Origin"
}
}
handle /health {
rewrite * /ping
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
}
handle /ping {
reverse_proxy localhost:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.header.X-Forwarded-For}
header_up X-Forwarded-For {http.request.header.X-Forwarded-For}
header_up X-Forwarded-Proto {http.request.header.X-Forwarded-Proto}
}
@@ -598,6 +783,7 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
}
}
EOF_CADDY
fi
chown cloudron:cloudron "$CADDY_CONFIG"