Самостоятелно хостване

Node и директория с права за запис са цялото изискване. Твърденията по-долу са прочетени от файловете, посочени до тях; всичко, което не можа да бъде потвърдено, не е тук.

Входни точки

  • package.json изисква Node >= 22.5. SQLite хранилището е собственият модул node:sqlite на Node.
  • Изобщо няма списък със зависимости: приложенията, пакетите, скриптовете и тестовете работят със стандартната библиотека на Node, а Dockerfile не инсталира нищо.
  • Съществуват три процеса; всеки отваря базата данни и изпълнява миграцията при стартиране.
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

Хранилище за данни

DATABASE_URL=sqlite:./data/llmeu.db не се нуждае от сървър, а директорията и файлът се създават при първо отваряне. Хендълът работи в WAL режим с включени външни ключове и 5 s изчакване при заетост.

packages/shared/src/db/schema.sql е схемата. Тя е само за създаване и идемпотентна, така че повторното ѝ изпълнение е безопасно; колона, добавена към съществуваща таблица, също трябва да бъде декларирана в добавъчната стъпка в packages/shared/src/db/index.mjs.

URL postgres:// поема отделен клон на адаптера. Този клон изисква пакета pg, който не е декларирана зависимост, а заглавната част на schema.sql казва да се третира пътят Postgres като непроверен, докато съществуват реален драйвер и тествана миграция. SQLite е пътят, който това хранилище изпълнява.

CLI за оператор

node scripts/db.mjs чете DATABASE_URL и не се нуждае от услуги. Команди:

Команда Какво прави
node scripts/db.mjs migrateПрилага schema.sql и отчита броя на изразите.
node scripts/db.mjs seedВмъква или опреснява каталога и демонстрационната организация и записва демонстрационния ключ в data/demo-key.txt с права 0600.
node scripts/db.mjs resetСамо за SQLite: премахва файла на базата данни и придружаващите го -wal и -shm, след което мигрира и зарежда начални данни. На Postgres отказва.
node scripts/db.mjs statusОтпечатва двигателя, броя на таблиците и броя на редовете на всяка непразна таблица.
node scripts/db.mjs demo-keyИздава нов ключ за демонстрационната организация и го отпечатва веднъж.
node scripts/db.mjs passwd <email>Задава парола на потребител от сървъра и изтрива всяка сесия на този потребител. Това е пътят за възстановяване, когато не е конфигуриран транспортен механизъм за поща. Без --password генерира такава и я отпечатва веднъж.

Среда

Групирани както ги групира .env.example.

Група Променливи Бележки
URL адреси и портовеAPP_URL, API_URL, WEB_PORT, API_PORT, API_EMBED, PUBLIC_API_URLAPI портът по подразбиране е 8088, не 8080. API_EMBED=false е за внедряване, което пуска API като отделен процес; PUBLIC_API_URL е базата, показвана в примерните фрагменти в документацията.
Хранилище на данниDATABASE_URL, REDIS_URLDATABASE_URL избира хранилището; REDIS_URL е запазен за опашката от задачи и не се чете от кодовия път на v1.
ИнференцияINFERENCE_MOCK, GPU_ENABLED, VLLM_BASE_URL, VLLM_REGION, VLLM_MODEL_VERSION, VLLM_BASE_URL_<REGION>, DEFAULT_REGION, PARTNER_*Вижте раздела за инференция по-долу; PARTNER_* обхваща базовия URL на партньора, региона, класа на суверенитет и API ключа.
ФактуриранеFX_EUR_USD, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRETРегистърът се поддържа в микро USD и EUR се изчислява за показване при 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Задайте MAIL_SMTP_HOST за SMTP, или MAIL_API_URL с MAIL_FROM за HTTP релей, или нито едно от двете.
СигурностNODE_ENV, LLMEU_IP_SALT, LLMEU_DEMO_PASSWORD, LLMEU_KEY_ENVNODE_ENV=production маркира сесийните бисквитки като Secure. LLMEU_IP_SALT добавя сол към хеширания IP на клиента и трябва да се сменя при всяко внедряване. LLMEU_KEY_ENV добавя префикс llmeu_live_ или llmeu_test_ към генерираните ключове.
РазниLOG_LEVELLOG_LEVEL задава минималното ниво на логване.

Docker

Compose и изображението са незадължителни: собственият набор от тестове на хранилището не изисква Docker, а основният път е локален процес без услуги.

  • Профилът по подразбиране стартира web: портове 3000 и 8088, SQLite на том llmeu-data в /app/data, вграденото API и проверка на състоянието на /healthz.
  • Същото изображение стартира worker с node apps/worker/src/run.mjs, изчаквайки web да стане здрав и споделяйки тома llmeu-data.
  • Два допълнителни профила са изключени по подразбиране: postgres (postgres:16-alpine) и redis (redis:7-alpine, резервиран и не се чете от кодовия път v1).
  • Профилът gpu стартира vllm/vllm-openai с резервация на NVIDIA устройство и монтира тегла само за четене от хоста; не е разрешен по подразбиране, защото твърдение за извод в ЕС без GPU би било невярно.
  • Dockerfile е FROM node:24-alpine с tini, без стъпка за изграждане и без инсталиране на зависимости, работи като потребител node, записва само под /app/data, експонира 3000 и 8088 и стартира apps/web/server/main.mjs.

Резервни копия

node scripts/backup.mjs без флагове записва ./backups/llmeu-<stamp>.db. SQLite се копира с VACUUM INTO, никога cp, защото жива WAL база данни, копирана с cp, може да доведе до разкъсано или остаряло състояние.

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

Всяко резервно копие на SQLite се проверява, преди скриптът да отчете успех: възстановява се във временно копие, PRAGMA integrity_check трябва да върне ok, схемата се прилага отново и се отпечатват броят на редовете за модели, организации и потребители.

С URL postgres:// скриптът използва pg_dump --format=custom и се нуждае от pg_dump в PATH; дъмп не може да бъде отворен като база данни, така че броят на редовете му изисква временно възстановяване.

Поща

Транзакционната поща — нулиране на парола, проверка на адрес, покани — използва MAIL_SMTP_* или MAIL_API_URL с MAIL_FROM. Транспортът се избира еднократно при стартиране и се отчита на всяка страница, която се нуждае от поща.

Внедряване без нито едно от двете е поддържано състояние: регистрацията, входът, смяната на парола, екипите и поканите работят, но пощата за нулиране на парола и за проверка не може да бъде обработена там. Страниците го казват, а node scripts/db.mjs passwd <email> е пътят за възстановяване.

Бекендове за инференция

Всеки ред за endpoint посочва среда за изпълнение и регион, а регистърът на бекендовете избира адаптера по регион, така че даден endpoint може да бъде обслужен само от машина в региона, който посочва.

  • INFERENCE_MOCK=true запазва детерминистичния mock бекенд, който не се нуждае от GPU и от тегла.
  • GPU_ENABLED=false изключва управляваните бекендове; при GPU_ENABLED=true VLLM_BASE_URL се прилага за единствения регион, посочен от VLLM_REGION.
  • Внедряване с няколко региона задава по една променлива за регион, именувана по slug на региона (например VLLM_BASE_URL_DE_FRA). Endpoint в регион без конфигуриран бекенд се отказва, вместо да бъде обслужен от машина в друг регион.
  • Партньорските бекендове идват от PARTNER_BASE_URL_<REGION> и използват PARTNER_SOVEREIGNTY и PARTNER_API_KEY; сървърът разрешава използване на партньори, когато PARTNER_BASE_URL е зададен.

Без GPU отговаря mock бекендът. Регионът му е dev-mock, а изходът му казва, че е mock бекендът, че не са изпълнявани реални тегла и че инференцията от първа страна изисква VLLM_BASE_URL и флага gpu_enabled. Успех от mock, който изглежда реален, е единственото нещо, което този продукт никога не бива да пуска.