Files
KNEL-TSYSDevStack-SupportSt…/Package-Workspace/Infrastructure/database-gateway/start.sh
T
mrcharles 3d38c507e8 feat: add Database-Gateway Cloudron package (Infrastructure) [#639]
Database Gateway 0.24.0 as the 12th package: multi-stage Go build
(CGO required by the libpg_query parser, hence an alpine:3.23 runtime
matching upstream), native OIDC wired to the Cloudron platform identity
provider, postgresql addon storage with goose migrations applied at
start, jq-generated config + OPA policy seeded to /app/data. Verified
end-to-end against a throwaway postgres (migrations, policy compile,
startup to the OIDC handoff). Docs gardened to 12 packages.

Ticket: https://projects.knownelement.com/issues/639
2026-09-01 19:28:06 -05:00

121 lines
4.0 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# Database Gateway runtime setup:
# 1. wait for the Cloudron postgresql addon (storage for profiles/bookmarks/
# query results)
# 2. seed /app/data/config.json + /app/data/opa/ on first run
# 3. apply the embedded schema migrations (migrate-up)
# 4. exec the gateway (web UI + LRPC API on 0.0.0.0:8080)
CONFIG_PATH="/app/data/config.json"
OPA_DIR="/app/data/opa"
COOKIE_SECRET_PATH="/app/data/.cookie_secret"
# --- 1. wait for PostgreSQL -------------------------------------------------
DB_HOST=${CLOUDRON_POSTGRESQL_HOST:-127.0.0.1}
DB_PORT=${CLOUDRON_POSTGRESQL_PORT:-5432}
DB_NAME=${CLOUDRON_POSTGRESQL_DATABASE:-dbgw}
DB_USER=${CLOUDRON_POSTGRESQL_USERNAME:-dbgw}
DB_PASSWORD=${CLOUDRON_POSTGRESQL_PASSWORD}
echo "Waiting for PostgreSQL at ${DB_HOST}:${DB_PORT} ..."
until PGPASSWORD="${DB_PASSWORD}" psql -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" -d "${DB_NAME}" -c '\q' >/dev/null 2>&1; do
echo "PostgreSQL is unavailable - sleeping"
sleep 2
done
echo "PostgreSQL is up"
# --- 2. seed persistent configuration ---------------------------------------
# Persistent cookie secret (rotating it would invalidate live sessions).
if [[ ! -f "${COOKIE_SECRET_PATH}" ]]; then
umask 077
openssl rand -hex 32 > "${COOKIE_SECRET_PATH}"
echo "Generated new cookie secret"
fi
COOKIE_SECRET=$(cat "${COOKIE_SECRET_PATH}")
# Default OPA policy: Cloudron "admins" see every target and may run any op;
# everyone else is denied until an operator extends the policy. Edit with the
# Cloudron file manager; changes apply on restart.
mkdir -p "${OPA_DIR}"
if [[ ! -f "${OPA_DIR}/simple.rego" ]]; then
cat > "${OPA_DIR}/simple.rego" <<'EOF'
package gateway
# Default Cloudron policy: the admins group is unrestricted; everyone else
# is denied until an operator edits this file (input.subjects contains
# user:<email> and role:<role> principals).
default allow_target := false
default allow_query := false
allow_target if {
"role:admin" in input.subjects
}
allow_query if {
"role:admin" in input.subjects
}
EOF
echo "Seeded default OPA policy at ${OPA_DIR}/simple.rego"
fi
# Seed the app config once (jq handles escaping of secrets into JSON). OIDC
# comes from the Cloudron platform identity provider; targets (the databases
# this gateway may reach) are added by the operator by editing
# ${CONFIG_PATH} with the Cloudron file manager.
if [[ ! -f "${CONFIG_PATH}" ]]; then
jq -n \
--arg db_host "${DB_HOST}" \
--arg db_name "${DB_NAME}" \
--arg db_user "${DB_USER}" \
--arg db_password "${DB_PASSWORD}" \
--argjson db_port "${DB_PORT}" \
--arg issuer "${CLOUDRON_OIDC_ISSUER}" \
--arg client_id "${CLOUDRON_OIDC_CLIENT_ID}" \
--arg client_secret "${CLOUDRON_OIDC_CLIENT_SECRET}" \
--arg origin "${CLOUDRON_APP_ORIGIN}" \
--arg cookie_secret "${COOKIE_SECRET}" \
--arg opa_dir "${OPA_DIR}" \
'{
targets: [],
users: {
client_id: $client_id,
client_secret: $client_secret,
issuer_url: $issuer,
redirect_url: ($origin + "/auth/callback"),
scopes: ["openid", "profile", "email", "groups"],
role_claim: "groups",
role_mapping: {
admins: "admin",
users: "user"
}
},
policy: { path: $opa_dir },
facade: {
port: 8080,
cookie_secret: $cookie_secret,
unsafe_cors_allow_all: false
},
storage: {
host: $db_host,
port: $db_port,
database: $db_name,
username: $db_user,
password: $db_password,
use_ssl: false,
max_pool_size: 16
}
}' > "${CONFIG_PATH}"
chmod 600 "${CONFIG_PATH}"
echo "Seeded config at ${CONFIG_PATH}"
fi
# --- 3. migrations -----------------------------------------------------------
echo "Applying database migrations ..."
/usr/local/bin/database-gateway -c "${CONFIG_PATH}" migrate-up
# --- 4. run --------------------------------------------------------------------
echo "Starting Database Gateway on :8080 ..."
exec /usr/local/bin/database-gateway -c "${CONFIG_PATH}" run