Files
customer-installer/CLAUDE.md

104 lines
4.9 KiB
Markdown
Raw Normal View History

# 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-<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 511)
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/<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 with `python3 -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:
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