4.1 KiB
name, description, metadata
| name | description | metadata | ||
|---|---|---|---|---|
| project_guruconnect_deploy | How to deploy GuruConnect (v2+) to production — the server (172.16.3.30) builds its own Linux binary; gotchas with the systemd watchdog, trusted-proxy env, and auto-run migrations |
|
GuruConnect v2 went live in production on 2026-05-30 (server + dashboard at v0.2.0,
public at connect.azcomputerguru.com via NPM -> localhost:3002). The deploy is manual
(the .gitea/workflows/deploy.yml "deploy to server" step is a stub that only builds a
package artifact). Repo on the box: /home/guru/guru-connect (separate repo
azcomputerguru/guru-connect, NOT a submodule there).
Build host = the server itself. 172.16.3.30 has rust (rustup, cargo 1.94, the
x86_64-unknown-linux-gnu target), node 20 + npm 10, and protoc (~/.local/bin, libprotoc 28.3)
— all on PATH only in a login shell (ssh guru@172.16.3.30 'bash -lc "..."'; a
non-interactive shell does NOT source ~/.profile so cargo/protoc look "missing"). GURU-5070
builds the Windows agent + a windows-target server, NOT the Linux release — so build the
Linux server ON the box. See reference_guru5070_rust_toolchain.
Deploy sequence (build while v1 runs, then a quick cutover restart):
- Backup first:
pg_dump "$DATABASE_URL" | gzip > ~/backups/guruconnect/pre-deploy-*.sql.gz; save the current commit + copy the running binary to~/guruconnect-server.vN.bak. - Get the code: the server's local
mainmay have diverged from origin (the v2 greenfield respec rewrote history —git pull --ff-onlywill refuse). Tree is clean, sogit fetch origin && git reset --hard origin/main(rollback SHA is saved)..envis gitignored, untouched. - SPA:
cd dashboard && npm ci && npm run build-> emits to../server/static/app/(gitignored). - Binary (from repo ROOT, login shell, PROTOC set):
cargo build --release -p guruconnect-server --target x86_64-unknown-linux-gnu.-pscopes to the server so the Windows-only agent crate isn't compiled; explicit--targetoverrides.cargo/config.toml's windows-msvc default. Output lands attarget/x86_64-unknown-linux-gnu/release/guruconnect-server= the unit's ExecStart. ~3 min. sqlx uses RUNTIME queries (noquery!macros, no.sqlxcache) so the build needs no DB. - Cutover:
sudo systemctl restart guruconnect. Migrations are sqlx-embedded in the binary and auto-run on startup (db.migrate()), so no manualpsql. Watchjournalctl -u guruconnectfor "Migrations complete" + "Server listening".
GOTCHAS (all hit on the 2026-05-30 deploy):
- systemd unit: the INSTALLED
/etc/systemd/system/guruconnect.servicehas noWatchdogSec(correct for v2, which sends nosd_notify). The repo'sserver/guruconnect.serviceDOES setWatchdogSec=30s— so do NOT runsetup-systemd.sh/ copy the repo unit, or v2 restart-loops every 30s. Unit: User=guru, EnvironmentFile=server/.env, WorkingDirectory=server/, ProtectSystem=strict. CONNECT_TRUSTED_PROXIESis a v2 env var (comma-separated IPs; defaults to loopback fail-closed). Publicconnect.azcomputerguru.comingresses through NPM on Jupiter (172.16.3.20), which forwards to the relay on 172.16.3.30:3002. So setCONNECT_TRUSTED_PROXIES=127.0.0.1,::1,172.16.3.20inserver/.env(the Jupiter NPM hop, NOT the relay host .30 — that was a wrong first guess). Without trusting 172.16.3.20 the relay logs every public agent as 172.16.3.20 instead of reading X-Forwarded-For; with it, the real client IP shows (verified: a Pavon agent logged its true public IP 98.172.64.243). OnlyJWT_SECRETis hard-required.- NULL tags bug:
connect_machines.tagsistext[]nullable with no default; v2 decodes it as non-Option, so rows with NULL tags throw "unexpected null" at reconcile (and likely the Machines list). Mitigated withUPDATE connect_machines SET tags='{}' WHERE tags IS NULL. Real fix is a todo (decode Option + migration default). - DB is Postgres 14
guruconnecton localhost; existing users (admin, howard, both role admin) survive migration. Rollback:git reset --hard <saved-sha>, rebuild, restart,psql < backup.