Files
mimic/init/scripts/config_gen.sh
T
2026-05-21 09:54:07 +00:00

143 lines
5.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/functions.sh"
resolve_paths
require_env
require_command "yq"
require_command "openssl"
require_docker
# ============================================================================
# PHASE 1: Infrastructure Setup
# ============================================================================
resolve_volume_path
mkdir -p "${VOLUME_PATH}/synapse" "${VOLUME_PATH}/mas" "${VOLUME_PATH}/postgres" "${VOLUME_PATH}/proxy"
if [[ "${WORKER_COUNT}" -gt 0 ]]; then
mkdir -p "${VOLUME_PATH}/webapp"
fi
log_info "Initializing PostgreSQL..."
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --wait matrix-db
# Wait for database readiness
for ATTEMPT in $(seq 1 60); do
if docker compose -f "$COMPOSE_FILE" exec -T matrix-db psql -U "$PG_USER" -c "SELECT 1;" > /dev/null 2>&1; then
break
fi
[[ $ATTEMPT -eq 30 ]] && { log_error "Database timeout"; exit 1; }
sleep 2
done
# Database initialization
INIT_SQL=$(cat <<EOF
DO \$\$ BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'mas') THEN
CREATE ROLE mas WITH LOGIN PASSWORD '${PG_PASSWORD_MAS}';
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'matrix') THEN
CREATE ROLE matrix WITH LOGIN PASSWORD '${PG_PASSWORD_MATRIX}';
END IF;
END \$\$;
SELECT CASE WHEN NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'auth')
THEN format('CREATE DATABASE %I OWNER %I', 'auth', 'mas') ELSE NULL END AS cmd \gexec
SELECT CASE WHEN NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'synapse')
THEN format('CREATE DATABASE %I OWNER %I', 'synapse', 'matrix') ELSE NULL END AS cmd \gexec
EOF
)
echo "$INIT_SQL" | docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T matrix-db psql -U "$PG_USER" -f - > /dev/null
# ============================================================================
# PHASE 2: Configuration Generation
# ============================================================================
log_info "Generating Synapse configuration..."
docker run -it --rm --network matrix_network \
-v "${VOLUME_PATH}/synapse:/data" \
-e SYNAPSE_SERVER_NAME="$HOMESERVER_FQDN" \
-e SYNAPSE_REPORT_STATS=no \
ghcr.io/element-hq/synapse:latest generate || { log_error "Synapse config generation failed"; exit 1; }
SYNAPSE_CFG="${VOLUME_PATH}/synapse/homeserver.yaml"
fix_ownership "${VOLUME_PATH}/synapse"
yq -y -i '.database.name = "psycopg2"' "$SYNAPSE_CFG"
yq -y -i ".database.args.user = \"${PG_USER_MATRIX}\"" "$SYNAPSE_CFG"
yq -y -i ".database.args.password = \"${PG_PASSWORD_MATRIX}\"" "$SYNAPSE_CFG"
yq -y -i ".database.args.database = \"${PG_DB_MATRIX}\"" "$SYNAPSE_CFG"
yq -y -i ".database.args.host = \"matrix-db\"" "$SYNAPSE_CFG"
yq -y -i ".database.args.port = 5432" "$SYNAPSE_CFG"
yq -y -i ".database.args.sslmode = \"prefer\"" "$SYNAPSE_CFG"
yq -y -i ".public_baseurl = \"https://${HOMESERVER_FQDN}\"" "$SYNAPSE_CFG"
yq -y -i ".server_name = \"${HOMESERVER_FQDN}\"" "$SYNAPSE_CFG"
log_info "Generating MAS configuration..."
docker run -it --rm --network matrix_network \
-v "${VOLUME_PATH}/mas:/data" \
ghcr.io/element-hq/matrix-authentication-service:latest config generate \
| grep -v '^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}' > "${VOLUME_PATH}/mas/config.yaml" || { log_error "Mas config generation failed"; exit 1; }
MAS_CFG="${VOLUME_PATH}/mas/config.yaml"
if ! yq '.clients' "$MAS_CFG" > /dev/null 2>&1; then
yq -y -i '.clients = []' "$MAS_CFG"
fi
yq -y -i ".public_base_url = \"https://${MAS_FQDN}\"" "$MAS_CFG"
yq -y -i ".http.listen = \"0.0.0.0:8000\"" "$MAS_CFG"
yq -y -i ".database.uri = \"postgres://${PG_USER_MAS}:${PG_PASSWORD_MAS}@matrix-db:5432/auth?sslmode=prefer\"" "$MAS_CFG"
fix_ownership "${VOLUME_PATH}/mas"
# ============================================================================
# PHASE 3: OIDC Linking
# ============================================================================
log_info "Linking Synapse and MAS via OIDC..."
CLIENT_ID="synapse-client"
CLIENT_SECRET=$(openssl rand -hex 32)
EXISTING_CLIENT=$(yq '.clients[] | select(.client_id == "'"${CLIENT_ID}"'")' "$MAS_CFG" 2>/dev/null || echo "")
if [[ -z "$EXISTING_CLIENT" ]]; then
CLIENT_OBJ="{
\"client_id\": \"${CLIENT_ID}\",
\"client_secret\": \"${CLIENT_SECRET}\",
\"redirect_uris\": [\"https://${HOMESERVER_FQDN}/_synapse/client/oidc/callback\"],
\"grant_types\": [\"authorization_code\", \"refresh_token\"],
\"response_types\": [\"code\"],
\"scopes\": [\"openid\", \"profile\", \"email\"],
\"application_type\": \"web\"
}"
yq -y -i ".clients += [$CLIENT_OBJ]" "$SYNAPSE_CFG" || { log_error "Failed to register Synapse client in MAS"; exit 1; }
log_info " -> Registered Synapse as OIDC client in MAS"
else
log_info " -> Synapse client already registered in MAS, skipping"
fi
ISSUER_URL="https://${MAS_FQDN}"
fix_ownership "$SYNAPSE_CFG"
if ! yq '.oidc_providers' "$SYNAPSE_CFG" 2>/dev/null | grep -q "idp_id"; then
yq -y -i ".oidc_providers += [{
\"idp_id\": \"mas\",
\"idp_name\": \"Matrix Authentication Service\",
\"idp_brand\": \"mas\",
\"issuer\": \"${ISSUER_URL}\",
\"client_id\": \"${CLIENT_ID}\",
\"client_secret\": \"${CLIENT_SECRET}\",
\"scopes\": [\"openid\", \"profile\"],
\"skip_verification\": false
}]" "$SYNAPSE_CFG" || { log_error "Failed to inject OIDC config"; exit 1; }
fi
if [[ "${INCLUDE_LIVEKIT:-FALSE}" == "TRUE" ]]; then
JWT_URL="https://${JWT_FQDN:-jwt.${DOMAIN}}"
yq -y -i ".livekit.url = \"$JWT_URL\"" "$SYNAPSE_CFG"
fi
log_info "Config generation complete"