# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Automates provisioning of customer Proxmox LXC containers running a Docker stack (n8n + PostgreSQL/pgvector + PostgREST) with automatic OPNsense NGINX reverse proxy registration. Intended for a multi-tenant SaaS setup ("BotKonzept") where each customer gets an isolated container. ## Key Commands ```bash # Create a new customer LXC (must run on Proxmox host) bash install.sh --storage local-zfs --bridge vmbr0 --ip dhcp --vlan 90 # With debug output (logs on stderr instead of only to file) DEBUG=1 bash install.sh --storage local-zfs --bridge vmbr0 # With APT caching proxy bash install.sh --storage local-zfs --apt-proxy http://192.168.45.2:3142 # Setup the BotKonzept management LXC (fixed CTID 5010) bash setup_botkonzept_lxc.sh # Delete an nginx proxy entry in OPNsense bash delete_nginx_proxy.sh --hostname sb- ``` `install.sh` outputs a single JSON line to stdout with all credentials and URLs. Detailed logs go to `logs/.log`. Credentials are saved to `credentials/.json`. ## Architecture ### Script Dependency Tree ``` install.sh ├── sources libsupabase.sh (Proxmox helpers, logging, crypto, n8n setup) ├── calls setup_nginx_proxy.sh (OPNsense API integration) └── uses lib_installer_json_api.sh (PostgREST DB storage - optional) setup_botkonzept_lxc.sh (Standalone, for management LXC CTID 5010) ``` ### Infrastructure Assumptions (hardcoded defaults) | Service | Address | |---|---| | OPNsense Firewall | `192.168.45.1:4444` | | Apt-Cacher NG | `192.168.45.2:3142` | | Docker Registry Mirror | `192.168.45.2:5000` | | Ollama API | `192.168.45.3:11434` | | Default VLAN | 90 | | Default storage | `local-zfs` | | Default base domain | `userman.de` | ### What `install.sh` Does (Steps 5–11) 1. **Step 5**: Creates and starts Proxmox LXC (Debian 12), waits for DHCP IP 2. **Step 6**: Installs Docker CE + Compose plugin inside the CT 3. **Step 7**: Generates secrets (PG password, JWT, n8n encryption key), writes `.env` and `docker-compose.yml` into CT, starts the stack 4. **Step 8**: Creates n8n owner account via REST API 5. **Step 10**: Imports and activates the RAG workflow via n8n API, sets up credentials (Postgres + Ollama) 6. **Step 10a**: Installs a systemd service (`n8n-workflow-reload.service`) that re-imports and re-activates the workflow on every LXC restart 7. **Step 11**: Registers an NGINX upstream/location in OPNsense via its REST API ### Docker Stack Inside Each LXC (`/opt/customer-stack/`) - `postgres` – pgvector/pgvector:pg16, initialized from `sql/` directory - `postgrest` – PostgREST, exposes Supabase-compatible REST API on port 3000 (mapped to `POSTGREST_PORT`) - `n8n` – n8n automation, port 5678 All three share a `customer-net` bridge network. The n8n instance connects to PostgREST via the Docker internal hostname `postgrest:3000` (not the external IP). ### Key Files | File | Purpose | |---|---| | `libsupabase.sh` | Core library: logging (`info`/`warn`/`die`), Proxmox helpers (`pct_exec`, `pct_push_text`, `pve_*`), crypto (`gen_password_policy`, `gen_hex_64`), n8n setup (`n8n_setup_rag_workflow`) | | `setup_nginx_proxy.sh` | OPNsense API client; registers upstream + location for new CT | | `lib_installer_json_api.sh` | Stores installer JSON output into the BotKonzept Postgres DB via PostgREST | | `sql/botkonzept_schema.sql` | Customer management schema (customers, instances, emails, payments) for the BotKonzept management LXC | | `sql/init_pgvector.sql` | Inline in `install.sh`; creates pgvector extension, `documents` table, `match_documents` function, PostgREST roles | | `templates/reload-workflow.sh` | Runs inside customer LXC on every restart; logs to `/opt/customer-stack/logs/workflow-reload.log` | | `RAGKI-BotPGVector.json` | Default n8n workflow template (RAG KI-Bot with PGVector) | ### Output and Logging - **Normal mode** (`DEBUG=0`): all script output goes to `logs/.log`; only the final JSON is printed to stdout (via fd 3) - **Debug mode** (`DEBUG=1`): logs also written to stderr; JSON is formatted with `python3 -m json.tool` - Each customer container hostname is `sb-`; CTID = unix_timestamp − 1,000,000,000 ### n8n Password Policy Passwords must be 8+ characters with at least 1 uppercase and 1 number. Enforced by `password_policy_check` in `libsupabase.sh`. Auto-generated passwords use `gen_password_policy`. ### Workflow Auto-Reload On LXC restart, `n8n-workflow-reload.service` runs `reload-workflow.sh`, which: 1. Waits for n8n API to be ready (up to 60s) 2. Logs in with owner credentials from `.env` 3. Deletes the existing "RAG KI-Bot (PGVector)" workflow 4. Looks up existing Postgres and Ollama credential IDs 5. Processes the workflow template (replaces credential IDs using Python) 6. Imports and activates the new workflow