−
100%
+
fit
scroll
# HexOS Portal Infrastructure **Last
Updated**: Day 00357 (2026-05-31) **Witness**:
Lumen **Purpose**: Orientation for portal
boot, dev/prod topology, and DB model --- ##
Topology ```
+----------------------------------------------------------+
| HEXLET (Mini Temple - macOS aarch64)
PRODUCTION | |
--------------------------------------------------------
| | Domain: portal.hex-os.dev (via cloudflared
tunnel) | | Process: pm2 -> hexos-portal --web
--port 3333 | | DB: PostgreSQL localhost:5432
<- canonical | | Static:
Portal-Web-Vessel/static/ (served by binary) |
| MCP: https://portal.hex-os.dev/mcp |
+----------------------------------------------------------+
^ all nodes try to connect here first |
+----------------------------------------------------------+
| hexperiment (DigitalOcean - Linux amd64)
DEVELOPMENT | |
--------------------------------------------------------
| | Domain: portal.hexperiment.dev | |
Process: pm2 -> hexos-portal --web --port 3333
| | DB: NO local PostgreSQL - connects to
HEXLET | | Falls back to Forest (SQLite) if
unreachable | | Role: dev copy - outer ring |
+----------------------------------------------------------+
``` No nginx. The portal binary handles all
routing, static files, WebSocket, and API via
tower_http (ServeDir) and axum. Cloudflared
tunnel exposes HEXLET externally. --- ## DB
Model (Day 357) **One canonical PostgreSQL:
HEXLET.** Every node (including hexperiment)
tries to connect to HEXLET's DB first. If
HEXLET is unreachable, it falls back to Forest
(local SQLite snapshot). **hexperiment must
NOT run a local PostgreSQL.** If its local
postgres is running, the portal connects there
instead of HEXLET and diverges. To verify
hexperiment is using the right DB: ```bash ssh
hexperiment "pgrep postgres && echo 'WARNING:
local postgres running' || echo 'OK: no local
postgres'" # If running, stop it: ssh
hexperiment "sudo systemctl stop postgresql"
``` --- ## Development Workflow hexperiment
runs newer code against the same canonical DB
as production. "Slightly ahead of production"
means the binary, not the data. ```
hexperiment (dev) HEXLET (prod)
----------------- ------------- Build + test
code -> mesh repo push cargo build --release
git pull + rebuild pm2 restart hexos-portal
pm2 restart hexos-portal ``` --- ## Startup
Commands ### Both nodes — pm2 manages the
portal Always verify pm2 has --static-dir in
its args before restarting: ```bash pm2 show
hexos-portal # check 'script args' includes
--static-dir ``` If --static-dir is missing,
re-register: ```bash pm2 delete hexos-portal
pm2 start /path/to/hexos-portal --name
hexos-portal --interpreter none \ -- --web
--port 3333 \ --static-dir
/path/to/Portal-Web-Vessel/static pm2 save ```
### HEXLET paths ``` binary:
~/HEXCRAFT/Sacred-Lab/HexOS/Portal/rust/target/release/hexos-portal
static-dir:
~/HEXCRAFT/Sacred-Lab/HexOS/Portal-Web-Vessel/static
pm2: /opt/homebrew/bin/pm2 ``` ### hexperiment
paths ``` binary:
~/HEXCRAFT/Sacred-Lab/HexOS/Portal/rust/target/release/hexos-portal
static-dir:
~/HEXCRAFT/Sacred-Lab/HexOS/Portal-Web-Vessel/static
pm2:
~/.nvm/versions/node/v22.17.0/lib/node_modules/pm2/bin/pm2
node: ~/.nvm/versions/node/v22.17.0/bin/node
``` ### Rebuild flow ```bash cd
~/HEXCRAFT/Sacred-Lab/HexOS/Portal/rust # Free
disk first if on hexperiment (tight 25G
droplet): rm -rf target/release/deps
target/release/build
target/release/.fingerprint cargo build
--release pm2 restart hexos-portal ``` --- ##
Static Files The binary serves static files
via tower_http::ServeDir. No nginx. -
`--static-dir` is required for /init/ shell
and /assets/ - Chips (/init/chips/*.js) come
from the DB (Hexocampus), not disk - Being
pages generate HTML inline in Rust — no
static-dir needed for them --- ## Token
Formats | Format | Type | Created by |
|--------|------|------------| |
`scrd_dmn_<hex>` | Daemon session token |
`api_handlers.rs` (current) | | `scrd_<hex>` |
User session token | `api_handlers.rs` | |
`scrd_trav_<hex>` | Traveler session |
`db/beings.rs` | | `dmn_<hex>` | Daemon
fingerprint stored in Thing | `db/beings.rs` |
MCP Bearer token in `.mcp.json` uses
`scrd_dmn_` format. It is a session stored via
`create_session` and validated by
`validate_session_from_things`. --- ## Boot
Orientation Checklist ```bash # 1. Which DB is
the portal connected to? △ status # shows DB
host + thing count # 2. Is hexperiment's local
postgres stopped? ssh hexperiment "pgrep
postgres || echo clean" # 3. Is HEXLET portal
running? curl -s
https://portal.hex-os.dev/api/health # 4. Does
pm2 have --static-dir? pm2 show hexos-portal |
grep args ``` --- ## Common Issues ###
`Session invalid` in `△ status` MCP daemon
token (`scrd_dmn_`) was not propagated to the
execution token context. Fixed Day 357 in
`mcp/mod.rs`: `set_execution_token` now called
inside `spawn_blocking`. ### hexperiment
connecting to wrong DB Local postgres is
running. Stop it: `sudo systemctl stop
postgresql` Portal will then connect to HEXLET
(or Forest if offline). ### Blank /init/ page
or missing assets Web server started without
`--static-dir` in pm2 config. Fix: delete and
re-register the pm2 entry with the flag (see
Startup Commands). ### Disk full on
hexperiment (25G droplet) Clear build
intermediates: `rm -rf target/release/deps
target/release/build
target/release/.fingerprint` This frees ~1.3G
and forces a full recompile on next build. ---
*Forged Day 00357 - replaces INFRASTRUCTURE.md
(Day 00193)* *Updated Day 00357 - removed
nginx (tower_http ServeDir), corrected pm2 on
both nodes* *Lumen*
△