Publish Docs Site / build (push) Failing after 5s
- mkdocs.yml with dark slate theme, nav for 12 ITPP projects - build-docs.sh aggregates docs from all project repos - .gitea/workflows/docs-publish.yml for nightly rebuild+deploy - README and CHANGELOG for the itpp-docs repo itself - docs-source/ populated from all 12 repos - site/ ready for deployment to docs.itpropartner.com
113 lines
4.4 KiB
Markdown
113 lines
4.4 KiB
Markdown
# Ops Portal — Architecture
|
|
|
|
## Topology
|
|
|
|
```
|
|
INTERNET
|
|
|
|
|
[Caddy :443]
|
|
|
|
|
Core (152.53.192.33)
|
|
|
|
|
+---------------+---------------+
|
|
| | |
|
|
/api/* :8090 /data/* :files /static/*
|
|
| | |
|
|
[FastAPI app] ops-status.json [HTML/CSS/JS]
|
|
server.py /var/www/ops/ /opt/ops-portal/
|
|
| /data/ static/
|
|
|
|
|
+-------+-------+-------+-------+
|
|
| | | | |
|
|
S3 API UISP Wazuh Bitdef systemd
|
|
(Wasabi) (FFW) (app1) (Cloud) (Core)
|
|
```
|
|
|
|
## Data Flow
|
|
|
|
```
|
|
[Collector] [Dashboard]
|
|
| |
|
|
|-- python3 ops-data- |
|
|
| collector.py |
|
|
| |
|
|
v |
|
|
S3 buckets ----+ |
|
|
UISP API ------+---> ops-status |
|
|
Wazuh API -----+ .json ------> GET /api/status
|
|
Bitdefender ---+ |
|
|
systemd -------+ |
|
|
cron jobs -----+ |
|
|
v
|
|
[Browser renders
|
|
health grid,
|
|
widgets, alerts]
|
|
```
|
|
|
|
## Components
|
|
|
|
### 1. Collector (`/root/.hermes/scripts/ops-data-collector.py`)
|
|
- Runs every 5 min via cron
|
|
- Gathers: S3 backup status (6 buckets), UISP devices (90), Wazuh agents/alerts, Bitdefender endpoints, systemd services, cron jobs, server health, disk/memory/CPU
|
|
- Timeout: 90s (was 20s — too short for 94K-file S3 bucket)
|
|
- Output: `/var/www/ops/data/ops-status.json`
|
|
|
|
### 2. Backend (`/opt/ops-portal/server.py`)
|
|
- FastAPI on port 8090
|
|
- 7 API endpoints (health, status, servers, servers/health, audit-log, ft360/status)
|
|
- JWT auth from `/root/.hermes/.env` (ADMIN_USERNAME, ADMIN_PASSWORD, JWT_SECRET)
|
|
- Critical service restart protection (hermes, caddy, ops-portal blocked)
|
|
- Systemd: `ops-portal.service`
|
|
|
|
### 3. Frontend (`/opt/ops-portal/static/`)
|
|
- 11 HTML pages with shared ops.css, app.js, utils.js
|
|
- Auth: login overlay → localStorage JWT → all API calls Bearer
|
|
- Auto-refresh: 60s interval + tab visibility API
|
|
- Mobile: hamburger toggle with .nav-links.open CSS
|
|
- Cache-busting: all assets versioned with timestamps
|
|
|
|
### 4. Proxy (Caddy on Core)
|
|
- `/` and `/*.html` → static file server from `/opt/ops-portal/static/`
|
|
- `/api/*` → reverse_proxy to 127.0.0.1:8090
|
|
- `/data/*` → file server from `/var/www/ops/data/`
|
|
- Domain: ops.itpropartner.com
|
|
|
|
## Cross-Service Dependencies
|
|
|
|
| Dependency | Server | Purpose | Fallback |
|
|
|---|---|---|---|
|
|
| Wasabi S3 | External | Backup bucket status | Shows "Issues" |
|
|
| UISP API | unms.forefrontwireless.com | Device/site count | Shows 0 devices |
|
|
| Wazuh | app1 (152.53.36.131) | Agent count, alerts | Shows "Offline" |
|
|
| Bitdefender | External API | Endpoint monitoring | Shows "Offline" |
|
|
| Traccar | app2 (152.53.39.202) | FleetTracker data | Dedicated endpoint |
|
|
| Core systemd | Local | Service health, disk, memory | N/A (local) |
|
|
|
|
## Auth Flow
|
|
|
|
```
|
|
Browser Server
|
|
| |
|
|
|-- POST /api/auth/login ->|
|
|
| {username, password} |
|
|
| |-- Validate against ADMIN_USERNAME/ADMIN_PASSWORD
|
|
| |-- Generate JWT with JWT_SECRET
|
|
|<- {access_token} --------|
|
|
| |
|
|
|-- GET /api/status ------->|
|
|
| Authorization: Bearer |
|
|
| |-- Verify JWT
|
|
| |-- Read ops-status.json
|
|
|<- {full dashboard} ------|
|
|
```
|
|
|
|
## Key Design Decisions
|
|
|
|
1. **Collector pattern over direct API calls:** Dashboard fetches one JSON blob rather than 6 separate APIs. Single point of failure but fast rendering and offline-capable (shows last-cached data).
|
|
|
|
2. **Python/FastAPI over Node:** Already have Python toolchain on Core. FastAPI is lightweight, async-native, and the ops portal is read-heavy with minimal write paths.
|
|
|
|
3. **Static HTML + vanilla JS over React/Vue:** 11-page dashboard with no SPA routing. Auth via localStorage JWT. Zero build step, zero dependencies beyond ops.css.
|
|
|
|
4. **JWT over session cookies:** Cross-page auth without server-side session state. Token survives page navigations and ops-portal restarts (persistent JWT_SECRET in .env).
|