Title: LLM selbst hosten: den Stack betreiben %E2%80%94 LLM EU Canonical: https://llmeu.com/de/docs/self-hosting/ Markdown mirror: https://llmeu.com/de/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 Einstieg - [Schnellstart](/de/docs/quickstart/) - [Konsole](/de/docs/console/) - [Migration](/de/docs/migration/) - [API-Referenz](/de/docs/api/) Referenz - [Authentifizierung](/de/docs/authentication/) - [Endpunkte](/de/docs/endpoints/) - [Fehler](/de/docs/errors/) - [Rate Limits](/de/docs/rate-limits/) - [Streaming](/de/docs/streaming/) - [Richtlinien](/de/docs/policies/) - [Routing und Richtlinien](/de/docs/routing/) - [Datenhaltung und Regionen](/de/docs/residency/) - [Nachweise und Pr%C3%BCfung](/de/docs/evidence/) - [OpenAI-Kompatibilit%C3%A4t](/de/docs/openai-compat/) Betrieb - [Selbst hosten](/de/docs/self-hosting/) # Selbst hosten Node und ein beschreibbares Verzeichnis sind die ganze Voraussetzung. Die folgenden Aussagen stammen aus den daneben genannten Dateien; was nicht best%C3%A4tigt werden konnte, steht nicht hier. ## Einstiegspunkte - package.json verlangt Node >= 22.5. Der SQLite-Speicher ist Nodes eigenes node:sqlite-Modul. - Es gibt %C3%BCberhaupt keine Abh%C3%A4ngigkeitsliste: Apps, Pakete, Skripte und Tests laufen mit Nodes Standardbibliothek, und das Dockerfile installiert nichts. - Drei Prozesse existieren; jeder %C3%B6ffnet die Datenbank und f%C3%BChrt beim Start die Migration aus. ``` 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 ``` ## Datenspeicher DATABASE_URL=sqlite:./data/llmeu.db braucht keinen Server; Verzeichnis und Datei werden beim ersten %C3%96ffnen angelegt. Das Handle l%C3%A4uft im WAL-Modus mit aktivierten Fremdschl%C3%BCsseln und 5 s busy_timeout. packages/shared/src/db/schema.sql ist das Schema. Es ist ausschlie%C3%9Flich anlegend und idempotent, erneutes Ausf%C3%BChren ist also sicher; eine Spalte, die einer bestehenden Tabelle hinzugef%C3%BCgt wird, muss zus%C3%A4tzlich im additiven Schritt in packages/shared/src/db/index.mjs stehen. Eine postgres://-URL nimmt einen separaten Adapterzweig. Dieser Zweig ben%C3%B6tigt das Paket pg, das keine deklarierte Abh%C3%A4ngigkeit ist, und der Kopf von schema.sql sagt, der Postgres-Pfad sei als ungepr%C3%BCft zu behandeln, bis ein echter Treiber und eine getestete Migration existieren. SQLite ist der Pfad, den dieses Repository ausf%C3%BChrt. ## Betreiber-CLI node scripts/db.mjs liest DATABASE_URL und braucht keine Dienste. Befehle: ## Umgebung Gruppiert wie in .env.example. ## Docker Compose und das Image sind optional: Die Testsuite des Repositories braucht kein Docker, und der prim%C3%A4re Weg ist ein lokaler Prozess ohne Dienste. - Das Standardprofil startet web: Ports 3000 und 8088, SQLite auf dem Volume llmeu-data unter /app/data, die eingebettete API und einen Healthcheck auf /healthz. - Dasselbe Image startet den Worker mit node apps/worker/src/run.mjs, wartet auf die Gesundheit von web und nutzt dasselbe Volume llmeu-data. - Zwei zus%C3%A4tzliche Profile sind standardm%C3%A4%C3%9Fig aus: postgres (postgres:16-alpine) und redis (redis:7-alpine, reserviert und vom v1-Codepfad nicht gelesen). - Das Profil gpu startet vllm/vllm-openai mit NVIDIA-Ger%C3%A4tereservierung und bindet Gewichte schreibgesch%C3%BCtzt vom Host ein; es ist nicht standardm%C3%A4%C3%9Fig aktiv, denn EU-Inferenz ohne GPU zu behaupten w%C3%A4re falsch. - Das Dockerfile ist FROM node:24-alpine mit tini, ohne Build-Schritt und ohne Abh%C3%A4ngigkeitsinstallation, l%C3%A4uft als Benutzer node, schreibt nur unter /app/data, exponiert 3000 und 8088 und startet apps/web/server/main.mjs. ## Backups node scripts/backup.mjs ohne Flags schreibt ./backups/llmeu- .db. SQLite wird mit VACUUM INTO kopiert, nie mit cp, denn eine laufende WAL-Datenbank kann mit cp einen zerrissenen oder veralteten Stand liefern. ``` 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 ``` Jedes SQLite-Backup wird gepr%C3%BCft, bevor das Skript Erfolg meldet: Es wird in eine tempor%C3%A4re Kopie wiederhergestellt, PRAGMA integrity_check muss ok liefern, das Schema wird erneut angewendet und die Zeilenzahlen f%C3%BCr models, organizations und users werden ausgegeben. Bei einer postgres://-URL nutzt das Skript pg_dump --format=custom und braucht pg_dump im PATH; ein Dump l%C3%A4sst sich nicht als Datenbank %C3%B6ffnen, seine Zeilenzahlen brauchen also eine Testwiederherstellung. ## Mail Transaktionsmail %E2%80%94 Passwort-Zur%C3%BCcksetzen, Adressbest%C3%A4tigung, Einladungen %E2%80%94 nutzt MAIL_SMTP_* oder MAIL_API_URL mit MAIL_FROM. Der Transport wird einmal beim Start gew%C3%A4hlt und auf jeder Seite gemeldet, die Mail braucht. Auch ohne beides ist ein unterst%C3%BCtzter Zustand: Registrierung, Anmeldung, Passwort%C3%A4nderung, Teams und Einladungen funktionieren, aber Mail zum Zur%C3%BCcksetzen und zur Best%C3%A4tigung kann die Bereitstellung nicht bearbeiten. Die Seiten sagen das, und node scripts/db.mjs passwd ist der Wiederherstellungsweg. ## Inferenz-Backends Eine Endpunktzeile nennt Runtime und Region; die Backend-Registry w%C3%A4hlt den Adapter nach Region, ein Endpunkt kann also nur von einer Maschine in der genannten Region beantwortet werden. - INFERENCE_MOCK=true beh%C3%A4lt das deterministische Entwicklungs-Backend, das keine GPU und keine Gewichte braucht. - GPU_ENABLED=false h%C3%A4lt verwaltete Backends heraus; mit GPU_ENABLED=true gilt VLLM_BASE_URL f%C3%BCr die eine Region, die VLLM_REGION nennt. - Eine Bereitstellung mit mehreren Regionen setzt eine Variable je Region, benannt nach dem Regions-Slug (zum Beispiel VLLM_BASE_URL_DE_FRA). Ein Endpunkt in einer Region ohne konfiguriertes Backend wird abgelehnt statt von einer Maschine in einer anderen Region bedient. - Partner-Backends stammen aus PARTNER_BASE_URL_ und %C3%BCbernehmen PARTNER_SOVEREIGNTY und PARTNER_API_KEY; der Server erlaubt Partner-Nutzung, wenn PARTNER_BASE_URL gesetzt ist. Ohne konfigurierte GPU antwortet das deterministische Entwicklungs-Backend, und seine Ausgabe sagt, dass keine echten Gewichte liefen und dass First-Party-Inferenz VLLM_BASE_URL und das Flag gpu_enabled braucht. Ein Ersatz-Erfolg, der echt aussieht, w%C3%A4re das eine, was dieses Produkt nie ausliefern darf.