diff options
Diffstat (limited to 'scripts/systemd/README.md')
| -rw-r--r-- | scripts/systemd/README.md | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/scripts/systemd/README.md b/scripts/systemd/README.md new file mode 100644 index 0000000..7e3fdaa --- /dev/null +++ b/scripts/systemd/README.md @@ -0,0 +1,72 @@ +# fund-lab production deployment (systemd --user) + +Loopback-only services behind the existing `cloudflared` tunnel. The tunnel +ingress already maps `fund.somhairle.bid -> http://127.0.0.1:8098`. + +## Topology + +| Component | Listen | Unit / mechanism | +|-----------|--------|------------------| +| API (`FundLab.Api.dll`, Release publish) | `127.0.0.1:5080` | `fundlab-api.service` | +| Web gateway (nginx: static `dist/` + `/api`,`/health` proxy) | `127.0.0.1:5176` (frontend) and `127.0.0.1:8098` (tunnel origin) | `fundlab-gateway.service` | +| PostgreSQL 16 (real data dir, docker named volume) | `127.0.0.1:55435` | docker container `fundlab-pg` (`--restart unless-stopped`) | + +Public request path: `cloudflared` -> `127.0.0.1:8098` (gateway) -> static +`src/FundLab.Web/dist` for `/`, and reverse-proxy to the API for `/api/*` and +`/health`. + +### Port note (necessary deviation) + +The tunnel origin is `8098`, but a single origin must serve **both** the +frontend (`/`) and the API (`/api`, `/health`). The API therefore listens on +`127.0.0.1:5080` and the nginx gateway owns `8098` (and `5176`). `curl +http://127.0.0.1:8098/health` still returns the API health payload because the +gateway proxies it. + +## Files + +- `fundlab-api.service`, `fundlab-gateway.service` — systemd user units. +- `nginx-fundlab.conf` — gateway config (high ports, unprivileged user; temp + dirs under `var/fund-lab/`). +- Runtime env/secrets: `.env.deploy` at the repo root (git-ignored via + `.env.*`; contains `FUND_LAB_DATABASE_URL`, `FUND_LAB_AUTH_TOKEN`, + `ASPNETCORE_URLS`, `FUND_LAB_AKSHARE_PYTHON`). Never commit it. +- Logs: `var/fund-lab/{api,gateway,nginx-*.log}` (git-ignored via `var/`). + +## Build + +```sh +# API (Release; FS3511 warning suppressed only for publish) +dotnet publish src/FundLab.Api/FundLab.Api.fsproj -c Release \ + -p:TreatWarningsAsErrors=false -o src/FundLab.Api/publish + +# Frontend -> src/FundLab.Web/dist +cd src/FundLab.Web +PATH="$PWD/../../.tools/node-v22.23.2/bin:$PATH" npm run build +``` + +## Install / run + +```sh +systemctl --user link "$PWD/scripts/systemd/fundlab-api.service" +systemctl --user link "$PWD/scripts/systemd/fundlab-gateway.service" +systemctl --user daemon-reload +systemctl --user enable --now fundlab-api.service fundlab-gateway.service +``` + +`loginctl` linger is already enabled for this user, so the units start on boot. + +## Verify + +```sh +curl -sS http://127.0.0.1:5080/health +curl -sS http://127.0.0.1:5176/ # frontend HTML +curl -sS http://127.0.0.1:8098/health +curl -sS https://fund.somhairle.bid/health +curl -sS https://fund.somhairle.bid/ # frontend HTML (not Somhairle's Dream) +curl -sS -H "Authorization: Bearer $FUND_LAB_AUTH_TOKEN" \ + https://fund.somhairle.bid/api/portfolio/summary +``` + +Auth is a static Bearer token (`FUND_LAB_AUTH_TOKEN`); there is no `/login` +endpoint. `/health` is anonymous; everything under `/api` requires the token. |
