auto: docs sync 2026-06-15T20:08:44+00:00

Files changed: .obsidian/workspace.json PHASE6_DECISION.md PLAN.md appservices.md archive_receiver_discovery.md archivist.md archivist_discovery.md argus.md docs/hardware/environment.md docs/services/services.md docs/software/recon.md echo6-landing-page-data-export.md hookshot_deployment_discovery.md hookshot_e2ee_discovery.md hookshot_payload_discovery.md hookshot_room_targeting_discovery.md matrix_host.md mautrix_signal.md pp_comparison.json projects/headscale-full-deployment.md projects/utility-caddy-initial-setup.md projects/vaultwarden-deployment.md runbooks/add-peertube-channel.md runbooks/authentik-oidc-application.md runbooks/proxmox-create-ubuntu-vm.md runbooks/proxmox-onboard-node.md runbooks/recon-operations.md runbooks/recon-service-integration.md scribd_session.json synapse.md synapse_retention_discovery.md
This commit is contained in:
echo6-autocommit 2026-06-15 20:08:44 +00:00
commit a5299d09a2
31 changed files with 80 additions and 29410 deletions

View file

@ -189,6 +189,19 @@
}, },
"active": "ea4cc678c44e8b67", "active": "ea4cc678c44e8b67",
"lastOpenFiles": [ "lastOpenFiles": [
"synapse_retention_discovery.md",
"synapse.md",
"mautrix_signal.md",
"matrix_host.md",
"hookshot_room_targeting_discovery.md",
"hookshot_payload_discovery.md",
"hookshot_e2ee_discovery.md",
"hookshot_deployment_discovery.md",
"argus.md",
"archivist_discovery.md",
"archivist.md",
"archive_receiver_discovery.md",
"appservices.md",
"AUDIT-2026-02-21.md", "AUDIT-2026-02-21.md",
"CLAUDE-baseline.md", "CLAUDE-baseline.md",
"echo6-landing-page-data-export.md", "echo6-landing-page-data-export.md",

View file

@ -113,10 +113,10 @@ incompatibility, which the recommended approach avoids entirely.
## Ref Files Produced ## Ref Files Produced
1. `.ref/synapse_retention_discovery.ref` — Current retention config, MSC2815 support, DB sizes, growth rate, rollback 1. `.ref/synapse_retention_discovery.md` — Current retention config, MSC2815 support, DB sizes, growth rate, rollback
2. `.ref/hookshot_deployment_discovery.ref` — Contabo resources, port conflicts, compose snippet 2. `.ref/hookshot_deployment_discovery.md` — Contabo resources, port conflicts, compose snippet
3. `.ref/hookshot_e2ee_discovery.ref`**BLOCKER documented** — E2EE+MAS incompatibility 3. `.ref/hookshot_e2ee_discovery.ref`**BLOCKER documented** — E2EE+MAS incompatibility
4. `.ref/hookshot_payload_discovery.ref` — Webhook payload shape (for future reference) 4. `.ref/hookshot_payload_discovery.md` — Webhook payload shape (for future reference)
5. `.ref/hookshot_room_targeting_discovery.ref` — Per-room model, no wildcard, current portals 5. `.ref/hookshot_room_targeting_discovery.md` — Per-room model, no wildcard, current portals
6. `.ref/archive_receiver_discovery.ref` — Storage options, alternative approaches, CT recommendations 6. `.ref/archive_receiver_discovery.md` — Storage options, alternative approaches, CT recommendations
7. `.ref/PHASE6_DECISION.md` — This file 7. `.ref/PHASE6_DECISION.md` — This file

12
PLAN.md
View file

@ -4,7 +4,7 @@
**Same Contabo host**, same Docker Compose stack at `/opt/matrix/docker-compose.yml`. **Same Contabo host**, same Docker Compose stack at `/opt/matrix/docker-compose.yml`.
Rationale: Synapse runs as Docker on Contabo (ref: `synapse.ref` — "Docker Compose at /opt/matrix/docker-compose.yml"). The bridge container joins the existing `matrix-net` network so it can reach both `matrix-synapse` and `matrix-postgres` by container name without exposing any new ports externally. Rationale: Synapse runs as Docker on Contabo (ref: `synapse.md` — "Docker Compose at /opt/matrix/docker-compose.yml"). The bridge container joins the existing `matrix-net` network so it can reach both `matrix-synapse` and `matrix-postgres` by container name without exposing any new ports externally.
## 2. Bridge Version ## 2. Bridge Version
@ -44,9 +44,9 @@ SELECT 1 FROM synapse.public.users LIMIT 1; -- should fail with permission deni
RESET ROLE; RESET ROLE;
``` ```
- Collation matches Synapse's DB settings (ref: `synapse.ref` — POSTGRES_INITDB_ARGS uses `--lc-collate=C --lc-ctype=C`) - Collation matches Synapse's DB settings (ref: `synapse.md` — POSTGRES_INITDB_ARGS uses `--lc-collate=C --lc-ctype=C`)
- No shared schema with Synapse or MAS - No shared schema with Synapse or MAS
- The `synapse` user has Superuser privileges so can create the role/DB (ref: `synapse.ref` — "synapse (Superuser, Create role, Create DB)") - The `synapse` user has Superuser privileges so can create the role/DB (ref: `synapse.md` — "synapse (Superuser, Create role, Create DB)")
- Bridge config URI: `postgres://mautrix_signal:<password>@matrix-postgres:5432/mautrix_signal?sslmode=disable` - Bridge config URI: `postgres://mautrix_signal:<password>@matrix-postgres:5432/mautrix_signal?sslmode=disable`
## 4. Networking ## 4. Networking
@ -54,7 +54,7 @@ RESET ROLE;
- **Appservice port:** 29328 (mautrix-signal default) - **Appservice port:** 29328 (mautrix-signal default)
- **Bind:** 0.0.0.0:29328 inside container (Docker internal only, NOT exposed to host) - **Bind:** 0.0.0.0:29328 inside container (Docker internal only, NOT exposed to host)
- **Appservice address in config:** `http://mautrix-signal:29328` (container name on matrix-net) - **Appservice address in config:** `http://mautrix-signal:29328` (container name on matrix-net)
- **Verified unused:** No ports in 29xxx range are in use (ref: `appservices.ref` — "Full 29000-29999 range — AVAILABLE") - **Verified unused:** No ports in 29xxx range are in use (ref: `appservices.md` — "Full 29000-29999 range — AVAILABLE")
- **No Caddy changes needed** — bridge communicates with Synapse over the internal Docker network - **No Caddy changes needed** — bridge communicates with Synapse over the internal Docker network
- **No firewall changes needed** — no host port mapping - **No firewall changes needed** — no host port mapping
@ -238,7 +238,7 @@ This ensures messages matt sends from Signal Desktop appear as `@matt:echo6.co`
## 9. Backup Impact ## 9. Backup Impact
The existing backup script (`/opt/matrix/scripts/pg_backup.sh`) only backs up the `synapse` database (ref: `synapse.ref` — "Backs up synapse DB only (NOT mas DB)"). The existing backup script (`/opt/matrix/scripts/pg_backup.sh`) only backs up the `synapse` database (ref: `synapse.md` — "Backs up synapse DB only (NOT mas DB)").
**Action required — BEFORE bridge goes live:** **Action required — BEFORE bridge goes live:**
@ -297,7 +297,7 @@ docker compose rm -f mautrix-signal
# msc3202_transaction_extensions: true # msc3202_transaction_extensions: true
# msc2409_to_device_messages_enabled: true # msc2409_to_device_messages_enabled: true
# - Only safe to remove if no other bridges depend on these flags. # - Only safe to remove if no other bridges depend on these flags.
# As of this plan, no other appservices exist (ref: appservices.ref), # As of this plan, no other appservices exist (ref: appservices.md),
# so removal is safe. # so removal is safe.
# 5. Remove registration files from Synapse volume # 5. Remove registration files from Synapse volume

View file

@ -31,7 +31,7 @@
### Final approach: host-side NFS + Proxmox bind mount ### Final approach: host-side NFS + Proxmox bind mount
- **Utility host fstab:** `192.168.1.245:/export/library /mnt/library nfs defaults,soft,timeo=150 0 0` - **Utility host fstab:** `192.168.1.245:/export/library /mnt/library nfs defaults,soft,timeo=150 0 0`
- **CT 118 mp0:** `/mnt/library,mp=/mnt/library,ro=0` - **CT 118 mp0:** `/mnt/library,mp=/mnt/library,ro=0`
- **Pattern source:** CT 130 (RECON) on data node uses identical approach - **Pattern source:** recon-vm (VM 1130, RECON) on data node uses identical approach
- Utility host did NOT have /mnt/library mounted before this deployment - Utility host did NOT have /mnt/library mounted before this deployment
### Write access ### Write access

View file

View file

@ -62,7 +62,7 @@ Five nodes running Proxmox VE:
- **NFS mounts:** pi-nas:/export/library → /mnt/library, /mnt/nav, /mnt/kiwix - **NFS mounts:** pi-nas:/export/library → /mnt/library, /mnt/nav, /mnt/kiwix
- **User:** zvx (sudo, SSH key auth) - **User:** zvx (sudo, SSH key auth)
- **Migrated from:** CT 130 (LXC) on 2026-04-19. Tailscale identity preserved (100.64.0.24). - **Migrated from:** CT 130 (LXC) on 2026-04-19. Tailscale identity preserved (100.64.0.24).
- **Note:** Old CT 130 is stopped on the data host, not yet destroyed. - **Note:** Old CT 130 (LXC) has since been destroyed (verified 2026-06-15) — only VM 1130 remains.
### arr VM Details ### arr VM Details

View file

@ -50,7 +50,7 @@
| mautrix-signal | Contabo | 29328 (internal) | Internal (matrix-net) | Signal bridge — @signalbot:echo6.co, E2BE, MSC4190, auto-portals | | mautrix-signal | Contabo | 29328 (internal) | Internal (matrix-net) | Signal bridge — @signalbot:echo6.co, E2BE, MSC4190, auto-portals |
| Matrix MAS | Contabo | 127.0.0.1:8085 | Internal (via Caddy) | Matrix Authentication Service (Docker, handles login/logout/OIDC for Synapse) | | Matrix MAS | Contabo | 127.0.0.1:8085 | Internal (via Caddy) | Matrix Authentication Service (Docker, handles login/logout/OIDC for Synapse) |
| Termix | Contabo | 0.0.0.0:8083 | Internal (no Caddy block) | Terminal sharing tool (Docker, ghcr.io/lukegus/termix:latest) | | Termix | Contabo | 0.0.0.0:8083 | Internal (no Caddy block) | Terminal sharing tool (Docker, ghcr.io/lukegus/termix:latest) |
| Archivist | utility (CT 118) | 192.168.1.118 | Internal | Signal/Matrix room archive bot (systemd) — see archivist.ref for details | | Archivist | utility (CT 118) | 192.168.1.118 | Internal | Signal/Matrix room archive bot (systemd) — see archivist.md for details |
| pt-transcoder | cortex (VM 150) | N/A | Internal | PeerTube H.265 NVENC transcoder (systemd, /opt/bulk-import/transcoder.py) | | pt-transcoder | cortex (VM 150) | N/A | Internal | PeerTube H.265 NVENC transcoder (systemd, /opt/bulk-import/transcoder.py) |
| recon-sparse | cortex (VM 150) | 192.168.1.150:8091 | Internal | RECON sparse embedding service (systemd, bge-m3 model, port 8091) | | recon-sparse | cortex (VM 150) | 192.168.1.150:8091 | Internal | RECON sparse embedding service (systemd, bge-m3 model, port 8091) |
| Samba | cortex (VM 150) | 192.168.1.150:445 | Internal | SMB file sharing — `//cortex/projects` → /home/zvx/projects (guest access) | | Samba | cortex (VM 150) | 192.168.1.150:445 | Internal | SMB file sharing — `//cortex/projects` → /home/zvx/projects (guest access) |
@ -137,7 +137,7 @@
- 1 core, 1GB RAM, 8GB disk - 1 core, 1GB RAM, 8GB disk
- Not registered in Headscale (no Tailscale) - Not registered in Headscale (no Tailscale)
- Source: forge.echo6.co/matt/matrix-archivist (private) - Source: forge.echo6.co/matt/matrix-archivist (private)
- See `/home/zvx/projects/.ref/archivist.ref` for implementation details - See `/home/zvx/projects/.ref/archivist.md` for implementation details
### cloud - CT 120 (192.168.1.182 / Tailscale: 100.64.0.2) ### cloud - CT 120 (192.168.1.182 / Tailscale: 100.64.0.2)
- Immich photo management (https://immich.echo6.co) - Immich photo management (https://immich.echo6.co)
@ -312,7 +312,7 @@
- E2BE enabled (MSC4190), double puppeting via doublepuppet.yaml - E2BE enabled (MSC4190), double puppeting via doublepuppet.yaml
- Signal account: +12083080811 (@matt:echo6.co) - Signal account: +12083080811 (@matt:echo6.co)
- Portals auto-create on incoming messages (no autocreate toggle available) - Portals auto-create on incoming messages (no autocreate toggle available)
- Ref: `/home/zvx/projects/.ref/mautrix_signal.ref` - Ref: `/home/zvx/projects/.ref/mautrix_signal.md`
## Adding New Services ## Adding New Services

View file

@ -6,11 +6,11 @@ RECON extracts knowledge from PDFs and web content into a searchable vector data
## Location ## Location
- **Host:** recon LXC (CT 130 on data node, 192.168.1.240) - **Host:** recon-vm (VM 1130 on data node, 192.168.1.240) — migrated from CT 130 on 2026-04-19
- **IP:** 192.168.1.130 / 100.64.0.24 (Tailscale) - **IP:** 192.168.1.130 / 100.64.0.24 (Tailscale)
- **Install:** `/opt/recon/` - **Install:** `/opt/recon/`
- **User:** zvx - **User:** zvx
- **Service:** `recon.service` (systemd, Type=simple, Restart=on-failure) - **Service:** `recon.service`, `recon-watchdog.service`, `kiwix.service` (systemd)
- **Dashboard:** https://recon.echo6.co (internal: http://100.64.0.24:8420) - **Dashboard:** https://recon.echo6.co (internal: http://100.64.0.24:8420)
- **Health:** https://recon.echo6.co/api/health - **Health:** https://recon.echo6.co/api/health
@ -23,8 +23,8 @@ RECON extracts knowledge from PDFs and web content into a searchable vector data
| Status DB | SQLite (WAL mode) | /opt/recon/data/recon.db | | Status DB | SQLite (WAL mode) | /opt/recon/data/recon.db |
| Vector DB | Qdrant | cortex:6333 (Docker) | | Vector DB | Qdrant | cortex:6333 (Docker) |
| Embeddings | TEI (bge-m3, 1024-dim) | cortex:8090 (Docker) | | Embeddings | TEI (bge-m3, 1024-dim) | cortex:8090 (Docker) |
| Enrichment | Gemini 2.0 Flash | Google API (4 keys) | | Enrichment | Gemini 2.5 Flash Lite | Google API (4 keys) |
| Vision OCR | Gemini 2.0 Flash | Google API (shared keys) | | Vision OCR | Gemini 2.5 Flash Lite | Google API (shared keys) |
| Text extraction | PyPDF2, poppler-utils, Tesseract | Local | | Text extraction | PyPDF2, poppler-utils, Tesseract | Local |
| PDF source | NFS | pi-nas:/export/library → /mnt/library | | PDF source | NFS | pi-nas:/export/library → /mnt/library |
| File server | nginx | localhost:8888 → files.echo6.co | | File server | nginx | localhost:8888 → files.echo6.co |
@ -45,7 +45,7 @@ Per page, in order. Each method only runs if the previous returned <50 chars:
1. **PyPDF2** — fast, free, works on text-based PDFs 1. **PyPDF2** — fast, free, works on text-based PDFs
2. **pdftotext** (poppler) — handles some PDFs PyPDF2 misses 2. **pdftotext** (poppler) — handles some PDFs PyPDF2 misses
3. **Tesseract OCR** — renders page to image, runs local OCR 3. **Tesseract OCR** — renders page to image, runs local OCR
4. **Gemini Vision** — renders page to PNG, sends to Gemini 2.0 Flash vision API 4. **Gemini Vision** — renders page to PNG, sends to Gemini 2.5 Flash Lite vision API
Method tracking saved in `data/text/{hash}/meta.json` as `ocr_methods` dict. Method tracking saved in `data/text/{hash}/meta.json` as `ocr_methods` dict.
@ -71,7 +71,7 @@ Key sections:
- `processing.extract_workers` (4), `enrich_workers` (16), `embed_workers` (4) - `processing.extract_workers` (4), `enrich_workers` (16), `embed_workers` (4)
- `processing.extract_timeout` (1800s), `page_timeout` (30s) - `processing.extract_timeout` (1800s), `page_timeout` (30s)
- `processing.enrich_max_retries` (5), `enrich_base_delay` (5.0) - `processing.enrich_max_retries` (5), `enrich_base_delay` (5.0)
- `gemini.model` (gemini-2.0-flash), `gemini.response_mime_type` (application/json) - `gemini.model` (gemini-2.5-flash-lite), `gemini.response_mime_type` (application/json)
- `service.scan_interval` (3600), `stage_poll_interval` (30) - `service.scan_interval` (3600), `stage_poll_interval` (30)
**API keys:** `/opt/recon/.env` — GEMINI_KEY_1 through GEMINI_KEY_4 **API keys:** `/opt/recon/.env` — GEMINI_KEY_1 through GEMINI_KEY_4

View file

@ -220,7 +220,7 @@ Authentik 2025.12.4 — custom CSS is applied via the Brand CSS field in System
| Node | Role | Key Services | | Node | Role | Key Services |
|------|------|-------------| |------|------|-------------|
| data | Proxmox host | Hosts RECON LXC (CT 130) | | data | Proxmox host | Hosts RECON VM (VM 1130) |
| utility | Proxmox host | Caddy reverse proxy (CT 101), TLS termination | | utility | Proxmox host | Caddy reverse proxy (CT 101), TLS termination |
| cloud | Proxmox host | — | | cloud | Proxmox host | — |
| media | Proxmox host | PeerTube LXC (CT 110) | | media | Proxmox host | PeerTube LXC (CT 110) |
@ -303,7 +303,7 @@ Core content, classification (domain/subdomain/skill level/scenario), provenance
| Stage | Workers | Bottleneck | Description | | Stage | Workers | Bottleneck | Description |
|-------|---------|------------|-------------| |-------|---------|------------|-------------|
| Extract | 4 | CPU-bound | PyPDF2 → pdftotext → Tesseract → Gemini Vision (4-method fallback chain) | | Extract | 4 | CPU-bound | PyPDF2 → pdftotext → Tesseract → Gemini Vision (4-method fallback chain) |
| Enrich | 16 | I/O-bound (Gemini API) | 10-page windows → Gemini 2.0 Flash → structured JSON concepts | | Enrich | 16 | I/O-bound (Gemini API) | 10-page windows → Gemini 2.5 Flash Lite → structured JSON concepts |
| Embed | batch | I/O-bound (TEI) | bge-m3 1024-dim → Qdrant insert, 128/batch | | Embed | batch | I/O-bound (TEI) | bge-m3 1024-dim → Qdrant insert, 128/batch |
| Scanner | 1 | Hourly cron | Auto-discovers new PDFs from NFS mount | | Scanner | 1 | Hourly cron | Auto-discovers new PDFs from NFS mount |
@ -433,7 +433,7 @@ files.echo6.co → Document/PDF download server
| Virtualization | Proxmox (5 nodes) | | Virtualization | Proxmox (5 nodes) |
| Networking | Tailscale/Headscale, Caddy, nginx, dnsmasq | | Networking | Tailscale/Headscale, Caddy, nginx, dnsmasq |
| GPU compute | NVIDIA RTX A4000 (CUDA, NVENC, Tensor) | | GPU compute | NVIDIA RTX A4000 (CUDA, NVENC, Tensor) |
| AI/ML | Gemini 2.0 Flash, Ollama, TEI (bge-m3), JOSIEFIED Qwen3 8B | | AI/ML | Gemini 2.5 Flash Lite, Ollama, TEI (bge-m3), JOSIEFIED Qwen3 8B |
| Vector DB | Qdrant (HNSW index, cosine similarity) | | Vector DB | Qdrant (HNSW index, cosine similarity) |
| Databases | SQLite (RECON), PostgreSQL (PeerTube) | | Databases | SQLite (RECON), PostgreSQL (PeerTube) |
| Video | PeerTube v8, yt-dlp, ffmpeg/NVENC, Whisper | | Video | PeerTube v8, yt-dlp, ffmpeg/NVENC, Whisper |

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
**Headscale location:** `/opt/headscale-vanilla` **Headscale location:** `/opt/headscale-vanilla`
**Container name:** `headscale-vanilla` **Container name:** `headscale-vanilla`
**Domain:** `vpn.echo6.co` **Domain:** `vpn.echo6.co`
**Auth key:** `hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ` **Auth key:** `<REDACTED-headscale-preauth-key>`
--- ---
@ -12,7 +12,7 @@
```bash ```bash
tailscale up --login-server https://vpn.echo6.co \ tailscale up --login-server https://vpn.echo6.co \
--auth-key hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ \ --auth-key <REDACTED-headscale-preauth-key> \
--hostname contabo --force-reauth --hostname contabo --force-reauth
``` ```
@ -41,27 +41,27 @@ Then register. **Do them in this exact order for sequential IPs:**
```bash ```bash
# utility (will get 100.64.0.2) # utility (will get 100.64.0.2)
tailscale up --login-server https://vpn.echo6.co \ tailscale up --login-server https://vpn.echo6.co \
--auth-key hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ \ --auth-key <REDACTED-headscale-preauth-key> \
--hostname utility --force-reauth --hostname utility --force-reauth
# data (will get 100.64.0.3) # data (will get 100.64.0.3)
tailscale up --login-server https://vpn.echo6.co \ tailscale up --login-server https://vpn.echo6.co \
--auth-key hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ \ --auth-key <REDACTED-headscale-preauth-key> \
--hostname data --force-reauth --hostname data --force-reauth
# cloud (will get 100.64.0.4) # cloud (will get 100.64.0.4)
tailscale up --login-server https://vpn.echo6.co \ tailscale up --login-server https://vpn.echo6.co \
--auth-key hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ \ --auth-key <REDACTED-headscale-preauth-key> \
--hostname cloud --force-reauth --hostname cloud --force-reauth
# media (will get 100.64.0.5) # media (will get 100.64.0.5)
tailscale up --login-server https://vpn.echo6.co \ tailscale up --login-server https://vpn.echo6.co \
--auth-key hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ \ --auth-key <REDACTED-headscale-preauth-key> \
--hostname media --force-reauth --hostname media --force-reauth
# aida-nebra (will get 100.64.0.6) # aida-nebra (will get 100.64.0.6)
tailscale up --login-server https://vpn.echo6.co \ tailscale up --login-server https://vpn.echo6.co \
--auth-key hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ \ --auth-key <REDACTED-headscale-preauth-key> \
--hostname aida-nebra --force-reauth --hostname aida-nebra --force-reauth
``` ```
@ -77,7 +77,7 @@ docker exec headscale-vanilla headscale nodes list
**Desktop (Windows — PowerShell as Admin):** **Desktop (Windows — PowerShell as Admin):**
```powershell ```powershell
tailscale up --login-server https://vpn.echo6.co ` tailscale up --login-server https://vpn.echo6.co `
--auth-key hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ ` --auth-key <REDACTED-headscale-preauth-key> `
--hostname desktop --force-reauth --hostname desktop --force-reauth
``` ```

View file

@ -9,7 +9,7 @@ One-time setup. Only needed if rebuilding from scratch.
| CT ID | 101 | | CT ID | 101 |
| Hostname | caddy | | Hostname | caddy |
| Local IP | 192.168.1.101 | | Local IP | 192.168.1.101 |
| Tailscale IP | 100.64.0.2 | | Tailscale IP | 100.64.0.8 |
| Public access | 199.6.36.163 (router forwards 80/443) | | Public access | 199.6.36.163 (router forwards 80/443) |
## 1. Create LXC ## 1. Create LXC
@ -63,7 +63,7 @@ curl -fsSL https://tailscale.com/install.sh | sh
pct exec 101 -- tailscale up --login-server https://vpn.echo6.co --hostname caddy pct exec 101 -- tailscale up --login-server https://vpn.echo6.co --hostname caddy
# On Contabo — register the node # On Contabo — register the node
ssh root@100.64.0.6 'docker exec headscale-standby headscale nodes register --key <KEY> --user echo6' ssh root@100.64.0.1 'docker exec headscale headscale nodes register --key <KEY> --user echo6'
# Verify # Verify
pct exec 101 -- tailscale status pct exec 101 -- tailscale status

View file

@ -1,7 +1,7 @@
# Vaultwarden Deployment # Vaultwarden Deployment
**Deployed:** 2026-02-05 **Deployed:** 2026-02-05
**Location:** Contabo VPS (5.189.158.149 / 100.64.0.6) **Location:** Contabo VPS (5.189.158.149 / 100.64.0.1)
**URL:** https://vault.echo6.co **URL:** https://vault.echo6.co
--- ---
@ -92,7 +92,7 @@ vault.echo6.co {
### dnsmasq Split DNS ### dnsmasq Split DNS
```conf ```conf
address=/vault.echo6.co/100.64.0.6 address=/vault.echo6.co/100.64.0.1
``` ```
--- ---

View file

@ -6,7 +6,7 @@ Add a YouTube channel to the PeerTube bulk import pipeline. Creates the PeerTube
## Prerequisites ## Prerequisites
- SSH access from CT 130 (RECON) → CT 110 (PeerTube): working - SSH access from recon-vm (VM 1130) → CT 110 (PeerTube): working
- Sudoers: `/etc/sudoers.d/recon-mgmt` on CT 110 (allows zvx to run yt-dlp, psql, tee as peertube) - Sudoers: `/etc/sudoers.d/recon-mgmt` on CT 110 (allows zvx to run yt-dlp, psql, tee as peertube)
- YouTube cookies at `/opt/bulk-import/config/cookies.txt` on CT 110 (not stale) - YouTube cookies at `/opt/bulk-import/config/cookies.txt` on CT 110 (not stale)
@ -35,7 +35,7 @@ PRIORITY="M" # H, M, or L
### Step 1: Resolve Channel Info ### Step 1: Resolve Channel Info
```bash ```bash
# From CT 130 or cortex: # From recon-vm or cortex:
ssh zvx@192.168.1.170 "sudo -u peertube /usr/local/bin/yt-dlp \ ssh zvx@192.168.1.170 "sudo -u peertube /usr/local/bin/yt-dlp \
--cookies /opt/bulk-import/config/cookies.txt \ --cookies /opt/bulk-import/config/cookies.txt \
--print channel --print channel_url --print channel_id \ --print channel --print channel_url --print channel_id \

View file

@ -4,7 +4,7 @@ Fully automated via Authentik API. No web UI interaction required.
**Prerequisite:** DNS must already exist for the service (run expose-service-contabo.md or expose-service-home.md first). **Prerequisite:** DNS must already exist for the service (run expose-service-contabo.md or expose-service-home.md first).
**Authentik instance:** https://auth.echo6.co (Contabo, 100.64.0.6) **Authentik instance:** https://auth.echo6.co (Contabo, 100.64.0.1)
--- ---
@ -40,7 +40,7 @@ These conflict with Authentik's internal OAuth2 endpoints and **cannot be used**
Create an API token from the Authentik admin account. This only needs to happen once — reuse the token across all OIDC setups. Create an API token from the Authentik admin account. This only needs to happen once — reuse the token across all OIDC setups.
```bash ```bash
ssh root@100.64.0.6 "docker exec authentik-server \ ssh root@100.64.0.1 "docker exec authentik-server \
ak create_token --user akadmin --identifier oidc-automation --expiring 2>/dev/null \ ak create_token --user akadmin --identifier oidc-automation --expiring 2>/dev/null \
|| echo 'Token may already exist — check credentials file'" || echo 'Token may already exist — check credentials file'"
``` ```
@ -63,7 +63,7 @@ The API requires UUIDs for flows, scope mappings, and signing keys. These are st
### Authorization flow ### Authorization flow
```bash ```bash
ssh root@100.64.0.6 "curl -s \ ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/flows/instances/?slug=default-provider-authorization-implicit-consent' \ '$AK_API/flows/instances/?slug=default-provider-authorization-implicit-consent' \
| jq -r '.results[0].pk'" | jq -r '.results[0].pk'"
@ -75,7 +75,7 @@ Store as `AUTH_FLOW_PK`.
```bash ```bash
# Get all scope mapping UUIDs at once # Get all scope mapping UUIDs at once
ssh root@100.64.0.6 "curl -s \ ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/propertymappings/provider/scope/?ordering=scope_name' \ '$AK_API/propertymappings/provider/scope/?ordering=scope_name' \
| jq -r '.results[] | select(.scope_name == \"openid\" or .scope_name == \"email\" or .scope_name == \"profile\" or .scope_name == \"offline_access\") | \"\(.scope_name): \(.pk)\"'" | jq -r '.results[] | select(.scope_name == \"openid\" or .scope_name == \"email\" or .scope_name == \"profile\" or .scope_name == \"offline_access\") | \"\(.scope_name): \(.pk)\"'"
@ -86,7 +86,7 @@ Store each UUID: `SCOPE_OPENID_PK`, `SCOPE_EMAIL_PK`, `SCOPE_PROFILE_PK`, `SCOPE
### Signing key ### Signing key
```bash ```bash
ssh root@100.64.0.6 "curl -s \ ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/crypto/certificatekeypairs/?name=authentik+Self-signed+Certificate&has_key=true' \ '$AK_API/crypto/certificatekeypairs/?name=authentik+Self-signed+Certificate&has_key=true' \
| jq -r '.results[0].pk'" | jq -r '.results[0].pk'"
@ -117,7 +117,7 @@ fi
Create the provider: Create the provider:
```bash ```bash
PROVIDER_RESPONSE=$(ssh root@100.64.0.6 "curl -s \ PROVIDER_RESPONSE=$(ssh root@100.64.0.1 "curl -s \
-X POST '$AK_API/providers/oauth2/' \ -X POST '$AK_API/providers/oauth2/' \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
@ -158,7 +158,7 @@ echo "Client Secret: $CLIENT_SECRET"
## Step 4: Create the Application ## Step 4: Create the Application
```bash ```bash
ssh root@100.64.0.6 "curl -s \ ssh root@100.64.0.1 "curl -s \
-X POST '$AK_API/core/applications/' \ -X POST '$AK_API/core/applications/' \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
@ -282,7 +282,7 @@ Check in order:
Debug via API: Debug via API:
```bash ```bash
ssh root@100.64.0.6 "curl -s \ ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/providers/oauth2/?search=$SERVICE_NAME' \ '$AK_API/providers/oauth2/?search=$SERVICE_NAME' \
| jq '.results[0] | {name, client_id, signing_key, access_token_validity, refresh_token_validity, property_mappings}'" | jq '.results[0] | {name, client_id, signing_key, access_token_validity, refresh_token_validity, property_mappings}'"
@ -291,7 +291,7 @@ ssh root@100.64.0.6 "curl -s \
Or via ak shell: Or via ak shell:
```bash ```bash
ssh root@100.64.0.6 "docker exec authentik-server ak shell -c \" ssh root@100.64.0.1 "docker exec authentik-server ak shell -c \"
from authentik.providers.oauth2.models import OAuth2Provider from authentik.providers.oauth2.models import OAuth2Provider
p = OAuth2Provider.objects.get(name='$SERVICE_NAME') p = OAuth2Provider.objects.get(name='$SERVICE_NAME')
print(f'Access Token: {p.access_token_validity}') print(f'Access Token: {p.access_token_validity}')
@ -316,7 +316,7 @@ The redirect URI in the app config must **exactly** match what's in Authentik
User isn't authorized for the application. By default all authenticated users have access. If you've added group restrictions via policy bindings, verify the user is in the correct group: User isn't authorized for the application. By default all authenticated users have access. If you've added group restrictions via policy bindings, verify the user is in the correct group:
```bash ```bash
ssh root@100.64.0.6 "curl -s \ ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/core/applications/$SERVICE_SLUG/' \ '$AK_API/core/applications/$SERVICE_SLUG/' \
| jq '{name, slug, policy_engine_mode}'" | jq '{name, slug, policy_engine_mode}'"
@ -330,12 +330,12 @@ Missing `offline_access` scope. Without refresh tokens, sessions only last as lo
```bash ```bash
# Delete application first (it references the provider) # Delete application first (it references the provider)
ssh root@100.64.0.6 "curl -s -X DELETE \ ssh root@100.64.0.1 "curl -s -X DELETE \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/core/applications/$SERVICE_SLUG/'" '$AK_API/core/applications/$SERVICE_SLUG/'"
# Then delete provider # Then delete provider
ssh root@100.64.0.6 "curl -s -X DELETE \ ssh root@100.64.0.1 "curl -s -X DELETE \
-H 'Authorization: Bearer $AK_TOKEN' \ -H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/providers/oauth2/$PROVIDER_PK/'" '$AK_API/providers/oauth2/$PROVIDER_PK/'"
``` ```

View file

@ -242,7 +242,7 @@ ssh zvx@$VM_IP 'curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash - &
Generate a preauth key on Contabo first: Generate a preauth key on Contabo first:
```bash ```bash
docker exec headscale-standby headscale preauthkeys create --user echo6 --reusable --expiration 72h docker exec headscale headscale preauthkeys create --user echo6 --reusable --expiration 72h
``` ```
Then register the VM: Then register the VM:
@ -254,7 +254,7 @@ ssh zvx@$VM_IP "sudo tailscale up --login-server https://vpn.echo6.co --auth-key
# Verify # Verify
ssh zvx@$VM_IP 'tailscale status' ssh zvx@$VM_IP 'tailscale status'
docker exec headscale-standby headscale nodes list docker exec headscale headscale nodes list
``` ```
## Step 13 — Final Verification ## Step 13 — Final Verification
@ -273,7 +273,7 @@ ssh zvx@$VM_IP "
echo '=== Disk ===' && df -h / echo '=== Disk ===' && df -h /
" "
docker exec headscale-standby headscale nodes list docker exec headscale headscale nodes list
``` ```
## Post-Creation ## Post-Creation

View file

@ -8,10 +8,11 @@ You install Proxmox. You give CC an IP and a root password. CC does the rest.
| Alias | Local IP | Tailscale IP | | Alias | Local IP | Tailscale IP |
|----------|-----------------|-----------------| |----------|-----------------|-----------------|
| data | 192.168.1.240 | 100.64.0.20 | | data | 192.168.1.240 | 100.64.0.6 |
| utility | 192.168.1.241 | 100.64.0.19 | | utility | 192.168.1.241 | 100.64.0.5 |
| cloud | 192.168.1.242 | 100.64.0.22 | | cloud | 192.168.1.242 | 100.64.0.4 |
| media | 192.168.1.243 | 100.64.0.21 | | media | 192.168.1.243 | 100.64.0.3 |
| toc | 192.168.1.244 | 100.64.0.13 |
Management host: **cortex** Management host: **cortex**

View file

@ -2,7 +2,7 @@
## Service Info ## Service Info
- **Host:** recon-vm (VM 131 on data node) — migrated from CT 130 on 2026-04-19 - **Host:** recon-vm (VM 1130 on data node) — migrated from CT 130 on 2026-04-19
- **IP:** 192.168.1.130 / 100.64.0.24 - **IP:** 192.168.1.130 / 100.64.0.24
- **Install:** /opt/recon/ - **Install:** /opt/recon/
- **User:** zvx - **User:** zvx
@ -186,4 +186,4 @@ sudo systemctl start recon
--- ---
*Last updated: 2026-04-19 — Updated for CT 130 → VM 131 migration* *Last updated: 2026-04-19 — Updated for CT 130 → VM 1130 migration*

View file

@ -8,7 +8,7 @@ Use this when you have a service running on a remote LXC/VM that needs a web man
## Prerequisites ## Prerequisites
- A running Flask or FastAPI dashboard (e.g., RECON on VM 131, WATCHTOWER on Contabo) - A running Flask or FastAPI dashboard (e.g., RECON on VM 1130, WATCHTOWER on Contabo)
- The target service running on a reachable host (LXC, VM, or bare metal) - The target service running on a reachable host (LXC, VM, or bare metal)
- SSH access from the dashboard host to the target host - SSH access from the dashboard host to the target host
- The dashboard runs as a known user (e.g., `zvx`, `recon`, `watchtower`) - The dashboard runs as a known user (e.g., `zvx`, `recon`, `watchtower`)
@ -20,7 +20,7 @@ Use this when you have a service running on a remote LXC/VM that needs a web man
Prompt the user for all of these before executing: Prompt the user for all of these before executing:
``` ```
DASHBOARD_HOST= # Host running the dashboard (e.g., "192.168.1.130", "CT 130") DASHBOARD_HOST= # Host running the dashboard (e.g., "192.168.1.130", "VM 1130")
DASHBOARD_USER= # User the dashboard runs as (e.g., "zvx") DASHBOARD_USER= # User the dashboard runs as (e.g., "zvx")
DASHBOARD_APP_PATH= # Path to the dashboard app (e.g., "/opt/recon/lib/api.py") DASHBOARD_APP_PATH= # Path to the dashboard app (e.g., "/opt/recon/lib/api.py")
DASHBOARD_STATIC_PATH= # Path to frontend files (e.g., "/opt/recon/lib/static/") DASHBOARD_STATIC_PATH= # Path to frontend files (e.g., "/opt/recon/lib/static/")
@ -418,10 +418,10 @@ lines = min(lines, 500) # Cap to prevent abuse
## Usage Examples ## Usage Examples
### RECON managing pipeline services (CT 130 dashboard → CT 110 PeerTube) ### RECON managing pipeline services (VM 1130 dashboard → CT 110 PeerTube)
``` ```
DASHBOARD_HOST=192.168.1.130 (VM 131, data node) DASHBOARD_HOST=192.168.1.130 (VM 1130, data node)
DASHBOARD_USER=zvx DASHBOARD_USER=zvx
TARGET_HOST=192.168.1.170 (CT 110, media node) TARGET_HOST=192.168.1.170 (CT 110, media node)
SERVICE_NAME=peertube SERVICE_NAME=peertube
@ -453,7 +453,7 @@ Services managed:
- pt-downloader (CT 110): start/stop/restart/status/logs - pt-downloader (CT 110): start/stop/restart/status/logs
- pt-importer (CT 110): start/stop/restart/status/logs - pt-importer (CT 110): start/stop/restart/status/logs
- pt-transcoder (cortex): start/stop/restart/status/logs - pt-transcoder (cortex): start/stop/restart/status/logs
- recon (VM 131): start/stop/restart/status/logs - recon (VM 1130): start/stop/restart/status/logs
Each service has its own sudoers file on its target host, Each service has its own sudoers file on its target host,
its own entry in SERVICE_INTEGRATIONS, and its own UI panel. its own entry in SERVICE_INTEGRATIONS, and its own UI panel.
@ -461,4 +461,4 @@ its own entry in SERVICE_INTEGRATIONS, and its own UI panel.
--- ---
*Last updated: 2026-04-19 — Updated CT 130 references to VM 131* *Last updated: 2026-04-19 — Updated CT 130 references to VM 1130*

File diff suppressed because one or more lines are too long