nessie

Instaliranje Nessie-ja

Pokrenite Nessie na infrastrukturi koju birate, od jedne mašine do upravljanog oblaka.

Šta je potrebno pre početka

Nessie je pnpm monorepozitorijum sa Node servisima i dva statička paketa. Bez obzira na to kako ga pokrećete, ove četiri stvari moraju prvo postojati.

  • PostgreSQL sa pgvector. Nije opciono i ne može se zameniti drugim rešenjem — migracije izvršavaju CREATE EXTENSION vector i kreiraju kolone vector(1024). Produkcija koristi pgvector/pgvector:pg17.
  • Node 22 i pnpm. Svaki Dockerfile u infrastructure/docker/ gradi se na node:22-slim, a repozitorijum fiksira menadžer paketa u korenskom package.json (pnpm@10.22.0).
  • Krajnja tačka OpenAI kompatibilnog modela i ključ za nju. Agenti i embedding-i prolaze kroz nju. Pogledajte „Podešavanje inferencije“ ispod.
  • Objektno skladište kompatibilno sa S3, za svaku instalaciju koja nije lokalna razvojna. Otpremanja na lokalnom disku se odbijaju van režima local, a to odbijanje je greška pri pokretanju, a ne umanjeno pokretanje — pogledajte „Jedna mašina ili upravljani oblak“.

Docker i reverzni proksi potrebni su za putanju sa kontejnerima opisanu dalje, a domen i TLS za sve što je dostupno sa interneta.

Dimenzionisanje hardvera, odnosno najmanji broj procesora, memorije i prostora na disku za određeni broj ljudi, nigde nije navedeno u repozitorijumu, pa ni ova stranica to ne navodi.

Komponente i način na koji se povezuju

KomponentaŠta jeIngress
api/HTTP/WebSocket API zasnovan na Fastify-ju. Svi klijenti razgovaraju samo sa njim.Da
worker/Orkestracija agenata i pozadinska izvršavanja. Proverava red poslova i ne otvara port.Ne
admin/Korisnički interfejs proizvoda — statički paket koji gradi Vite, a služi ga nginx.Da
web/Javni sajt. Statičan je, opcioni i nije povezan sa radom proizvoda.Da
PostgreSQLBaza podataka, red poslova i realtime magistrala — sve tri.Ne
Objektno skladištePrilozi, avatari i fajlovi baze znanja. Kompatibilno sa S3; u produkciji se koristi MinIO.Ne
gateway/Opcioni posrednik za push obaveštenja za APNs i FCM. Isključen je dok ga ne uključite namerno.Da

API i worker su jedna slika. Dva paketa su čvrsto povezana, pa Dockerfile.app jednom gradi ceo tim, a worker kontejner menja komandu u node worker/dist/index.js. U režimu local uopšte nema worker kontejnera: API pokreće worker ugrađen u sopstveni proces.

Nema Redis-a. Red poslova i transport u realnom vremenu zasnovani su na Postgres-u, odlukom, a ne propustom — Google Cloud stablo briše svoje Pub/Sub i Redis module iz istog razloga.

Portovi

Pri lokalnom razvoju API je podrazumevano na 5454, a admin na 5455. Svaki checkout može da uzme sopstveni par tako što postavi NESSIE_API_PORT i NESSIE_ADMIN_PORT, u okruženju ili u .env repozitorijuma; svaki alat u repozitorijumu, uključujući testne pakete u pregledaču, čita ista dva podatka. Izaberite par pre pokretanja i zadržite ga: premeštanje servisa koji radi na drugi port ostavlja admina da razgovara sa pogrešnim API-jem.

Produkcija je drugačija stvar i na nju to pravilo ne utiče. Kontejner API-ja sluša interno na 5554 (fiksirano pomoću NESSIE_API_PORT), a push posrednik na 5556, oba iza reverznog proksija.

Pokretanje na jednoj mašini, za razvoj

Repozitorijum sadrži Compose datoteku sa samo bazom podataka, što je sve što lokalna petlja zahteva.

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 se zovu nessie. Stavite string za povezivanje u .env u korenu repozitorijuma — razvojna skripta API-ja ga čita — zatim primenite migracije i jednom izgradite worker, jer u režimu local API učitava worker iz njegovog 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 admin paralelno, uz automatsko ponovno učitavanje, na portovima 5454 i 5455. Proverite da je API odgovorio na GET /api/health.

Postgres i zahtev za pgvector

Tri ekstenzije kreiraju same migracije — vector, pg_trgm i pgcrypto, pa uloga koja ih pokreće mora smeti da kreira ekstenzije. Na upravljanom Postgres-u to je prva stvar koju treba proveriti.

Širina vektora je deo šeme, a ne podešavanje. Kolone thoughts.embedding, thought_recalls.query_embedding i knowledge_page_chunks.embedding su vector(N), a N je jednom navedeno kao EMBEDDING_DIMENSIONS u packages/schemas/src/embedding.ts — trenutno 1024, što je izvorna širina modela za embedding koji koristi produkcija. Svaki zahtev za embedding šalje tu širinu, pa provajder koji bi odgovorio drugom širinom ne uspeva glasno, umesto da upiše vektore koje baza odbija. Prelazak na model za embedding druge širine znači izmenu te konstante, pisanje migracije koja menja tip tri kolone i ponovno generisanje embedding-a: vektori različitih širina ne mogu se pretvarati jedni u druge, pa migracija njihove vrednosti postavlja na null umesto da ih skraćuje.

Ako Nessie pokrećete pored drugih aplikacija na zajedničkoj Docker mreži, dajte kontejneru baze jedinstveno ime. Servis iz Compose-a projekta zove se nessie-postgres, nikada postgres, jer ime servisa postaje DNS alias na zajedničkoj mreži, pa se sukob pretvara u to da postgres:5432 naizmenično (round-robin) šalje saobraćaj na dve baze.

Konfiguracija

Konfiguracija u toku rada je slojevita: datoteka nessie.config.json montirana samo za čitanje u API i worker, a preko nje idu promenljive okruženja. Preslikavanje između njih je ConfigEnvMap u packages/config, a to je merodavan spisak.

NESSIE_MODE bira oblik instalacije: local (podrazumevani, put za razvojni rad), hosted ili selfHosted — što postavlja samostalna instalacija. Ovaj režim isključuje razvojnu prijavu i zahteva listu dozvoljenih CORS izvora.

Ovo su podešavanja bez kojih se instalacija selfHosted neće pokrenuti ili neće raditi:

PromenljivaZašto
DATABASE_URL / NESSIE_DB_URLString za povezivanje sa Postgres-om.
NESSIE_AUTH_SECRET32 bajta u heksadecimalnom zapisu (openssl rand -hex 32). Potpisuje sesije i bootstrap tokene. Pokretanje ne uspeva bez njega van režima local, a mora biti ista vrednost na svakoj replici i kroz sva postavljanja, inače se sve sesije prekidaju pri svakom izdanju.
NESSIE_ENCRYPTION_KEY_RING, NESSIE_ENCRYPTION_ACTIVE_KEY_VERSIONJSON prsten ključeva i oznaka koja bira aktivni koren, potrebni van režima local. Ovo je poseban koren od tajnog ključa za potpisivanje — prsten šifruje svaku trajnu tajnu koju Nessie čuva. Ne koristite jedno umesto drugog.
NESSIE_STORAGE_PROVIDERMora biti s3. filesystem je podrazumevani i odbija se u režimima hosted i selfHosted, pa instalacija koja ovde ništa ne podesi ne uspeva da se pokrene, umesto da upisuje otpremanja na disk do kojeg drugi kontejneri ne mogu da dođu.
NESSIE_CORS_ORIGINSIzvor admin dela. Admin i API su odvojeni izvori, a API mora na listi dozvoljenih imati onaj koji služi.
NESSIE_API_PUBLIC_URL, NESSIE_ADMIN_PUBLIC_URLKoriste se za izradu OAuth URI-ja za preusmeravanje van HTTP zahteva. API baca grešku u trenutku zahteva bez prvog.
NESSIE_MODEL_PROVIDER, _BASE_URL, _API_KEYKuda ide inferencija. Pogledajte dole.

infrastructure/compose/.env.prod.example ima tačan oblik svih njih, a opcioni blokovi — objektno skladište, sef za tajne, SSO i povezana pošta — navedeni su u komentarima na svom mestu. Potpun katalog, uključujući svako opciono podešavanje, nalazi se u docs/deployment/configuration.md.

Postavljanje pomoću Docker Compose-a

Kopirajte .env.prod.example u .env pored docker-compose.prod.yml i popunite ga, zatim pokrenite bazu, izgradite, primenite migracije i pokrenite servise. Redosled je bitan: migracije i početni podaci izvršavaju se nad bazom koja je već podignuta, pre nego što išta počne da služi.

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

Produkcioni Dockerfile-ovi pokreću lint svakog paketa pre nego što ga izgrade, pa je greška u lint proveri ujedno i greška pri izgradnji.

Korak reconcile nije opcioni

reconcile postavlja podrazumevana pravila politike svake organizacije i dopunjuje dodele alata za zaštićene MCP alate i alate Personal Assistant-a. API je to ranije radio pri pokretanju na svakoj replici; sada se samo poveže, počne da sluša i ništa više ne radi, pa bez ovog koraka prva organizacija nema pravila politike i svako vezivanje agenta biva odbijeno. Korak je idempotentan, pa je pokretanje pri svakom postavljanju besplatno — a nadogradnja primenjena ručno takođe mora da ga pokrene.

Prvi vlasnički nalog

Nova selfHosted instalacija nema korisnike, pa API izdaje jednokratni bootstrap token i beleži URL za podešavanje. Token se čuva u Postgres-u, 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 napravite vlasnički nalog. Token ističe posle 15 minuta; ponovo pokrenite API servis da biste izdali novi.

Ako podesite SSO, uopšte nema koraka bootstrap-a. Bootstrap režim se gasi čim se omogući spoljni provajder autentikacije — inače bi preoteo ekran za prijavu — a prva osoba koja se prijavi preko SSO-a pravi podrazumevani tim i postaje njegov vlasnik.

Podešavanje inferencije

Chat je kompatibilan sa OpenAI-jem. NESSIE_MODEL_BASE_URL je krajnja tačka, NESSIE_MODEL_API_KEY bearer ključ, a NESSIE_MODEL_PROVIDER imenuje adapter — Nessie ima ugrađene adaptere za openai, kimi i deepseek, a sve ostalo ide preko opšteg konektora kompatibilnog sa OpenAI-jem. NESSIE_MODEL_NAME postavlja podrazumevani model instalacije, a izbor modela koji je agent sam odabrao i dalje ima prednost.

Embedding-i se usmeravaju odvojeno, jer provajder za chat možda uopšte ne služi embedding-e — DeepSeek, na primer, nema krajnju tačku za embedding-e. Svako nepostavljeno polje NESSIE_EMBEDDING_* nasleđuje provajdera za chat, pa instalacija koja nijedno ne postavi radi embedding preko krajnje tačke za chat. Postavite NESSIE_EMBEDDING_PROVIDER, NESSIE_EMBEDDING_MODEL i, na proksiju koji usmerava po servisu, segment servisa, kada provajder za chat ne može da radi embedding. Pogrešno podešavanje ne prijavljuje grešku glasno: pretraga pamćenja i pretraga baze znanja prelaze na leksički kanal i nastavljaju rad, uz zapisivanje kb_search: query embedding failed.

Sopstveno obračunavanje potrošnje Nessie-ja — evidencija tokena po organizaciji i budžetska kapija — ne zavisi od toga na koju krajnju tačku ga usmerite i radi isto bez obzira na to da li je potpisano pripisivanje po pozivu podešeno.

Prijava

Nessie autentifikuje ljude preko UnlikeOtherAI, koji upravlja i strukturom organizacija i timova. Stranica za prijavu u adminu prikazuje jedno dugme „Login / Register“.

Integracija je JWT tok zasnovan na konfiguraciji, a ne standardni OIDC: API na GET /api/auth/sso/config služi potpisani RS256 konfiguracioni dokument, a odgovarajući JWKS na GET /.well-known/jwks.json, oba na API hostu. Postavljanje je jednokratni niz koraka — generišite 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 dugme jednom, čime se podnosi zahtev za integraciju; sačekajte odobrenje, što na kontakt adresu šalje jednokratni link sa tajnim ključem klijenta; zatim postavite UOA_CLIENT_SECRET i ponovo pokrenite API. kid mora biti jedinstven po domenu.

Postavljanje iza domena, uz TLS

Instalacija služi tri naziva: javni sajt, admin i API. Admin i API izvori nisu zamenjivi. Dockerfile.admin ugrađuje VITE_API_BASE_URL u paket u vreme izgradnje, pa svaki izgrađeni admin artefakt — uključujući i desktop build koji ga ugrađuje — mora biti izgrađen za API izvor. Ako ga izgradite za sopstveni izvor admina, /api/auth/providers se razrešava u HTML školjku admina, a prijava ostaje zaglavljena na „Loading providers...“.

Produkcija završava TLS na Caddy-ju, koji dobija sertifikate po nazivu hosta preko HTTP-01 i za to ne treba dodatak za DNS provajdera. Usmerite proksi na admin i web kontejnere na portu 80, a na API na njegov interni port.

Postavite NESSIE_API_TRUSTED_PROXY_HOPS na broj proksija ispred API-ja — 1 iza jednog reverznog proksija. Podrazumevano je 0, što u potpunosti zanemaruje X-Forwarded-For. Ovo je jedna odluka sa dve posledice: ona određuje i ključ po kome se računaju ograničenja broja autentifikacionih zahteva, pa ako je premala, svaki klijent deli zajedničku kvotu proksija, a ako je prevelika, klijent može da falsifikuje sopstvenu adresu. Grešite na manju stranu i izmerite.

Zasebna adresa za svaku organizaciju i tim je moguća i podrazumevano isključena. Upravlja njome NESSIE_TEAM_HOST_BASE_DOMAIN: ako nije postavljeno, timovi se uopšte ne usmeravaju po hostu, a kapija za izdavanje sertifikata NESSIE_TLS_CHECK_KEY odbija sve dok nije postavljena — što je ispravna podrazumevana vrednost za instalaciju koja ovu funkciju ne koristi.

Provere zdravlja

Krajnja tačkaPitanje na koje odgovara
GET /api/healthDa li je ovaj proces živ? Otkazuje tek kada počne da se prazni.
GET /api/health/readyMože li ova replika da prihvati nove zahteve? Ovu treba povezati sa load balancer-om.
GET /api/ops/healthKako ide instalacija? Izveštaj za osobu — otkucaji worker-a, dubina reda i mrtvi poslovi — a ne sonda.

Na SIGTERM API se prazni, umesto da odmah stane. NESSIE_SHUTDOWN_TIMEOUT_MS ograničava to pražnjenje i podrazumevano iznosi 25 sekundi; držite ga ispod roka za gašenje koji orkestrator daje kontejneru, inače runtime ubije proces pre nego što pražnjenje išta donese.

Nadogradnja

Nadogradnja je prisma migrate deploy nad postojećom bazom, zatim početni podaci, pa reconcile. Iste četiri komande kao pri prvom postavljanju.

Put je testiran za rutu koju samostalni korisnik zaista prolazi, a ne nad praznom bazom: CI vraća snimak uzet dvadeset migracija unazad, migrira ga do trenutnog čela, proverava šemu i pokreće proveru ispravnosti nad osnovnim tabelama. Svako izdanje unutar tog pomičnog prozora je dokazan izvor nadogradnje. Fascikle migracija su nepromenljive kada se commit-uju, a lint korak obara izgradnju ako se neka preimenuje, promeni joj se redni broj, obriše ili izmeni, jer sve četiri stvari kvare migrate deploy za bazu koja je već zabeležila staru verziju.

Jedna neuspela migracija blokira svako sledeće postavljanje. migrate deploy staje na prvom neuspehu i odbija svaku kasniju migraciju sa P3009, pa instalacija ostaje na starom izdanju dok je neko ručno ne otključa. Produkcija samog projekta je jedan dan odbijala svako postavljanje na ovaj način. Otključati je znači potvrditi da je neuspela migracija zaista poništena — nijedan objekat koji kreira ne sme da postoji, a sve što menja mora da ima prvobitni oblik — i tek tada je označiti kao poništenu. Migracija koja je delimično primenjena nije kandidat za to.

Rezervna kopija i vraćanje za samostalnu Compose instalaciju nisu dokumentovani u repozitorijumu, pa ova stranica ne opisuje postupak za to.

Jedna mašina ili upravljani oblak

Put sa jednim hostom preko Docker Compose-a je onaj koji je dokazan: na njemu radi produkcija samog projekta, na jednom serveru, sa bazom, objektnim skladištem, API-jem, workerom, adminom i sajtom kao kontejnerima iza zajedničkog reverznog proksija.

Skaliranje preko jedne mašine menja tri stvari, a sve su sprovedene pravilima, a ne preporukama. Van režima local, Nessie pokreće API i worker kao zasebne procese i u više kopija, pa je svaka mogućnost koja pretpostavlja da jedan proces poseduje disk mašine odbijena: objektno skladište na fajl sistemu (greška pri pokretanju), šabloni izvršnog okruženja sa provajderom docker (neaktivni, a provizionisanje glasno ne uspeva) i ugrađeni alati file_read, file_write i file_glob (neuspešan rezultat alata koji agent može da pročita). Svako odbijanje imenuje podešavanje, režim i ono što treba koristiti umesto toga.

Za upravljani oblak repozitorijum sadrži Terraform stablo u infrastructure/terraform/ za Google Cloud: API kao Cloud Run servis sa najmanje jednom instancom — jer drži trajni Postgres LISTEN klijent i pokreće sweep-ove održavanja, pa skaliranje na nulu zaustavlja isporuku u realnom vremenu — worker kao Cloud Run worker pool, jer ne otvara port i Service nikada ne bi postao spreman; migracioni job koji mora da prođe pre svakog izdanja; Cloud SQL za PostgreSQL 17; i GCS bucket dostupan preko backend-a kompatibilnog sa S3.

Ta putanja je napisana, ali nije isprobana. Repozitorijum to kaže otvoreno, i ova stranica takođe: za nju ne postoji Google Cloud projekat, ništa u stablu nije planirano niti primenjeno nad pravim projektom, višedelno otpremanje u GCS nije testirano nad pravim bucket-om, tip resursa worker pool je nevalidiran, a broj hopova pouzdanog proksija u njemu je privremena vrednost koju treba izmeriti, a ne merenje. Admin i javni sajt tamo uopšte nisu modelovani. Tretirajte je kao polaznu tačku koju sami proveravate, a ne kao podržanu instalaciju.

Gde se podaci instalacije nalaze, šta softver čuva i šta namerno ne čuva, opisano je na posebnoj stranici: Napravljeno u EU i gde se nalaze vaši podaci.