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",
"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",
"CLAUDE-baseline.md",
"echo6-landing-page-data-export.md",

View file

@ -113,10 +113,10 @@ incompatibility, which the recommended approach avoids entirely.
## Ref Files Produced
1. `.ref/synapse_retention_discovery.ref` — Current retention config, MSC2815 support, DB sizes, growth rate, rollback
2. `.ref/hookshot_deployment_discovery.ref` — Contabo resources, port conflicts, compose snippet
1. `.ref/synapse_retention_discovery.md` — Current retention config, MSC2815 support, DB sizes, growth rate, rollback
2. `.ref/hookshot_deployment_discovery.md` — Contabo resources, port conflicts, compose snippet
3. `.ref/hookshot_e2ee_discovery.ref`**BLOCKER documented** — E2EE+MAS incompatibility
4. `.ref/hookshot_payload_discovery.ref` — Webhook payload shape (for future reference)
5. `.ref/hookshot_room_targeting_discovery.ref` — Per-room model, no wildcard, current portals
6. `.ref/archive_receiver_discovery.ref` — Storage options, alternative approaches, CT recommendations
4. `.ref/hookshot_payload_discovery.md` — Webhook payload shape (for future reference)
5. `.ref/hookshot_room_targeting_discovery.md` — Per-room model, no wildcard, current portals
6. `.ref/archive_receiver_discovery.md` — Storage options, alternative approaches, CT recommendations
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`.
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
@ -44,9 +44,9 @@ SELECT 1 FROM synapse.public.users LIMIT 1; -- should fail with permission deni
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
- 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`
## 4. Networking
@ -54,7 +54,7 @@ RESET ROLE;
- **Appservice port:** 29328 (mautrix-signal default)
- **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)
- **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 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
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:**
@ -297,7 +297,7 @@ docker compose rm -f mautrix-signal
# msc3202_transaction_extensions: true
# msc2409_to_device_messages_enabled: true
# - 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.
# 5. Remove registration files from Synapse volume

View file

@ -31,7 +31,7 @@
### 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`
- **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
### 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
- **User:** zvx (sudo, SSH key auth)
- **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

View file

@ -50,7 +50,7 @@
| 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) |
| 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) |
| 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) |
@ -137,7 +137,7 @@
- 1 core, 1GB RAM, 8GB disk
- Not registered in Headscale (no Tailscale)
- 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)
- Immich photo management (https://immich.echo6.co)
@ -312,7 +312,7 @@
- E2BE enabled (MSC4190), double puppeting via doublepuppet.yaml
- Signal account: +12083080811 (@matt:echo6.co)
- 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

View file

@ -6,11 +6,11 @@ RECON extracts knowledge from PDFs and web content into a searchable vector data
## 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)
- **Install:** `/opt/recon/`
- **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)
- **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 |
| Vector DB | Qdrant | cortex:6333 (Docker) |
| Embeddings | TEI (bge-m3, 1024-dim) | cortex:8090 (Docker) |
| Enrichment | Gemini 2.0 Flash | Google API (4 keys) |
| Vision OCR | Gemini 2.0 Flash | Google API (shared keys) |
| Enrichment | Gemini 2.5 Flash Lite | Google API (4 keys) |
| Vision OCR | Gemini 2.5 Flash Lite | Google API (shared keys) |
| Text extraction | PyPDF2, poppler-utils, Tesseract | Local |
| PDF source | NFS | pi-nas:/export/library → /mnt/library |
| 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
2. **pdftotext** (poppler) — handles some PDFs PyPDF2 misses
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.
@ -71,7 +71,7 @@ Key sections:
- `processing.extract_workers` (4), `enrich_workers` (16), `embed_workers` (4)
- `processing.extract_timeout` (1800s), `page_timeout` (30s)
- `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)
**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 |
|------|------|-------------|
| 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 |
| cloud | Proxmox host | — |
| media | Proxmox host | PeerTube LXC (CT 110) |
@ -303,7 +303,7 @@ Core content, classification (domain/subdomain/skill level/scenario), provenance
| Stage | Workers | Bottleneck | Description |
|-------|---------|------------|-------------|
| 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 |
| 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) |
| Networking | Tailscale/Headscale, Caddy, nginx, dnsmasq |
| 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) |
| Databases | SQLite (RECON), PostgreSQL (PeerTube) |
| 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`
**Container name:** `headscale-vanilla`
**Domain:** `vpn.echo6.co`
**Auth key:** `hskey-auth-LOd5lzxvsHaP-GP9K6QkG6UW60UFeoDbKv5OxR9yJXupFvfy-Ps_SGmYu5QxG5g-I7JsVDEebZpVJ`
**Auth key:** `<REDACTED-headscale-preauth-key>`
---
@ -12,7 +12,7 @@
```bash
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
```
@ -41,27 +41,27 @@ Then register. **Do them in this exact order for sequential IPs:**
```bash
# utility (will get 100.64.0.2)
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
# data (will get 100.64.0.3)
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
# cloud (will get 100.64.0.4)
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
# media (will get 100.64.0.5)
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
# aida-nebra (will get 100.64.0.6)
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
```
@ -77,7 +77,7 @@ docker exec headscale-vanilla headscale nodes list
**Desktop (Windows — PowerShell as Admin):**
```powershell
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
```

View file

@ -9,7 +9,7 @@ One-time setup. Only needed if rebuilding from scratch.
| CT ID | 101 |
| Hostname | caddy |
| 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) |
## 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
# 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
pct exec 101 -- tailscale status

View file

@ -1,7 +1,7 @@
# Vaultwarden Deployment
**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
---
@ -92,7 +92,7 @@ vault.echo6.co {
### dnsmasq Split DNS
```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
- 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)
- 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
```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 \
--cookies /opt/bulk-import/config/cookies.txt \
--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).
**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.
```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 \
|| 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
```bash
ssh root@100.64.0.6 "curl -s \
ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/flows/instances/?slug=default-provider-authorization-implicit-consent' \
| jq -r '.results[0].pk'"
@ -75,7 +75,7 @@ Store as `AUTH_FLOW_PK`.
```bash
# 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' \
'$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)\"'"
@ -86,7 +86,7 @@ Store each UUID: `SCOPE_OPENID_PK`, `SCOPE_EMAIL_PK`, `SCOPE_PROFILE_PK`, `SCOPE
### Signing key
```bash
ssh root@100.64.0.6 "curl -s \
ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/crypto/certificatekeypairs/?name=authentik+Self-signed+Certificate&has_key=true' \
| jq -r '.results[0].pk'"
@ -117,7 +117,7 @@ fi
Create the provider:
```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/' \
-H 'Authorization: Bearer $AK_TOKEN' \
-H 'Content-Type: application/json' \
@ -158,7 +158,7 @@ echo "Client Secret: $CLIENT_SECRET"
## Step 4: Create the Application
```bash
ssh root@100.64.0.6 "curl -s \
ssh root@100.64.0.1 "curl -s \
-X POST '$AK_API/core/applications/' \
-H 'Authorization: Bearer $AK_TOKEN' \
-H 'Content-Type: application/json' \
@ -282,7 +282,7 @@ Check in order:
Debug via API:
```bash
ssh root@100.64.0.6 "curl -s \
ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/providers/oauth2/?search=$SERVICE_NAME' \
| 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:
```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
p = OAuth2Provider.objects.get(name='$SERVICE_NAME')
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:
```bash
ssh root@100.64.0.6 "curl -s \
ssh root@100.64.0.1 "curl -s \
-H 'Authorization: Bearer $AK_TOKEN' \
'$AK_API/core/applications/$SERVICE_SLUG/' \
| jq '{name, slug, policy_engine_mode}'"
@ -330,12 +330,12 @@ Missing `offline_access` scope. Without refresh tokens, sessions only last as lo
```bash
# 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' \
'$AK_API/core/applications/$SERVICE_SLUG/'"
# 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' \
'$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:
```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:
@ -254,7 +254,7 @@ ssh zvx@$VM_IP "sudo tailscale up --login-server https://vpn.echo6.co --auth-key
# Verify
ssh zvx@$VM_IP 'tailscale status'
docker exec headscale-standby headscale nodes list
docker exec headscale headscale nodes list
```
## Step 13 — Final Verification
@ -273,7 +273,7 @@ ssh zvx@$VM_IP "
echo '=== Disk ===' && df -h /
"
docker exec headscale-standby headscale nodes list
docker exec headscale headscale nodes list
```
## 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 |
|----------|-----------------|-----------------|
| data | 192.168.1.240 | 100.64.0.20 |
| utility | 192.168.1.241 | 100.64.0.19 |
| cloud | 192.168.1.242 | 100.64.0.22 |
| media | 192.168.1.243 | 100.64.0.21 |
| data | 192.168.1.240 | 100.64.0.6 |
| utility | 192.168.1.241 | 100.64.0.5 |
| cloud | 192.168.1.242 | 100.64.0.4 |
| media | 192.168.1.243 | 100.64.0.3 |
| toc | 192.168.1.244 | 100.64.0.13 |
Management host: **cortex**

View file

@ -2,7 +2,7 @@
## 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
- **Install:** /opt/recon/
- **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
- 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)
- SSH access from the dashboard host to the target host
- 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:
```
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_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/")
@ -418,10 +418,10 @@ lines = min(lines, 500) # Cap to prevent abuse
## 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
TARGET_HOST=192.168.1.170 (CT 110, media node)
SERVICE_NAME=peertube
@ -453,7 +453,7 @@ Services managed:
- pt-downloader (CT 110): start/stop/restart/status/logs
- pt-importer (CT 110): 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,
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