Files
cameleer-saas/docker/cameleer-traefik/entrypoint.sh
hsiegeln dc7ac3a1ec
All checks were successful
CI / build (push) Successful in 1m22s
CI / docker (push) Successful in 48s
feat: split auth domain — Logto gets dedicated AUTH_HOST
Support separate auth domain (e.g. auth.cameleer.io) for Logto while
keeping the SaaS app on PUBLIC_HOST (e.g. app.cameleer.io). AUTH_HOST
defaults to PUBLIC_HOST for backward-compatible single-domain setups.

- Logto routing: Host(AUTH_HOST) replaces PathPrefix('/') catch-all
- Root redirect moved from traefik-dynamic.yml to Docker labels with
  Host(PUBLIC_HOST) scope so it doesn't intercept auth domain
- Self-signed cert generates SANs for both domains
- Bootstrap Host header uses AUTH_HOST for Logto endpoint validation
- Spring issuer-uri and oidcissueruri use new authhost property
- Both installers (sh + ps1) prompt for AUTH_HOST in expert mode

Local dev: AUTH_HOST=auth.localhost (resolves to 127.0.0.1, no hosts file)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 18:11:47 +02:00

69 lines
2.6 KiB
Bash

#!/bin/sh
set -e
CERTS_DIR="/certs"
# Skip if certs already exist (idempotent)
if [ ! -f "$CERTS_DIR/cert.pem" ]; then
mkdir -p "$CERTS_DIR"
if [ -n "$CERT_FILE" ] && [ -n "$KEY_FILE" ]; then
# User-supplied certificate
echo "[certs] Installing user-supplied certificate..."
cp "$CERT_FILE" "$CERTS_DIR/cert.pem"
cp "$KEY_FILE" "$CERTS_DIR/key.pem"
if [ -n "$CA_FILE" ]; then
cp "$CA_FILE" "$CERTS_DIR/ca.pem"
fi
# Validate key matches cert
CERT_MOD=$(openssl x509 -noout -modulus -in "$CERTS_DIR/cert.pem" 2>/dev/null | md5sum)
KEY_MOD=$(openssl rsa -noout -modulus -in "$CERTS_DIR/key.pem" 2>/dev/null | md5sum)
if [ "$CERT_MOD" != "$KEY_MOD" ]; then
echo "[certs] ERROR: Certificate and key do not match!"
rm -f "$CERTS_DIR/cert.pem" "$CERTS_DIR/key.pem" "$CERTS_DIR/ca.pem"
exit 1
fi
SELF_SIGNED=false
echo "[certs] Installed user-supplied certificate."
else
# Generate self-signed certificate
HOST="${PUBLIC_HOST:-localhost}"
AUTH="${AUTH_HOST:-$HOST}"
echo "[certs] Generating self-signed certificate for $HOST..."
# Build SAN list; deduplicate when AUTH_HOST equals PUBLIC_HOST
if [ "$AUTH" = "$HOST" ]; then
SAN="DNS:$HOST,DNS:*.$HOST"
else
SAN="DNS:$HOST,DNS:*.$HOST,DNS:$AUTH,DNS:*.$AUTH"
echo "[certs] (+ auth domain: $AUTH)"
fi
openssl req -x509 -newkey rsa:4096 \
-keyout "$CERTS_DIR/key.pem" -out "$CERTS_DIR/cert.pem" \
-days 365 -nodes \
-subj "/CN=$HOST" \
-addext "subjectAltName=$SAN"
SELF_SIGNED=true
echo "[certs] Generated self-signed certificate for $HOST."
fi
# Write metadata for SaaS app to seed DB
SUBJECT=$(openssl x509 -noout -subject -in "$CERTS_DIR/cert.pem" 2>/dev/null | sed 's/subject=//')
FINGERPRINT=$(openssl x509 -noout -fingerprint -sha256 -in "$CERTS_DIR/cert.pem" 2>/dev/null | sed 's/.*=//')
NOT_BEFORE=$(openssl x509 -noout -startdate -in "$CERTS_DIR/cert.pem" 2>/dev/null | sed 's/notBefore=//')
NOT_AFTER=$(openssl x509 -noout -enddate -in "$CERTS_DIR/cert.pem" 2>/dev/null | sed 's/notAfter=//')
HAS_CA=false
[ -f "$CERTS_DIR/ca.pem" ] && HAS_CA=true
cat > "$CERTS_DIR/meta.json" <<METAEOF
{"subject":"$SUBJECT","fingerprint":"$FINGERPRINT","selfSigned":$SELF_SIGNED,"hasCa":$HAS_CA,"notBefore":"$NOT_BEFORE","notAfter":"$NOT_AFTER"}
METAEOF
mkdir -p "$CERTS_DIR/staged" "$CERTS_DIR/prev"
chmod 775 "$CERTS_DIR" "$CERTS_DIR/staged" "$CERTS_DIR/prev"
chmod 660 "$CERTS_DIR"/*.pem 2>/dev/null || true
else
echo "[certs] Certificates already exist, skipping generation."
fi
# Start Traefik
exec traefik "$@"