Standardize NOMAD host-run service paths

This commit is contained in:
Fizzlepoof
2026-05-15 03:08:03 +00:00
parent 837d6e5866
commit 5783963816
5 changed files with 56 additions and 17 deletions

View File

@@ -19,6 +19,16 @@ Each stack contains:
- `.env.example` — committed with placeholder values - `.env.example` — committed with placeholder values
- optional init scripts (e.g. `initdb/`, `initdb-mariadb/`) - optional init scripts (e.g. `initdb/`, `initdb-mariadb/`)
## Host-Run Services
If something on NOMAD is not deployed as a Docker compose stack, its live runtime belongs under `/opt/<service>`.
Examples:
- `/opt/project-nomad`
- `/opt/newt`
- `/opt/doris-dashboard`
Use the repo for source/staging, but do not run production host services from an agent workspace or random checkout under `/home/fizzlepoof/.openclaw/workspace`.
## Deployment Order ## Deployment Order
1. `databases/` — must be up before anything else 1. `databases/` — must be up before anything else
2. `infrastructure/` — newt creates the pangolin network 2. `infrastructure/` — newt creates the pangolin network

View File

@@ -185,10 +185,11 @@ These are expected to be managed by Wings/Pelican rather than a local compose fi
- Project N.O.M.A.D.-managed app containers stay exactly as-is and are **hands-off** unless John explicitly says otherwise. - Project N.O.M.A.D.-managed app containers stay exactly as-is and are **hands-off** unless John explicitly says otherwise.
- `whisper` and `node-exporter` are not protected services; they can be removed, but their exact runtime has been documented above for rebuild/recovery. - `whisper` and `node-exporter` are not protected services; they can be removed, but their exact runtime has been documented above for rebuild/recovery.
- Pelican/Wings-managed game containers are part of the permanent game-server stack on NOMAD and stay in place. - Pelican/Wings-managed game containers are part of the permanent game-server stack on NOMAD and stay in place.
- Doris Dashboard source now lives in the canonical homelab repo at `/home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard` rather than the old workspace-only repo. - Doris Dashboard source belongs in the homelab repo, and the live NOMAD runtime belongs at `/opt/doris-dashboard`.
### Doris Dashboard (local NOMAD homepage) ### Doris Dashboard (local NOMAD homepage)
- Canonical repo path: `/home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard` - Live runtime path: `/opt/doris-dashboard`
- Repo source path: `/home/fizzlepoof/repos/truenas-stacks/home/doris-dashboard`
- Purpose: local-only dashboard for briefing/news/weather/homelab pulse/Paperless review on NOMAD - Purpose: local-only dashboard for briefing/news/weather/homelab pulse/Paperless review on NOMAD
- Generator: `home/doris-dashboard/bin/generate_dashboard.py` - Generator: `home/doris-dashboard/bin/generate_dashboard.py`
- Interactive LAN server: `home/doris-dashboard/bin/dashboard_server.py` - Interactive LAN server: `home/doris-dashboard/bin/dashboard_server.py`
@@ -196,7 +197,12 @@ These are expected to be managed by Wings/Pelican rather than a local compose fi
- Runtime notes: - Runtime notes:
- Generated output and queue snapshots are runtime data; source/config lives in git, generated JSON/HTML does not need to be treated as canonical. - Generated output and queue snapshots are runtime data; source/config lives in git, generated JSON/HTML does not need to be treated as canonical.
- Topic thumbs write back to `doris-digest/data/feedback.json`. - Topic thumbs write back to `doris-digest/data/feedback.json`.
- Paperless acknowledge/dismiss state writes to `home/doris-dashboard/data/paperless_review_state.json` on the local checkout. - Paperless acknowledge/dismiss state writes to `/opt/doris-dashboard/data/paperless_review_state.json` on the live host.
### Host-run service path rule
- Docker/compose-managed stacks live under `/mnt/docker-ssd/docker/compose`.
- Host-run services that are not compose stacks live under `/opt/<service>`.
- Do not run production services from any agent workspace or ad-hoc checkout under `/home/fizzlepoof/.openclaw/workspace`.
### Safe to remove / how to restore ### Safe to remove / how to restore
#### Safe to remove now #### Safe to remove now

View File

@@ -2,16 +2,22 @@
Local static homepage for Johns morning briefing and peek-anytime news dashboard. Local static homepage for Johns morning briefing and peek-anytime news dashboard.
Canonical path: Live runtime path:
```bash ```bash
/home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard /opt/doris-dashboard
```
Source path in the homelab repo:
```bash
/home/fizzlepoof/repos/truenas-stacks/home/doris-dashboard
``` ```
Generated page: Generated page:
```bash ```bash
/home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard/public/index.html /opt/doris-dashboard/public/index.html
``` ```
## What it shows ## What it shows
@@ -29,14 +35,14 @@ Generated page:
## Generate manually ## Generate manually
```bash ```bash
cd /home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard cd /opt/doris-dashboard
bin/generate_dashboard.py bin/generate_dashboard.py
``` ```
## Preview locally ## Preview locally
```bash ```bash
cd /home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard/public cd /opt/doris-dashboard/public
python3 -m http.server 8787 python3 -m http.server 8787
``` ```
@@ -54,9 +60,10 @@ Installed in `fizzlepoof`s crontab:
```cron ```cron
# BEGIN DORIS DASHBOARD # BEGIN DORIS DASHBOARD
DORIS_DASHBOARD_DIR=/home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard DORIS_DASHBOARD_DIR=/opt/doris-dashboard
# Refresh local dashboard after digest collection windows. DORIS_DIGEST_DIR=/home/fizzlepoof/.openclaw/workspace/doris-digest
5,35 6-23 * * * cd $DORIS_DASHBOARD_DIR && bin/generate_dashboard.py >> logs/generate.log 2>&1 # Refresh local dashboard after digest collection windows; wrapper enforces Chicago daytime.
5,35 * * * * cd $DORIS_DASHBOARD_DIR && bin/cron_generate_dashboard.sh >> logs/generate.log 2>&1
# END DORIS DASHBOARD # END DORIS DASHBOARD
``` ```
@@ -139,7 +146,7 @@ Added sections/data:
The generated page still lives at: The generated page still lives at:
```bash ```bash
/home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard/public/index.html /opt/doris-dashboard/public/index.html
``` ```
And the LAN service remains: And the LAN service remains:
@@ -151,7 +158,7 @@ http://10.5.1.16:8787/
Verification commands: Verification commands:
```bash ```bash
cd /home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard cd /opt/doris-dashboard
python3 -m py_compile bin/generate_dashboard.py python3 -m py_compile bin/generate_dashboard.py
bin/generate_dashboard.py bin/generate_dashboard.py
curl -fsS http://127.0.0.1:8787/ | grep 'Doris Dashboard' curl -fsS http://127.0.0.1:8787/ | grep 'Doris Dashboard'
@@ -190,7 +197,7 @@ Implementation notes:
Verify: Verify:
```bash ```bash
cd /home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard cd /opt/doris-dashboard
bin/generate_dashboard.py bin/generate_dashboard.py
python3 - <<'PY' python3 - <<'PY'
import json import json
@@ -219,6 +226,16 @@ Important note:
- The interactive actions require the dashboard to be served by `bin/dashboard_server.py`, not plain `python -m http.server`. - The interactive actions require the dashboard to be served by `bin/dashboard_server.py`, not plain `python -m http.server`.
## Runtime path sanity
The live systemd unit and crontab must point only at:
```bash
/opt/doris-dashboard
```
Do not run the dashboard from an agent workspace. Agent workspaces are for editing and staging; NOMAD host-run services belong under `/opt/<service>`.
## Cron fix — 2026-05-13 ## Cron fix — 2026-05-13
The dashboard cron now uses `bin/cron_generate_dashboard.sh`, which checks America/Chicago daytime internally. This avoids relying on `CRON_TZ`, which NOMAD's cron did not honor consistently. The dashboard cron now uses `bin/cron_generate_dashboard.sh`, which checks America/Chicago daytime internally. This avoids relying on `CRON_TZ`, which NOMAD's cron did not honor consistently.

View File

@@ -1,6 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
export DORIS_DASHBOARD_DIR="${DORIS_DASHBOARD_DIR:-$(pwd)}"
export DORIS_DIGEST_DIR="${DORIS_DIGEST_DIR:-/home/fizzlepoof/.openclaw/workspace/doris-digest}"
hour="$(TZ=America/Chicago date +%H)" hour="$(TZ=America/Chicago date +%H)"
if (( 10#$hour < 6 || 10#$hour > 23 )); then exit 0; fi if (( 10#$hour < 6 || 10#$hour > 23 )); then exit 0; fi
bin/generate_dashboard.py bin/generate_dashboard.py

View File

@@ -7,9 +7,11 @@ Wants=network-online.target
Type=simple Type=simple
User=fizzlepoof User=fizzlepoof
Group=fizzlepoof Group=fizzlepoof
WorkingDirectory=/home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard Environment=DORIS_DASHBOARD_DIR=/opt/doris-dashboard
ExecStartPre=/home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard/bin/generate_dashboard.py Environment=DORIS_DIGEST_DIR=/home/fizzlepoof/.openclaw/workspace/doris-digest
ExecStart=/usr/bin/python3 /home/fizzlepoof/.openclaw/workspace/sgt_angel/truenas-stacks/home/doris-dashboard/bin/dashboard_server.py WorkingDirectory=/opt/doris-dashboard
ExecStartPre=/opt/doris-dashboard/bin/generate_dashboard.py
ExecStart=/usr/bin/python3 /opt/doris-dashboard/bin/dashboard_server.py
Restart=on-failure Restart=on-failure
RestartSec=5 RestartSec=5