From 91a086e7234282856cdffc504ef064cc48abd253 Mon Sep 17 00:00:00 2001 From: Karti Tripathi Date: Tue, 15 Sep 2026 12:18:22 -0700 Subject: [PATCH] ci: take the deploy target out of the public workflow This repo is public, so .gitea/workflows/ci.yml was publishing the web host's tailnet address in a plaintext env: block, together with the deploy account, the checkout path and the unit restarted under sudo -- a complete map of the deploy for any anonymous reader. Host, account, path and service now come from repo secrets (DEPLOY_HOST, DEPLOY_USER, DEPLOY_PATH, DEPLOY_SERVICE), which Gitea masks in run logs. The path and unit name are passed to the remote shell as positional args inside a quoted heredoc so they are never interpolated into the log either. The deploy key secret is renamed CLOUD2_SSH_KEY -> DEPLOY_SSH_KEY to match; it was never actually set, which is why every deploy run so far is red. The rest of docs/DEPLOY.md already used the web-host/build-host pseudonyms; this drops the remaining absolute deploy-account paths from its prose. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012AaUFYkUTsJn1fnJ89qbvW --- .gitea/workflows/ci.yml | 51 ++++++++++++++++++++++++++++++----------- docs/DEPLOY.md | 6 ++--- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 0139f1d..28166df 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -5,8 +5,17 @@ # `needs:`, because Gitea's cross-workflow triggers are less reliable than GitHub's. A red # build cannot deploy. # -# Requires one repo secret: CLOUD2_SSH_KEY — the private half of a deploy key whose public -# half is in ubuntu@web-host's authorized_keys. +# This repo is PUBLIC, so nothing here may name the deploy target. The host, the account, +# the checkout path and the service name all come from repo secrets; the workflow only +# describes the shape of the deploy. +# +# Requires these repo secrets: +# DEPLOY_SSH_KEY — private half of a deploy key whose public half is in the deploy +# account's authorized_keys on the web host +# DEPLOY_HOST — the web host to deploy to +# DEPLOY_USER — the account to ssh in as +# DEPLOY_PATH — the checkout on the web host that is reset to origin/main +# DEPLOY_SERVICE — the systemd unit restarted after the build name: CI @@ -17,9 +26,6 @@ on: branches: [main] workflow_dispatch: -env: - CLOUD2_HOST: 100.92.185.76 - jobs: verify: runs-on: ubuntu-latest @@ -68,26 +74,43 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up SSH + env: + DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} run: | mkdir -p ~/.ssh - echo "${{ secrets.CLOUD2_SSH_KEY }}" > ~/.ssh/deploy_key + printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key - ssh-keyscan -H "$CLOUD2_HOST" >> ~/.ssh/known_hosts 2>/dev/null + ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null - - name: Deploy to web-host + - name: Deploy to the web host + env: + DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} + DEPLOY_USER: ${{ secrets.DEPLOY_USER }} + DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }} + DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }} run: | - ssh -i ~/.ssh/deploy_key -o BatchMode=yes ubuntu@"$CLOUD2_HOST" bash -s <<'REMOTE' + # The path and unit name are passed as positional args, not interpolated: + # the heredoc is quoted so the runner never expands them into the log. + ssh -i ~/.ssh/deploy_key -o BatchMode=yes "$DEPLOY_USER@$DEPLOY_HOST" \ + bash -s -- "$DEPLOY_PATH" "$DEPLOY_SERVICE" <<'REMOTE' set -euo pipefail - cd /home/ubuntu/workspace/bench.karti.ai + checkout="$1" + service="$2" + cd "$checkout" git fetch origin -q git reset --hard origin/main -q cd site npm install --no-audit --no-fund npm run build - sudo systemctl restart bench-karti + sudo systemctl restart "$service" REMOTE - name: Verify the deploy + env: + DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} + DEPLOY_USER: ${{ secrets.DEPLOY_USER }} + DEPLOY_SERVICE: ${{ secrets.DEPLOY_SERVICE }} run: | for i in $(seq 1 20); do if curl -sf https://bench.karti.ai/api/health | grep -q '"ok":true'; then @@ -97,6 +120,8 @@ jobs: sleep 3 done echo "::error::bench.karti.ai did not come back healthy after deploy" - ssh -i ~/.ssh/deploy_key -o BatchMode=yes ubuntu@"$CLOUD2_HOST" \ - 'sudo journalctl -u bench-karti -n 40 --no-pager' || true + ssh -i ~/.ssh/deploy_key -o BatchMode=yes "$DEPLOY_USER@$DEPLOY_HOST" \ + bash -s -- "$DEPLOY_SERVICE" <<'REMOTE' || true + sudo journalctl -u "$1" -n 40 --no-pager + REMOTE exit 1 diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md index a55a83e..4e42a41 100644 --- a/docs/DEPLOY.md +++ b/docs/DEPLOY.md @@ -12,7 +12,7 @@ What that leaves on the box: - Caddy vhost for `bench.karti.ai` is now `redir https://lumbridgecorp.com/bench permanent` (a pre-change Caddyfile backup is at `/etc/caddy/Caddyfile.bak-bench-`) - DNS `bench.karti.ai A 170.9.14.61` and the Let's Encrypt cert stay — the redirect needs both -- checkout at `/home/ubuntu/workspace/bench.karti.ai` remains, now on `origin` = +- checkout at `~/workspace/bench.karti.ai` remains, now on `origin` = `karti/lumbridge-bench`; the `bench-karti` unit is stopped and disabled, not removed **To bring a Bench UI back up**, deploy it as part of Lumbridge rather than reviving the subdomain. @@ -45,13 +45,13 @@ forever. Either add the `www` records or drop them from their vhosts. | repo | `karti/lumbridge-bench` on gitea, **private** | | host | web-host, port **8909** | | service | `bench-karti` compatibility service (systemd) | -| checkout | `/home/ubuntu/workspace/bench.karti.ai` compatibility path | +| checkout | `~/workspace/bench.karti.ai` compatibility path | | domain | `bench.karti.ai` → web-host, DNS via oci on build-host (profile `cloud2-sanjose`) | ## One-time setup on web-host ```bash -cd /home/ubuntu/workspace +cd ~/workspace git clone https://gitea.example.internal:8444/karti/lumbridge-bench.git bench.karti.ai cd bench.karti.ai/site cp .env.example .env.local # loopback Lumbridge control plane