diff --git a/Architecture.md b/Architecture.md new file mode 100644 index 0000000..ac8c9e4 --- /dev/null +++ b/Architecture.md @@ -0,0 +1,186 @@ +# Atlas OS — System Architecture + +## Overview: The One-Box Philosophy + +Atlas OS is deliberately a single-server architecture. One Hetzner CPX32 VPS +(8 vCPU · 16 GB RAM · 150 GB NVMe · Nuremberg) runs the complete operational +infrastructure of Atlas Corporation: CRM, finance, communications, AI, document +management, fleet control, and 11 websites. + +**Why one box?** For a solo founder, operational simplicity outweighs redundancy. +One server = one bill, one SSH target, one Caddy config, one Authentik instance, +and zero inter-datacenter latency. The Tailscale overlay provides device-level +redundancy for access even if Caddy is down. + +--- + +## Network Topology + +``` + ┌──────────────────────────────────────────────┐ + Public Internet │ atlas-01 (Hetzner CPX32) │ + ───────────── │ ┌─────────┐ ┌──────────┐ │ + Browser/App ──────►│ │ Caddy │───►│Authentik │──► Services │ + │ │ (TLS) │ │ (SSO) │ │ + │ └─────────┘ └──────────┘ │ + │ │ + Tailscale mesh │ ┌────────────────────────────────────────┐ │ + ──────────────── │ │ Private tailnet (100.x.x.x) │ │ + iOS / PC / Laptop─►│ │ Webtop desktop · internal dashboards │ │ + │ └────────────────────────────────────────┘ │ + └──────────────────────────────────────────────┘ +``` + +### Public → SSO path (every service except mail ports) +1. Request hits Caddy (443 → Docker port) +2. Caddy runs `forward_auth` against Authentik outpost +3. Authentik validates session cookie / issues redirect to login +4. On success: Caddy copies `X-Authentik-*` headers and proxies to service + +### Tailscale-only services +- Webtop remote desktop (`tailscale serve :8497`) +- Internal dashboards (portal, status feeds) +- atlas-01 SSH (blocked on public firewall, tailnet-only) + +--- + +## Service Layers + +### Tier 0 — Identity & Security +- **Authentik** (`auth.atlascorporation.nl`) — OIDC/SSO, MFA, app proxies +- **Vaultwarden** (`vault.atlascorporation.nl`) — end-to-end encrypted password vault +- **Caddy** — automatic TLS, reverse proxy, the sole public entry point + +### Tier 1 — Core Business +- **Odoo 19** — CRM, invoicing, project management, contacts +- **Nextcloud 31** — file storage, DAV (calendar/contacts sync to iOS) +- **Stalwart** — self-hosted email: SMTP, IMAPS, JMAP, Sieve +- **Forgejo** — self-hosted git (this very repo) + +### Tier 2 — Finance & Operations +- **Firefly III** — double-entry bookkeeping, budgets, reconciliation +- **Enable Banking** — PSD2 bank feed (ING, Knab → Firefly) +- **Paperless-ngx** — document management, OCR, auto-tagging +- **n8n** — workflow automation (webhooks, scheduled tasks) +- **Uptime Kuma** — service health monitoring with alerting + +### Tier 3 — AI & Intelligence +- **LiteLLM proxy** — unified OpenAI-compat API to all models (local + cloud) +- **Open-WebUI** — ChatGPT-style UI on top of LiteLLM +- **Atlas Brain** (`atlas_brain.py`) — Python signal collector, runs every 15 min +- **Atlas Loop** — background nudge cycle, publishes to NATS +- **Atlas Meridian** — autonomous decision engine / battle responder +- **Langfuse** — LLM observability: every call traced with latency, cost, tokens +- **Local model router** (`:8888`) — OpenAI-compat router for local Ollama models + +### Tier 4 — Fleet & Infrastructure +- **MeshCentral** — remote device access, POS terminal fleet management +- **NATS** — real-time pub/sub event bus across all Tailscale devices +- **Atlas heartbeat sink** — aggregates device heartbeats from the NATS mesh +- **Atlas cockpit feeds** — on-disk JSON feeds consumed by the OS desktop +- **Webtop** — full XFCE Linux desktop in the browser (tailnet-only) + +### Tier 5 — Managed Sites (11 sites) + +All served via Caddy. WordPress sites run in isolated Docker stacks: + +| Domain | Stack | Notes | +|--------|-------|-------| +| `atlasworks.nl` | Docker: works-wordpress | Live WooCommerce (Caddy :8111) | +| `atlascorporation.nl` | Docker: corp-wordpress | Corporate site | +| `atlasagency.nl` | Docker: agency-wordpress | Agency services | +| `atlasacademy.nl` | TransIP nginx (static HTML) | Academy landing | +| `atlaspos.nl` | TransIP | AtlasPOS product site | +| `atlashub.nl` | Docker: atlashub | Hub platform | +| `bicosagency.nl` | Docker: bicos-wordpress | Client site | +| `budgetenergiecoach.nl` | Docker | Client site | +| `hkintercare.nl` | Docker: hkincare-wordpress | Client site | +| `jouwenergieadvies.nl` | Docker | Client site | +| `reclamemans.nl` | Docker | Client site | + +--- + +## Data Flow — Atlas Brain Cycle + +``` +Every 15 minutes (atlas-brain.service): + ┌──────────────────────────────────────────┐ + │ Signal collection phase │ + │ ├── 7 IMAP mailboxes (read-only) │ + │ ├── Odoo REST API (leads, contacts) │ + │ ├── Enable Banking (bank transactions) │ + │ └── atlas-01 health/fleet feeds │ + └──────────────────┬───────────────────────┘ + │ + ▼ + atlas-state.json + │ + ▼ + LLM synthesis (model router): + atlas-auto (local) → Groq 70B → Claude Opus + │ + ▼ + atlas-brief-spoken.json (daily brief) + │ + ▼ + Atlas OS cockpit panels (Today · Money · Inbox · Pipeline) +``` + +--- + +## The AI Mesh + +``` +atlas-01 (NATS JetStream server) + │ + ├── subjects: + │ atlas.events.* system events (disk, CPU, service state) + │ atlas.heartbeat.* device health pings + │ atlas.jobs.* delegated compute jobs (Ollama on NEBULA) + │ atlas.brief.* daily brief push to all devices + │ + └── subscribers: + Caddy PC (this machine) ← atlas-events-collector + NEBULA (HP EliteBook) ← atlas-delegate-worker (5 Ollama models) + MET-Desktop ← Odoo failover + fleet monitor +``` + +--- + +## Caddy SSO Pattern + +Every SSO-gated service uses this Caddyfile block (see `deploy/caddy/Caddyfile.template`): + +```caddy +app.example.com { + # Authentik outpost endpoints (must come first) + reverse_proxy /outpost.goauthentik.io/* authentik-server:9000 + + # SSO gate — redirects to login if no valid session + forward_auth authentik-server:9000 { + uri /outpost.goauthentik.io/auth/caddy + copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email + X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt + } + + # Only reached after successful authentication + reverse_proxy localhost:APP_PORT +} +``` + +--- + +## Docker Compose Topology + +| Stack | File | Services | +|-------|------|----------| +| Core | `deploy/compose/atlas-core.yml` | Authentik, Nextcloud, Stalwart, Forgejo, Vaultwarden | +| AI | `deploy/compose/atlas-ai.yml` | LiteLLM, Open-WebUI, Langfuse | +| Business | `atlas-odoo.yml` | Odoo 19 + PostgreSQL | +| Finance | `atlas-finance.yml` | Firefly III + Paperless-ngx + Enable Banking | +| Fleet | `atlas-fleet.yml` | MeshCentral + NATS + Uptime Kuma | +| Sites | Per-site compose | WordPress stacks | +| Desktop | `deploy/webtop-docker-compose.yml` | Webtop (tailnet-only) | + +All stacks share the `atlas-net` Docker network. Caddy is the **sole** process with +public port bindings (80/443). All internal services bind only to `127.0.0.1:PORT`.