From 43be3e1105c6df3838ceca4efd4142bec02f3bd4 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 7 Jul 2026 20:35:41 -0500 Subject: [PATCH] Stop tracking INFRASTRUCTURE-REFERENCE.md (full credentials doc) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Untracked from git and added to .gitignore. The file stays on disk at public_html/admin/downloads/ (served behind admin auth) and in the jarvis-private + VM110 copies — it is no longer pushed to GitHub going forward. NOTE: prior revisions remain in GitHub history; a git filter-repo purge + force-push is still pending user sign-off, as are rotations of the secrets that were in it. Co-Authored-By: Claude Fable 5 --- .gitignore | 1 + .../downloads/INFRASTRUCTURE-REFERENCE.md | 1044 ----------------- 2 files changed, 1 insertion(+), 1044 deletions(-) delete mode 100644 public_html/admin/downloads/INFRASTRUCTURE-REFERENCE.md diff --git a/.gitignore b/.gitignore index bab85c1..bcce031 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Credentials - never commit +public_html/admin/downloads/INFRASTRUCTURE-REFERENCE.md api/config.php backup/ diff --git a/public_html/admin/downloads/INFRASTRUCTURE-REFERENCE.md b/public_html/admin/downloads/INFRASTRUCTURE-REFERENCE.md deleted file mode 100644 index 323cc14..0000000 --- a/public_html/admin/downloads/INFRASTRUCTURE-REFERENCE.md +++ /dev/null @@ -1,1044 +0,0 @@ -# INFRASTRUCTURE REFERENCE — COMPLETE SYSTEM MAP -**Last Updated:** 2026-07-07 (WAN IP change + FortiGate VIP update; JARVIS auto-deploy pipeline fully restored; admin panel fixes — Works tab, Site Health, Email Intelligence/Outbox; backup systems audited and fixed to include actual data, not just DB/config; new Blair HQ Backup Downloads feature) -**Owner:** Myron Blair — myronblair@outlook.com - ---- - -## TABLE OF CONTENTS -1. [Network Overview](#1-network-overview) -2. [Cloud Servers](#2-cloud-servers) -3. [On-Premise — Proxmox Hypervisors](#3-on-premise--proxmox-hypervisors) -4. [On-Premise — Virtual Machines](#4-on-premise--virtual-machines) -5. [NAS Storage](#5-nas-storage) -6. [Websites (all on DO)](#6-websites--all-on-do) -7. [JARVIS AI System](#7-jarvis-ai-system) -8. [Phone System (FusionPBX)](#8-phone-system-fusionpbx) -9. [Networking & VPN](#9-networking--vpn) -10. [Backup Systems](#10-backup-systems) -11. [SSH Quick Reference](#11-ssh-quick-reference) -12. [Critical Credentials Master List](#12-critical-credentials-master-list) -13. [Git & Repository Management](#13-git--repository-management) -14. [Network Equipment & Client Device Inventory](#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.245.77.197 (dynamic, DDNS: orbisne.fortiddns.com — changed 2026-07-07, - previously 97.154.207.5, and 97.154.109.245 before that. All 35 FortiGate - VIPs' extip updated to match on each change — see Section 9 for the full list.) - │ - ├─► 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 (VIP list confirmed 2026-07-07 via `show firewall vip` — this -replaces the earlier partial/approximate list; all extip values = current WAN IP above): - homeassistant-8123 → 10.48.200.97:8123 (Home Assistant) - proxmox1-8006 → 10.48.200.90:8006 (PVE1 web UI) - proxmox2-8007to8006 → 10.48.200.91:8006 (PVE2 web UI, ext 8007) - proxmoxbku-8007to8008 → 10.48.200.92:8007 (ext 8008) - reolink-9000/1935/554/8000 → 10.48.200.95 (4 VIPs, one per port) - proxmox-ssh-claude-connection → 10.48.200.29:22 - jarvis-8443 → 10.48.200.211:80 (JARVIS — working forward, use this for external HTTP to JARVIS) - jarvis-1972 → 10.48.200.211:80 (legacy port, confirmed working again 2026-07-07 after the WAN IP/VIP update — earlier notes calling this "dead" were from before that fix) - tunnel-51820 / Wireguard-CT110 → 10.48.200.67:51821 (UDP, WireGuard — 2 VIPs, same target) - dns-53 → 10.48.200.90:53 - bbs-23 → 10.48.200.112:23 (SynchroNet BBS) - NOVACPX-* (18 VIPs) → 10.48.200.110 or .200 — HTTP/HTTPS/user/reseller/admin/webmail/SSH/FTP/SMTP/POP3/IMAP/DNS ports for NovaCPX hosting panel - NPM-HTTP / NPM-HTTPS → 10.48.200.200:80/443 (Nginx Proxy Manager, VM 105) -No VIP maps external port 80 directly to JARVIS — use jarvis-8443 (or the working -jarvis-1972) for external HTTP access instead. -``` - ---- - -## 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//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:** -```bash -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:8006` — `root / Joker1974!!!` | -| **Purpose** | Runs VMs 101, 112, 113, 118, 120, 210, CT110 | - -**Useful commands:** -```bash -qm list # list all VMs -qm start/stop/restart # control VMs -qm guest exec -- 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:8006` — `root / 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:8123` — `myron / [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:** -```bash -curl -X POST "http://10.48.200.33:8096/Library/Refresh" \ - -H "X-Emby-Token: 635142c218f2457e813a2de8dec75b05" -``` - -**If NFS stale after MediaStack changes:** -```bash -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":** -```bash -systemctl stop radarr -sqlite3 /var/lib/radarr/radarr.db "DELETE FROM IndexerStatus WHERE ProviderId=1;" -systemctl start radarr -``` - -**SSH from DO:** -```bash -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:8882` — `admin / 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.conf` → `OLLAMA_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//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 (Fri–Thu) 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.php` — `admin / 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 `.htaccess` — **required 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.php`** — `logActivity()` 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_db` — `jarvis_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.`) 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. - -### Major fixes (2026-07-07) - -**`/var/www/jarvis` finally became a real git repo.** It had no `.git` at all — the actual live admin panel had diverged completely from `myronblair/jarvis` on GitHub (the 2026-07-06 security review above was done via direct SSH edits on the live server, never committed anywhere). Reconciled by committing the live state as the new baseline and merging origin/master history with `-s ours` (preserves lineage without overwriting the live content), then pushed. `/tmp/jarvis-deploy` (a separate, stale clone used briefly as a staging area) is now superseded — don't use it; edit `/var/www/jarvis` directly. - -**KB Intent Generator cron was silently broken since ~2026-07-05.** The rotation-engine refactor (moving from a hardcoded topic array to the `kb_generator_topics` table) had dropped the `$SYSTEM` prompt and the entire `safe_insert()` function — every 6-hour run crashed instantly on an uncaught `TypeError`, invisible everywhere because `config.php` sets `error_reporting(0)`. Restored both from a `.bak2` backup. Table grew from 386 → 900+ real intents once fixed. - -**GitHub auto-deploy pipeline was completely non-functional — likely since it was first set up, not just recently:** -- The GitHub webhook itself pointed at the dead port `:1972` (already known-stale) → 502 on every delivery -- `WEBHOOK_SECRET` was never defined in `config.php` → `webhook.php` would have 500'd even if reached -- Branch check compared against `refs/heads/main`, but this repo has always used `master` → every real push would have been silently skipped -- `/usr/local/bin/jarvis-deploy.sh` (the queue consumer) didn't exist on this host at all -- **All fixed**: webhook URL updated to use port **1972** (confirmed working again after the 2026-07-07 WAN IP change — Cloudflare passes this non-standard port through cleanly, unlike port 80 which it force-redirects to HTTPS), secret added, branch check fixed, `jarvis-deploy.sh` rebuilt (git pull + per-file PHP syntax check + auto-revert on failure, `/var/log/jarvis/deploy.log`, cron `* * * * *`) and `jarvis-watchdog.sh` rebuilt (checks nginx/php8.3-fpm/mariadb/redis-server, restarts if down, `/var/log/jarvis/watchdog.log`, cron `*/5 * * * *`) — both were referenced in the Works tab and by cron history but the actual scripts had never existed on this VM. Verified end-to-end with a real push: webhook → queue → cron puller → `git pull` → live, inside ~1 minute. - -**Admin panel (Works / Site Health / Email Intelligence tabs) — several real bugs, not just polish:** -- Facts Collector always showed "UNKNOWN" last-run (log-format regex expected a `[bracketed]` timestamp; this script's lines don't have one) — it was actually running fine every 3 min the whole time -- Calendar Sync always showed "UNKNOWN" *and* was never actually scheduled at all (no crontab entry existed, despite the UI listing it as an active "every 15 min" job) — added the missing cron entry, fixed a regex typo (`\d{2}{4}` → `\d{4}`) -- Only KB Intent Generator's "RUN" button had a live-streaming-log popup; Facts Collector/Stats Cache/Calendar Sync just fired a toast with no way to see the eventual result. Added a generic `worker_log`/`worker_history` backend pair and reused the same popup pattern for all of them -- Site Health: `parkerslingshotrentals.com` showed as truncated "parkerslingshots" (stale frontend label map referencing an old backend key name that no longer exists) — fixed, and widened the card layout (`.site-grid`/`.site-card`, 260px min vs the shared 160px stat-card) since domain names don't fit the generic dashboard-stat width. Also fixed the site-check freshness guard (300s vs a 180s cron interval meant sites were only re-checked every *other* run) — now 170s -- **Email Intelligence inbox always 404'd** — it proxied to `https://165.22.1.228/api/email`, a leftover from before JARVIS moved off the DO server; that endpoint hasn't existed since the migration. Now reads `email_triage` directly (same table `email_action_items` already used) -- **Compose/reply email silently produced blank drafts regardless of AI provider status** — the PHP dispatcher and the Python reactor used different field names for the same payload (`recipient`/`subject`/`auto_send` vs the reactor's `to_email`/`subject_hint`/`send`; `content` vs `body` for replies). Fixed both call sites -- **`llm_call()`'s provider fallback never actually fired** for any explicitly-requested provider (i.e. every real caller) — a failure on the first-choice provider raised straight up instead of falling through to the others. Fixed; also fixed `_ollama_call()` silently returning `""` instead of raising when Ollama reports an error (e.g. model not pulled), which had been masking failures as fake successes -- **Ollama had no text-completion model installed** (only `llava:7b`, the vision model) — pulled `llama3.1:8b` (~4.9GB) so the Claude→Groq→Ollama fallback chain is a real 3-tier chain, not 1.5. Bumped Ollama's call timeout 30s→90s (cold loads alone took 15s+ in testing) -- Added Groq 429 retry-with-backoff (parses Groq's own rate-limit-reset header) — this account's tier is only 12,000 tokens/min, and `gmail_triage` alone can exhaust it, so transient contention with compose/reply is common -- **Compose modal used to toast "dispatched" and never check back** — if the job failed 30–90s later in the background there was no notification at all, it just silently vanished. Now polls the actual job status (`arc_job_get`) until done/failed and shows the real result -- Added a missing **SEND button** for queued drafts in the Outbox — compose had always only ever produced a `status='queued'` draft with no way to actually send it. Also fixed VIEW always showing "(no body)" (it read from the list endpoint, which omits body for performance, instead of the single-item endpoint) -- Still open: Claude API credits are depleted (billing, not a code issue) — restore at console.anthropic.com if Claude-quality drafting is wanted as the default again - -### 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` - -```bash -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: `[rotated 2026-07-07 — stored in api/config.php on VM211, not documented here]` -Install command: `curl -sk http://10.48.200.211/install-agent.sh | bash -s ` - -### 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 -```bash -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.245.77.197 (dynamic — changed 2026-07-07; see Section 1 for the full VIP list, all 35 updated same day) -- DDNS: `orbisne.fortiddns.com` (FortiGate auto-updates on IP change) -- **Note:** a WAN IP change requires manually updating every VIP's `extip` (the FortiGate does not do this automatically even though DDNS updates) — the FortiGate CLI script used 2026-07-07 is a simple loop of `edit ""` / `set extip ` / `next` for all 35 VIPs. Also update Cloudflare's DNS A-records for any `*.orbishosting.com` hostnames pointing at this WAN IP. -- 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:9443` — `admin / 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 `eth0` — **including 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 - -**Audited 2026-07-07 — file-coverage gap found and fixed in 2 of the 4 systems below.** The core question asked: if the source server were lost outright, does the backup actually contain what's needed to restore it, or just a database/config fragment? JARVIS and the DO server both failed that test and are now fixed; Proxmox and FusionPBX were checked and are genuinely fine as designed. - -### JARVIS 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_db` — `jarvis_user / J4rv1s_Pr0t0c0l_2026!` -- **Fixed 2026-07-07:** this was MySQL-dump-only — a DB dump alone is useless without the actual application. Now also archives `/var/www/jarvis` (app code + `config.php`), `/opt/jarvis-arc` (reactor daemon), the nginx site config, the `jarvis-arc.service` systemd unit, and the root crontab. Also fixed a typo (`$SIYE`→`$SIZE`) that silently broke the backup-size line in the log. Latest test run: 20MB. - -### DO Server Backup -- **Repo:** `myronblair/do-server-config` -- **Schedule:** Weekly, Sunday 4am -- **Launcher:** `/usr/local/bin/do-server-backup` on DO -- **Fixed 2026-07-07:** previously covered scripts/systemd/WireGuard/OLS-vhosts/cron/SSH keys/`/opt/infra` — real server *configuration* — but captured **zero actual data**: no website files for any of the 7 hosted sites, and only a list of database *names* (`mysql/databases.txt`), never the data itself. If the droplet were lost, you'd get the server environment back but lose every site's real content and every business database. Now also archives `sites//public_html/` for all 7 sites (rsync, `.git` excluded — each site's own repo already covers code history) and gzipped `mysqldump` output for every real business DB (`epic_epic_db`, `epic_parkersling`, `park_slingshot`, `toms_tjj_db`, `tomt_ttg_db`, `workt_track_db` — CyberPanel's own internal DB and MySQL system schemas are skipped). Verified live: all 6 DBs dumped with real content, all 7 sites' files present, repo still only 5.4MB after the first full run (318 files, ~48K lines). -- **Restore:** 8-phase wizard in `restore.sh` (predates the 2026-07-07 file/DB additions — the wizard itself hasn't been updated yet to restore `sites/`/`databases/`, only the original config pieces. Worth revisiting before relying on it for a full restore.) -- **Downloadable zip:** as of 2026-07-07, `backup.sh` also writes `/opt/do-server-backup.zip` (current working tree minus `.git`, regenerated every run) — see "Blair HQ Backup Downloads" below. - -### 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 (host-level config only, by design) -- **VM disks:** **Verified 2026-07-07** — real nightly `vzdump` job `backup-aa6b1890-23c0` (all VMs, snapshot mode, keep-last=3, 21:00 daily, to `SynologyProx`) genuinely covers full VM disk data separately. Confirmed via `pvesh get /cluster/backup` — this is not just documented, it's an active, enabled job. No gap here; config-in-git + data-via-vzdump is a legitimate split, not an oversight. - -### FusionPBX Backup -- **Repo:** `myronblair/fusionpbx-config` -- **Schedule:** Weekly, Sunday 5am -- **Launcher:** `/usr/local/bin/fusionpbx-backup` -- **Covers:** PostgreSQL dump (gzip, ~29-60MB) + FreeSWITCH configs + call recordings -- **Verified 2026-07-07:** already does a real `pg_dump` of the actual `fusionpbx` database (dialplans, SIP gateways, IVR, ring groups, devices, voicemail, users — all real data, not just a name list) plus `pg_dumpall --globals-only`, plus config files and recordings. No gap here. -- **Restore:** 10-phase wizard in `restore.sh` -- **Known issue (found 2026-07-05, still open):** 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). - -### Blair HQ Backup Downloads (`web.orbishosting.com`, added 2026-07-07) -A new **Backup Downloads** card on the Blair HQ dashboard (next to the existing Backup Status card) surfaces the actual JARVIS and DO Server backup files for direct download — source location, timestamp, and file size are shown, pulled from `/downloads/backup-files-status.json`. -- **Pull script:** `/usr/local/bin/pull-backups.sh` on VM110 (NovaCPX), cron `0 5 * * *` (daily, safely after both source backups) — SCPs the latest `jarvis_backup_*.tar.gz` from VM211 (key-based SSH; a new ed25519 keypair was generated on VM110 and added to VM211's `authorized_keys` for this specifically) and `/opt/do-server-backup.zip` from the DO server (password auth via `sshpass`), then writes the status JSON. Log: `/home/webacct/logs/pull-backups.log`. -- **Security fix that made this safe to build**: `/home/webacct/public_html/downloads/` had **zero access protection** — anything dropped there (including the infra reference doc, previously) was fetchable by anyone on the open internet with no login, since `web.orbishosting.com` is fully public (confirmed reachable from outside, HTTP 200). Added HTTP Basic Auth (`myron` / `Joker1974!!!`) scoped to the `/downloads/` location in `/etc/nginx/sites-enabled/novacpx-webacct.conf`, with `backup-status.json` and `backup-files-status.json` explicitly exempted (exact-match `location` blocks ahead of the auth'd prefix block) since the dashboard's own client-side JS fetches those with no credentials to send. -- **Also fixed while auditing this:** a daily VM110 cron (`0 4 * * * curl ... -o .../INFRASTRUCTURE-REFERENCE.md`) had been silently overwriting the infra doc with an empty file every night since the 2026-07-06 security review relocated the real copy off any public path — the cron's source URL no longer existed. Restored a LAN-only static copy at `/var/www/jarvis/public_html/admin/downloads/INFRASTRUCTURE-REFERENCE.md` on VM211 (safe: VM211 isn't internet-reachable directly, only from the internal LAN) so this automation has something real to pull again. The authenticated `docs_download` action in the JARVIS admin UI is unaffected either way. - -### 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 `scp`s 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": "", "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 - -```bash -# 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 | `[rotated 2026-07-07 — stored in api/config.php on VM211, not documented here]` | -| 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///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//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.*