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

60 KiB
Raw Blame History

INFRASTRUCTURE REFERENCE — COMPLETE SYSTEM MAP

Last Updated: 2026-07-06 (Section 14: added a 4th WiFi extender + corrected Pioneer VSX-822 attribution)
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
  14. Network Equipment & Client Device Inventory

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 103    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 106    10.48.200.210  Ollama (local LLM + vision) — llama3.1:8b, llava:7b
    │     └── CT110     10.48.200.19/.67  WireGuard exit container (disabled at boot 2026-07-06, legacy/unused)
    │
    ├─► 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 100 — SynchroNet (PVE1)

Field Value
IP 10.48.200.112
OS Windows
Purpose SynchroNet BBS (bulletin board system)
Note VM is named "SynchroNet-50" in Proxmox but its real IP is .112, not .50.50 is an unrelated Raspberry Pi 5 hobby device (see Section 14). Confirmed 2026-07-06.

VM 105 — Nginx Proxy Manager (PVE1)

Field Value
IP 10.48.200.200
Purpose Reverse proxy management (NPM)
Note Confirmed 2026-07-06; VM name NPM-200 matches its IP correctly (unlike SynchroNet/Ollama above).

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 24.04.4 LTS (verified 2026-07-06; previously logged as 22.04 — reinstalled/upgraded at some point)
SSH ssh root@10.48.200.33 — password: Joker1974!!! (enabled 2026-06-14)
Web UI http://10.48.200.33:8096 (Jellyfin 10.11.11)
Purpose Media streaming server — Movies and TV shows
JARVIS Agent jarvis-agent.service running (verified 2026-07-06)
Remote access Tailscale installed, node jellyfin-112 at 100.81.145.48 — used for off-LAN streaming access

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: 635142c218f2457e813a2de8dec75b05 (regenerated 2026-07-06 — previous token 7c0ccf78... had gone stale/invalid. The account's real username is admin, not myron — confirmed via the Users table in /var/lib/jellyfin/data/jellyfin.db; it's hidden from the public login list, which is why /Users/Public returns empty.)

If library scan needed:

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

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 103 — MediaStack (PVE1)

Field Value
IP 10.48.200.35
OS Ubuntu 24.04.4 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
Not Docker Despite the name, all services below run bare-metal via systemd, not docker-compose

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 rotates (US Dallas servers), not a fixed IP (previous "181.214.226.188" was just a snapshot, not stable). All download/general traffic exits via NordVPN with LAN traffic exempted (Kill Switch + Firewall + LAN Discovery all enabled as of 2026-07-06 — see Section 9 for the full incident/fix history). If downloads stall, check nordvpn status first, then ip rule show for rules 32764/32765/table 205.

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 106 — 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!!! (also reachable as ssh myron@10.48.200.210 — password Joker1974!, then sudo). VM's name is Ollama-95 but its real IP is .210, not .95 — a prior version of this doc had a stray SSH line pointed at .95 (nothing listens there); confirmed 2026-07-06 that .210 is correct.
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
2026-07-06 incident MediaStack's wg0 client for this tunnel (/etc/wireguard/wg0.conf) had a PostUp hook installing its own iptables kill-switch (REJECT all output not via wg0 or marked 51820), and wg-quick@wg0.service was still enabled at boot on MediaStack despite this tunnel being unused — this caused a full LAN/SSH lockout to MediaStack the moment that service came up. Disabled wg-quick@wg0 at boot on MediaStack to prevent recurrence; the tunnel itself and CT110 are untouched. See NordVPN section below for the related (separate) LAN Discovery bug found in the same incident.

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 and its subpaths /volume1/video/movies, /volume1/video/tv — all exported to MediaStack (10.48.200.35) only, per /etc/exports on the NAS (verified 2026-07-06)

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...

Code review pass — all 4 DO-hosted business sites (2026-07-06)

Full security/correctness review of tomsjavajive.com, tomtomgames.com, parkerslingshotrentals.com, epictravelexpeditions.com (orbishosting.com apex and orbis.orbishosting.com excluded — not live/do-not-touch per earlier note). 10 findings, all fixed, tested, committed, and pushed to each site's main branch same day.

Critical (live exploitable, now fixed):

  • tomsjavajive.com api/orders.php had a literal // Admin check would go here comment — anyone who knew/found an order_id could silently change any order's status (cancelled/delivered/refunded) or overwrite tracking numbers, and read another customer's full order (name, email, address, items), with zero auth. Fixed: update_status now requires AdminAuth::isLoggedIn(); the GET ?id= lookup now requires admin or the order's own customer.
  • parkerslingshotrentals.com uploads/ — customer driver's license and insurance-card photos were directly downloadable with no login at all (the Order deny,allow/Require all denied pattern in uploads/.htaccess doesn't work on this OpenLiteSpeed setup, same class of gotcha as the .git exposure found earlier). Verified live via a throwaway test file before fixing. Fixed with the working RewriteRule .* - [F,L] pattern in both the nested uploads/.htaccess and the root .htaccessrequired an actual systemctl restart lshttpd to take effect (touching /usr/local/lsws/cgid alone, which only prevents the cron's own restart trigger, was NOT sufficient for a new rewrite rule to be picked up — worth remembering for future .htaccess changes on this server).

High (fixed):

  • tomsjavajive.com admin/orders.php — the exact "same named PDO param reused twice" bug that already bit awardPoints() had recurred in the order search box (:search bound once, referenced 3 times), causing a fatal SQLSTATE[HY093] on every admin search. Fixed with distinct :search1/:search2/:search3.
  • tomtomgames.com admin/index.php — stored XSS: renderGamerOverview() inserted username/alias/email into innerHTML without the escHtmlA() helper used correctly everywhere else in the same file. Alias has no character restriction, so a malicious alias could execute script in an admin's session the moment they open that user's profile. Fixed.

Medium (fixed):

  • tomtomgames.com includes/square.php (untracked by git — lives outside public_html, fix deployed to the server only) — charge()/refund() generated a fresh uniqid() idempotency key on every call, defeating Square's duplicate-protection entirely. Fixed: keyed off md5(source_id) for charges and md5(payment_id . amount) for refunds, so retries/double-clicks are recognized as duplicates.
  • parkerslingshotrentals.com contact.php — booking availability check + insert had no locking, allowing a double-booking race under concurrent submissions; the deposit-hold idempotency key was suffixed with time() (changes every second, so retries aren't deduped). Fixed: wrapped the check+insert in a MySQL GET_LOCK/RELEASE_LOCK pair scoped to the requested date range, and made the idempotency key stable ({ref}-dep, no time suffix).
  • epictravelexpeditions.com api/config.php — DB credentials, JWT secret, admin password hash, and mail API key sat in plaintext inside the webroot (protected only by an .htaccess rewrite rule, unlike every sibling site where secrets already live outside public_html). Relocated to /home/epictravelexpeditions.com/api-secrets.php (was already gitignored, so no git history exposure). .git itself was already correctly relocated to git-data/ (just a 49-byte pointer file in the webroot, blocked by .htaccess) — no action needed there.

Low (fixed):

  • tomtomgames.com api/purchase.phplogActivity() referenced undefined $paymentMethod/$amountDollars (should be $method/$priceCents) in two places, producing PHP warnings and blank values in the purchase audit log for every transaction. Fixed.
  • epictravelexpeditions.com api/api/testimonials.php — the public image-upload endpoint (no login required, by design) had no rate limiting, allowing storage/bandwidth abuse via scripted repeat uploads. Added a upload_rate_limits table + per-IP cap (5 uploads/hour).

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.

Functional bugs fixed (2026-07-06)

  • "WEB HOST" card on the front dashboard always showed --%/offline. Root cause: the DO server (165.22.1.228) never had the JARVIS monitoring agent installed — every other host in the fleet had one, this one didn't. Installed it with curl -sk http://10.48.200.211/install-agent.sh | bash -s jarvis-do linux (hostname arg jarvis-do + the DO server's actual machine hostname orbis produces the expected agent_id=jarvis-do_orbis that do_server.php queries for). Also found and fixed two secondary issues hit along the way: the agent's config pointed at a dead/stale Tailscale peer (jarvis-211, 100.77.178.42, offline 9+ days) instead of the current active one (jarvis-211-1, 100.78.153.71) — likely left over from a VM Tailscale re-auth at some point; and a stale cached API key in /var/lib/jarvis-agent/state.json from a registration attempt that never actually completed server-side, which had to be deleted to force a clean re-registration. Verified live: do_server field in /api/do now returns real cpu/mem/disk/online:true instead of an empty array.
  • "WEBSITES" list (part of the same JARVIS SERVER panel) was always empty, and the KB intent generator's 4-hour "don't run again too soon" guard was potentially never actually throttling correctly. Root cause, found while investigating the above: api/config.php sets date_default_timezone_set('America/Chicago'), and several places compute "how old is this DB timestamp" via PHP's time() - strtotime($mysqlDatetimeString). Since MySQL's NOW()/stored datetimes are naive UTC strings, strtotime() under a non-UTC default timezone misinterprets them as being in Chicago time, which throws every such comparison off by the UTC offset (5-6 hours) — in this case making facts_collector.php's freshness gate for the sites (and incidentally proxmox/ollama) categories always look artificially fresh, so the site-health checks that populate the WEBSITES list stopped actually running. Fixed in facts_collector.php's $fresh() helper and kb_intent_generator.php's run-guard by moving the elapsed-time comparison entirely into SQL (updated_at > DATE_SUB(NOW(), INTERVAL ? SECOND)), which sidesteps PHP timezone handling altogether. Also fixed a leftover cosmetic label (do_server.php) still showing jarvis.orbishosting.com:1972 from before the JARVIS port fix.
  • Note for future work: the time() - strtotime($dbTimestamp) anti-pattern appears in a couple of other files (chat.php, email.php, planner.php) but only for display formatting of dates, not elapsed-time threshold checks — lower priority, not fixed in this pass, but worth a look if any displayed timestamps look off by a few hours.

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: rotating US (Dallas) NordVPN servers, not a fixed IP
  • Policy routing: table 205 (non-LAN traffic via nordlynx), managed partly by NordVPN itself and partly by a custom nordvpn-routing.service unit (/etc/systemd/system/nordvpn-routing.service) that adds the ip rule for fwmark 0xe1f1 → table 205
  • Required for IPTorrents access (blocks non-VPN IPs)

2026-07-06 incident (fixed): nordvpnd had been crash-looping since ~2026-06-07 (/var/lib/nordvpn/data/settings.dat was corrupted/empty) — meaning NordVPN was not actually protecting MediaStack's traffic for about a month; downloads were exiting on the plain home IP. Fixed by clearing the corrupt file, restarting the daemon, and re-logging in.

While fixing this, found NordVPN's own "LAN Discovery" setting was disabled. With Routing: enabled and LAN Discovery off, connecting NordVPN's full-tunnel routing suppresses the main routing table's resolution for anything that would exit via eth0including same-subnet LAN traffic — so the entire VM became unreachable (SSH/ping) from the rest of the LAN the moment NordVPN connected. Fixed with nordvpn set lan-discovery on, which adds explicit priority rules for private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16) ahead of the tunnel catch-all. Verified LAN reachability holds with Kill Switch + Firewall both re-enabled after this fix.

If MediaStack becomes unreachable after a NordVPN reconnect again: check nordvpn settings for LAN Discovery: enabled first. If SSH is already dead, the network path itself is unusable — recover via the Proxmox host instead: qm guest exec 103 -- /bin/bash -c 'export HOME=/root; nordvpn ...' (guest-exec needs HOME set manually or the nordvpn CLI fails).

Current confirmed-good settings (2026-07-06): Firewall enabled, Kill Switch enabled, Auto-connect enabled, LAN Discovery enabled, Routing enabled.


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.210  # Ollama (NOT .95 - that's a naming leftover, nothing listens there)
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; use VMID not IP)
sshpass -p 'Joker1974!!!' ssh root@10.48.200.90 \
  'qm guest exec 106 -- bash -c "export HOME=/root; CMD"'   # Ollama = VMID 106
# Other VMIDs: Jellyfin=112, MediaStack=103, JARVIS=211, NovaCPX=120, HomeAssistant=101, Homebridge=118

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: 635142c218f2457e813a2de8dec75b05
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 635142c218f2457e813a2de8dec75b05
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.


14. NETWORK EQUIPMENT & CLIENT DEVICE INVENTORY

Compiled 2026-07-06 from a live ARP scan off PVE1 (~90 hosts), MAC-vendor lookups, and direct confirmation from Myron. Built to support a future VLAN segmentation project — see VLAN-Segmentation-Plan.docx in the home folder for the full plan; this section is the durable factual record to carry forward (e.g. into JARVIS) independent of that plan's status.

14.1 Core Network Equipment

Device Model Role
Firewall FortiGate 60F Primary/active firewall — confirmed the top unit in the rack. A second Fortinet unit is stacked below it; its role is not yet identified — not confirmed as an HA pair.
Primary switch Cisco Catalyst 3560-E Series PoE-48 48-port, full PoE, enterprise-managed — full 802.1Q VLAN/trunk support
Secondary switch FortiSwitch 108F-FPOE 8-port PoE, FortiLink-managed
KVM switch TRENDnet TK-802R Physical console access to rack servers — not networked
WiFi extender 1 TP-Link RE305 — 10.48.200.16 WiFi clients only, no wired devices
WiFi extender 2 TP-Link RE305 — 10.48.200.89 WiFi clients only, no wired devices
WiFi extender 3 TP-Link RE305 — 10.48.200.93 Wired network printers plugged into its Ethernet port; no WiFi clients on this unit
WiFi extender 4 Brand unconfirmed (Shenzhen Xunman-branded/OEM) — MAC fc:22:1c:30:60:14 seen at 10.48.200.100/.64 Wired Pioneer VSX-822 AV receiver plugged into its Ethernet port; no wireless clients of its own — same bridge-mode pattern as extender 3 above
Wireless bridge Good Story Networks WB610H — 10.48.200.80 Links the main house network to the storage shed (a detached building). OEM manufacturer is Shenzhen LiWiFi Technology Co., Ltd (rebranded by Good Story Networks). Plan: once fully deployed, this bridge replaces the need for the RE305 units at .16 and .89 — see the VLAN plan doc for details. VLAN/802.1Q trunk capability not yet confirmed — check before relying on it for segmented WiFi.

Note on consumer extenders and VLANs: budget range extenders like the RE305 (and likely extender 4 above) generally cannot map multiple SSIDs to separate VLANs over a trunk — they repeat one network. This matters if/when wireless VLAN segmentation is implemented; see the VLAN plan doc's "Wireless VLAN Feasibility" section.

14.2 Client & Peripheral Device Inventory (by category)

Printers:

IP Device
10.48.200.76 Epson ET-3750
10.48.200.204 HP LaserJet 500 Color MFP M570dn (wired to the RE305 at .93)
10.48.200.205 HP LaserJet M1536dnf MFP (wired to the RE305 at .93)
10.48.200.201, .202 Unidentified — likely more printers/peripherals on the same RE305 port, given the pattern above (not yet confirmed)

Storage:

IP Device
10.48.200.249 Synology NAS
10.48.200.41 WD My Cloud — a second NAS alongside the Synology

AV / Entertainment:

IP Device
10.48.200.42, .72 Vizio smart TVs
10.48.200.100 Pioneer VSX-822 AV Receiver — confirmed 2026-07-06, wired into a 4th WiFi range extender/AP (Shenzhen Xunman-branded/OEM, MAC fc:22:1c:30:60:14, no wireless clients of its own). This explains the earlier MAC discrepancy cleanly: the extender reports its own MAC in ARP for the wired Pioneer behind it, same bridge-mode pattern seen with the RE305 at .93 and its wired printers — the Pioneer's own labeled MAC (74:5E:1C:0E:7C:0B, genuine Pioneer Corporation OUI) simply never appears on the wire. 10.48.200.64 shares this same extender's MAC — likely the same device (Pioneer or the extender itself) at a prior IP, not a separate device.

Smart home / IoT:

IP Device
10.48.200.38 Samsung SmartThings hub (MAC vendor: Physical Graph Corporation, the original SmartThings company)
10.48.200.250, .251 Goalake Smart Switch 1 and 2
10.48.200.5, .7, .8, .9, .36, .61, .74 Generic ESP32/ESP8266-based smart plugs/sensors (Espressif chipset)
10.48.200.14, .60 Tuya Smart plugs/switches
10.48.200.34 Bouffalo Lab-chipset IoT device
10.48.200.116 FN-LINK-chipset IoT device
10.48.200.6, .10, .15, .23, .24, .27, .28, .30, .31, .32, .37, .62, .82, .86, .87, .105 TP-Link Tapo smart devices (16 total)
10.48.200.17, .39, .40, .46, .53, .68, .71, .106, .115, .118 Amazon devices (Echo/Fire TV/Kindle)

Security cameras:

IP Device
10.48.200.57, .78, .94, .95, .101, .103, .104 Reolink cameras + NVR (7 addresses total — one of these is the NVR itself, not confirmed which). Cameras are PoE-connected directly to the Catalyst 3560-E, not cabled to the NVR; the NVR pulls streams over the network like any other client. Feeds are viewed both locally on the LAN and remotely via the Reolink app.
10.48.200.21, .22 Ring doorbell/camera — also viewed both locally and via the Ring app remotely

VoIP (Yealink) — see Section 8 for extension details: .2, .3, .43, .65, .83, .85

Personal computers / hobby devices:

IP Device
10.48.200.54 Apple device (iPhone/iPad/Mac)
10.48.200.66 Dell PC
10.48.200.52 Intel-NIC PC
10.48.200.45 Microsoft device (Surface or Xbox — not yet confirmed which)
10.48.200.50 Raspberry Pi 5 — hobby/tinkering only, no production workload

Still unidentified as of 2026-07-06 (MAC vendor lookup only, no direct confirmation yet):

IP Vendor signature Notes
10.48.200.13 Murata Manufacturing Embedded WiFi module — device unknown
10.48.200.59 Guangzhou Shiyuan Electronic Often AV/display equipment — device unknown
10.48.200.119 Macherey-Nagel GmbH & Co. KG A lab-equipment brand (chromatography/filtration) — unusual on a home network, device unknown
10.48.200.77 Liteon Technology Could be a PC PSU with network mgmt, or a peripheral — device unknown
10.48.200.201, .202 (shares MAC with the RE305 at .93 and the confirmed printers at .204/.205) Likely more printers/peripherals, not confirmed

Minor known artifact, low priority: MAC 7a:e1:7e:44:08:29 is shared across 10.48.200.93 (RE305), .204/.205 (confirmed printers, benign RE305 bridge-mode behavior), and .251 (Goalake Smart Switch 2 — does NOT fit the "wired to the RE305" explanation, so this one specific overlap looks like a genuine duplicate/cloned MAC, common in ultra-budget IoT hardware). Worth a quick check of the Goalake switch's real MAC via its own admin UI at some point; not urgent.


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