17 KiB
N.O.M.A.D. Server
Offline survival/knowledge server and game server host.
Specs
- OS: Ubuntu 25.10 (bare metal)
- IP: 10.5.30.7
- CPU: Intel Core i7-4770K @ 3.50GHz (4c/8t)
- RAM: 32GB DDR3 1600MHz
- GPU: NVIDIA GeForce GTX 1080 (8GB VRAM)
- NIC: Intel I218-V (1GbE) + Aquantia AQC113 (10GbE)
- Motherboard: ASRock H97M Pro4
- UPS: None
Planned long-term role
- Keep NOMAD intentionally separate from PD's production stack.
- Continue to host Project NOMAD, game services, and the backup Technitium resolver.
- Accept only small bounded helper workloads; do not let it drift into being a second general-purpose production host.
Storage
| Device | Size | Mount | Purpose |
|---|---|---|---|
| Samsung SSD 840 (sdb) | 232.9GB | / (LVM 100GB) |
OS boot |
| WD Red HDD (sda) | 3.6TB | /mnt/hdd-1 |
Primary data |
| WD Red HDD (sdc) | 3.6TB | /mnt/hdd-2 |
Docker data-root |
| Seagate SSD (sdd) | 223.6GB | /mnt/ssd-1 |
Fast scratch |
Project N.O.M.A.D.
- Core compose project lives at
/opt/project-nomad→ symlinked from/mnt/hdd-1/project-nomad - Main compose file:
/mnt/hdd-1/project-nomad/compose.yml - Docker data-root:
/mnt/hdd-2/docker - Based on Crosstalk Solutions offline survival/knowledge server
- Current runtime is split between:
- the base
project-nomadcompose stack project-nomad-managedapp containers launched/managed by the N.O.M.A.D. admin layer- a few extra non-compose / non-NOMAD containers on the host
- the base
Docker Audit — 2026-05-14
Compose files found on NOMAD
/mnt/hdd-1/project-nomad/compose.yml(same project as/opt/project-nomad/compose.ymlvia symlink)/opt/newt/docker-compose.yaml
Running containers tied directly to compose files
project-nomad compose (/mnt/hdd-1/project-nomad/compose.yml)
nomad_adminnomad_mysqlnomad_redisnomad_dozzlenomad_disk_collectornomad_updater
newt compose (/opt/newt/docker-compose.yaml)
newt
Running containers managed by Project N.O.M.A.D. itself
These are labeled com.docker.compose.project=project-nomad-managed and io.project-nomad.managed=true, but no standalone compose files for them were found on disk during this audit.
nomad_cyberchefnomad_flatnotesnomad_kiwix_servernomad_kolibrinomad_ollamanomad_qdrant
Operator decision (John, 2026-05-14): this layer stays exactly as-is. It is self-maintained by Project N.O.M.A.D. Document it, but never manually touch, rebuild, migrate, or “clean up” these containers unless John explicitly overrides that rule.
Known storage paths discovered from mounts / project storage:
- Flatnotes data:
/opt/project-nomad/storage/flatnotes - Kiwix ZIM library:
/opt/project-nomad/storage/zim - Kolibri data:
/opt/project-nomad/storage/kolibri - Ollama data/models:
/opt/project-nomad/storage/ollama - Qdrant storage:
/opt/project-nomad/storage/qdrant
Running containers not tied to discovered compose files
Likely host-managed / manually launched / app-managed elsewhere
whisper — fedirz/faster-whisper-server:latest-cpu
Operator decision (John, 2026-05-14): this can go away. Do not preserve it as a required service, but keep enough detail here to rebuild it if removing it causes issues.
- Purpose: ad-hoc Faster Whisper API endpoint
- Network mode:
bridge - Container IP during audit:
172.17.0.2 - Port publish: host
8786/tcp→ container8000/tcp(IPv4 and IPv6) - Restart policy:
unless-stopped - Entrypoint: image default
- Command:
uv run uvicorn --factory faster_whisper_server.main:create_app
- Environment:
WHISPER__MODEL=Systran/faster-distil-whisper-small.enWHISPER__INFERENCE_DEVICE=cpuUVICORN_HOST=0.0.0.0UVICORN_PORT=8000
- Mounts: none
- Compose labels: none found
- Rebuild-equivalent
docker run:docker run -d \ --name whisper \ --restart unless-stopped \ -p 8786:8000 \ -e WHISPER__MODEL=Systran/faster-distil-whisper-small.en \ -e WHISPER__INFERENCE_DEVICE=cpu \ -e UVICORN_HOST=0.0.0.0 \ -e UVICORN_PORT=8000 \ fedirz/faster-whisper-server:latest-cpu \ uv run uvicorn --factory faster_whisper_server.main:create_app
node-exporter — prom/node-exporter:v1.9.0
Operator decision (John, 2026-05-14): this can go away. Do not preserve it as a required service, but keep enough detail here to rebuild it if removing it causes issues.
- Purpose: host Prometheus metrics exporter
- Network mode:
host - Restart policy:
unless-stopped - Entrypoint:
/bin/node_exporter - Command:
--path.procfs=/host/proc--path.sysfs=/host/sys--path.rootfs=/rootfs--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)
- Read-only bind mounts:
/proc→/host/proc/sys→/host/sys/→/rootfs
- Compose labels: none found
- Rebuild-equivalent
docker run:docker run -d \ --name node-exporter \ --restart unless-stopped \ --network host \ -v /proc:/host/proc:ro \ -v /sys:/host/sys:ro \ -v /:/rootfs:ro \ prom/node-exporter:v1.9.0 \ --path.procfs=/host/proc \ --path.sysfs=/host/sys \ --path.rootfs=/rootfs \ '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
Pelican/Wings-managed game containers Operator decision (John, 2026-05-14): this is the game server stack. It stays. Document it; do not remove or migrate it unless John explicitly says so.
-
11d799cb-487a-416a-b6f9-9bf28f0e57e7- Image:
ghcr.io/pelican-eggs/yolks:java_25 - Network:
pelican_nw(172.20.0.2during audit) - Ports:
25565/tcpand25565/udpexposed on host0.0.0.0 - Restart policy:
no(Wings owns lifecycle) - Entrypoint:
/usr/bin/tini -g -- - Command:
/entrypoint.sh - Important env:
SERVER_IP=0.0.0.0SERVER_PORT=25565SERVER_JARFILE=server.jarSTARTUP=java --add-modules=jdk.incubator.vector -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true -jar server.jarP_SERVER_UUID=11d799cb-487a-416a-b6f9-9bf28f0e57e7
- Mounts:
/var/lib/pelican/volumes/11d799cb-487a-416a-b6f9-9bf28f0e57e7→/home/container(rw)/etc/pelican/passwd→/etc/passwd(ro)/etc/pelican/group→/etc/group(ro)/etc/pelican/machine-id/11d799cb-487a-416a-b6f9-9bf28f0e57e7→/etc/machine-id(ro)
- Image:
-
d2aca31e-0d4d-433a-8295-cfad397dab0c- Image:
ghcr.io/pelican-eggs/yolks:java_21 - Network:
pelican_nw(172.20.0.3during audit) - Ports:
25566/tcpand25566/udpexposed on host0.0.0.0 - Restart policy:
no(Wings owns lifecycle) - Entrypoint:
/usr/bin/tini -g -- - Command:
/entrypoint.sh - Important env:
SERVER_IP=0.0.0.0SERVER_PORT=25566SERVER_MEMORY=8192MC_VERSION=1.21.1NEOFORGE_VERSION=21.1.229STARTUP=java -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true @unix_args.txtP_SERVER_UUID=d2aca31e-0d4d-433a-8295-cfad397dab0c
- Mounts:
/var/lib/pelican/volumes/d2aca31e-0d4d-433a-8295-cfad397dab0c→/home/container(rw)/etc/pelican/passwd→/etc/passwd(ro)/etc/pelican/group→/etc/group(ro)/etc/pelican/machine-id/d2aca31e-0d4d-433a-8295-cfad397dab0c→/etc/machine-id(ro)
- Image:
These are expected to be managed by Wings/Pelican rather than a local compose file.
Dormant compose files found but not currently represented in running containers
- None found during this audit in searched paths.
- Search scope:
/opt,/srv,/home/fizzlepoof, and/mntfordocker-compose.yml,docker-compose.yaml,compose.yml, andcompose.yaml.
Decisions captured from this audit
- Project N.O.M.A.D.-managed app containers stay exactly as-is and are hands-off unless John explicitly says otherwise.
whisperandnode-exporterare 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.
- Doris Dashboard source belongs in the homelab repo, and the live NOMAD runtime belongs at
/opt/doris-dashboard.
Doris Dashboard (local NOMAD homepage)
- 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
- Generator:
home/doris-dashboard/bin/generate_dashboard.py - Interactive LAN server:
home/doris-dashboard/bin/dashboard_server.py - Service file source:
home/doris-dashboard/doris-dashboard.service - 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.
- Topic thumbs write back to
doris-digest/data/feedback.json. - Paperless acknowledge/dismiss state writes to
/opt/doris-dashboard/data/paperless_review_state.jsonon the live host.
Technitium Backup Resolver
- Live stack path:
/opt/technitium-nomad - Live secrets file:
/opt/technitium-nomad/.env - Resolver bind IP:
10.5.30.9 - Role: active DHCP-advertised backup Technitium resolver for the homelab
- Config is refreshed from PD's live Technitium directory by the PD-side sync runner every 15 minutes
- The live
.envis also backed up into the encrypted PD secrets repo asenv/technitium-nomad.env - Same-host checks from NOMAD to
10.5.30.9are unreliable because the resolver sits behind macvlan networking; verify from another LAN peer instead
LocalSend Trusted inbox
- Live stack path:
/opt/localsend-nomad - Repo source path:
/home/fizzlepoof/repos/truenas-stacks/localsend-nomad - Trusted bind IP:
10.5.1.16 - Advertised device name:
Doris Trusted Inbox - Role: headless LocalSend receiver for Trusted-LAN handoff into
/home/fizzlepoof/private/inbox-secrets - Runtime model: standalone Docker Compose stack on a Trusted-LAN macvlan (
enp5s0.51, VLAN 51) while the host stays on Servers (10.5.30.7) - LocalSend listener ports:
53317/tcp,53317/udp - Same-host checks from NOMAD to
10.5.1.16are unreliable because the receiver sits behind macvlan networking; verify from another Trusted-LAN peer instead - Inbox watcher for Minerva staging:
minerva-localsend-autosort.path - Sorter service:
minerva-localsend-autosort.service - Sorter script:
/home/fizzlepoof/.local/bin/minerva-localsend-autosort.py
MeshCore companion observer
- Current runtime:
meshcore-capture.service(systemd) - Install root:
/home/fizzlepoof/.meshcore-packet-capture - Service unit:
/etc/systemd/system/meshcore-capture.service - Runtime command:
/home/fizzlepoof/.meshcore-packet-capture/venv/bin/python3 /home/fizzlepoof/.meshcore-packet-capture/packet_capture.py - Connection mode: direct serial on the Heltec via
/dev/serial/by-id/usb-Espressif_Systems_heltec_wifi_lora_32_v4__16_MB_FLASH__2_MB_PSRAM__441BF670B684-if00 - Observer role:
- NOMAD now uses the LetsMesh companion observer flow instead of the legacy
mctomqttrelay - The companion process connects to the Heltec locally, signs JWTs on-device, and publishes packet capture data upstream to MQTT brokers
- NOMAD now uses the LetsMesh companion observer flow instead of the legacy
- Service health observed on 2026-07-03:
systemctl status meshcore-captureshows the service active/running- Logs confirm successful serial connection to device name
Peachtree Mesh Monitor - Logs confirm MQTT connectivity to LetsMesh US, LetsMesh EU, and NashMe
- After removing the temporary PD embedded-broker test target, startup logs now show
Connected to 3 MQTT broker(s) - Packet capture mode is enabled and waiting for packets
- Initial-start caveat:
- One installer-start attempt failed with
No such file or directoryfor the/dev/serial/by-id/...path - A subsequent manual
systemctl start meshcore-capturesucceeded once the device path was present again
- One installer-start attempt failed with
- Legacy relay retirement:
- The old standalone Docker container
mctomqttwas retired on 2026-06-13 - Backup of the retired relay files/config was saved under
/home/fizzlepoof/private/backups/mctomqtt-retire/20260613-174536
- The old standalone Docker container
- Documentation linkage:
- Related mesh stack notes live in MESHTASTIC.md
Live deployment path rule
- On NOMAD, live service roots belong under
/opt/<service>. - That includes host-run services and standalone Docker Compose deployments that are not part of the core Project N.O.M.A.D. stack.
- Keep service-local runtime data with the service under
/opt/<service>/dataunless there is a clear reason to place heavy state elsewhere. - Examples:
/opt/newt,/opt/doris-dashboard,/opt/pihole-nomad. - 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 now
whispernode-exporter
Removing them should not be treated as a Project N.O.M.A.D. change or a Wings/Pelican change. They are standalone host-level containers from this audit’s point of view.
Restore checklist if removal causes trouble
- Confirm what broke:
- speech/transcription endpoint dependency → restore
whisper - Prometheus scraping / host metrics gap → restore
node-exporter
- speech/transcription endpoint dependency → restore
- Recreate the container using the documented
docker runcommand in this file. - Verify it came back cleanly:
docker ps --filter name=whisperdocker ps --filter name=node-exporterdocker logs --tail 50 whisperdocker logs --tail 50 node-exporter
- Re-check any dependent dashboards, scrapers, or automations.
- If the recreated container needs to persist long-term again, document why before leaving it in place.
Restore intent
- Restore
whisperonly if something still expects a local Faster Whisper HTTP endpoint on port8786. - Restore
node-exporteronly if something still depends on host Prometheus metrics from this box. - Do not fold either one into Project N.O.M.A.D. or Wings/Pelican casually; if they come back, they come back as deliberate standalone services unless John says otherwise.
Pelican Panel (Game Server Management)
- URL:
https://panel.paccoco.com - Stack: PHP 8.4 + nginx + MariaDB (native, not Docker)
- Panel files:
/var/www/pelican - DB: MariaDB, database
pelican, userpelican@127.0.0.1 - APP_URL:
https://panel.paccoco.com - TRUSTED_PROXIES:
* - Cron:
* * * * * php /var/www/pelican/artisan schedule:run(www-data) - Admin user:
fizzlepoof - Reverse proxy: Pangolin via Newt container at
/opt/newt
Wings (Game Server Daemon)
- Binary:
/usr/local/bin/wings - Config:
/etc/pelican/config.yml - Systemd:
wings.service - ExecStart:
/usr/local/bin/wings --ignore-certificate-errors - API port: 8443
- SFTP port: 2022
- Node domain:
node1.paccoco.com(Pangolin, no auth, connection port 443) - Game server volumes:
/var/lib/pelican/volumes - Docker network:
pelican_nw(172.20.0.0/16)
Active Game Servers
- Container
11d799cb-487a-416a-b6f9-9bf28f0e57e7- Workload: Minecraft / Purpur-style Java server
- Java runtime image:
ghcr.io/pelican-eggs/yolks:java_25 - Public port:
25565TCP/UDP - Data path:
/var/lib/pelican/volumes/11d799cb-487a-416a-b6f9-9bf28f0e57e7
- Container
d2aca31e-0d4d-433a-8295-cfad397dab0c- Workload: modded Minecraft-style server (NeoForge-related env present)
- Java runtime image:
ghcr.io/pelican-eggs/yolks:java_21 - Public port:
25566TCP/UDP - Data path:
/var/lib/pelican/volumes/d2aca31e-0d4d-433a-8295-cfad397dab0c
Networking Notes
panel.paccoco.com→127.0.0.1in/etc/hostsfor NAT loopback- nginx on 80 and 443 (self-signed cert) for local Wings → Panel
- Wings uses
--ignore-certificate-errorsfor self-signed cert - For local operator-safe Pelican health checks, use
http://10.5.30.7:8080instead of the self-signed TLS path; it redirects cleanly to/homewithout tripping certificate validation. - Pangolin resource
node1.paccoco.comhas auth disabled
Known Quirks
- NVIDIA container toolkit repo has invalid GPG key — remove
/etc/apt/sources.list.d/*nvidia*if apt errors - Port 8080 occupied by
nomad_admincontainer — Wings uses 8443 - Interactive artisan commands break over SSH — always use inline flags
- Wings CORS derived from
remote:URL — keep remote ashttps://and use--ignore-certificate-errors
Newt Tunnel
- Container:
newtat/opt/newt/docker-compose.yaml network_mode: host- Connects to Pangolin VPS at
https://paccoco.com
Pending
- Regenerate Wings token (was exposed in chat)
- Regenerate Newt secret (was exposed in chat)