nessie

Kako instalirati Nessie

Pokrenite Nessie na infrastrukturi koju odaberete, od jednog računala do upravljanog oblaka.

Što trebate imati prije početka

Nessie je pnpm monorepozitorij s Node servisima i dvama statičnim paketima. Bez obzira na način pokretanja, prvo moraju postojati ove četiri stvari.

  • PostgreSQL s pgvector. Nije opcionalno i ne može se zamijeniti — migracije izvršavaju CREATE EXTENSION vector i kreiraju stupce vector(1024). Produkcija koristi pgvector/pgvector:pg17.
  • Node 22 i pnpm. Svaki Dockerfile u infrastructure/docker/ gradi se na node:22-slim, a repozitorij u korijenskom package.json fiksira verziju upravitelja paketa (pnpm@10.22.0).
  • Krajnja točka modela kompatibilna s OpenAI-jem i ključ za nju. Agenti i embeddings prolaze kroz nju. Pogledajte „Konfiguriranje inferencije“ u nastavku.
  • Objektna pohrana kompatibilna sa S3, za svaku instalaciju koja nije lokalni razvojni primjerak. Učitavanje na lokalni disk odbija se izvan načina local, a to odbijanje je greška pri pokretanju, a ne degradirano pokretanje — pogledajte „Jedan stroj ili upravljani oblak“.

Docker i reverse proxy potrebni su za put s kontejnerima opisan dalje u tekstu, a domena i TLS za sve što je dostupno s interneta.

Dimenzioniranje hardvera — minimalni procesor, memorija i disk za određeni broj ljudi — nigdje nije navedeno u repozitoriju, pa ni ova stranica to ne navodi.

Komponente i način na koji su povezane

KomponentaŠto jeIngress
api/HTTP/WebSocket API temeljen na Fastifyju. Svi klijenti komuniciraju samo s ovim.Da
worker/Orkestracija agenata i pozadinska izvođenja. Provjerava red poslova; ne veže se ni na jedan port.Ne
admin/Sučelje proizvoda — statički paket koji gradi Vite, a poslužuje nginx.Da
web/Javna web stranica. Statička, neobavezna i nepovezana s pokretanjem proizvoda.Da
PostgreSQLBaza podataka, red poslova i realtime sabirnica — sve tri.Ne
Objektna pohranaPrivitci, avatari i datoteke baze znanja. Kompatibilno s S3; u produkciji MinIO.Ne
gateway/Neobavezni relej za push obavijesti preko APNs-a i FCM-a. Isključen je dok ga ne uključite namjerno.Da

API i worker su jedna slika. Dva paketa usko su povezana, pa Dockerfile.app jednom izgradi cijeli sustav, a kontejner workera prepisuje naredbu u node worker/dist/index.js. U načinu local uopće nema kontejnera workera: API pokreće worker ugrađen u vlastiti proces.

Nema Redisa. Red poslova i realtime transport temelje se na Postgresu, i to iz odluke, a ne iz propusta — stablo za Google Cloud iz istog razloga briše svoje Pub/Sub i Redis module.

Portovi

U lokalnom razvoju API je prema zadanim postavkama na 5454, a administracija na 5455. Checkout može preuzeti vlastiti par postavljanjem NESSIE_API_PORT i NESSIE_ADMIN_PORT, u okruženju ili u repozitorijskoj datoteci .env; svaki alat u repozitoriju, uključujući testne pakete za preglednik, čita ista dva podatka. Odaberite par prije pokretanja i zadržite ga: premještanje pokrenute usluge na drugi port uzrokuje da administracija razgovara s pogrešnim API-jem.

Produkcija je druga stvar i tim pravilom nije promijenjena. API kontejner sluša interno na 5554 (fiksirano s NESSIE_API_PORT), a push relej na 5556, oboje iza reverse proxyja.

Pokretanje na jednom računalu, za razvoj

Repozitorij sadrži Compose datoteku samo s bazom podataka, a to je sve što lokalni tijek rada treba.

pnpm install
docker compose -f infrastructure/compose/docker-compose.yml up -d postgres

Taj kontejner objavljuje Postgres na 55432, a korisničko ime, lozinka i baza nose naziv nessie. Stavite connection string u .env u korijenu repozitorija — čita ga razvojna skripta API-ja — zatim primijenite migracije i jednom izgradite worker, jer u načinu local API učitava worker iz njegova izgrađenog dist:

DATABASE_URL=postgresql://nessie:nessie@localhost:55432/nessie

pnpm --filter @nessie/api prisma:migrate:deploy
pnpm --filter @nessie/worker build
pnpm dev

pnpm dev pokreće API i administraciju paralelno, s hot reloadom, na portovima 5454 i 5455. Provjerite odgovara li API na GET /api/health.

Postgres i zahtjev za pgvector

Tri proširenja stvaraju same migracije — vector, pg_trgm i pgcrypto — pa uloga koja ih pokreće mora smjeti stvarati proširenja. Na upravljanom Postgresu to je prva stvar koju treba provjeriti.

Širina vektora dio je sheme, a ne postavka. thoughts.embedding, thought_recalls.query_embedding i knowledge_page_chunks.embedding su stupci vector(N), a N je jednom naveden kao EMBEDDING_DIMENSIONS u packages/schemas/src/embedding.ts — trenutno 1024, širina koju model za embeddings koji koristi produkcija izvorno vraća. Svaki zahtjev za embeddings šalje tu širinu, pa davatelj koji bi odgovorio drugom širinom javlja glasnu grešku umjesto da upisuje vektore koje baza odbija. Prelazak na model za embeddings druge širine znači promijeniti tu konstantu, napisati migraciju koja ponovno tipizira tri stupca i ponovno izračunati embeddings: vektori različitih širina ne mogu se pretvoriti, pa migracija njihove vrijednosti postavlja na null umjesto da ih skraćuje.

Ako Nessie pokrećete uz druge aplikacije na zajedničkoj Docker mreži, dajte njegovom kontejneru baze zasebno ime. Compose usluga projekta zove se nessie-postgres, a nikad postgres, jer naziv usluge postaje DNS alias na zajedničkoj mreži, a sukob uzrokuje da se postgres:5432 izmjenjuje (round-robin) između dviju baza.

Konfiguracija

Konfiguracija za vrijeme izvođenja slojevita je: datoteka nessie.config.json montira se samo za čitanje u API i worker, a varijable okoline imaju prednost nad njom. Preslikavanje između njih je ConfigEnvMap u packages/config, a to je mjerodavni popis.

NESSIE_MODE određuje oblik instalacije: local (zadani način i put za razvojne programere), hosted ili selfHosted, što postavlja samostalno hostirana instalacija. Onemogućuje prijavu za razvoj i zahtijeva popis dopuštenih CORS izvora.

To su postavke bez kojih se selfHosted instalacija neće pokrenuti ili neće raditi:

VarijablaZašto
DATABASE_URL / NESSIE_DB_URLConnection string za Postgres.
NESSIE_AUTH_SECRET32 bajta u heksadecimalnom zapisu (openssl rand -hex 32). Potpisuje sesije i bootstrap tokene. Pokretanje ne uspijeva bez njega izvan načina local, a mora biti ista vrijednost na svakoj replici i kroz sva izdanja, inače se svaka sesija prekine pri svakoj objavi.
NESSIE_ENCRYPTION_KEY_RING, NESSIE_ENCRYPTION_ACTIVE_KEY_VERSIONJSON prsten ključeva i oznaka koja bira aktivni korijen, obvezni izvan načina local. Riječ je o zasebnom korijenu od potpisnog tajnog ključa — prsten šifrira svaku trajnu tajnu koju Nessie pohranjuje. Ne koristite jedan kao drugi.
NESSIE_STORAGE_PROVIDERMora biti s3. filesystem je zadani i odbijen je u načinima hosted i selfHosted, pa instalacija koja ovdje ništa ne postavi neće se pokrenuti, umjesto da učitavanja piše na disk kojemu ne može pristupiti nijedan drugi kontejner.
NESSIE_CORS_ORIGINSIzvor administracije. Administracija i API su zasebni izvori, a API mora na popis dopuštenih staviti onaj koji poslužuje.
NESSIE_API_PUBLIC_URL, NESSIE_ADMIN_PUBLIC_URLKoriste se za izradu OAuth URI-ja za preusmjeravanje izvan HTTP zahtjeva. API baca grešku pri zahtjevu bez prvog.
NESSIE_MODEL_PROVIDER, _BASE_URL, _API_KEYKamo ide inferencija. Pogledajte u nastavku.

infrastructure/compose/.env.prod.example ima točan oblik svih njih, s neobaveznim blokovima — objektnom pohranom, sigurnosnim spremištem tajni, SSO-om, povezanom poštom — komentiranim na mjestu. Potpuni popis, uključujući svaku neobaveznu postavku, nalazi se u docs/deployment/configuration.md.

Postavljanje pomoću Docker Composea

Kopirajte .env.prod.example u .env pored docker-compose.prod.yml i ispunite ga, zatim podignite bazu, izgradite, migrirajte i pokrenite. Redoslijed je važan: migracije i početni podaci (seed) izvršavaju se nad bazom koja je već podignuta, prije nego što ijedna usluga počne posluživati.

COMPOSE="docker compose -f infrastructure/compose/docker-compose.prod.yml"

bash infrastructure/compose/ensure-encryption-key-ring.sh infrastructure/compose/.env
$COMPOSE up -d nessie-postgres
$COMPOSE build nessie-api nessie-admin nessie-web
$COMPOSE run --rm --no-deps nessie-api pnpm --filter @nessie/api prisma:migrate:deploy
$COMPOSE run --rm --no-deps nessie-api pnpm --filter @nessie/api seed:connectors
$COMPOSE run --rm --no-deps nessie-api pnpm --filter @nessie/api seed:apps
$COMPOSE run --rm --no-deps nessie-api pnpm --filter @nessie/api reconcile
$COMPOSE up -d

Produkcijski Dockerfileovi pokreću lint svakog paketa prije njegove izgradnje, pa je neuspjeli lint ujedno i neuspjela izgradnja.

Korak reconcile nije neobavezan

reconcile postavlja zadana pravila politike svake organizacije i naknadno dodjeljuje dozvole za zaštićene MCP alate i alate osobnog asistenta. API je to nekad radio pri pokretanju na svakoj replici; sada se samo poveže, počne slušati i ništa više ne radi, pa bez ovog koraka prva organizacija nema nijedno pravilo politike i svako vezanje agenta je odbijeno. Korak je idempotentan, pa je pokretanje na svakoj objavi besplatno — a nadogradnja primijenjena ručno također ga mora pokrenuti.

Prvi vlasnički račun

Nova selfHosted instalacija nema korisnike, pa API izrađuje jednokratni bootstrap token i bilježi URL za postavljanje. Token se nalazi u Postgresu, a ne u procesu, pa se sve replike slažu oko njega.

docker compose -f infrastructure/compose/docker-compose.prod.yml logs nessie-api 2>&1 | grep bootstrap

Otvorite https://<your-admin-host>/bootstrap?token=<token> i stvorite vlasnički račun. Token istječe nakon 15 minuta; ponovno pokrenite uslugu API da bi izradila novi.

Ako konfigurirate SSO, nema uopće koraka bootstrapa. Bootstrap način se gasi čim se omogući vanjski pružatelj autentikacije — inače bi preoteo prijavnu stranicu — a prva osoba koja se prijavi putem SSO-a pokreće zadani tim i postaje njegov vlasnik.

Konfiguriranje inferencije

Chat je kompatibilan s OpenAI API-jem. NESSIE_MODEL_BASE_URL je krajnja točka, NESSIE_MODEL_API_KEY bearer token, a NESSIE_MODEL_PROVIDER imenuje adapter — Nessie ima ugrađene adaptere za openai, kimi i deepseek, a sve ostalo dohvaća preko općeg konektora kompatibilnog s OpenAI API-jem. NESSIE_MODEL_NAME postavlja zadani model instalacije, a odabir modela pojedinog agenta i dalje ga nadjačava.

Embeddings se usmjeravaju zasebno, jer davatelj chata možda uopće ne nudi embeddings — DeepSeek, primjerice, nema krajnju točku za embeddings. Svako nepostavljeno polje NESSIE_EMBEDDING_* nasljeđuje davatelja chata, pa instalacija koja ništa od toga ne postavi generira embeddings preko krajnje točke chata. Postavite NESSIE_EMBEDDING_PROVIDER, NESSIE_EMBEDDING_MODEL i, na proxyju koji usmjerava prema usluzi, segment usluge, kad davatelj chata ne može generirati embeddings. Pogreška ovdje prolazi tiho, umjesto da bude glasna: pamćenje i pretraga baze znanja prelaze na leksički kanal i nastavljaju raditi, uz zapis kb_search: query embedding failed.

Vlastiti obračun potrošnje Nessieja — evidencija tokena po organizaciji i ograničenje budžeta — nije pogođen krajnjom točkom na koju ga usmjeravate i radi jednako bez obzira je li konfiguriran potpisani zapis pozivatelja po pozivu.

Prijava

Nessie autentificira osobe preko UnlikeOtherAI, koji također upravlja strukturom organizacija i timova. Stranica za prijavu u administraciji prikazuje jedan gumb „Login / Register“.

Integracija je tok s konfiguracijskim JWT-om, a ne standardni OIDC: API na GET /api/auth/sso/config poslužuje potpisani RS256 konfiguracijski dokument, a odgovarajući JWKS na GET /.well-known/jwks.json, oboje na API hostu. Postavljanje je jednokratni slijed — generirajte RSA-2048 par ključeva i postavite UOA_CONFIG_JWT_PRIVATE_KEY_B64, UOA_CONFIG_JWT_KID, UOA_DOMAIN, UOA_CONFIG_URL, UOA_JWKS_URL, UOA_REDIRECT_URL i UOA_CONTACT_EMAIL; kliknite gumb jednom, čime se podiže zahtjev za integraciju; odobrite ga, što šalje jednokratnu poveznicu na kontaktnu adresu s klijentskom tajnom; postavite UOA_CLIENT_SECRET i ponovno pokrenite API. kid mora biti jedinstven po domeni.

Postavljanje iza domene, s TLS-om

Instalacija poslužuje tri naziva: javnu web stranicu, administraciju i API. Izvori administracije i API-ja nisu zamjenjivi. Dockerfile.admin ugrađuje VITE_API_BASE_URL u paket u vrijeme izgradnje, pa svaki izgrađeni artefakt administracije — uključujući desktop izgradnju koja ga ugrađuje — mora biti izgrađen za API izvor. Ako ga izgradite za vlastiti izvor administracije, /api/auth/providers razrješava se na HTML ljusku administracije, a prijava ostaje zaglavljena na „Loading providers...“.

Produkcija završava TLS na Caddyju, koji dobiva certifikate po nazivu hosta putem HTTP-01 i za to ne treba dodatak za DNS pružatelja. Usmjerite proxy na administracijski i web kontejner na portu 80, a na API na njegov interni port.

Postavite NESSIE_API_TRUSTED_PROXY_HOPS na broj proxyja ispred API-ja — 1 iza jednog reverse proxyja. Zadano je 0, što u potpunosti ignorira X-Forwarded-For. Ova jedna odluka ima dvije posljedice: njome se ujedno određuju ograničenja brzine za autentifikaciju, pa je premala vrijednost čini da svi klijenti dijele isti spremnik proxyja, a prevelika omogućuje klijentu da krivotvori vlastitu adresu. Grešite prema manjoj vrijednosti i izmjerite je.

Posluživanje svake organizacije i tima na vlastitoj poddomeni moguće je, a prema zadanom je isključeno. Upravlja njime NESSIE_TEAM_HOST_BASE_DOMAIN: ako nije postavljen, organizacije se uopće ne usmjeravaju prema nazivu hosta, a vrata za izdavanje certifikata NESSIE_TLS_CHECK_KEY odbijaju sve dok nije postavljen — što je ispravan zadani izbor za instalaciju koja tu značajku ne koristi.

Provjere stanja

Krajnja točkaPitanje na koje odgovara
GET /api/healthJe li ovaj proces živ? Ne uspijeva tek kad počne postupno gašenje.
GET /api/health/readySmije li ova replika primati nove zahtjeve? Na nju treba usmjeriti load balancer.
GET /api/ops/healthKako ide instalaciji? Izvještaj za osobu — otkucaji workera, dubina reda, mrtvi poslovi — a ne sonda.

Na SIGTERM API se postupno gasi umjesto da odmah umre. NESSIE_SHUTDOWN_TIMEOUT_MS ograničava to gašenje i zadano je na 25 sekundi; držite ga ispod razdoblja milosti koje vaš orkestrator daje kontejneru, inače runtime prvi ubije proces i gašenje ne donosi nikakvu korist.

Nadogradnja

Nadogradnja je prisma migrate deploy nad postojećom bazom, zatim početni podaci (seed), pa reconcile. Iste su četiri naredbe kao pri prvoj instalaciji.

Put je testiran za rutu kojom samostalni korisnik zaista ide, a ne na svježoj bazi: CI vraća snimku uzetu dvadeset migracija unazad, migrira je na trenutni head, provjerava shemu i pokreće provjeru dima nad osnovnim tablicama. Svako izdanje unutar tog zadnjeg prozora dokazana je izvorna nadogradnja. Mape migracija nepromjenjive su nakon što su commitane, a korak lintanja ruši izgradnju ako se neka preimenuje, preoznači, obriše ili izmijeni, jer sve to kvari migrate deploy za bazu koja je već zabilježila stari redak.

Jedna neuspjela migracija zaustavlja svaku sljedeću instalaciju. migrate deploy staje na prvom neuspjehu i odbija svaku kasniju migraciju s P3009, pa instalacija ostaje na starom izdanju dok je netko ručno ne očisti. Vlastita produkcija projekta jedan je dan odbijala svaku instalaciju na ovaj način. Čišćenje znači potvrditi da je neuspjela migracija zaista poništena — nijedan objekt koji stvara ne smije postojati, a ono što mijenja mora biti u izvornom obliku — i tek tada je označiti kao poništenu. Migracija koja je djelomično primijenjena nije kandidat.

Sigurnosna kopija i vraćanje za samostalno hostiranu Docker Compose instalaciju nisu dokumentirani u repozitoriju, pa ova stranica ne opisuje postupak za to.

Jedan stroj ili upravljani oblak

Put s jednim Docker Compose hostom iznad je dokazan: to je ono što pokreće vlastita produkcija projekta, na jednom poslužitelju, s bazom, objektnom pohranom, API-jem, workerom, administracijom i web stranicom kao kontejnerima iza zajedničkog reverse proxyja.

Skaliranje preko jednog stroja mijenja tri stvari, i sve su prisilne, a ne preporučene. Izvan načina local Nessie pokreće API i worker kao zasebne procese, i to kao nekoliko kopija svakog, pa je svaka mogućnost koja pretpostavlja da jedan proces posjeduje disk stroja odbijena: objektna pohrana na datotečnom sustavu (greška pri pokretanju), predlošci izvršnog okruženja s providerom docker (neaktivni, a provizija glasno pada) i ugrađeni alati file_read, file_write i file_glob (neuspjeli rezultat alata koji agent može pročitati). Svako odbijanje imenuje postavku, način i ono što treba koristiti umjesto toga.

Za upravljani oblak repozitorij sadrži Terraform stablo u infrastructure/terraform/ za Google Cloud: API kao Cloud Run servis s najmanje jednom instancom — drži trajni Postgres LISTEN klijent i pokreće održavanja, pa bi skaliranje na nulu zaustavilo realtime isporuku — worker kao Cloud Run worker pool, jer ne veže port pa bi servis nikad ne postao spreman, migrate job koji blokira svaki rollout, Cloud SQL za PostgreSQL 17 i GCS bucket dostupan preko backenda kompatibilnog s S3.

Taj put je napisan, ali nije isproban. Repozitorij to kaže otvoreno, i ova stranica također: za njega ne postoji projekt u Google Cloudu, ništa u stablu nije planirano ni primijenjeno nad stvarnim projektom, put višedijelnog učitavanja u GCS nije testiran na stvarnom bucketu, vrsta resursa worker poola nije provjerena, a broj hopova pouzdanog proxyja u njemu je privremena vrijednost koju treba izmjeriti, a ne izmjerena vrijednost. Administracija i javna web stranica tamo uopće nisu modelirane. Smatrajte to polazištem koje ćete sami provjeriti, a ne podržanom instalacijom.

Gdje se nalaze podaci instalacije, što softver drži i što namjerno ne drži, zasebna je stranica: Izrađeno u EU-u i gdje žive vaši podaci.