4.9 KiB
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
# 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-<unixts>
install.sh outputs a single JSON line to stdout with all credentials and URLs. Detailed logs go to logs/<hostname>.log. Credentials are saved to credentials/<hostname>.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)
- Step 5: Creates and starts Proxmox LXC (Debian 12), waits for DHCP IP
- Step 6: Installs Docker CE + Compose plugin inside the CT
- Step 7: Generates secrets (PG password, JWT, n8n encryption key), writes
.envanddocker-compose.ymlinto CT, starts the stack - Step 8: Creates n8n owner account via REST API
- Step 10: Imports and activates the RAG workflow via n8n API, sets up credentials (Postgres + Ollama)
- Step 10a: Installs a systemd service (
n8n-workflow-reload.service) that re-imports and re-activates the workflow on every LXC restart - 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 fromsql/directorypostgrest– PostgREST, exposes Supabase-compatible REST API on port 3000 (mapped toPOSTGREST_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 tologs/<hostname>.log; only the final JSON is printed to stdout (via fd 3) - Debug mode (
DEBUG=1): logs also written to stderr; JSON is formatted withpython3 -m json.tool - Each customer container hostname is
sb-<unix_timestamp>; 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:
- Waits for n8n API to be ready (up to 60s)
- Logs in with owner credentials from
.env - Deletes the existing "RAG KI-Bot (PGVector)" workflow
- Looks up existing Postgres and Ollama credential IDs
- Processes the workflow template (replaces credential IDs using Python)
- Imports and activates the new workflow