|
|
|
|
@@ -28,7 +28,15 @@ STARTUP_FLAG="$DATA_DIR/startup.lock"
|
|
|
|
|
mkdir -p "$LOG_DIR" "$CONFIG_DIR" "$TMP_DIR" "$SECRETS_DIR" "$MUSEUM_RUNTIME_DIR" "$WEB_RUNTIME_DIR" "$MUSEUM_CONFIG_DIR"
|
|
|
|
|
chown -R cloudron:cloudron "$DATA_DIR"
|
|
|
|
|
|
|
|
|
|
LOG_FILE="$LOG_DIR/startup.log"
|
|
|
|
|
touch "$LOG_FILE"
|
|
|
|
|
chown cloudron:cloudron "$LOG_FILE"
|
|
|
|
|
chmod 640 "$LOG_FILE"
|
|
|
|
|
# Mirror all output to a persistent log file while retaining stdout/stderr for Cloudron aggregation
|
|
|
|
|
exec > >(tee -a "$LOG_FILE") 2>&1
|
|
|
|
|
|
|
|
|
|
log INFO "Starting Ente for Cloudron"
|
|
|
|
|
log INFO "Startup logs are mirrored to $LOG_FILE"
|
|
|
|
|
|
|
|
|
|
if ! command -v setpriv >/dev/null 2>&1; then
|
|
|
|
|
log ERROR "setpriv command not found"
|
|
|
|
|
@@ -42,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
|
|
|
|
|
@@ -112,26 +167,64 @@ if [ "$S3_NOT_CONFIGURED" = "false" ]; then
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
log INFO "Using S3 endpoint $S3_ENDPOINT_HOST (region $S3_REGION, bucket $S3_BUCKET)"
|
|
|
|
|
S3_REGION_LOWER="$(printf '%s' "$S3_REGION" | tr '[:upper:]' '[:lower:]')"
|
|
|
|
|
if printf '%s' "$S3_ENDPOINT_HOST" | grep -q '\.r2\.cloudflarestorage\.com$' && [ "$S3_REGION_LOWER" != "auto" ]; then
|
|
|
|
|
log WARN "Cloudflare R2 endpoints require S3_REGION=auto; current value '$S3_REGION' may cause upload failures"
|
|
|
|
|
fi
|
|
|
|
|
else
|
|
|
|
|
S3_ENDPOINT_HOST="s3.example.com"
|
|
|
|
|
log WARN "S3 not configured - using placeholder values"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
DEFAULT_FORCE_PATH_STYLE="true"
|
|
|
|
|
if printf '%s' "$S3_ENDPOINT_HOST" | grep -q '\.r2\.cloudflarestorage\.com$'; then
|
|
|
|
|
if [ -z "${S3_FORCE_PATH_STYLE:-}" ] && [ -z "${ENTE_S3_FORCE_PATH_STYLE:-}" ]; then
|
|
|
|
|
log INFO "Detected Cloudflare R2 endpoint; defaulting to path-style URLs (required by R2)"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
S3_FORCE_PATH_STYLE_RAW="${S3_FORCE_PATH_STYLE:-${ENTE_S3_FORCE_PATH_STYLE:-$DEFAULT_FORCE_PATH_STYLE}}"
|
|
|
|
|
S3_FORCE_PATH_STYLE="$(printf '%s' "$S3_FORCE_PATH_STYLE_RAW" | tr '[:upper:]' '[:lower:]')"
|
|
|
|
|
S3_ARE_LOCAL_BUCKETS="$(printf '%s' "${S3_ARE_LOCAL_BUCKETS:-${ENTE_S3_ARE_LOCAL_BUCKETS:-false}}" | tr '[:upper:]' '[:lower:]')"
|
|
|
|
|
|
|
|
|
|
S3_PRIMARY_DC="${ENTE_S3_PRIMARY_DC:-b2-eu-cen}"
|
|
|
|
|
S3_SECONDARY_DC="${ENTE_S3_SECONDARY_DC:-$S3_PRIMARY_DC}"
|
|
|
|
|
S3_DERIVED_DC="${ENTE_S3_DERIVED_DC:-$S3_PRIMARY_DC}"
|
|
|
|
|
|
|
|
|
|
S3_DCS=()
|
|
|
|
|
add_s3_dc() {
|
|
|
|
|
local candidate="$1"
|
|
|
|
|
if [ -z "$candidate" ]; then
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
for existing in "${S3_DCS[@]}"; do
|
|
|
|
|
if [ "$existing" = "$candidate" ]; then
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
S3_DCS+=("$candidate")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_s3_dc "$S3_PRIMARY_DC"
|
|
|
|
|
add_s3_dc "$S3_SECONDARY_DC"
|
|
|
|
|
add_s3_dc "$S3_DERIVED_DC"
|
|
|
|
|
|
|
|
|
|
S3_PREFIX_DISPLAY="${S3_PREFIX:-<none>}"
|
|
|
|
|
log INFO "Resolved S3 configuration: host=$S3_ENDPOINT_HOST region=$S3_REGION pathStyle=$S3_FORCE_PATH_STYLE localBuckets=$S3_ARE_LOCAL_BUCKETS primaryDC=$S3_PRIMARY_DC derivedDC=$S3_DERIVED_DC prefix=$S3_PREFIX_DISPLAY"
|
|
|
|
|
|
|
|
|
|
DEFAULT_GIN_TRUSTED_PROXIES="127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
|
|
|
|
|
GIN_TRUSTED_PROXIES="${GIN_TRUSTED_PROXIES:-$DEFAULT_GIN_TRUSTED_PROXIES}"
|
|
|
|
|
export GIN_TRUSTED_PROXIES
|
|
|
|
|
log INFO "Configured trusted proxy ranges for Museum: $GIN_TRUSTED_PROXIES"
|
|
|
|
|
|
|
|
|
|
MASTER_KEY_FILE="$SECRETS_DIR/master_key"
|
|
|
|
|
HASH_KEY_FILE="$SECRETS_DIR/hash_key"
|
|
|
|
|
JWT_SECRET_FILE="$SECRETS_DIR/jwt_secret"
|
|
|
|
|
SESSION_SECRET_FILE="$SECRETS_DIR/session_secret"
|
|
|
|
|
|
|
|
|
|
SMTP_HOST="${CLOUDRON_MAIL_SMTP_SERVER:-}"
|
|
|
|
|
SMTP_PORT="${CLOUDRON_MAIL_SMTP_PORT:-25}"
|
|
|
|
|
SMTP_ENCRYPTION="${CLOUDRON_MAIL_SMTP_ENCRYPTION:-}"
|
|
|
|
|
if [ -n "${CLOUDRON_MAIL_SMTPS_PORT:-}" ]; then
|
|
|
|
|
SMTP_PORT="${CLOUDRON_MAIL_SMTPS_PORT}"
|
|
|
|
|
SMTP_ENCRYPTION="tls"
|
|
|
|
|
if [ -n "${CLOUDRON_MAIL_DOMAIN:-}" ]; then
|
|
|
|
|
SMTP_HOST="mail.${CLOUDRON_MAIL_DOMAIN}"
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
SMTP_HOST="${CLOUDRON_MAIL_SMTP_SERVER:-mail}"
|
|
|
|
|
SMTP_PORT="${CLOUDRON_MAIL_SMTPS_PORT:-2465}"
|
|
|
|
|
SMTP_ENCRYPTION="tls"
|
|
|
|
|
SMTP_USERNAME="${CLOUDRON_MAIL_SMTP_USERNAME:-}"
|
|
|
|
|
SMTP_PASSWORD="${CLOUDRON_MAIL_SMTP_PASSWORD:-}"
|
|
|
|
|
SMTP_EMAIL="${CLOUDRON_MAIL_FROM:-no-reply@$RP_ID}"
|
|
|
|
|
@@ -146,7 +239,7 @@ fi
|
|
|
|
|
normalize_b64() {
|
|
|
|
|
local value="$1"
|
|
|
|
|
value="$(printf '%s' "$value" | tr -d '\r\n')"
|
|
|
|
|
value="$(printf '%s' "$value" | tr '-_' '+/')"
|
|
|
|
|
value="$(printf '%s' "$value" | tr -- '-_' '+/')"
|
|
|
|
|
local mod=$(( ${#value} % 4 ))
|
|
|
|
|
if [ $mod -eq 2 ]; then
|
|
|
|
|
value="${value}=="
|
|
|
|
|
@@ -161,7 +254,7 @@ normalize_b64() {
|
|
|
|
|
normalize_b64url() {
|
|
|
|
|
local value="$1"
|
|
|
|
|
value="$(printf '%s' "$value" | tr -d '\r\n')"
|
|
|
|
|
value="$(printf '%s' "$value" | tr '+/' '-_')"
|
|
|
|
|
value="$(printf '%s' "$value" | tr -- '+/' '-_')"
|
|
|
|
|
local mod=$(( ${#value} % 4 ))
|
|
|
|
|
if [ $mod -eq 2 ]; then
|
|
|
|
|
value="${value}=="
|
|
|
|
|
@@ -180,7 +273,7 @@ generate_b64() {
|
|
|
|
|
|
|
|
|
|
generate_b64url() {
|
|
|
|
|
local bytes="$1"
|
|
|
|
|
openssl rand -base64 "$bytes" | tr '+/' '-_' | tr -d '\n'
|
|
|
|
|
openssl rand -base64 "$bytes" | tr -- '+/' '-_' | tr -d '\n'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure_secret() {
|
|
|
|
|
@@ -244,22 +337,22 @@ if [ ! -x "$MUSEUM_BIN" ]; then
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ ! -f "$MUSEUM_CONFIG" ]; then
|
|
|
|
|
log INFO "Rendering Museum configuration"
|
|
|
|
|
cat > "$MUSEUM_CONFIG" <<EOF_CFG
|
|
|
|
|
# Always regenerate Museum config to pick up S3 changes
|
|
|
|
|
log INFO "Rendering Museum configuration"
|
|
|
|
|
cat > "$MUSEUM_CONFIG" <<EOF_CFG
|
|
|
|
|
log-file: ""
|
|
|
|
|
http:
|
|
|
|
|
port: 8080
|
|
|
|
|
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}
|
|
|
|
|
@@ -270,19 +363,30 @@ db:
|
|
|
|
|
sslmode: disable
|
|
|
|
|
|
|
|
|
|
s3:
|
|
|
|
|
are_local_buckets: false
|
|
|
|
|
use_path_style_urls: true
|
|
|
|
|
are_local_buckets: ${S3_ARE_LOCAL_BUCKETS}
|
|
|
|
|
use_path_style_urls: ${S3_FORCE_PATH_STYLE}
|
|
|
|
|
hot_storage:
|
|
|
|
|
primary: primary-storage
|
|
|
|
|
secondary: primary-storage
|
|
|
|
|
primary-storage:
|
|
|
|
|
primary: ${S3_PRIMARY_DC}
|
|
|
|
|
secondary: ${S3_SECONDARY_DC}
|
|
|
|
|
derived-storage: ${S3_DERIVED_DC}
|
|
|
|
|
EOF_CFG
|
|
|
|
|
|
|
|
|
|
for dc in "${S3_DCS[@]}"; do
|
|
|
|
|
cat >> "$MUSEUM_CONFIG" <<EOF_CFG
|
|
|
|
|
$dc:
|
|
|
|
|
key: "$S3_ACCESS_KEY"
|
|
|
|
|
secret: "$S3_SECRET_KEY"
|
|
|
|
|
endpoint: "$S3_ENDPOINT_HOST"
|
|
|
|
|
region: "$S3_REGION"
|
|
|
|
|
bucket: "$S3_BUCKET"
|
|
|
|
|
path_prefix: "$S3_PREFIX"
|
|
|
|
|
EOF_CFG
|
|
|
|
|
if [ -n "$S3_PREFIX" ]; then
|
|
|
|
|
printf ' path_prefix: "%s"\n' "$S3_PREFIX" >> "$MUSEUM_CONFIG"
|
|
|
|
|
fi
|
|
|
|
|
printf '\n' >> "$MUSEUM_CONFIG"
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
cat >> "$MUSEUM_CONFIG" <<EOF_CFG
|
|
|
|
|
smtp:
|
|
|
|
|
host: "${SMTP_HOST}"
|
|
|
|
|
port: "${SMTP_PORT}"
|
|
|
|
|
@@ -299,7 +403,7 @@ internal:
|
|
|
|
|
webauthn:
|
|
|
|
|
rpid: "$RP_ID"
|
|
|
|
|
rporigins:
|
|
|
|
|
- "$BASE_URL"
|
|
|
|
|
- "$PHOTOS_URL"
|
|
|
|
|
|
|
|
|
|
key:
|
|
|
|
|
encryption: $MASTER_KEY
|
|
|
|
|
@@ -320,15 +424,12 @@ 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
|
|
|
|
|
|
|
|
|
|
chown cloudron:cloudron "$MUSEUM_CONFIG"
|
|
|
|
|
chmod 600 "$MUSEUM_CONFIG"
|
|
|
|
|
else
|
|
|
|
|
log INFO "Museum configuration already present; leaving untouched"
|
|
|
|
|
fi
|
|
|
|
|
chown cloudron:cloudron "$MUSEUM_CONFIG"
|
|
|
|
|
chmod 600 "$MUSEUM_CONFIG"
|
|
|
|
|
|
|
|
|
|
log INFO "Preparing frontend assets"
|
|
|
|
|
if [ -d "$WEB_SOURCE_DIR" ]; then
|
|
|
|
|
@@ -399,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
|
|
|
|
|
@@ -429,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 {
|
|
|
|
|
@@ -445,44 +550,178 @@ 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.remote}
|
|
|
|
|
header_up X-Forwarded-For {http.request.remote}
|
|
|
|
|
header_up X-Forwarded-Proto {http.request.scheme}
|
|
|
|
|
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"
|
|
|
|
|
}
|
|
|
|
|
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"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handle /health {
|
|
|
|
|
rewrite * /ping
|
|
|
|
|
reverse_proxy localhost:8080 {
|
|
|
|
|
header_up Host {http.request.host}
|
|
|
|
|
header_up X-Real-IP {http.request.remote}
|
|
|
|
|
header_up X-Forwarded-For {http.request.remote}
|
|
|
|
|
header_up X-Forwarded-Proto {http.request.scheme}
|
|
|
|
|
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.remote}
|
|
|
|
|
header_up X-Forwarded-For {http.request.remote}
|
|
|
|
|
header_up X-Forwarded-Proto {http.request.scheme}
|
|
|
|
|
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}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -496,6 +735,11 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
|
|
|
|
|
file_server
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handle /images/* {
|
|
|
|
|
root * $WEB_RUNTIME_DIR/photos
|
|
|
|
|
file_server
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handle /auth/* {
|
|
|
|
|
root * $WEB_RUNTIME_DIR
|
|
|
|
|
try_files {path} {path}/index.html /auth/index.html
|
|
|
|
|
@@ -539,6 +783,7 @@ cat > "$CADDY_CONFIG" <<EOF_CADDY
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
EOF_CADDY
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
chown cloudron:cloudron "$CADDY_CONFIG"
|
|
|
|
|
|
|
|
|
|
|