Αυτοφιλοξενία
Το Node και ένας κατάλογος με δικαίωμα εγγραφής είναι η μόνη απαίτηση. Οι δηλώσεις παρακάτω διαβάστηκαν από τα αρχεία που αναφέρονται δίπλα τους· ό,τι δεν μπορούσε να επιβεβαιωθεί δεν βρίσκεται εδώ.
Σημεία εισόδου
- Το package.json απαιτεί Node >= 22.5. Η αποθήκη SQLite είναι το δικό του module 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 είναι το σχήμα. Είναι μόνο για δημιουργία και idempotent, οπότε η εκ νέου εκτέλεσή του είναι ασφαλής· μια στήλη που προστίθεται σε υπάρχοντα πίνακα πρέπει επίσης να δηλώνεται στο πρόσθετο βήμα στο packages/shared/src/db/index.mjs.
Ένα URL postgres:// ακολουθεί ξεχωριστό κλάδο προσαρμογέα. Αυτός ο κλάδος απαιτεί το πακέτο pg, το οποίο δεν είναι δηλωμένη εξάρτηση, και η κεφαλίδα του schema.sql λέει να αντιμετωπίζεται η διαδρομή Postgres ως ανεπαλήθευτη μέχρι να υπάρξει πραγματικός driver και δοκιμασμένη μετανάστευση. Το 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, έπειτα εκτελεί μετανάστευση και seed. Στο 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_URL | Η θύρα API έχει προεπιλογή 8088, όχι 8080. Το API_EMBED=false είναι για ανάπτυξη που εκτελεί το API ως δική της διεργασία· το PUBLIC_API_URL είναι η βάση που εμφανίζεται σε αποσπάσματα τεκμηρίωσης. |
| Αποθήκευση δεδομένων | DATABASE_URL, REDIS_URL | Το DATABASE_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_ENV | Το NODE_ENV=production επισημαίνει τα cookies συνεδρίας ως Secure. Το LLMEU_IP_SALT προσθέτει άλας στην κατακερματισμένη IP πελάτη και πρέπει να αλλάζει ανά ανάπτυξη. Το LLMEU_KEY_ENV βάζει πρόθεμα στα παραγόμενα κλειδιά με llmeu_live_ ή llmeu_test_. |
| Διάφορα | LOG_LEVEL | Το LOG_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, χωρίς βήμα build και χωρίς εγκατάσταση εξαρτήσεων, εκτελείται ως χρήστης 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 επαληθεύεται πριν το script αναφέρει επιτυχία: επαναφέρεται σε προσωρινό αντίγραφο, το PRAGMA integrity_check πρέπει να επιστρέψει ok, το σχήμα επανεφαρμόζεται και εκτυπώνονται οι μετρήσεις γραμμών για models, organizations και users.
Με URL postgres://, το script χρησιμοποιεί pg_dump --format=custom και χρειάζεται το pg_dump στο PATH· ένα dump δεν μπορεί να ανοίξει ως βάση δεδομένων, οπότε οι μετρήσεις γραμμών του χρειάζονται δοκιμαστική επαναφορά.
Αλληλογραφία
Η συναλλακτική αλληλογραφία — επαναφορά κωδικού, επαλήθευση διεύθυνσης, προσκλήσεις — χρησιμοποιεί MAIL_SMTP_* ή MAIL_API_URL με MAIL_FROM. Το κανάλι μεταφοράς επιλέγεται μία φορά κατά την εκκίνηση και αναφέρεται σε κάθε σελίδα που χρειάζεται αλληλογραφία.
Μια ανάπτυξη χωρίς κανένα από τα δύο είναι υποστηριζόμενη κατάσταση: εγγραφή, σύνδεση, αλλαγή κωδικού, ομάδες και προσκλήσεις λειτουργούν, αλλά η αλληλογραφία επαναφοράς κωδικού και επαλήθευσης δεν μπορεί να επεξεργαστεί εκεί. Οι σελίδες το δηλώνουν, και το node scripts/db.mjs passwd <email> είναι η οδός ανάκτησης.
Backends συμπερασματολογίας
Μια γραμμή endpoint ονομάζει ένα runtime και μια περιοχή, και το μητρώο backend επιλέγει τον προσαρμογέα ανά περιοχή, επομένως ένα endpoint μπορεί να απαντηθεί μόνο από μηχάνημα στην περιοχή που ονομάζει.
- Το INFERENCE_MOCK=true διατηρεί το ντετερμινιστικό mock backend, το οποίο δεν χρειάζεται GPU ούτε βάρη.
- Το GPU_ENABLED=false κρατά έξω τα διαχειριζόμενα backends· με GPU_ENABLED=true, το VLLM_BASE_URL ισχύει για τη μοναδική περιοχή που ονομάζει το VLLM_REGION.
- Μια ανάπτυξη με πολλές περιοχές ορίζει μία μεταβλητή ανά περιοχή, με όνομα από το slug της περιοχής (για παράδειγμα VLLM_BASE_URL_DE_FRA). Ένα endpoint σε περιοχή χωρίς διαμορφωμένο backend απορρίπτεται, αντί να εξυπηρετηθεί από μηχάνημα σε άλλη περιοχή.
- Τα partner backends προέρχονται από το PARTNER_BASE_URL_<REGION> και παίρνουν PARTNER_SOVEREIGNTY και PARTNER_API_KEY· ο διακομιστής επιτρέπει τη χρήση συνεργάτη όταν έχει οριστεί το PARTNER_BASE_URL.
Χωρίς GPU απαντά το mock backend. Η περιοχή του είναι dev-mock, και η έξοδός του δηλώνει ότι είναι το mock backend, ότι δεν εκτελέστηκαν πραγματικά βάρη και ότι η first-party συμπερασματολογία χρειάζεται το VLLM_BASE_URL και τη σημαία gpu_enabled. Μια mock επιτυχία που θα φαινόταν πραγματική θα ήταν το ένα πράγμα που αυτό το προϊόν δεν πρέπει ποτέ να διαθέσει.