Files
jarvis/public_html/admin/downloads/INFRASTRUCTURE-REFERENCE.md
T

42 KiB
Raw Blame History

INFRASTRUCTURE REFERENCE — COMPLETE SYSTEM MAP

Last Updated: 2026-07-06
Owner: Myron Blair — myronblair@outlook.com


TABLE OF CONTENTS

  1. Network Overview
  2. Cloud Servers
  3. On-Premise — Proxmox Hypervisors
  4. On-Premise — Virtual Machines
  5. NAS Storage
  6. Websites (all on DO)
  7. JARVIS AI System
  8. Phone System (FusionPBX)
  9. Networking & VPN
  10. Backup Systems
  11. SSH Quick Reference
  12. Critical Credentials Master List
  13. Git & Repository Management

1. NETWORK OVERVIEW

INTERNET
    │
    ▼
[Cloudflare CDN] ──────────────────────────────────────────────────────────────
    │ (proxied DNS for public sites)
    │
    ├─► [DigitalOcean 165.22.1.228] — CyberPanel/OLS — All websites (7 sites)
    │
    └─► [FusionPBX 134.209.72.226] — FreeSWITCH PBX (SSH via DO relay)

HOME NETWORK (FortiGate router at 10.48.200.1)
    WAN: 97.154.109.245 (dynamic, DDNS: orbisne.fortiddns.com)
    │
    ├─► PVE1 Proxmox    10.48.200.90  (primary hypervisor)
    │     ├── VM 101    10.48.200.97  Home Assistant
    │     ├── VM 112    10.48.200.33  Jellyfin
    │     ├── VM 113    10.48.200.35  MediaStack (Sonarr/Radarr/qBT/Prowlarr)
    │     ├── VM 118    10.48.200.18  Homebridge
    │     ├── VM 120    10.48.200.110 NovaCPX hosting panel
    │     ├── VM 210    10.48.200.210  Ollama (local LLM + vision) — llama3.1:8b, llava:7b
    │     └── CT110     10.48.200.19  WireGuard exit container
    │
    ├─► PVE2 Proxmox    10.48.200.91  (secondary hypervisor)
    │     └── VM 302    10.48.200.99  NetworkBackup
    │
    ├─► Synology NAS    10.48.200.249 — Media & backup storage
    ├─► Yealink T48S    10.48.200.2   — Ext 1000 (Myron Blair, Desk)
    ├─► Yealink T48S    10.48.200.43  — Ext 1001 (Tommy Ivy, Desk)
    ├─► Yealink AX86R   10.48.200.65  — Ext 1002 (Myron Blair, WiFi Work)
    ├─► Yealink T57W    10.48.200.3   — External SIP (United Mirror & Glass)
    ├─► Yealink T57W    10.48.200.83  — Ext 1003 (Kitchen)
    └─► Yealink T57W    10.48.200.85  — Ext 1004 (Master Bedroom)

FortiGate Port Forwards:
  orbisne.fortiddns.com:8006  → PVE1:8006    (Proxmox web UI)
  orbisne.fortiddns.com:8123  → HA:8123      (Home Assistant)
  orbisne.fortiddns.com:22    → HA VM:22     (SSH — key only, unreliable)

2. CLOUD SERVERS

2A. DigitalOcean — Main Server

Field Value
IP 165.22.1.228
OS Ubuntu 22.04 LTS
Panel CyberPanel (OpenLiteSpeed)
SSH ssh root@165.22.1.228 — password: Gonewalk1974!@#
Purpose All public websites (7 sites) — webhook deploy for websites

Key Paths:

  • All sites: /home/<domain>/public_html/

  • Deploy log: per-site (website deploys only)

  • Watchdog log: /usr/local/lsws/logs/watchdog.log

  • Infra repo: /opt/infra

Services running:

  • OpenLiteSpeed web server (lsws) — serves all 7 sites
  • MySQL 8 — all site databases on localhost
  • Redis — session/cache
  • PHP 8.5 (lsphp85) — runtime for all sites
  • Cron jobs: website deploy runner (every 1 min), watchdog (every 5 min)

CyberPanel Web UI: https://165.22.1.228:8090
Login: myron / Joker1974!!!

phpMyAdmin: https://165.22.1.228/phpmyadmin
Login: myron / Joker1974!!!


2B. FusionPBX / FreeSWITCH — PBX Server

Field Value
IP 134.209.72.226
OS Debian (DigitalOcean droplet)
SSH Direct via Tailscale: ssh root@100.74.46.120 — password: Joker1974!@#
Direct SSH Only from: 107.178.2.130 / 97.154.109.245
Purpose VoIP phone system — handles all inbound/outbound calls

Web UI: https://fusion.orbishosting.com
Login: admin / fY7XP5swgtpbzrYLhkeVYkA4744

Database: PostgreSQL
User: fusionpbx / Password: pSJaF9mUJqPr4Sj5mwJyRqvCCpc / Host: 127.0.0.1

SIP Trunk: SignalWire
DID: +1 (817) 764-5007
Gateway: signalwire on external profile (port 5080, UDP)

How calls flow:

Caller → SignalWire SIP → FusionPBX:5080 → IVR (ext 900) → Ring extensions
Outbound: Phone → FusionPBX:5080 → SignalWire → PSTN

SSH Relay Command:

sshpass -p 'Gonewalk1974!@#' ssh -o StrictHostKeyChecking=no root@165.22.1.228 \
  'sshpass -p "Joker1974!@#" ssh -o StrictHostKeyChecking=no root@134.209.72.226 "COMMAND"'

3. ON-PREMISE — PROXMOX HYPERVISORS

PVE1 — Primary Hypervisor

Field Value
Local IP 10.48.200.90
External orbisne.fortiddns.com (FortiGate DDNS — auto-updates on WAN IP change)
OS Proxmox VE 8.x
SSH ssh root@orbisne.fortiddns.com OR ssh root@10.48.200.90 — password: Joker1974!!!
Web UI https://orbisne.fortiddns.com:8006root / Joker1974!!!
Purpose Runs VMs 101, 112, 113, 118, 120, 210, CT110

Useful commands:

qm list                          # list all VMs
qm start/stop/restart <VMID>     # control VMs
qm guest exec <VMID> -- bash -c "cmd"  # run command inside VM (requires QEMU agent)

JARVIS API Token: root@pam!jarvis=c45b5feb-f9a9-445d-a626-14fbb959f78b


PVE2 — Secondary Hypervisor

Field Value
Local IP 10.48.200.91
OS Proxmox VE 8.x
SSH ssh root@10.48.200.91 — password: Joker1974!!!
Web UI https://10.48.200.91:8006root / Joker1974!!!
Purpose Runs VM 302 (NetworkBackup); part of shared Proxmox cluster with PVE1

4. ON-PREMISE — VIRTUAL MACHINES

VM 101 — Home Assistant (PVE1)

Field Value
IP 10.48.200.97
OS Ubuntu + Home Assistant OS/Supervised
Web UI http://orbisne.fortiddns.com:8123myron / [HA password]
SSH Via HA web terminal only (Settings → Add-ons → Advanced SSH & Web Terminal)
Purpose Smart home automation — 212 entities (lights, switches, scenes, sensors)
JARVIS Agent ID: homeassistant_ha — pushes entity states to JARVIS every 10s

JARVIS ↔ HA Integration:

  • HA custom component at /config/custom_components/jarvis_agent/
  • Pushes all entity state changes to JARVIS /api/agent/ha_state (debounced 2s)
  • JARVIS admin toggles → queued in agent_commands table → HA executes natively
  • HA Long-lived Token (Jarvis2): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzNmI0N2I1Njk5ZGQ0MTQ2ODMwZWFmYjZiYTQ1MjJkMSIsImlhdCI6MTc4MDIwMzU5NCwiZXhwIjoyMDk1NTYzNTk0fQ.sYRok-jRDlA4lFgWxLQELcEjkJNGQdprk6ZziLwLtXE

VM 112 — Jellyfin Media Server (PVE1)

Field Value
IP 10.48.200.33
OS Ubuntu 22.04 LTS
SSH ssh root@10.48.200.33 — password: Joker1974!!! (enabled 2026-06-14)
Web UI http://10.48.200.33:8096
Purpose Media streaming server — Movies and TV shows
JARVIS Agent Not yet installed

Media Libraries:

  • Movies: /mnt/mediastack/movies — NFS from MediaStack (10.48.200.35:/media/movies)
  • TV: /mnt/mediastack/tv — NFS from MediaStack (10.48.200.35:/media/tv)

NFS chain: Jellyfin → MediaStack → Synology NAS (/volume1/video/movies and /volume1/video/tv)

Admin token: 7c0ccf78b91d4b5bafa607f585f24f2d

If library scan needed:

curl -X POST "http://10.48.200.33:8096/Library/Refresh" \
  -H "X-Emby-Token: 7c0ccf78b91d4b5bafa607f585f24f2d"

If NFS stale after MediaStack changes:

umount -l /mnt/mediastack/movies && umount -l /mnt/mediastack/tv
mount /mnt/mediastack/movies && mount /mnt/mediastack/tv

VM 113 — MediaStack (PVE1)

Field Value
IP 10.48.200.35
OS Ubuntu 24.04 LTS
SSH Via PVE1: ssh -i /root/.ssh/id_rsa root@10.48.200.35 (no direct access from DO)
Purpose Automated media download pipeline + NFS server to Jellyfin
JARVIS Agent ID: MediaStack_2c00b1b8

Services:

Service Port Login API Key
qBittorrent :8080 admin / Joker1974!!!
Sonarr :8989 admin / Joker1974!!! b43e04350a594846b4ee95261c29e9e0
Radarr :7878 admin / Joker1974!!! 53c4268360444feeae5f98c0cc24e0e3
Prowlarr :9696 admin / Joker1974!!! 9d0ce6c5660743b5bf1c7951efc62252

All services run as root — required by Synology NFS ACL (only root can write).

VPN: NordVPN — nordlynx WireGuard interface — exit IP 181.214.226.188 (US Dallas)
All download traffic exits via NordVPN. If downloads stall, check: ip rule show for rules 32764/32765.

Media Flow:

IPTorrents (Prowlarr) → Sonarr/Radarr search → qBittorrent download
→ /mnt/nas/video/downloads (NAS)
→ Sonarr/Radarr import → /mnt/nas/video/tv or /mnt/nas/video/movies (NAS)
→ NFS → Jellyfin /mnt/mediastack/movies or /mnt/mediastack/tv

Indexer: IPTorrents via Prowlarr cookie auth
Cookie: uid=2237410; pass=JzLP2niTWxBJAZIU3yvtLbJzD55kdLeB
(Expires — if search fails, log into iptorrents.com, copy uid+pass cookies)

If Radarr/Sonarr shows "0 active indexers":

systemctl stop radarr
sqlite3 /var/lib/radarr/radarr.db "DELETE FROM IndexerStatus WHERE ProviderId=1;"
systemctl start radarr

SSH from DO:

sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@10.48.200.90 \
  'ssh -o StrictHostKeyChecking=no -i /root/.ssh/id_rsa root@10.48.200.35 "COMMAND"'

VM 118 — Homebridge (PVE1)

Field Value
IP 10.48.200.18
OS Linux
SSH ssh myron@10.48.200.18 — password: Joker1974!
Purpose Apple HomeKit bridge — exposes non-HomeKit devices to Apple Home app
JARVIS Agent ID: homebridge_b57cbaea

VM 120 — NovaCPX Hosting Panel (PVE1)

Field Value
IP 10.48.200.110
OS Ubuntu 24.04 LTS
SSH ssh root@10.48.200.110 — password: Joker1974!!! (direct, no PVE hop)
Purpose Custom web hosting control panel (cPanel alternative), v1.0.27
JARVIS Agent ID: novacpx_e3b07264

Ports:

Port Panel
:8880 User panel
:8881 Reseller panel
:8882 Admin panel
:8883 Roundcube webmail

Admin: https://10.48.200.110:8882admin / Admin2026!
phpMyAdmin: http://10.48.200.110/phpmyadmin

File Paths:

  • Web root: /srv/novacpx/public/
  • DB (SQLite): /var/lib/novacpx/panel.db
  • Config: /etc/novacpx/config.ini
  • Git repo: /opt/novacpx-src/
  • GitHub: myronblair/novacpx (auto-deploy on push to main)

VM 210 — Ollama Local LLM + Vision (PVE1)

Field Value
IP 10.48.200.210
OS Ubuntu (cloud image)
SSH ssh root@10.48.200.210 via PVE1 hop — password: Joker1974!!!
Purpose Local AI inference — chat (llama3.1:8b) + vision (llava:7b)
API http://10.48.200.210:11434 (Ollama REST API)
JARVIS Agent ID: ollama-ai_ubuntu
Models llama3.1:8b (chat/Tier 1), llava:7b (vision cascade)

JARVIS uses this as Tier 1 AI — if Ollama is down, falls back to Groq (cloud). Vision cascade: Arc Reactor calls Claude first; if Claude credits depleted, falls back to llava:7b via Ollama. Vision is enabled via: /etc/systemd/system/jarvis-arc.service.d/vision.confOLLAMA_VISION_MODEL=llava:7b


VM 302 — NetworkBackup (PVE2)

Field Value
IP 10.48.200.99
OS Ubuntu/Linux
SSH ssh myron@10.48.200.99 — password: Joker1974! (then sudo)
Purpose Network backup storage / backup operations
JARVIS Agent ID: networkbackup_NetworkB

CT110 — WireGuard Exit Container (PVE1)

Field Value
IP 10.48.200.19 / 10.48.200.67
Purpose Legacy WireGuard exit tunnel to DO (10.200.0.4 via wg-exit) — currently NOT used by MediaStack/Jellyfin
Note MediaStack uses NordVPN directly; Jellyfin uses wg1 peer on MediaStack for NFS only

5. NAS STORAGE

Synology NAS

Field Value
IP 10.48.200.249
Login nas / Joker1974!!!
DSM Web UI http://10.48.200.249:5000
Purpose Primary media and download storage

NFS Share: /volume1/video (exported to MediaStack only)

Directory structure:

/volume1/video/
  movies/       ← Radarr imports here; NFS-exported to Jellyfin via MediaStack
  tv/           ← Sonarr imports here; NFS-exported to Jellyfin via MediaStack
  downloads/    ← qBittorrent downloads here (temp)
    incomplete/ ← in-progress torrents

Important: Synology NFS ACL only allows root to write. All services on MediaStack run as root.


6. WEBSITES (ALL ON DO)

All sites are at /home/<domain>/public_html/ on DO (165.22.1.228).
Auto-deploy: Push to main on GitHub → webhook → server pulls in ~1 min.
GitHub PAT: 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 (rotated 2026-07-05 — old PAT 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 was found exposed in .git/config on all 6 original sites and must be treated as compromised/revoked)


jarvis.orbishosting.com — JARVIS AI Dashboard (MOVED TO PVE1 VM 211)

Field Value
URL http://jarvis.orbishosting.com (port 80 — old :1972 reference was wrong, corrected 2026-07-04)
Path /var/www/jarvis/ (on JARVIS VM 10.48.200.211)
GitHub myronblair/jarvis
Login myron / Joker1974!!!
Purpose Iron Man-style AI home dashboard with voice control, smart home, media, planner

See Section 7 for full JARVIS details.


worktracking.orbishosting.com — ChuckCo Time Keeper

Field Value
URL https://worktracking.orbishosting.com
Path /home/worktracking.orbishosting.com/public_html/
GitHub myronblair/chucko (private)
Gitea myron/chucko (pull-mirror of GitHub)
Local clone C:\Users\myron\repos\chucko on admin Windows machine
Purpose Work-tracking app for a flat-rate 5-day (FriThu) work week — self-reported hours via personal secret-URL tokens (no login), single shared admin password, phone-friendly screenshot pages for texting workers/payer
Admin URL https://worktracking.orbishosting.com/admin/login.php — password Joker1974!!!
DB workt_track_db / workt_track_user / ZWCNMRP2N5NVPsghmve5aRS9
Linked from Blair HQ web.orbishosting.com dashboard's "Websites" card has direct links to the admin login and the all-workers overview page (site-wide token 972f82cbf7832fdb2cffcdcc84129a4af69e30bd)
Note Built 2026-07-05. includes/config.php (DB creds, admin password hash, site token) lives outside public_html/webroot and is intentionally NOT in the git repo.
Admin login rate limiting Added 2026-07-06 — login_attempts table (ip_address, attempts, last_attempt) in workt_track_db; 5 failed attempts locks that IP out for 15 minutes.
Code review (2026-07-06) 5 findings fixed and deployed: w.php mark_paid now rejects any week_start that isn't the true current week (was trusting client input); admin/worker.php no longer double-HTML-escapes the page title; all.php now shows a Paid/Unpaid badge per worker for the displayed week; s.php/p.php/all.php validate the week param before building dates (malformed input used to throw an uncaught DateTime exception); admin login rate-limited (see above).

tomsjavajive.com — Tom's Java Jive

Field Value
URL https://tomsjavajive.com
Path /home/tomsjavajive.com/public_html/
GitHub myronblair/tomsjavajive
Purpose Coffee shop e-commerce — products, orders, loyalty, wallet, reviews
Admin URL https://tomsjavajive.com/admin/
Admin Login admin@tomsjavajive.com / Joker1974!!! OR myronblair@outlook.com / Joker1974!!!
DB toms_tjj_db / toms_tjj_user / +60wlPc+55e@gFq4
Email CyberMail API key: sk_live_7f9b0f9a29f6de31a0d229d4af75d56b094ad724fc58a57d
Email From noreply@tomsjavajive.com / Toms Java Jive (set in DB settings table)

epictravelexpeditions.com — Epic Travel Expeditions

Field Value
URL https://epictravelexpeditions.com
Path /home/epictravelexpeditions.com/public_html/
GitHub myronblair/epictravelexpeditions
Purpose Travel booking / expeditions website
DB epic_travel_db (see api/config.php)

parkerslingshot.epictravelexpeditions.com — Parker Slingshot (OLD)

Field Value
URL https://parkerslingshot.epictravelexpeditions.com
Path /home/epictravelexpeditions.com/parkerslingshot/
GitHub myronblair/parkerslingshot
Purpose Old slingshot rental site (superseded by parkerslingshotrentals.com)

parkerslingshotrentals.com — Parker Slingshot Rentals (LIVE)

Field Value
URL https://www.parkerslingshotrentals.com
Path /home/parkerslingshotrentals.com/public_html/
GitHub myronblair/parkerslingshotrentals
Purpose Polaris Slingshot rental — bookings, e-signature waiver, admin management
Admin /admin/index.phpadmin / Parker2026!
DB park_slingshot / park_slingshotuser / 4@rxg*8kovxCr7w6
Square Production token: EAAAl3FsAu_2ri8kZE_ENEyi2T_C8HXXm5XQFY6Lbnd8SX6FqYp8J_upUeXNYh7v

orbishosting.com — Orbis Hosting (Landing Page)

Field Value
URL https://orbishosting.com
Path /home/orbishosting.com/public_html/
GitHub myronblair/orbishosting
Purpose Public landing page for Orbis Hosting brand

orbis.orbishosting.com — Orbis Hosting Portal

Field Value
URL https://orbis.orbishosting.com
Path /home/orbis.orbishosting.com/public_html/
GitHub myronblair/orbis-hosting-portal
Purpose Customer-facing hosting portal

tomtomgames.com — TomTom Games

Field Value
URL https://tomtomgames.com
Path /home/tomtomgames.com/public_html/
GitHub myronblair/tomtomgames
Purpose Gaming website
DB tomtom_games_db (see config)
Email CyberMail API key: sk_live_7f9b...

7. JARVIS AI SYSTEM

URL: http://jarvis.orbishosting.com
Files: /var/www/jarvis/ on JARVIS VM (PVE1 VM 211 — 10.48.200.211, 8 cores, 16GB RAM)
DB: jarvis_dbjarvis_user / J4rv1s_Pr0t0c0l_2026!
Login: myron / Joker1974!!!
Admin portal: http://jarvis.orbishosting.com/admin

Security hardening (2026-07-06 code review)

Full front-end + admin panel review found and fixed 8 issues, 2 of them live critical exposures:

  • INFRASTRUCTURE-REFERENCE.md was publicly downloadable with zero auth (static nginx path bypassed the admin session check entirely). Fixed: file moved to /var/www/jarvis-private/INFRASTRUCTURE-REFERENCE.md (owned www-data:www-data, mode 640, NOT under public_html so nginx never serves it directly), and the DOCS tab now downloads it via a new authenticated docs_download action in admin/index.php that gates on the existing loggedIn() check and streams the file with readfile().
  • Two full backup copies of the 5000-line admin panel (index.php.bak2, index.php.bak.<date>) were sitting in public_html/admin/ and downloadable with no auth, exposing the entire admin source/attack surface. Relocated to /root/jarvis-old-backups/ (no secrets were found in them, so no credential rotation was needed).
  • esc() (the admin panel's JS HTML-escaper) doesn't escape ', so it doesn't protect values embedded inside a single-quoted JS string within an onclick attribute — HTML-decoding happens before the JS parser sees it. Added a proper escJs() helper (backslash + quote + newline escaping, then HTML-escape) and applied it to the Network/Alerts/Intents/Custom-News/Calendar-Feeds edit-modal onclick handlers, which were reachable by e.g. any device on the LAN setting a malicious DHCP/mDNS hostname.
  • Same class of bug on the front-end dashboard (assets/js/jarvis-app.js, assets/js/panels/jarvis-agents.js): device names and news article titles/sources were inserted into innerHTML completely unescaped — a rogue LAN device or a malicious/compromised news feed could inject script that runs with the logged-in session. Added escHtml()/escJs() helpers directly in jarvis-app.js and applied them to device names, VM names, agent hostnames, and news content.
  • session.cookie_httponly was Off server-wide (PHP default), meaning the actual session cookie — not just the app's own bearer token — was readable via document.cookie from any of the above XSS bugs. Fixed at the PHP-FPM level (/etc/php/8.3/fpm/php.ini): session.cookie_httponly = 1, session.cookie_samesite = Lax, php8.3-fpm restarted. Verified live: Set-Cookie now includes HttpOnly; SameSite=Lax.
  • api.php had Access-Control-Allow-Origin: * — tightened to an explicit allow-list of the real JARVIS origin only, with Access-Control-Allow-Credentials: true only sent when the origin matches.
  • Two admin actions (Arc Reactor restart/setup) called an undefined function k() instead of the real JSON responder j(), causing a PHP fatal error even though the underlying systemctl command still fired. Fixed (verified via direct API test — clean {"ok":true,...} response now).
  • Calendar feed passwords were stored and returned in plaintext via cal_feeds_list's SELECT *. Changed to return a has_password boolean instead of the raw password (the edit UI never actually displayed the password back anyway — write-only field, "leave blank to keep").

All fixes verified via direct API testing (SSH + curl through the login/action flow) since this doesn't have a staging environment. Pushed to myronblair/jarvis master, commit 24bc876.

Architecture (end-to-end)

Voice (browser mic)
  → SpeechRecognition API
  → Wake phrase: "wake up JARVIS" / "daddy's home"
  → "JARVIS [command]" triggers action
  → /api/chat.php (4-tier AI)
       Tier 0.7: KB intents / planner (tasks, appointments)
       Tier 1:   Knowledge Base (MySQL)
       Tier 1.5: Ollama (10.48.200.210:11434, llama3.1:8b) — local LLM
       Vision:   Ollama llava:7b (via Arc Reactor _vision_call cascade)
       Tier 2:   Groq (cloud, model: compound-beta-mini)
       Tier 3:   Claude API (Anthropic, fallback)
  → ElevenLabs TTS → browser speaker

Arc Reactor (AI Job Processor)

Service: jarvis-arc (systemd) — port 7474 Runtime: /opt/jarvis-arc/ (Python venv, reactor.py) Log: /var/log/jarvis/arc.log Admin button: Workers → Daemons → SETUP (live popup) / RESTART Vision: Claude → Ollama llava:7b → graceful fallback Vision config: /etc/systemd/system/jarvis-arc.service.d/vision.conf

systemctl status jarvis-arc
systemctl restart jarvis-arc
journalctl -u jarvis-arc -f

To re-deploy Arc Reactor from source: Use Workers → Daemons → SETUP in JARVIS admin (live log popup shows progress).

Planner: Tasks / Directives / Missions

Admin UI sections backed by real schema + live API — verified working 2026-07-02 (created/read/deleted a test row in each, end-to-end).

Tasks — simple to-do list, stored directly in jarvis_db.

  • Table: tasks (title, notes, category, priority [urgent/high/normal/low], status [pending/in_progress/done/cancelled], due_date, due_time)
  • API: task_list (GET), task_save (POST, form-encoded), task_done (POST), task_delete (POST)

Directives — OKR-style goals with key results, stored directly in jarvis_db.

  • Tables: directives (title, description, category, status, priority, target_date) + directive_key_results (directive_id, title, current_value, target_value, unit) + directive_links (directive_id, link_type, link_id — links a directive to a task/etc.)
  • API: directive_list, directive_get, directive_save (POST, JSON body via php://input, id passed as ?id= query param on update), directive_delete

Missions — automation workflows, NOT stored in jarvis_db — proxied through Arc Reactor (port 7474) which owns the mission state.

  • Arc Reactor endpoints used by admin: GET/POST /missions, GET /missions/{id}, GET /missions/{id}/runs, PUT/POST /missions/{id}, DELETE /missions/{id}, POST /missions/{id}/run
  • JARVIS-side mirror tables exist (missions, mission_runs, mission_steps) but the admin panel reads/writes live via Arc Reactor's HTTP API, not directly against these tables
  • API: mission_list, mission_get, mission_runs, mission_save (POST, JSON body, id as ?id= on update), mission_delete, mission_run, mission_toggle
  • If Arc Reactor is down, these calls return {"error":"Arc Reactor unreachable"} — check systemctl status jarvis-arc first

As of 2026-07-02: all three tables are empty (0 rows) — features are fully functional, just unused so far.

Deploy Pipeline

Code edit → git push → GitHub webhook → /webhook.php (HMAC verified)
→ /tmp/jarvis-deploy-queue.txt → /usr/local/bin/jarvis-deploy.sh (cron 1min)
→ git pull + PHP syntax check → deploy or auto-revert

Webhook secret: 4c8805f0285214ff0a0602b5880270b935f36a896946c7f1

Agent System

Agents installed on all servers — phone home every 10s (heartbeat) / 30s (metrics).
Registration key: f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518
Install command: curl -sk http://10.48.200.211/install-agent.sh | bash -s <hostname> <linux|proxmox>

Self-Healing Watchdog

/usr/local/bin/jarvis-watchdog.sh — runs every 5 min (root cron on DO)
Restarts: lsws, mysql, redis if down
Restarts offline Proxmox VM agents via qm guest exec

Cron Jobs (DO server)

Schedule Script Purpose
Every 1 min jarvis-deploy.sh Process GitHub deploy queue
Every 3 min facts_collector.php Collect agent metrics, KB facts, site health
Every 5 min stats_cache.php Weather, news, Proxmox stats refresh
Every 5 min jarvis-watchdog.sh Self-healing: restart dead services

8. PHONE SYSTEM (FUSIONPBX)

Extensions

Ext Name Phone IP SIP Password
1000 Myron Blair — Desk Yealink T48S 10.48.200.2 Xk9mPw3nQv7rLs2t
1001 Tommy Ivy — Desk Yealink T48S 10.48.200.43 Tv8xNm4pWq6rZs3k
1002 Myron Blair — WiFi Work Yealink AX86R 10.48.200.65 yXHaJTwa8rj?$GkrVFQB
1003 Kitchen Yealink T57W 10.48.200.83
1004 Master Bedroom Yealink T57W 10.48.200.85
1010 Parker County Slingshot Virtual (voicemail only)
1011 Epic Travel Expeditions Virtual (voicemail only)
1012 Tom's Java Jive Virtual (voicemail only)
900 IVR (auto-attendant)

Phone SIP Settings (all phones):

  • Server: 134.209.72.226
  • Port: 5080
  • Transport: UDP

Provisioning URL: https://fusion.orbishosting.com/app/provision/
(Username: provision-master, Password: Joker1974!!!)

Call Flow

Inbound (+18177645007)
→ SignalWire → FusionPBX:5080 (UDP)
→ signalwire-inbound dialplan (catch-all ^.*$)
→ IVR ext 900 (ivr_menu_16k.wav)
→ Routes to extensions 1000/1001/1002/1003/1004

Outbound
→ Phone → FusionPBX:5080
→ signalwire gateway → SignalWire → PSTN

FreeSWITCH CLI Commands

fs_cli -x "sofia status profile external reg"   # check registrations
fs_cli -x "sofia xmlstatus gateway"             # check SignalWire gateway
fs_cli -x "reloadxml"                           # reload config (safe)
fs_cli -x "reloadacl"                           # reload ACL (safe)
# AVOID: sofia profile external restart (drops all phone registrations)

9. NETWORKING & VPN

FortiGate Firewall

  • WAN IP: 97.154.109.245 (dynamic)
  • DDNS: orbisne.fortiddns.com (FortiGate auto-updates on IP change)
  • Blocks: outbound port 53 (DNS) — MediaStack uses PVE1 dnsmasq (10.48.200.90) as resolver → 100.100.100.100
  • Upstream DNS (changed 2026-07-05): Network → DNS set to "Specify" mode — Primary 1.1.1.1 (Cloudflare), Secondary 8.8.4.4 (Google). Previously defaulted to the router itself (10.48.200.1)/ISP-provided servers. Admin: https://10.48.200.1:9443admin / Joker1974!!!. Note: 8.8.8.8 specifically showed as "Unreachable" during setup (transient — ISP's own DNS servers were also showing high latency at that moment); 1.1.1.1/8.8.4.4 tested healthy and are what's live now.

Port Forwards:

External Port Internal Destination Purpose
:8006 PVE1:8006 Proxmox web UI
:8123 HA VM:8123 Home Assistant
:22 HA VM:22 HA SSH (unreliable)

WireGuard — Jellyfin ↔ MediaStack

  • MediaStack runs WireGuard server on wg1 (port 51820, subnet 10.200.0.1/24)
  • Jellyfin peer: 10.200.0.3 (active handshake)
  • Used for NFS media file access ONLY — not internet VPN

NordVPN — MediaStack Internet Traffic

  • Interface: nordlynx on MediaStack
  • Exit IP: 181.214.226.188 (US Dallas)
  • Policy routing: table 205 (all traffic via nordlynx), managed by nordvpn-routing.service
  • Required for IPTorrents access (blocks non-VPN IPs)

10. BACKUP SYSTEMS

JARVIS Database Backup

  • Script: /usr/local/bin/jarvis-backup.sh (also at /var/www/jarvis/deploy/)
  • Output: /var/backups/jarvis/jarvis_backup_TIMESTAMP.tar.gz
  • Log: /var/backups/jarvis/backup.log
  • Retention: 7 days (auto-purge)
  • Trigger: JARVIS admin → Backups → RUN BACKUP NOW, or run script directly
  • DB: jarvis_dbjarvis_user / J4rv1s_Pr0t0c0l_2026!

DO Server Backup

  • Repo: myronblair/do-server-config
  • Schedule: Weekly, Sunday 4am
  • Launcher: /usr/local/bin/do-server-backup on DO
  • Covers: Scripts, systemd units, WireGuard, OLS vhosts, cron, MySQL credentials
  • Restore: 8-phase wizard in restore.sh
  • DB backups: jarvis-backup.sh runs daily (separate)

Proxmox Config Backup

  • Repo: myronblair/proxmox-config
  • Schedule: Weekly, Sunday 3am (both PVE1 and PVE2)
  • Launcher: /usr/local/bin/proxmox-backup on each node
  • Covers: VM .conf files, network, cron, systemd, scripts
  • VM disks: Covered by Proxmox Backup Server (PBS)

FusionPBX Backup

  • Repo: myronblair/fusionpbx-config
  • Schedule: Weekly, Sunday 5am
  • Launcher: /usr/local/bin/fusionpbx-backup
  • Covers: PostgreSQL dump (gzip, ~29-60MB) + FreeSWITCH configs
  • Restore: 10-phase wizard in restore.sh
  • Known issue (found 2026-07-05): this repo has grown to ~166MB on GitHub / ~196MB on Gitea because the DB dump gets committed directly into git history on every backup run (3 copies in history as of this writing, each ~60MB) rather than being excluded/rotated. Options not yet decided: gitignore the dump going forward, or purge it from history with git filter-repo + force-push (destructive, needs explicit sign-off).

MSP360 Backup Status (Dashboard Integration)

  • Client software: MSP360 (CloudBerry) Backup CLI installed on all 6 hosts — PVE1, JARVIS (211), NovaCPX (110), Jellyfin (33), MediaStack (35), Homebridge (18)
  • Storage target: NAS-MSPBackups destination → Synology NAS CIFS share, mounted at /mnt/nas-backups/MSPBackups
  • Mount reliability: /usr/local/bin/msp360-mount-ensure.sh (cron */15 * * * * on hosts using the NAS mount) — bind-mounts the MSPBackups subdir onto itself since MSP360's pre-flight mountpoint check fails on a subdirectory of a CIFS mount otherwise
  • Collector: /usr/local/bin/backup-status-collect.sh on PVE1 (runs via key-trusted root SSH — PVE1 is the only host with passwordless SSH to all 6 targets; other hosts use password auth via sshpass)
    • Queries each host's plan via cbb plan -l (legacy v1 CLI — outputs State: / Last result: fields directly, unlike cbbV2/cbbCommandLineV2 which needs plan list -b and different parsing)
    • Writes /tmp/backup-status.json, then scps it to root@10.48.200.110:/home/webacct/public_html/downloads/backup-status.json
    • Schedule: daily 0 6 * * * on PVE1 (>> /var/log/backup-status-collect.log)
  • Dashboard card: web.orbishosting.com "BACKUP STATUS" card (index.html) fetches /downloads/backup-status.json client-side (loadBackupStatus()), color-codes dots by result (green=Success, yellow=Warning, red=Fail, cyan=Running, gray=unknown)
  • JSON schema: {"updated": "<ISO8601 UTC>", "hosts": [{"name","ip","state","result"}, ...]}
  • Homebridge (2026-07-04): dropped MSP360 entirely. After extensive troubleshooting (RAM starvation, a bug where its account scanned every other host's shared backup data, missing bind-mount depths, CIFS tuning, a full plan recreation) Homebridge's MSP360 agent kept failing with a false "storage drive not mounted" error at a consistent ~60-75s mark, root cause never conclusively identified (survived every environmental fix, looked like an app-level bug tied to any custom/non-default account path). Since Homebridge (VM 118) was already being backed up successfully every night by the cluster-wide Proxmox vzdump job (backup-aa6b1890-23c0, all VMs, 21:00 daily, keep-last=3, to SynologyProx storage), MSP360 was stopped/disabled on Homebridge (systemctl disable msp360-backup.service msp360-backupWA.service) and removed from the dashboard collector's per-host MSP360 check. The collector now reads Homebridge's status directly from /mnt/pve/SynologyProx/dump/vzdump-qemu-118-*.vma.zst on PVE1 instead of querying an in-guest agent.
  • Known state (2026-07-04): 4/5 remaining MSP360 hosts report Warning, NovaCPX reports Fail — plan-level result, not investigated further; worth checking each host's MSP360 GUI/log for root cause if backups need to be trusted for restore. Homebridge reports Success via Proxmox.

11. SSH QUICK REFERENCE

# DO (main web server)
sshpass -p 'Gonewalk1974!@#' ssh -o StrictHostKeyChecking=no root@165.22.1.228

# FusionPBX (must relay via DO)
sshpass -p 'Gonewalk1974!@#' ssh root@165.22.1.228 \
  'sshpass -p "Joker1974!@#" ssh root@134.209.72.226 "CMD"'

# PVE1 (direct or via DDNS)
sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@orbisne.fortiddns.com
sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@10.48.200.90

# PVE2
sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@10.48.200.91

# MediaStack (via PVE1)
sshpass -p 'Joker1974!!!' ssh root@10.48.200.90 \
  'ssh -i /root/.ssh/id_rsa root@10.48.200.35 "CMD"'

# Jellyfin (direct, password enabled 2026-06-14)
sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@10.48.200.33

# NovaCPX (direct)
sshpass -p 'Joker1974!!!' ssh -o StrictHostKeyChecking=no root@10.48.200.110

# Ollama / Homebridge / NetworkBackup (myron user, then sudo)
sshpass -p 'Joker1974!' ssh myron@10.48.200.95   # Ollama
sshpass -p 'Joker1974!' ssh myron@10.48.200.18   # Homebridge
sshpass -p 'Joker1974!' ssh myron@10.48.200.99   # NetworkBackup

# Run command inside VM via Proxmox (requires QEMU agent installed)
sshpass -p 'Joker1974!!!' ssh root@10.48.200.90 \
  'qm guest exec 210 -- bash -c "CMD"'

Password fallback order: Joker1974!@#Joker1974!!!Joker1974!


12. CRITICAL CREDENTIALS MASTER LIST

SSH / Root Access

System User Password Notes
DO (165.22.1.228) root Gonewalk1974!@# Main web server
FusionPBX (134.209.72.226) root Joker1974!@# Via DO relay
PVE1 (10.48.200.90) root Joker1974!!! Also via DDNS
PVE2 (10.48.200.91) root Joker1974!!!
MediaStack (10.48.200.35) root key only Via PVE1 (/root/.ssh/id_rsa)
Jellyfin (10.48.200.33) root Joker1974!!! Enabled 2026-06-14
NovaCPX (10.48.200.110) root Joker1974!!! Direct SSH works
Ollama / Homebridge / Backup VMs myron Joker1974! Then sudo

Web Panels & Admin

System URL User Password
CyberPanel https://165.22.1.228:8090 myron Joker1974!!!
phpMyAdmin (DO) https://165.22.1.228/phpmyadmin myron Joker1974!!!
Proxmox PVE1 https://orbisne.fortiddns.com:8006 root Joker1974!!!
Proxmox PVE2 https://10.48.200.91:8006 root Joker1974!!!
JARVIS http://jarvis.orbishosting.com myron Joker1974!!!
JARVIS Admin http://jarvis.orbishosting.com/admin myron Joker1974!!!
ChuckCo Time Keeper Admin https://worktracking.orbishosting.com/admin/login.php Joker1974!!!
FusionPBX https://fusion.orbishosting.com admin fY7XP5swgtpbzrYLhkeVYkA4744
Home Assistant http://orbisne.fortiddns.com:8123 myron (HA password)
NovaCPX Admin https://10.48.200.110:8882 admin Admin2026!
Jellyfin http://10.48.200.33:8096 token: 7c0ccf78b91d4b5bafa607f585f24f2d
qBittorrent http://10.48.200.35:8080 admin Joker1974!!!
Sonarr http://10.48.200.35:8989 admin Joker1974!!!
Radarr http://10.48.200.35:7878 admin Joker1974!!!
Prowlarr http://10.48.200.35:9696 admin Joker1974!!!
Synology NAS http://10.48.200.249:5000 nas Joker1974!!!
Parker Slingshot Admin https://parkerslingshotrentals.com/admin admin Parker2026!
TJJ Admin https://tomsjavajive.com/admin admin@tomsjavajive.com OR myronblair@outlook.com Joker1974!!!

Databases

Site DB Name DB User DB Password
JARVIS jarvis_db jarvis_user J4rv1s_Pr0t0c0l_2026!
Tom's Java Jive toms_tjj_db toms_tjj_user +60wlPc+55e@gFq4
Parker Slingshot Rentals park_slingshot park_slingshotuser 4@rxg*8kovxCr7w6
Epic Travel epic_travel_db (see config.php) (see config.php)
Epic/Parker Slingshot epic_parkersling epic_parkersling Joker1974!!!
NovaCPX SQLite: /var/lib/novacpx/panel.db
ChuckCo Time Keeper workt_track_db workt_track_user ZWCNMRP2N5NVPsghmve5aRS9
FusionPBX PostgreSQL fusionpbx pSJaF9mUJqPr4Sj5mwJyRqvCCpc
MySQL root (DO) root b71e5c1a8c7457541b9c1db822de37adfa271926a38b6c20

API Keys

Service Key
GitHub PAT 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 (rotated 2026-07-05, scopes repo+workflow)
JARVIS Agent Registration f846a9aaf7ce9a61742c63c87c4186052a71d2a580c65518
Proxmox API Token root@pam!jarvis=c45b5feb-f9a9-445d-a626-14fbb959f78b
HA Long-lived Token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzNmI0N2I1Njk5ZGQ0MTQ2ODMwZWFmYjZiYTQ1MjJkMSIsImlhdCI6MTc4MDIwMzU5NCwiZXhwIjoyMDk1NTYzNTk0fQ.sYRok-jRDlA4lFgWxLQELcEjkJNGQdprk6ZziLwLtXE
Sonarr API b43e04350a594846b4ee95261c29e9e0
Radarr API 53c4268360444feeae5f98c0cc24e0e3
Prowlarr API 9d0ce6c5660743b5bf1c7951efc62252
Jellyfin Admin Token 7c0ccf78b91d4b5bafa607f585f24f2d
Square (Parker) Production EAAAl3FsAu_2ri8kZE_ENEyi2T_C8HXXm5XQFY6Lbnd8SX6FqYp8J_upUeXNYh7v
Square App ID (Parker) sq0idp-YSM7BU9IVyOWSzpeP-0nzQ
Webhook HMAC Secret 4c8805f0285214ff0a0602b5880270b935f36a896946c7f1

SIP / Phone

Extension Name SIP Password
1000 Myron Blair — Desk (10.48.200.2) Xk9mPw3nQv7rLs2t
1001 Tommy Ivy — Desk (10.48.200.43) Tv8xNm4pWq6rZs3k
1002 Myron Blair — WiFi Work (10.48.200.65) yXHaJTwa8rj?$GkrVFQB
1003 Kitchen (10.48.200.83)
1004 Master Bedroom (10.48.200.85)
1010 Parker County Slingshot (voicemail only)
1011 Epic Travel Expeditions (voicemail only)
1012 Tom's Java Jive (voicemail only)

13. GIT & REPOSITORY MANAGEMENT

GitHub (myronblair, 26 private repos as of 2026-07-05) is the permanent/source-of-truth storage. Gitea (gitea.orbishosting.com, hosted on the Synology NAS, login myron / Joker1974!!!) mirrors it one-way — GitHub → Gitea only, via pull-mirrors triggered by POST /api/v1/repos/<owner>/<repo>/mirror-sync. Never push directly to a Gitea remote.

5 repos are Gitea-only by design, never pushed to GitHub (deliberately kept off a third-party cloud service since they hold real credentials): fortigate-config, infra-private, jarvis-secrets, msp360-config, proxmox-secrets.

Local clones live on the admin Windows machine at C:\Users\myron\repos\ (currently chucko, web-dashboard — more cloned there as needed). Periodic maintenance: git gc --aggressive --prune=now to keep loose objects packed.

Per-site deploy pattern (the 7 DO-hosted sites + jarvis + web-dashboard): .git metadata is relocated outside the public webroot (e.g. /home/<site>/git-data with a gitdir: pointer file left in public_html/.git) so .git itself is never web-accessible, while git commands run normally from inside public_html. Most sites deploy via a GitHub webhook → queue file → cron puller (~1 min); chucko (ChuckCo Time Keeper) currently has no auto-deploy hook — pushes are manual (SSH in, git pull/push directly).

Known repo-hygiene issue: fusionpbx-config bloated to ~166-196MB from repeatedly committing a large DB dump straight into history — see Section 10.

This document contains sensitive credentials. Store securely and do not share.