Selvhosting
Node og en skrivbar mappe er hele kravet. Udsagnene nedenfor er læst fra de filer, der er nævnt ved siden af dem; alt, der ikke kunne bekræftes, er ikke her.
Indgangspunkter
- package.json kræver Node >= 22.5. SQLite-lageret er Nodes eget node:sqlite-modul.
- Der er slet ingen afhængighedsliste: apps, pakker, scripts og tests kører på Nodes standardbibliotek, og Dockerfile installerer intet.
- Der findes tre processer; hver åbner databasen og kører migreringen ved opstart.
node apps/web/server/main.mjs # hub + console + embedded API
API_EMBED=false node apps/api/src/main.mjs # API only, no pages
node apps/worker/src/run.mjs # probes, latency, rollup, housekeeping
Datalager
DATABASE_URL=sqlite:./data/llmeu.db kræver ingen server, og mappen og filen oprettes ved første åbning. Håndtaget kører i WAL-tilstand med fremmednøgler slået til og en 5 s busy-timeout.
packages/shared/src/db/schema.sql er skemaet. Det er kun-oprettende og idempotent, så gentagen kørsel er sikker; en kolonne, der føjes til en eksisterende tabel, skal også erklæres i det additive trin i packages/shared/src/db/index.mjs.
En postgres:// URL tager en separat adaptergren. Den gren kræver pg-pakken, som ikke er en erklæret afhængighed, og headeren i schema.sql siger, at Postgres-stien skal behandles som uverificeret, indtil en rigtig driver og en testet migrering findes. SQLite er den sti, dette repository kører.
Operatør-CLI
node scripts/db.mjs læser DATABASE_URL og kræver ingen tjenester. Kommandoer:
| Kommando | Hvad den gør |
|---|---|
| node scripts/db.mjs migrate | Anvender schema.sql og rapporterer antallet af sætninger. |
| node scripts/db.mjs seed | Indsætter eller opdaterer kataloget og demo-organisationen og skriver demo-nøglen til data/demo-key.txt med tilstand 0600. |
| node scripts/db.mjs reset | Kun for SQLite: fjerner databasefilen og dens -wal- og -shm-ledsagere, migrerer derefter og seeder. På Postgres nægter den. |
| node scripts/db.mjs status | Udskriver motoren, antallet af tabeller og rækkeantallet for hver ikke-tom tabel. |
| node scripts/db.mjs demo-key | Udgiver en ny nøgle til demo-organisationen og udskriver den én gang. |
| node scripts/db.mjs passwd <email> | Sætter en brugers adgangskode fra serveren og sletter alle sessioner for den bruger. Dette er gendannelsesvejen, når ingen mailtransport er konfigureret. Uden --password genererer den en og udskriver den én gang. |
Miljø
Grupperet, som .env.example grupperer dem.
| Gruppe | Variabler | Noter |
|---|---|---|
| URL'er og porte | APP_URL, API_URL, WEB_PORT, API_PORT, API_EMBED, PUBLIC_API_URL | API-porten er som standard 8088, ikke 8080. API_EMBED=false er til en udrulning, der kører API'en som sin egen proces; PUBLIC_API_URL er den basis, der vises i dokumentationseksempler. |
| Datalager | DATABASE_URL, REDIS_URL | DATABASE_URL vælger lageret; REDIS_URL er reserveret til jobkøen og læses ikke af v1-kodevejen. |
| Inferens | INFERENCE_MOCK, GPU_ENABLED, VLLM_BASE_URL, VLLM_REGION, VLLM_MODEL_VERSION, VLLM_BASE_URL_<REGION>, DEFAULT_REGION, PARTNER_* | Se afsnittet om inferens nedenfor; PARTNER_* dækker partnerens basis-URL, region, suverænitetsklasse og API-nøgle. |
| Fakturering | FX_EUR_USD, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET | Hovedbogen føres i USD-mikroer, og EUR udledes til visning ved FX_EUR_USD. |
| MAIL_FROM, MAIL_SMTP_HOST, MAIL_SMTP_PORT, MAIL_SMTP_SECURE, MAIL_SMTP_USER, MAIL_SMTP_PASS, MAIL_TIMEOUT_MS, MAIL_API_URL, MAIL_API_KEY | Angiv MAIL_SMTP_HOST til SMTP, eller MAIL_API_URL med MAIL_FROM til et HTTP-relay, eller ingen af dem. | |
| Sikkerhed | NODE_ENV, LLMEU_IP_SALT, LLMEU_DEMO_PASSWORD, LLMEU_KEY_ENV | NODE_ENV=production markerer sessionscookies som Secure. LLMEU_IP_SALT salter den hash'ede klient-IP og bør ændres pr. udrulning. LLMEU_KEY_ENV giver genererede nøgler præfikset llmeu_live_ eller llmeu_test_. |
| Diverse | LOG_LEVEL | LOG_LEVEL angiver det mindste logniveau. |
Docker
Compose og imaget er valgfrie: repositoriets egen suite kræver ikke Docker, og den primære sti er en lokal proces uden tjenester.
- Standardprofilen kører web: porte 3000 og 8088, SQLite på llmeu-data-volumenet på /app/data, den indlejrede API og et healthcheck på /healthz.
- Det samme image kører workeren med node apps/worker/src/run.mjs, venter på, at web bliver sund, og deler llmeu-data-volumenet.
- To ekstra profiler er slået fra som standard: postgres (postgres:16-alpine) og redis (redis:7-alpine, reserveret og læses ikke af v1-kodestien).
- gpu-profilen kører vllm/vllm-openai med en NVIDIA-enhedsreservation og monterer vægte skrivebeskyttet fra værten; den er ikke aktiveret som standard, fordi at hævde EU-inference uden en GPU ville være falsk.
- Dockerfile er FROM node:24-alpine med tini, intet byggetrin og ingen afhængighedsinstallation, kører som node-brugeren, skriver kun under /app/data, eksponerer 3000 og 8088 og starter apps/web/server/main.mjs.
Backups
node scripts/backup.mjs uden flag skriver ./backups/llmeu-<stamp>.db. SQLite kopieres med VACUUM INTO, aldrig cp, fordi en levende WAL-database kopieret med cp kan give en flænget eller forældet tilstand.
node scripts/backup.mjs # ./backups/llmeu-<stamp>.db
node scripts/backup.mjs --out /srv/backups/ # explicit destination
node scripts/backup.mjs --verify ./backups/llmeu-<stamp>.db
node scripts/backup.mjs --restore ./backups/llmeu-<stamp>.db --yes
node scripts/backup.mjs --list
Hver SQLite-backup verificeres, før scriptet rapporterer succes: den gendannes til en midlertidig kopi, PRAGMA integrity_check skal returnere ok, skemaet anvendes igen, og rækkeantal for modeller, organisationer og brugere udskrives.
Med en postgres:// URL bruger scriptet pg_dump --format=custom og kræver pg_dump i PATH; en dump kan ikke åbnes som en database, så dens rækkeantal kræver en midlertidig gendannelse.
Transaktionsmail — nulstilling af adgangskode, adressebekræftelse, invitationer — bruger MAIL_SMTP_* eller MAIL_API_URL med MAIL_FROM. Transporten vælges én gang ved opstart og rapporteres på hver side, der har brug for mail.
En udrulning uden nogen af dem er en understøttet tilstand: tilmelding, login, ændring af adgangskode, teams og invitationer virker, men nulstilling af adgangskode og bekræftelsesmail kan ikke behandles der. Siderne siger det, og node scripts/db.mjs passwd <email> er gendannelsesvejen.
Inferens-backends
En endpoint-række angiver en runtime og en region, og backend-registret vælger adapteren efter region, så et endpoint kan kun besvares af en maskine i den region, den angiver.
- INFERENCE_MOCK=true beholder den deterministiske mock-backend, som ikke kræver GPU eller vægte.
- GPU_ENABLED=false holder administrerede backends ude; med GPU_ENABLED=true gælder VLLM_BASE_URL for den enkelte region, der er angivet af VLLM_REGION.
- En udrulning med flere regioner angiver én variabel pr. region, opkaldt efter regionens slug (for eksempel VLLM_BASE_URL_DE_FRA). Et endpoint i en region uden en konfigureret backend afvises i stedet for at blive betjent fra en maskine i en anden region.
- Partner-backends kommer fra PARTNER_BASE_URL_<REGION> og tager PARTNER_SOVEREIGNTY og PARTNER_API_KEY; serveren tillader partnerbrug, når PARTNER_BASE_URL er angivet.
Uden GPU svarer mock-backenden. Dens region er dev-mock, og dens output siger, at det er mock-backenden, at ingen rigtige vægte blev kørt, og at first-party-inferens kræver VLLM_BASE_URL og flaget gpu_enabled. En mock-succes, der så ægte ud, ville være det ene, dette produkt aldrig må levere.