New diagrams: - business-flow.svg: acquisition → check → order → filing → delivery - technical-architecture.svg: full Docker stack, data tier, external services - order-flow.svg: detailed worker pipeline with eSign gate and handler map Updated docs: - infrastructure.md: DocServer, email servers, backup server sections - architecture.md: linked to new SVGs, updated date Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
208 lines
15 KiB
XML
208 lines
15 KiB
XML
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 950" font-family="Inter, system-ui, sans-serif" font-size="10">
|
|
<defs>
|
|
<marker id="a" markerWidth="7" markerHeight="5" refX="7" refY="2.5" orient="auto">
|
|
<path d="M0,0 L7,2.5 L0,5 Z" fill="#94a3b8"/>
|
|
</marker>
|
|
</defs>
|
|
|
|
<text x="700" y="25" text-anchor="middle" font-size="16" font-weight="700" fill="#1e3a5f">Performance West — Technical Architecture</text>
|
|
<text x="700" y="42" text-anchor="middle" font-size="9" fill="#94a3b8">207.174.124.71 (Debian 13) — Docker Compose multi-service stack — Updated 2026-05-07</text>
|
|
|
|
<!-- ═══ INTERNET / CLIENT LAYER ═══ -->
|
|
<rect x="20" y="55" width="1360" height="50" rx="8" fill="#f0f4f8" stroke="#cbd5e1"/>
|
|
<text x="700" y="75" text-anchor="middle" font-size="11" font-weight="700" fill="#475569">Internet — Clients & External APIs</text>
|
|
<text x="120" y="93" text-anchor="middle" font-size="9" fill="#64748b">Browsers</text>
|
|
<text x="340" y="93" text-anchor="middle" font-size="9" fill="#64748b">Email recipients</text>
|
|
<text x="560" y="93" text-anchor="middle" font-size="9" fill="#64748b">Stripe / PayPal</text>
|
|
<text x="780" y="93" text-anchor="middle" font-size="9" fill="#64748b">FCC CORES / ECFS / USAC</text>
|
|
<text x="1020" y="93" text-anchor="middle" font-size="9" fill="#64748b">ERPNext portal users</text>
|
|
<text x="1260" y="93" text-anchor="middle" font-size="9" fill="#64748b">Umami / Grafana</text>
|
|
|
|
<!-- Arrows down -->
|
|
<line x1="120" y1="105" x2="120" y2="130" stroke="#94a3b8" stroke-width="1" marker-end="url(#a)"/>
|
|
<line x1="560" y1="105" x2="560" y2="130" stroke="#94a3b8" stroke-width="1" marker-end="url(#a)"/>
|
|
<line x1="1020" y1="105" x2="1020" y2="130" stroke="#94a3b8" stroke-width="1" marker-end="url(#a)"/>
|
|
|
|
<!-- ═══ NGINX REVERSE PROXY ═══ -->
|
|
<rect x="20" y="130" width="1360" height="40" rx="8" fill="#1e3a5f"/>
|
|
<text x="700" y="155" text-anchor="middle" font-size="11" font-weight="700" fill="#fff">nginx Reverse Proxy — TLS termination, sub_filter branding, rate limiting</text>
|
|
<text x="120" y="165" font-size="8" fill="#94a3b8">:443 → site:4322</text>
|
|
<text x="340" y="165" font-size="8" fill="#94a3b8">:443 → api:3001</text>
|
|
<text x="560" y="165" font-size="8" fill="#94a3b8">portal → erpnext:8000</text>
|
|
<text x="780" y="165" font-size="8" fill="#94a3b8">lists → listmonk:9100</text>
|
|
<text x="1000" y="165" font-size="8" fill="#94a3b8">analytics → umami:3100</text>
|
|
<text x="1200" y="165" font-size="8" fill="#94a3b8">grafana:3000</text>
|
|
|
|
<!-- ═══ APPLICATION TIER ═══ -->
|
|
<text x="30" y="195" font-size="11" font-weight="700" fill="#1e3a5f">Application Tier</text>
|
|
|
|
<!-- Site container -->
|
|
<rect x="20" y="205" width="200" height="90" rx="8" fill="#dbeafe" stroke="#93c5fd"/>
|
|
<text x="120" y="222" text-anchor="middle" font-size="10" font-weight="700" fill="#1e3a5f">site (Astro → nginx)</text>
|
|
<text x="30" y="238" font-size="9" fill="#475569">Static site + public HTML</text>
|
|
<text x="30" y="251" font-size="9" fill="#475569">Compliance checker, order pages</text>
|
|
<text x="30" y="264" font-size="9" fill="#475569">eSign portal, pricing</text>
|
|
<text x="30" y="277" font-size="8" fill="#94a3b8">Port 4322 | nginx:alpine</text>
|
|
|
|
<!-- API container -->
|
|
<rect x="235" y="205" width="200" height="90" rx="8" fill="#dbeafe" stroke="#93c5fd"/>
|
|
<text x="335" y="222" text-anchor="middle" font-size="10" font-weight="700" fill="#1e3a5f">api (Express.js)</text>
|
|
<text x="245" y="238" font-size="9" fill="#475569">REST API, checkout, webhooks</text>
|
|
<text x="245" y="251" font-size="9" fill="#475569">FCC lookup, compliance orders</text>
|
|
<text x="245" y="264" font-size="9" fill="#475569">Portal auth (JWT 72h)</text>
|
|
<text x="245" y="277" font-size="8" fill="#94a3b8">Port 3001 | node:22-slim</text>
|
|
|
|
<!-- Workers container -->
|
|
<rect x="450" y="205" width="220" height="90" rx="8" fill="#ede9fe" stroke="#c4b5fd"/>
|
|
<text x="560" y="222" text-anchor="middle" font-size="10" font-weight="700" fill="#5b21b6">workers (Python)</text>
|
|
<text x="460" y="238" font-size="9" fill="#475569">Job server, 27 service handlers</text>
|
|
<text x="460" y="251" font-size="9" fill="#475569">Playwright FCC/USAC automation</text>
|
|
<text x="460" y="264" font-size="9" fill="#475569">DOCX gen → PDF (Word VM / LO)</text>
|
|
<text x="460" y="277" font-size="8" fill="#94a3b8">Port 8090 | python:3.12-slim</text>
|
|
|
|
<!-- ERPNext -->
|
|
<rect x="685" y="205" width="200" height="90" rx="8" fill="#fef3c7" stroke="#fcd34d"/>
|
|
<text x="785" y="222" text-anchor="middle" font-size="10" font-weight="700" fill="#92400e">erpnext (Frappe)</text>
|
|
<text x="695" y="238" font-size="9" fill="#475569">CRM, Sales Orders, Invoices</text>
|
|
<text x="695" y="251" font-size="9" fill="#475569">Customer portal (/orders)</text>
|
|
<text x="695" y="264" font-size="9" fill="#475569">Custom: PW apps + payments</text>
|
|
<text x="695" y="277" font-size="8" fill="#94a3b8">Port 8080 | frappe/erpnext:v15</text>
|
|
|
|
<!-- Listmonk -->
|
|
<rect x="900" y="205" width="170" height="90" rx="8" fill="#dcfce7" stroke="#86efac"/>
|
|
<text x="985" y="222" text-anchor="middle" font-size="10" font-weight="700" fill="#059669">listmonk</text>
|
|
<text x="910" y="238" font-size="9" fill="#475569">Email campaigns (110+)</text>
|
|
<text x="910" y="251" font-size="9" fill="#475569">Subscriber lists (9)</text>
|
|
<text x="910" y="264" font-size="9" fill="#475569">Bounce webhook API</text>
|
|
<text x="910" y="277" font-size="8" fill="#94a3b8">Port 9100 | listmonk:latest</text>
|
|
|
|
<!-- Monitoring stack -->
|
|
<rect x="1085" y="205" width="295" height="90" rx="8" fill="#fef2f2" stroke="#fca5a5"/>
|
|
<text x="1232" y="222" text-anchor="middle" font-size="10" font-weight="700" fill="#991b1b">Monitoring Stack</text>
|
|
<text x="1095" y="238" font-size="9" fill="#475569">Prometheus + Alertmanager → Telegram</text>
|
|
<text x="1095" y="251" font-size="9" fill="#475569">Grafana dashboards (3000)</text>
|
|
<text x="1095" y="264" font-size="9" fill="#475569">Umami analytics (3100)</text>
|
|
<text x="1095" y="277" font-size="8" fill="#94a3b8">cAdvisor, node-exporter, blackbox</text>
|
|
|
|
<!-- ═══ DATA TIER ═══ -->
|
|
<text x="30" y="320" font-size="11" font-weight="700" fill="#1e3a5f">Data Tier</text>
|
|
|
|
<!-- PostgreSQL -->
|
|
<rect x="20" y="330" width="200" height="75" rx="8" fill="#e0f2fe" stroke="#7dd3fc"/>
|
|
<text x="120" y="347" text-anchor="middle" font-size="10" font-weight="700" fill="#0369a1">PostgreSQL</text>
|
|
<text x="30" y="363" font-size="9" fill="#475569">compliance_orders, telecom_entities</text>
|
|
<text x="30" y="376" font-size="9" fill="#475569">esign_records, check_log</text>
|
|
<text x="30" y="389" font-size="9" fill="#475569">77 migrations applied</text>
|
|
<text x="30" y="400" font-size="8" fill="#94a3b8">Port 5432 | 4x/day backup</text>
|
|
|
|
<!-- MariaDB -->
|
|
<rect x="235" y="330" width="200" height="75" rx="8" fill="#e0f2fe" stroke="#7dd3fc"/>
|
|
<text x="335" y="347" text-anchor="middle" font-size="10" font-weight="700" fill="#0369a1">MariaDB (ERPNext)</text>
|
|
<text x="245" y="363" font-size="9" fill="#475569">Sales Orders, Invoices, Customers</text>
|
|
<text x="245" y="376" font-size="9" fill="#475569">Compliance Calendar/Deadline</text>
|
|
<text x="245" y="389" font-size="9" fill="#475569">7 custom DocTypes</text>
|
|
<text x="245" y="400" font-size="8" fill="#94a3b8">Port 3306 | daily backup</text>
|
|
|
|
<!-- MinIO -->
|
|
<rect x="450" y="330" width="200" height="75" rx="8" fill="#e0f2fe" stroke="#7dd3fc"/>
|
|
<text x="550" y="347" text-anchor="middle" font-size="10" font-weight="700" fill="#0369a1">MinIO (S3)</text>
|
|
<text x="460" y="363" font-size="9" fill="#475569">Document storage (DOCX, PDF)</text>
|
|
<text x="460" y="376" font-size="9" fill="#475569">Compliance packets, binders</text>
|
|
<text x="460" y="389" font-size="9" fill="#475569">DocServer DOCX↔PDF queue</text>
|
|
<text x="460" y="400" font-size="8" fill="#94a3b8">Port 9000/9001 | daily mirror</text>
|
|
|
|
<!-- Redis -->
|
|
<rect x="665" y="330" width="130" height="75" rx="8" fill="#e0f2fe" stroke="#7dd3fc"/>
|
|
<text x="730" y="347" text-anchor="middle" font-size="10" font-weight="700" fill="#0369a1">Redis</text>
|
|
<text x="675" y="363" font-size="9" fill="#475569">ERPNext cache</text>
|
|
<text x="675" y="376" font-size="9" fill="#475569">Queue, SocketIO</text>
|
|
<text x="675" y="400" font-size="8" fill="#94a3b8">Port 6379</text>
|
|
|
|
<!-- Ollama -->
|
|
<rect x="810" y="330" width="130" height="75" rx="8" fill="#f5f3ff" stroke="#c4b5fd"/>
|
|
<text x="875" y="347" text-anchor="middle" font-size="10" font-weight="700" fill="#5b21b6">Ollama (LLM)</text>
|
|
<text x="820" y="363" font-size="9" fill="#475569">qwen2.5:7b</text>
|
|
<text x="820" y="376" font-size="9" fill="#475569">Doc generation</text>
|
|
<text x="820" y="400" font-size="8" fill="#94a3b8">Port 11434</text>
|
|
|
|
<!-- Forgejo -->
|
|
<rect x="955" y="330" width="130" height="75" rx="8" fill="#f8fafc" stroke="#e2e8f0"/>
|
|
<text x="1020" y="347" text-anchor="middle" font-size="10" font-weight="700" fill="#374151">Forgejo (Git)</text>
|
|
<text x="965" y="363" font-size="9" fill="#475569">git.performancewest.net</text>
|
|
<text x="965" y="376" font-size="9" fill="#475569">Source code repo</text>
|
|
<text x="965" y="400" font-size="8" fill="#94a3b8">Port 2222 (SSH) / 3033</text>
|
|
|
|
<!-- k3s / SHKeeper -->
|
|
<rect x="1100" y="330" width="130" height="75" rx="8" fill="#fef3c7" stroke="#fcd34d"/>
|
|
<text x="1165" y="347" text-anchor="middle" font-size="10" font-weight="700" fill="#92400e">k3s (SHKeeper)</text>
|
|
<text x="1110" y="363" font-size="9" fill="#475569">Crypto payments</text>
|
|
<text x="1110" y="376" font-size="9" fill="#475569">BTC, ETH, USDC</text>
|
|
<text x="1110" y="400" font-size="8" fill="#94a3b8">crypto.performancewest.net</text>
|
|
|
|
<!-- Umami PG -->
|
|
<rect x="1245" y="330" width="130" height="75" rx="8" fill="#e0f2fe" stroke="#7dd3fc"/>
|
|
<text x="1310" y="347" text-anchor="middle" font-size="10" font-weight="700" fill="#0369a1">Umami PG</text>
|
|
<text x="1255" y="363" font-size="9" fill="#475569">Analytics events</text>
|
|
<text x="1255" y="376" font-size="9" fill="#475569">Sessions, page views</text>
|
|
<text x="1255" y="400" font-size="8" fill="#94a3b8">Internal only</text>
|
|
|
|
<!-- ═══ EXTERNAL SERVICES ═══ -->
|
|
<text x="30" y="435" font-size="11" font-weight="700" fill="#1e3a5f">External Services & Servers</text>
|
|
|
|
<rect x="20" y="445" width="190" height="80" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
<text x="115" y="462" text-anchor="middle" font-size="10" font-weight="700" fill="#374151">Carbonio Mail</text>
|
|
<text x="30" y="478" font-size="9" fill="#475569">207.174.124.15</text>
|
|
<text x="30" y="491" font-size="9" fill="#475569">co.carrierone.com</text>
|
|
<text x="30" y="504" font-size="9" fill="#475569">DKIM + transactional email</text>
|
|
<text x="30" y="517" font-size="8" fill="#94a3b8">PTR: co.carrierone.com</text>
|
|
|
|
<rect x="225" y="445" width="190" height="80" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
<text x="320" y="462" text-anchor="middle" font-size="10" font-weight="700" fill="#374151">HestiaCP</text>
|
|
<text x="235" y="478" font-size="9" fill="#475569">207.174.124.22</text>
|
|
<text x="235" y="491" font-size="9" fill="#475569">cp.carrierone.com</text>
|
|
<text x="235" y="504" font-size="9" fill="#475569">DNS, Exim4 MTA, .ca domains</text>
|
|
<text x="235" y="517" font-size="8" fill="#94a3b8">PTR: cp.carrierone.com</text>
|
|
|
|
<rect x="430" y="445" width="190" height="80" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
<text x="525" y="462" text-anchor="middle" font-size="10" font-weight="700" fill="#374151">Postfix (local)</text>
|
|
<text x="440" y="478" font-size="9" fill="#475569">207.174.124.71</text>
|
|
<text x="440" y="491" font-size="9" fill="#475569">Campaign SMTP + OpenDKIM</text>
|
|
<text x="440" y="504" font-size="9" fill="#475569">Bounce watcher daemon</text>
|
|
<text x="440" y="517" font-size="8" fill="#94a3b8">PTR: perfwest.performancewest.net</text>
|
|
|
|
<rect x="635" y="445" width="170" height="80" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
<text x="720" y="462" text-anchor="middle" font-size="10" font-weight="700" fill="#374151">Windows DocServer</text>
|
|
<text x="645" y="478" font-size="9" fill="#475569">Word COM → PDF</text>
|
|
<text x="645" y="491" font-size="9" fill="#475569">Polls MinIO to-convert/</text>
|
|
<text x="645" y="504" font-size="9" fill="#475569">Fallback: LibreOffice</text>
|
|
<text x="645" y="517" font-size="8" fill="#94a3b8">Requires RDP login after reboot</text>
|
|
|
|
<rect x="820" y="445" width="170" height="80" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
<text x="905" y="462" text-anchor="middle" font-size="10" font-weight="700" fill="#374151">Backup Server</text>
|
|
<text x="830" y="478" font-size="9" fill="#475569">207.174.124.50</text>
|
|
<text x="830" y="491" font-size="9" fill="#475569">appbackups LXC</text>
|
|
<text x="830" y="504" font-size="9" fill="#475569">PG, MariaDB, MinIO, Forgejo</text>
|
|
<text x="830" y="517" font-size="8" fill="#94a3b8">Off-site rsync daily</text>
|
|
|
|
<rect x="1005" y="445" width="190" height="80" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
<text x="1100" y="462" text-anchor="middle" font-size="10" font-weight="700" fill="#374151">DNS (HE + HestiaCP)</text>
|
|
<text x="1015" y="478" font-size="9" fill="#475569">ns0.cp.carrierone.com</text>
|
|
<text x="1015" y="491" font-size="9" fill="#475569">ns1-5.he.net (Hurricane Electric)</text>
|
|
<text x="1015" y="504" font-size="9" fill="#475569">DNSSEC: not enabled</text>
|
|
<text x="1015" y="517" font-size="8" fill="#94a3b8">Reverse zone: 124.174.207.in-addr.arpa</text>
|
|
|
|
<rect x="1210" y="445" width="170" height="80" rx="8" fill="#fff" stroke="#e2e8f0"/>
|
|
<text x="1295" y="462" text-anchor="middle" font-size="10" font-weight="700" fill="#374151">ARIN</text>
|
|
<text x="1220" y="478" font-size="9" fill="#475569">IP block: 207.174.124.0/23</text>
|
|
<text x="1220" y="491" font-size="9" fill="#475569">Owner: Carrier One (COTN)</text>
|
|
<text x="1220" y="504" font-size="9" fill="#475569">rDNS delegated to HestiaCP</text>
|
|
|
|
<!-- ═══ CRON JOBS ═══ -->
|
|
<rect x="20" y="545" width="1360" height="55" rx="8" fill="#f8fafc" stroke="#e2e8f0"/>
|
|
<text x="700" y="565" text-anchor="middle" font-size="11" font-weight="700" fill="#1e3a5f">Scheduled Jobs (systemd timers + cron)</text>
|
|
<text x="35" y="582" font-size="8" fill="#475569">PG backup 4x/day | MariaDB daily | MinIO mirror 3:30 AM | Forgejo dump 4 AM | Entity scraper 3 AM | Entity cache 2 AM | RMD scraper 4 AM | Renewal check 11 PM</text>
|
|
<text x="35" y="594" font-size="8" fill="#475569">Campaign warmup 8:15 AM M-F | Payment reminder every 5m | AMB scraper 6 AM | CDR retention midnight | Container security 3:30 AM | Cold wallet sweep 10 PM | Bounce watcher (daemon)</text>
|
|
|
|
<!-- Footer -->
|
|
<text x="700" y="625" text-anchor="middle" font-size="9" fill="#94a3b8">Performance West Inc. — 207.174.124.71 — Debian 13 — Docker Compose — Updated 2026-05-07</text>
|
|
</svg>
|