diff --git a/.gitea/workflows/demo-bootstrap.yml b/.gitea/workflows/demo-bootstrap.yml new file mode 100644 index 0000000..b72552f --- /dev/null +++ b/.gitea/workflows/demo-bootstrap.yml @@ -0,0 +1,94 @@ +# ONE-SHOT, NEVER MERGED. Lives only on the chore/demo-bootstrap branch, which is +# deleted after it runs. It does the demo host's one-time setup while the org lead +# is away (deploy/demo/README.md): writes /opt/demo.runicgateway.com/.env from +# deploy/demo/.env.example with every secret generated ON THE HOST, and reports +# whether the host reaches the panel and the rig's sidecar. +# +# It never overwrites an existing .env, and it never prints a value: the log holds +# only yes/no facts and HTTP status codes. + +name: Demo bootstrap (one-shot) + +on: + push: + branches: [chore/demo-bootstrap] + +jobs: + bootstrap: + runs-on: demo-site + env: + DEMO_DIR: /opt/demo.runicgateway.com + PTERODACTYL_URL: http://192.168.0.12 + PTERODACTYL_SERVER: 6eb9d621 + SIDECAR_URL: http://192.168.0.12:21004 + steps: + - name: Check out the deploy files + uses: actions/checkout@v4 + + - name: Host facts + run: | + echo "host: $(hostname) user: $(id -un) ($(id -u))" + echo "docker: $(docker version --format '{{.Server.Version}}' 2>&1 | head -1)" + echo "compose: $(docker compose version --short 2>&1 | head -1)" + echo "node: $(node --version 2>&1 | head -1)" + echo "curl: $(command -v curl || echo missing)" + echo "sudo -n: $(sudo -n true 2>/dev/null && echo yes || echo no)" + echo "$DEMO_DIR exists: $(test -d "$DEMO_DIR" && echo yes || echo no)" + echo "$DEMO_DIR/.env exists: $(test -f "$DEMO_DIR/.env" && echo yes || echo no)" + + - name: Reach the panel and the sidecar + run: | + code() { curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$@" || true; } + echo "panel $PTERODACTYL_URL/ -> $(code "$PTERODACTYL_URL/")" + echo "sidecar $SIDECAR_URL/health -> $(code "$SIDECAR_URL/health")" + + - name: Write the .env + env: + PTERODACTYL_CLIENT_KEY: ${{ secrets.PTERODACTYL_CLIENT_KEY }} + run: | + set -euo pipefail + SUDO="" + if ! mkdir -p "$DEMO_DIR" 2>/dev/null || ! test -w "$DEMO_DIR"; then + sudo -n mkdir -p "$DEMO_DIR" + sudo -n chown "$(id -u):$(id -g)" "$DEMO_DIR" + fi + if test -f "$DEMO_DIR/.env"; then + echo "$DEMO_DIR/.env already exists; left untouched." + exit 0 + fi + echo "PTERODACTYL_CLIENT_KEY secret present: $(test -n "$PTERODACTYL_CLIENT_KEY" && echo yes || echo no)" + + # The rig's web token: the startup variable first, then sidecar.toml. + api() { curl -s --max-time 15 -H "Authorization: Bearer $PTERODACTYL_CLIENT_KEY" -H 'Accept: application/json' "$PTERODACTYL_URL/api/client/servers/$PTERODACTYL_SERVER/$1"; } + RIG_TOKEN=$(api startup | node -e "let s='';process.stdin.on('data',c=>s+=c).on('end',()=>{try{const v=JSON.parse(s).data.find(x=>x.attributes.env_variable==='RUSTLINK_WEB_TOKEN');process.stdout.write((v&&v.attributes.server_value)||'')}catch{}})") || true + echo "rig token from the startup variables: $(test -n "$RIG_TOKEN" && echo yes || echo no)" + if test -z "$RIG_TOKEN"; then + RIG_TOKEN=$(api 'files/contents?file=%2Frust-link%2Fsidecar.toml' | sed -n 's/^[[:space:]]*auth_token[[:space:]]*=[[:space:]]*"\(.*\)".*/\1/p' | head -1) || true + echo "rig token from rust-link/sidecar.toml: $(test -n "$RIG_TOKEN" && echo yes || echo no)" + fi + if test -n "$RIG_TOKEN"; then + echo "sidecar /server with that token -> $(curl -s -o /dev/null -w '%{http_code}' --max-time 10 -H "Authorization: Bearer $RIG_TOKEN" "$SIDECAR_URL/server" || true)" + fi + + hex() { head -c "$1" /dev/urandom | od -An -tx1 | tr -d ' \n'; } + f="$DEMO_DIR/.env.new" + cp deploy/demo/.env.example "$f" + chmod 600 "$f" + setkv() { K="$1" V="$2" awk 'index($0, ENVIRON["K"] "=") == 1 { $0 = ENVIRON["K"] "=" ENVIRON["V"] } { print }' "$f" > "$f.tmp"; mv "$f.tmp" "$f"; } + setkv DB_PASSWORD "$(hex 24)" + setkv DB_ROOT_PASSWORD "$(hex 24)" + setkv JWT_SECRET "$(hex 32)" + setkv SECRET_ENC_KEY "$(hex 32)" + setkv BOT_INTERNAL_KEY "$(hex 32)" + # The three published logins are shown on the site, so short is fine. + setkv DEMO_ADMIN_PASSWORD "demo-$(hex 5)" + setkv DEMO_MODERATOR_PASSWORD "demo-$(hex 5)" + setkv DEMO_PLAYER_PASSWORD "demo-$(hex 5)" + setkv PLAY_REVIEW_PASSWORD "$(hex 16)" + # The walks' stand-in id (76561199910000001); the default-set step gives it play data. + setkv DEMO_PLAYER_STEAM_ID 76561199910000001 + setkv DEMO_RIG_SIDECAR_TOKEN "$RIG_TOKEN" + mv "$f" "$DEMO_DIR/.env" + chmod 600 "$DEMO_DIR/.env" + echo "wrote $DEMO_DIR/.env (mode 600). Empty keys left:" + grep -E '^[A-Z_]+=$' "$DEMO_DIR/.env" | cut -d= -f1 || true