accounts/entrypoint.sh
Haitao Pan 3c5a018b63 merged
2026-01-23 17:35:18 +08:00

205 lines
6.2 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# -----------------------------------------------------------------------------
# Stunnel Configuration
# -----------------------------------------------------------------------------
USE_STUNNEL=0
if [ -n "${DB_TLS_HOST:-}" ] && [ -n "${DB_TLS_PORT:-}" ]; then
USE_STUNNEL=1
echo "Configuring Stunnel..."
STUNNEL_CONF="/etc/stunnel/stunnel.conf"
mkdir -p /etc/stunnel
# Write certificate files from env vars if present
if [ -n "${DB_CA:-}" ]; then
echo "${DB_CA}" > /etc/stunnel/ca.pem
fi
if [ -n "${DB_CERT:-}" ]; then
echo "${DB_CERT}" > /etc/stunnel/cert.pem
fi
if [ -n "${DB_KEY:-}" ]; then
echo "${DB_KEY}" > /etc/stunnel/key.pem
fi
# Generate stunnel.conf
cat > "${STUNNEL_CONF}" <<EOF
foreground = no
pid = /var/run/stunnel/stunnel.pid
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
debug = 5
output = /var/log/stunnel.log
[postgres]
client = yes
accept = 127.0.0.1:5432
connect = ${DB_TLS_HOST}:${DB_TLS_PORT}
verify = 2
EOF
if [ -f "/etc/stunnel/ca.pem" ]; then
echo "CAfile = /etc/stunnel/ca.pem" >> "${STUNNEL_CONF}"
fi
if [ -f "/etc/stunnel/cert.pem" ] && [ -f "/etc/stunnel/key.pem" ]; then
echo "cert = /etc/stunnel/cert.pem" >> "${STUNNEL_CONF}"
echo "key = /etc/stunnel/key.pem" >> "${STUNNEL_CONF}"
fi
echo "Starting Stunnel..."
stunnel "${STUNNEL_CONF}"
# Wait for stunnel to be up (simple check)
STUNNEL_UP=0
for i in {1..30}; do
if nc -z 127.0.0.1 5432; then
echo "Stunnel is up!"
STUNNEL_UP=1
break
fi
echo "Waiting for Stunnel... ($i/30)"
sleep 1
done
if [ "${STUNNEL_UP}" -eq 0 ]; then
echo "Error: Stunnel failed to start or is not reachable on port 5432."
echo "Stunnel logs:"
if [ -f "/var/log/stunnel.log" ]; then
cat /var/log/stunnel.log
else
echo "No stunnel log found."
fi
exit 1
fi
fi
# -----------------------------------------------------------------------------
# App Configuration
# -----------------------------------------------------------------------------
CONFIG_FILE="${CONFIG_PATH:-/etc/xcontrol/account.yaml}"
# Copy default config if missing
if [ ! -f "${CONFIG_FILE}" ]; then
if [ -f "/app/config/account.yaml" ]; then
mkdir -p "$(dirname "${CONFIG_FILE}")"
cp "/app/config/account.yaml" "${CONFIG_FILE}"
elif [ -f "/usr/local/bin/account.yaml" ]; then
mkdir -p "$(dirname "${CONFIG_FILE}")"
cp "/usr/local/bin/account.yaml" "${CONFIG_FILE}"
else
echo "Warning: No configuration file found to copy from."
fi
fi
# Modify server port if Cloud Run provides PORT
if [ -n "${PORT:-}" ]; then
tmp_cfg=$(mktemp)
awk -v port="$PORT" '
/^server:/ {print; in_server=1; addr_written=0; next}
in_server && /^ addr:/ {print " addr: \":" port "\""; addr_written=1; next}
in_server && /^ [^ ]/ {in_server=0}
{print}
END {
if (port != "" && in_server == 0 && addr_written == 0) {
print "server:";
print " addr: \":" port "\"";
}
}
' "${CONFIG_FILE}" > "${tmp_cfg}"
mv "${tmp_cfg}" "${CONFIG_FILE}"
fi
# Database Configuration
DEFAULT_DB_USER="shenlan"
DEFAULT_DB_PASS="password"
DEFAULT_DB_HOST="127.0.0.1"
DEFAULT_DB_PORT="5432"
DEFAULT_DB_NAME="account"
DEFAULT_SSLMODE="disable"
# If Stunnel is active, force connection to localhost:5432
if [ "$USE_STUNNEL" -eq 1 ]; then
DB_HOST="127.0.0.1"
DB_PORT="5432"
fi
# Override store driver/DSN from environment and fallback to memory when absent
store_driver="${STORE_DRIVER:-}"
store_dsn="${DB_DSN:-${DATABASE_URL:-}}"
# If DB_HOST is set (either by user or Stunnel logic), construct DSN
if [ -n "${DB_HOST:-}" ]; then
DB_USER="${DB_USER:-$DEFAULT_DB_USER}"
DB_PASS="${DB_PASSWORD:-$DEFAULT_DB_PASS}"
DB_PORT="${DB_PORT:-$DEFAULT_DB_PORT}"
DB_NAME="${DB_NAME:-$DEFAULT_DB_NAME}"
DB_SSLMODE="${DB_SSLMODE:-$DEFAULT_SSLMODE}"
# Construct DSN
# Format: postgres://user:password@host:port/dbname?sslmode=disable
DSN="postgres://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=${DB_SSLMODE}"
store_dsn="$DSN"
if [ -z "${store_driver}" ]; then
store_driver="postgres"
fi
elif [ -n "${store_dsn}" ]; then
if [ -z "${store_driver}" ]; then
store_driver="postgres"
fi
elif [ -z "${store_driver}" ] && [ -z "${store_dsn}" ]; then
store_driver="memory"
fi
# Apply store configuration to config file
if [ -n "${store_driver}" ] || [ -n "${store_dsn}" ]; then
tmp_cfg=$(mktemp)
awk -v driver="$store_driver" -v dsn="$store_dsn" '
BEGIN {in_store=0; driver_written=0; dsn_written=0}
/^store:/ {print; in_store=1; next}
in_store && /^ driver:/ {
if (driver != "") {print " driver: \"" driver "\""; driver_written=1; next}
}
in_store && /^ dsn:/ {
if (dsn != "") {print " dsn: \"" dsn "\""; dsn_written=1; next}
}
in_store && /^[^ ]/ {
if (driver != "" && driver_written == 0) {print " driver: \"" driver "\""; driver_written=1}
if (dsn != "" && dsn_written == 0) {print " dsn: \"" dsn "\""; dsn_written=1}
in_store=0
}
{print}
END {
if (in_store) {
if (driver != "" && driver_written == 0) print " driver: \"" driver "\"";
if (dsn != "" && dsn_written == 0) print " dsn: \"" dsn "\"";
}
}
' "${CONFIG_FILE}" > "${tmp_cfg}"
mv "${tmp_cfg}" "${CONFIG_FILE}"
fi
# Inject DB Password into DSN if DB_PASSWORD is set
if [ -n "${DB_PASSWORD:-}" ]; then
sed -i "s|:password@|:${DB_PASSWORD}@|g" "${CONFIG_FILE}"
fi
# Inject Auth Secrets
if [ -n "${AUTH_PUBLIC_TOKEN:-}" ]; then
ESCAPED_TOKEN=$(printf '%s\n' "$AUTH_PUBLIC_TOKEN" | sed 's/|/\\|/g')
sed -i "s|publicToken: \".*\"|publicToken: \"${ESCAPED_TOKEN}\"|g" "${CONFIG_FILE}"
fi
if [ -n "${AUTH_REFRESH_SECRET:-}" ]; then
ESCAPED_SECRET=$(printf '%s\n' "$AUTH_REFRESH_SECRET" | sed 's/|/\\|/g')
sed -i "s|refreshSecret: \".*\"|refreshSecret: \"${ESCAPED_SECRET}\"|g" "${CONFIG_FILE}"
fi
if [ -n "${AUTH_ACCESS_SECRET:-}" ]; then
ESCAPED_SECRET=$(printf '%s\n' "$AUTH_ACCESS_SECRET" | sed 's/|/\\|/g')
sed -i "s|accessSecret: \".*\"|accessSecret: \"${ESCAPED_SECRET}\"|g" "${CONFIG_FILE}"
fi
exec /usr/local/bin/account --config "${CONFIG_FILE}" "$@"