generated from eblume/project-template
doc(heph-pwa): production runbook — host the app from the hub (indri) with OIDC
All checks were successful
Build / validate (pull_request) Successful in 6m18s
All checks were successful
Build / validate (pull_request) Successful in 6m18s
Add host-heph-pwa.md: a deployment how-to for serving the PWA from the canonical hub in the hub/spoke OIDC setup (post-release) — fetch the shell at the hub's tag, add --web-root, terminate TLS (tailscale serve / reverse proxy), and the token-paste caveat with the device-code-login follow-up. Cross-linked from heph-pwa and the how-to index. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
271c609c14
commit
936c2635ef
3 changed files with 129 additions and 0 deletions
|
|
@ -112,6 +112,7 @@ Search (🔍 or `/`) runs full-text search across tasks and docs.
|
|||
|
||||
## Related
|
||||
|
||||
- [[host-heph-pwa]] — serve this app from the hub (indri) with OIDC, in the hub/spoke deployment
|
||||
- [[set-up-sync-hub]] — stand up the server-mode hub the app talks to
|
||||
- [[run-the-daemon]] — run `hephd` as a managed service
|
||||
- [[v1-prototype-tech-spec]] — data model, RPC API, quick-add spec
|
||||
|
|
|
|||
127
docs/how-to/host-heph-pwa.md
Normal file
127
docs/how-to/host-heph-pwa.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
---
|
||||
title: Host heph-pwa from the hub
|
||||
modified: 2026-06-04
|
||||
tags:
|
||||
- how-to
|
||||
---
|
||||
|
||||
# Host heph-pwa from the hub
|
||||
|
||||
How to serve the [[heph-pwa]] mobile app from the canonical **hub** (`indri`) in
|
||||
the hub-and-spoke deployment, with OIDC auth — the production counterpart of the
|
||||
unauthenticated single-machine demo. Assumes the `heph-pwa` work is **merged and
|
||||
released**, so the installed `hephd` already has `--web-root` and CORS.
|
||||
|
||||
> Read [[set-up-sync-hub]] first — this builds directly on the hub it stands up
|
||||
> (server mode, Authentik OIDC, Tailscale transport).
|
||||
|
||||
## What the app needs from the hub
|
||||
|
||||
The PWA is a thin, online-only client: it loads its static shell over HTTP and
|
||||
makes JSON-RPC calls to the hub's `/rpc`. So the hub must (1) serve the shell
|
||||
files and (2) accept the app's authenticated RPC calls. Both are already in
|
||||
`hephd --mode server`:
|
||||
|
||||
- `--web-root <dir>` serves the shell for any non-API path (with an `index.html`
|
||||
SPA fallback). The shell is unauthenticated — it is only HTML/JS; all data
|
||||
still flows through the OIDC-gated `/rpc`.
|
||||
- Every response carries permissive CORS headers and answers the `OPTIONS`
|
||||
preflight, so the shell may instead be hosted anywhere and still call the hub
|
||||
cross-origin.
|
||||
|
||||
## 1. Put the shell on the hub
|
||||
|
||||
The release does not yet bundle the app, so fetch the `heph-pwa/` directory at
|
||||
the **same version tag** the hub runs (keeping shell and hub in lockstep matters
|
||||
— see *Upgrades* below), and copy it to a stable path:
|
||||
|
||||
```bash
|
||||
# on indri, matching the running hephd version (e.g. v1.4.0)
|
||||
git clone --depth 1 --branch v1.4.0 \
|
||||
https://forge.ops.eblu.me/eblume/hephaestus.git /tmp/heph-src
|
||||
sudo mkdir -p /var/lib/heph/web
|
||||
sudo cp -r /tmp/heph-src/heph-pwa/. /var/lib/heph/web/
|
||||
```
|
||||
|
||||
> **Future improvement:** have the release workflow package a `heph-pwa-<version>.tar.gz`
|
||||
> asset (as it already does for docs), so this step becomes "download + extract"
|
||||
> and the lockstep is automatic. Until then, pin the clone to the hub's tag.
|
||||
|
||||
## 2. Add `--web-root` to the hub service
|
||||
|
||||
Extend the hub invocation from [[set-up-sync-hub]] with `--web-root` (everything
|
||||
else — issuer, audience, db — unchanged):
|
||||
|
||||
```bash
|
||||
hephd --mode server \
|
||||
--http-addr 0.0.0.0:8787 \
|
||||
--db /var/lib/heph/heph.db \
|
||||
--web-root /var/lib/heph/web \
|
||||
--oidc-issuer https://authentik.ops.eblu.me/application/o/heph/ \
|
||||
--oidc-audience <heph-client-id>
|
||||
```
|
||||
|
||||
In the systemd unit (or launchd plist), add the two `--web-root` arguments and
|
||||
`systemctl restart hephd`. Self-update is compatible now that the release ships
|
||||
the flag — just refresh the web-root on each upgrade (next section).
|
||||
|
||||
## 3. Terminate TLS (recommended)
|
||||
|
||||
Serve the app over **HTTPS** so it is a *secure context*: only then do the
|
||||
service worker (offline launch), proper PWA install, and the Web Speech mic
|
||||
work. (On iOS, "Add to Home Screen" and keyboard dictation work over plain HTTP
|
||||
too, so HTTPS is a polish step, not a blocker.) Two good options:
|
||||
|
||||
- **Tailscale serve** — tailnet-only, automatic MagicDNS cert, no public
|
||||
exposure:
|
||||
|
||||
```bash
|
||||
tailscale serve --bg --https=443 http://127.0.0.1:8787
|
||||
# app is then at https://indri.<tailnet>.ts.net/
|
||||
```
|
||||
|
||||
Bind `hephd` to `127.0.0.1:8787` in this case and let Tailscale be the only
|
||||
thing exposing it.
|
||||
|
||||
- **Reverse proxy** (Caddy / nginx) terminating a real cert, if the hub should
|
||||
be reachable beyond the tailnet. Proxy all paths (`/`, `/rpc`, `/sync/*`) to
|
||||
`hephd`.
|
||||
|
||||
Either way the app is same-origin with the hub, so no CORS is involved and the
|
||||
app defaults its hub URL to its own origin.
|
||||
|
||||
## 4. Connect a phone
|
||||
|
||||
1. Ensure the phone is on the tailnet (or can reach the proxy).
|
||||
2. Open the hub URL (`https://indri.<tailnet>.ts.net/`) and **Add to Home Screen**.
|
||||
3. The app defaults its **Hub URL** to the origin it loaded from — no typing.
|
||||
4. **Token:** the hub requires an OIDC bearer token, and the PWA does **not yet
|
||||
implement the in-app device-code login** — paste a token into Settings →
|
||||
Token for now. Obtain one via the device-code flow against the Authentik
|
||||
client (the same flow the CLI uses; e.g. reuse the access token a logged-in
|
||||
spoke cached, or run a one-off device-code grant). Tap **Test** to confirm.
|
||||
|
||||
> **Known gap / next step:** wire the RFC 8628 device-code flow into the PWA's
|
||||
> Settings so login is in-app (open the verification URL, poll for the token,
|
||||
> store it, and refresh it) — removing the manual paste. Tracked as follow-up
|
||||
> work for `heph-pwa`.
|
||||
|
||||
## Upgrades
|
||||
|
||||
On each hub upgrade, refresh the shell so it matches the running `hephd`:
|
||||
|
||||
```bash
|
||||
git -C /tmp/heph-src fetch --depth 1 origin v1.5.0 && git -C /tmp/heph-src checkout v1.5.0
|
||||
sudo cp -r /tmp/heph-src/heph-pwa/. /var/lib/heph/web/
|
||||
```
|
||||
|
||||
The service worker is versioned (`CACHE = "heph-pwa-vN"`), so an updated shell
|
||||
evicts the old cache on next load. Hard-refresh once if a phone seems stuck on a
|
||||
stale version.
|
||||
|
||||
## Related
|
||||
|
||||
- [[heph-pwa]] — the app itself (features, quick-add, voice, triage)
|
||||
- [[set-up-sync-hub]] — stand up the hub + Authentik OIDC this doc extends
|
||||
- [[run-the-daemon]] — run `hephd` as a managed service
|
||||
- [[v1-prototype-tech-spec]] — RPC API and auth model
|
||||
|
|
@ -22,3 +22,4 @@ Task-oriented guides for common operations.
|
|||
- [[import-todoist]] — Seed a heph store from your Todoist projects + tasks (`mise run import-todoist`)
|
||||
- [[self-update]] — Opt-in `hephd` self-update: poll the forge for new releases and auto-update
|
||||
- [[heph-pwa]] — The mobile app: an installable PWA mirror of heph-tui (browse, triage, fast quick-add, voice)
|
||||
- [[host-heph-pwa]] — Serve the mobile app from the hub (indri) with OIDC, in the hub/spoke deployment
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue