#!/bin/sh set -e # Generate session secret if not set or default if [ "$TEN31_SESSION_SECRET" = "change-me" ]; then if [ -f /data/.session-secret ]; then export TEN31_SESSION_SECRET=$(cat /data/.session-secret) else export TEN31_SESSION_SECRET=$(python3 -c "import secrets; print(secrets.token_hex(32))") echo "$TEN31_SESSION_SECRET" > /data/.session-secret chmod 600 /data/.session-secret fi fi # Create first approver on first boot if no users exist if [ ! -f /data/.initialized ]; then echo "First boot: running migrations and creating the admin account..." ADMIN_NAME="${TEN31_ADMIN_NAME:-Jonathan}" ADMIN_USERNAME="${TEN31_ADMIN_USERNAME:-admin}" ADMIN_EMAIL="${TEN31_ADMIN_EMAIL:-jonathan@ten31.xyz}" # No weak default: use an operator-supplied password if given, else generate a strong random # one and record it (0600) so it can be retrieved once via the "Show Initial Admin Password" # action. There is no fixed default credential to guess. ADMIN_PW_FILE="$(dirname "$TEN31_DB_PATH")/.admin-password" if [ -n "$TEN31_ADMIN_PASSWORD" ]; then ADMIN_PASSWORD="$TEN31_ADMIN_PASSWORD" GENERATED="" else ADMIN_PASSWORD="$(python3 -c "import secrets; print(secrets.token_urlsafe(18))")" GENERATED="yes" fi if python3 -m ten31portal.cli create-user \ --name "$ADMIN_NAME" \ --username "$ADMIN_USERNAME" \ --email "$ADMIN_EMAIL" \ --role approver \ --password "$ADMIN_PASSWORD" \ --service-admin; then if [ -n "$GENERATED" ]; then printf '%s' "$ADMIN_PASSWORD" > "$ADMIN_PW_FILE" chmod 600 "$ADMIN_PW_FILE" echo "Admin '$ADMIN_USERNAME' created with a generated password." echo " Retrieve it once via the 'Show Initial Admin Password' service action, then change it." else echo "Admin '$ADMIN_USERNAME' created with the operator-supplied password." fi fi touch /data/.initialized fi # Log level is overridable at runtime for debugging; defaults to info. LOG_LEVEL="${TEN31_LOG_LEVEL:-info}" # Hand off to the server as an unprivileged user. The platform mounts /data owned by root, so # (while still root) we take ownership of the data volume first, then drop privileges with # setpriv — the long-running server process is never root, limiting what a compromise can reach. if [ "$(id -u)" = "0" ]; then chown -R 10001:10001 /data exec setpriv --reuid=10001 --regid=10001 --clear-groups \ uvicorn ten31portal.main:app --host 0.0.0.0 --port 8000 --log-level "$LOG_LEVEL" else exec uvicorn ten31portal.main:app --host 0.0.0.0 --port 8000 --log-level "$LOG_LEVEL" fi