Title: LLM zelf hosten: de stack draaien %E2%80%94 LLM EU Canonical: https://llmeu.com/nl/docs/self-hosting/ Markdown mirror: https://llmeu.com/nl/docs/self-hosting.md Machine-readable: https://llmeu.com/llms.txt (index) - https://llmeu.com/llms-full.txt (full catalogue) - https://llmeu.com/llms-catalogue.json Aan de slag - [Snelstart](/nl/docs/quickstart/) - [Console](/nl/docs/console/) - [Migratie](/nl/docs/migration/) - [API-referentie](/nl/docs/api/) Referentie - [Authenticatie](/nl/docs/authentication/) - [Eindpunten](/nl/docs/endpoints/) - [Fouten](/nl/docs/errors/) - [Snelheidslimieten](/nl/docs/rate-limits/) - [Streaming](/nl/docs/streaming/) - [Beleid](/nl/docs/policies/) - [Routing en beleid](/nl/docs/routing/) - [Residentie en regio's](/nl/docs/residency/) - [Bewijs en verificatie](/nl/docs/evidence/) - [OpenAI-compatibiliteit](/nl/docs/openai-compat/) Bedienen - [Zelfhosting](/nl/docs/self-hosting/) # Zelfhosting Node en een beschrijfbare map vormen de hele vereiste. De onderstaande uitspraken zijn gelezen uit de bestanden die ernaast worden genoemd; alles wat niet kon worden bevestigd, staat hier niet. ## Entrypoints - package.json vereist Node >= 22.5. De SQLite-opslag is Node's eigen node:sqlite-module. - Er is helemaal geen afhankelijkhedenlijst: apps, packages, scripts en tests draaien op Node's standaardbibliotheek, en de Dockerfile installeert niets. - Er bestaan drie processen; elk opent de database en voert de migratie uit bij het opstarten. ``` 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 ``` ## Datastore DATABASE_URL=sqlite:./data/llmeu.db heeft geen server nodig, en de map en het bestand worden bij de eerste opening aangemaakt. De handle draait in WAL-modus met foreign keys aan en een busy timeout van 5 s. packages/shared/src/db/schema.sql is het schema. Het is alleen voor aanmaken en idempotent, dus opnieuw uitvoeren is veilig; een kolom die aan een bestaande tabel wordt toegevoegd, moet ook worden gedeclareerd in de additieve stap in packages/shared/src/db/index.mjs. Een postgres://-URL neemt een aparte adapterbranch. Die branch vereist het pg-pakket, dat geen gedeclareerde afhankelijkheid is, en de kop van schema.sql zegt dat het Postgres-pad als niet-geverifieerd moet worden behandeld totdat er een echte driver en een geteste migratie bestaan. SQLite is het pad dat deze repository draait. ## Operator-CLI node scripts/db.mjs leest DATABASE_URL en heeft geen services nodig. Opdrachten: ## Omgeving Gegroepeerd zoals .env.example ze groepeert. ## Docker Compose en de image zijn optioneel: de eigen suite van de repository vereist geen Docker, en het primaire pad is een lokaal proces zonder services. - Het standaardprofiel draait web: poorten 3000 en 8088, SQLite op het llmeu-data-volume op /app/data, de ingebedde API, en een healthcheck op /healthz. - Dezelfde image draait de worker met node apps/worker/src/run.mjs, wacht tot web gezond is en deelt het llmeu-data-volume. - Twee extra profielen staan standaard uit: postgres (postgres:16-alpine) en redis (redis:7-alpine, gereserveerd en niet gelezen door het v1-codepad). - Het gpu-profiel draait vllm/vllm-openai met een NVIDIA-apparaatreservering en mount gewichten alleen-lezen vanaf de host; het is niet standaard ingeschakeld, omdat EU-inference claimen zonder GPU onjuist zou zijn. - De Dockerfile is FROM node:24-alpine met tini, zonder buildstap en zonder dependency-installatie, draait als de node-gebruiker, schrijft alleen onder /app/data, stelt 3000 en 8088 beschikbaar, en start apps/web/server/main.mjs. ## Back-ups node scripts/backup.mjs zonder flags schrijft ./backups/llmeu- .db. SQLite wordt gekopieerd met VACUUM INTO, nooit cp, omdat een levende WAL-database die met cp wordt gekopieerd een beschadigde of verouderde staat kan opleveren. ``` node scripts/backup.mjs # ./backups/llmeu-.db node scripts/backup.mjs --out /srv/backups/ # explicit destination node scripts/backup.mjs --verify ./backups/llmeu-.db node scripts/backup.mjs --restore ./backups/llmeu-.db --yes node scripts/backup.mjs --list ``` Elke SQLite-back-up wordt geverifieerd voordat het script succes meldt: deze wordt hersteld naar een tijdelijke kopie, PRAGMA integrity_check moet ok teruggeven, het schema wordt opnieuw toegepast, en rijenaantallen voor models, organizations en users worden afgedrukt. Met een postgres://-URL gebruikt het script pg_dump --format=custom en heeft pg_dump nodig in PATH; een dump kan niet als database worden geopend, dus de rijenaantallen ervan vereisen een scratch-restore. ## E-mail Transactionele e-mail %E2%80%94 wachtwoordreset, adresverificatie, uitnodigingen %E2%80%94 gebruikt MAIL_SMTP_* of MAIL_API_URL met MAIL_FROM. Het transport wordt eenmalig bij het opstarten gekozen en gemeld op elke pagina die e-mail nodig heeft. Een deployment met geen van beide is een ondersteunde toestand: aanmelden, inloggen, wachtwoord wijzigen, teams en uitnodigingen werken, maar wachtwoordreset- en verificatie-e-mail kunnen daar niet worden verwerkt. De pagina's zeggen dat, en node scripts/db.mjs passwd is de herstelroute. ## Inferentiebackends Een endpointrij noemt een runtime en een regio, en het backendregister kiest de adapter op basis van regio, dus een endpoint kan alleen worden beantwoord door een machine in de regio die het noemt. - INFERENCE_MOCK=true houdt de deterministische ontwikkelbackend, die geen GPU en geen gewichten nodig heeft. - GPU_ENABLED=false houdt beheerde backends buiten; met GPU_ENABLED=true is VLLM_BASE_URL van toepassing op de enige regio die door VLLM_REGION wordt genoemd. - Een deployment met meerdere regio's stelt %C3%A9%C3%A9n variabele per regio in, vernoemd naar de regioslug (bijvoorbeeld VLLM_BASE_URL_DE_FRA). Een endpoint in een regio zonder geconfigureerde backend wordt geweigerd, in plaats van te worden bediend vanaf een machine in een andere regio. - Partnerbackends komen van PARTNER_BASE_URL_ en gebruiken PARTNER_SOVEREIGNTY en PARTNER_API_KEY; de server staat partnergebruik toe wanneer PARTNER_BASE_URL is ingesteld. Zonder geconfigureerde GPU antwoordt de deterministische ontwikkelbackend en zijn uitvoer zegt dat er geen echte gewichten zijn gebruikt en dat first-party-inferentie VLLM_BASE_URL en de gpu_enabled-vlag nodig heeft. Een vervangende succesmelding die echt leek, zou het enige zijn dat dit product nooit mag uitbrengen.