scroll # Portal Awakens (Day 382) How the live Portalactually boots — the full set of flags, env,and companion processes needed to run the wayit does. Grounded in `ecosystem.config.js` +`rust/src/main.rs` (clap `Args`, dotenvyloader) as of Day 382. Companion to[[Postgres-Node-Topology.00382]] and[[Portal-API-Reference.00382]]. ## The liveweb process — `portal-hexlet` ```./rust/target/release/hexos-portal \ --web \--port 3333 \ --static-dir/Volumes/HEXCRAFT/Sacred-Lab/HexOS/Vessels/Web-Vessel/static\ --stream ``` | Flag | Effect | |---|---| |`--web` | Web-server mode — servesWeb-Vessel + full API + websocket. The masterswitch; without it the binary is a CLI/daemon.| | `--port 3333` | Listen port. Also the clap**default**, so technically redundant — butexplicit is correct; cloudflared proxies toit. | | `--static-dir …/Web-Vessel/static` |Where the site is served from. **Must** be`Vessels/Web-Vessel/static` — the old`Portal-Web-Vessel` path doesn't exist andwould 404 the whole site. | | `--stream` |**NOT inert — it's a stitch between the twobinaries.** Does two separable things, onlyone of which was ever feature-gated (seebelow). On this binary it turns on the `/hls`route that serves the segments the standalone`hexos-stream` app produces. | ### `--stream`is a stitch, not a no-op `--stream` does twoseparable things: | Half | Gate | This binary| |---|---|---| | Embedded RTMP ingest(in-process) | `#[cfg(feature = "stream")]`— **compile-time** | **never built in** →prints `⚠️ --stream flag requires buildingwith: cargo build --features stream`. Theembedded RTMP server was never compiled intothe live binary — `stream` is opt-in(`default = ["pty"]`), never used. | | Serving`/hls` over `/tmp/hexos-stream/hls` | plain**runtime** `if stream` (`main.rs:361`) |**active** → `effective_hls_dir =Some("/tmp/hexos-stream/hls")` →`server/mod.rs:1396` nests the `/hls` ServeDir→ logs `📡 HLS serving: /hls →/tmp/hexos-stream/hls` | So the stitch: thestandalone **`hexos-stream`** binary ingestsRTMP on `:1935` and writes HLS segments intothe shared dir `/tmp/hexos-stream/hls`;**`--stream` on Portal** turns on the `/hls`route that serves those exact segments at`hexcraft.dev/hls`. The two binaries arebridged by (a) that shared filesystem dir and(b) the flag toggling Portal's read side.**Drop `--stream` and playback 404s** —Portal stops exposing the directory (`else {None }`, main.rs:363-364). Confirmed live (Day382) by the boot log showing BOTH the `⚠️`warning AND `📡 HLS serving` on the sameboot. **The flags that shape the live processare `--web`, `--port`, `--static-dir`, and`--stream` (its HLS-serving half).**Everything else that makes Portal "run the wayit does" is **env, not flags.** ## Requiredenv ### Set by pm2 (ecosystem `env` block —committed, secret-free) | Var | Value | Why ||---|---|---| | `RUST_LOG` | `info` | Loglevel | | `HEXCRAFT_HEARTH_ID` | `hexlet` |Sovereignty — flips DB discovery tolocalhost-FIRST (db/mod.rs `is_sovereign`), sothe daemon stops reaching across the mesh to`[email protected]` and eating a ~30s pooltimeout on every restart | |`HEXCRAFT_DB_NAME` | `hexlet` | Which PostgresDB this process talks to — a separate axisfrom hearth id | | `CLAUDE_BIN` |`/Users/hex/.local/bin/claude` | TheBrilliant's chronicle Muse pass shells out tothis claude CLI (subscription auth, no raw APIkey); falls to data-only if absent | |`PORTAL_BSKY_INBOUND` | `1` | Enable Jetstreaminbound | | `PORTAL_BSKY_JETSTREAM_HOST` |`jetstream1.us-west.bsky.network` | Pinnedknown-good instance (defaultjetstream2.us-east lagged) | |`PORTAL_BSKY_NOTIFICATIONS_HANDLE` |`hex.hexcraft.dev` | Bluesky account | ###Loaded by Portal itself from `Sacred-Lab/.env`(NOT in ecosystem) Portal calls`dotenvy::from_path` at startup (`main.rs:36``load_dotenv`), checking in order: 1.`$HOME/HEXCRAFT/Sacred-Lab/.env` ← thecanonical one 2. `$HOME/.hexcraft/.env` 3.`./.env` (relative to cwd) `dotenvy` is**set-if-absent** — it never overrides a varpm2 already set. So the ecosystem block winsfor `HEARTH_ID`/`DB_NAME`, and `.env`-onlysecrets load cleanly. | Var | Purpose ||---|---| | `HEXCRAFT_MESH_SECRET` |Node-to-node auth — validated constant-timeby `verify_mesh_secret()` (Day 382,[[Portal-API-Reference.00382]]). Must matchacross all nodes; same file = same value | |`PORTAL_BSKY_NOTIFICATIONS_APP_PASSWORD` |Bluesky auth | | `PORTAL_TOKEN` | Daemon / MCPsession token (Claude Code reads via`${PORTAL_TOKEN}` in `.mcp.json`) | |`HEXCRAFT_ENCRYPTION_KEY` | Thing Boxencryption (hexlet box) | |`CLOUDFLARE_API_KEY_NEW`, `ASANA_PAT_HEX` |External API keys | **`.env` is gitignored**— it does NOT travel with `git push` / meshdeploy. It already exists on hexlet. A *new*node needs its own `.env` placed manuallybefore first start, or its mesh writes getrejected (safe-fail: they silently stopsyncing until the file's added). BecausePortal loads `.env` on its own at startup, aplain `pm2 restart` picks up secret changes— `--update-env` is only load-bearing whenyou change the **ecosystem env block** itself.## Companion pm2 apps (part of "the way itruns") | App | Command | Role | |---|---|---|| `portal-hexperiment` | `--web --port 3334--static-dir …` (no `--stream`),`HEXCRAFT_DB_NAME=hexperiment` | Local dev —same binary, second DB, localhost-only, notedge-exposed | | `hexos-stream` | `--rtmp-addr0.0.0.0:1935 --http-addr 0.0.0.0:8443--hls-dir /tmp/hexos-stream/hls` | TheRTMP→HLS media server (separate crate).Ingests RTMP, writes HLS segments to theshared dir. Portal's `--stream` serves thosesegments at `/hls` — the two are stitchedvia that dir (see `--stream` section above) || `cloudflared` | `start-cloudflared.sh`(interpreter: none) | Public ingress / edgetunnel | ⚰️ **Entombed (Day 375):**`lumen-daemon` pm2 app retired — theBrilliant's daily chronicle now runsin-process (`maybe_create_daily_chronicle()`at the daily tick, Muse via the claudesubprocess). ccmd-006. ## Flags that exist butthe live process does NOT use `--api` (webimplies it), `--daemon` (the dark-command path— `hx` / local forge), `--forest` (SQLiteoffline sovereignty), `--migrate`, `--token`,`--tcp-port`, `--vessel`, `--plain` /`--json`, and `--rtmp-addr` / `--hls-dir`(those belong to `hexos-stream`, notPortal-with-`--stream`). ## Restart / bootmechanics - hexlet runs everything under**PM2**; launchd agent `pm2.hex.plist`resurrects on boot. - Source of truth:`/Volumes/HEXCRAFT/Sacred-Lab/HexOS/Portal/ecosystem.config.js`.- Restart one app from the ecosystem file,then persist: ``` ssh hexlet "zsh -l -c 'cd/Volumes/HEXCRAFT/Sacred-Lab/HexOS/Portal &&pm2 restart ecosystem.config.js --only <app>--update-env'" ssh hexlet "zsh -l -c 'pm2save'" ``` - PM2 over SSH needs a login shell:`ssh hexlet "zsh -l -c '<pm2 cmd>'"`. - Verifya stream-capable Portal binary by the boot logline `📡 Stream server: RTMP=… HLS=…`,NOT by `strings` (clap args compile inunconditionally even without the feature). ##Source pointers - `Portal/ecosystem.config.js`— all four app definitions, env blocks. -`Portal/rust/src/main.rs:36` (`load_dotenv`),`:187-255` (clap `Args`), `:361-365` (the `ifstream` → `effective_hls_dir` stitch),`:349-352` (the`#[cfg(not(feature="stream"))]` RTMP warningbranch). -`Portal/rust/src/server/mod.rs:1395-1398` —the `/hls` ServeDir nest gated on`config.hls_dir`. -`Portal/rust/src/db/mod.rs` — `is_sovereign`/ `DbConfig::db_name` (HEARTH_ID vs DB_NAMEaxes). - `Sacred-Lab/.env` — the secretsource (gitignored). </content>