Namestitev Nessie
Zaženite Nessie na infrastrukturi, ki jo izberete, od enega samega računalnika do upravljane oblačne storitve.
Kaj potrebujete, preden začnete
Nessie je pnpm monorepo z Node storitvami in dvema statičnima paketoma. Ne glede na to, kako ga poganjate, morajo prej obstajati iste štiri stvari.
- PostgreSQL s
pgvector. Ni neobvezno in se ne da nadomestiti — migracije izvedejoCREATE EXTENSION vectorin ustvarijo stolpcevector(1024). Produkcija teče napgvector/pgvector:pg17. - Node 22 in pnpm. Vsaka Dockerfile datoteka v
infrastructure/docker/temelji nanode:22-slim, repozitorij pa v korenski datotekipackage.jsonpripne upravitelja paketov (pnpm@10.22.0). - Krajišče modela, združljivo z OpenAI, in ključ zanj. Agenti in vdelave (embeddings) gredo prek njega. Glejte „Nastavitev sklepanja“ spodaj.
- Shramba objektov, združljiva s S3, za vsako namestitev, ki ni lokalni razvojni primer. Nalaganja na lokalni disk so zunaj načina
localzavrnjena, zavrnitev pa pomeni napako ob zagonu, ne okrnjenega zagona — glejte „En stroj ali upravljani oblak“.
Docker in obratni posrednik sta potrebna za pot z vsebniki, opisano nižje, domena in TLS pa za vse, kar je dostopno z interneta.
Dimenzioniranje strojne opreme — najmanjši procesor, pomnilnik in disk za določeno število ljudi — ni navedeno nikjer v repozitoriju, zato tudi ta stran tega ne navaja.
Komponente in njihovo povezovanje
| Komponenta | Kaj je | Dohodni promet |
|---|---|---|
api/ | Fastify API za HTTP/WebSocket. Vsi odjemalci komunicirajo samo z njim. | Da |
worker/ | Usklajevanje agentov in zagoni v ozadju. Preverja čakalno vrsto opravil in ne odpira vrat. | Ne |
admin/ | Skrbniški vmesnik izdelka — statični paket, ki ga zgradi Vite in streže nginx. | Da |
web/ | Javna spletna stran. Statična, neobvezna in ni povezana z zagonom izdelka. | Da |
| PostgreSQL | Podatkovna baza, čakalna vrsta opravil in vodilo v realnem času — vse tri hkrati. | Ne |
| Shramba objektov | Priloge, avatarji in datoteke baze znanja. Združljivo s S3; v produkciji MinIO. | Ne |
gateway/ | Neobvezen posrednik za potisna obvestila prek APNs in FCM. Izklopljen, dokler ga ne omogočite namerno. | Da |
API in delavec sta ena slika. Ta dva paketa sta tesno povezana, zato Dockerfile.app enkrat zgradi celoten repozitorij, vsebnik delavca pa ukaz prepiše na node worker/dist/index.js. V načinu local vsebnika delavca sploh ni: API zažene delavca, vgrajenega v svoj lasten proces.
Redisa ni. Čakalna vrsta opravil in prenos v realnem času temeljita na PostgreSQL — po odločitvi, ne po pomanjkljivosti. Drevo za Google Cloud zaradi istega razloga izbriše svoja modula za Pub/Sub in Redis.
Vrata
Pri lokalnem razvoju je API privzeto na 5454, skrbniški vmesnik pa na 5455. Kopija repozitorija lahko vzame svoj par vrat, če nastavite NESSIE_API_PORT in NESSIE_ADMIN_PORT, v okolju ali v datoteki .env repozitorija; vsako orodje v repozitoriju, vključno s testnimi paketi za brskalnik, bere isti dve vrednosti. Par izberite pred zagonom in ga obdržite: če zagnano storitev premaknete na druga vrata, skrbniški vmesnik govori z napačnim API-jem.
Produkcija je drugačna in se s tem pravilom ne spreminja. API vsebnik interno posluša na 5554 (določeno z NESSIE_API_PORT), posrednik potisnih obvestil pa na 5556; oba sta za obratnim posrednikom.
Zagon na enem stroju za razvoj
Repozitorij vsebuje datoteko Compose samo z bazo podatkov, kar je vse, kar lokalni razvojni cikel potrebuje.
pnpm install
docker compose -f infrastructure/compose/docker-compose.yml up -d postgresTa vsebnik objavi PostgreSQL na 55432, z uporabniškim imenom, geslom in podatkovno bazo, vsemi imenovanimi nessie. Povezovalni niz dajte v .env v korenu repozitorija — razvojni skript API-ja ga prebere — nato enkrat uporabite migracije in zgradite delavca, ker API v načinu local naloži delavca iz njegovega zgrajenega dist:
DATABASE_URL=postgresql://nessie:nessie@localhost:55432/nessie
pnpm --filter @nessie/api prisma:migrate:deploy
pnpm --filter @nessie/worker build
pnpm devpnpm dev zažene API in skrbniški vmesnik vzporedno s samodejnim osveževanjem, na vratih 5454 in 5455. Preverite, ali je API odgovoril na GET /api/health.
PostgreSQL in zahteva pgvector
Tri razširitve ustvarijo same migracije — vector, pg_trgm in pgcrypto — zato mora vloga, ki jih izvaja, smeti ustvarjati razširitve. Pri upravljanem PostgreSQL je to prva stvar, ki jo je treba preveriti.
Širina vektorjev je del sheme, ne nastavitev. thoughts.embedding, thought_recalls.query_embedding in knowledge_page_chunks.embedding so stolpci vector(N), N pa je enkrat zapisan kot EMBEDDING_DIMENSIONS v packages/schemas/src/embedding.ts — trenutno 1024, izvorna širina modela vdelav, ki ga uporablja produkcija. Vsaka zahteva za vdelavo pošlje to širino, zato ponudnik, ki bi odgovoril z drugačno, glasno odpove, namesto da bi zapisal vektorje, ki jih baza zavrne. Prehod na model vdelav druge širine pomeni urediti to konstanto, napisati migracijo, ki preoblikuje tri stolpce, in vse ponovno vdelati: vektorjev različnih širin ni mogoče pretvoriti, zato jih migracija nastavi na NULL, ne pa jih odreže.
Če Nessie poganjate poleg drugih aplikacij v skupnem omrežju Docker, dajte njegovemu vsebniku baze drugo ime. Projektna storitev Compose se imenuje nessie-postgres in nikoli postgres, ker ime storitve postane alias DNS v skupnem omrežju, trk pa bi povzročil, da bi se postgres:5432 izmenično usmerjal med dvema podatkovnima bazama.
Nastavitve
Nastavitve med izvajanjem so v plasteh: datoteka nessie.config.json, pripeta samo za branje v API in delavca, z okoljskimi spremenljivkami čez njo. Preslikavo med njima določa ConfigEnvMap v packages/config, ki je merodajni seznam.
NESSIE_MODE določa obliko namestitve: local (privzeta in razvojna pot), hosted ali selfHosted — to nastavi lastna namestitev. Ta način onemogoči prijavo za razvoj in zahteva seznam dovoljenih izvorov CORS.
To so nastavitve, brez katerih se namestitev selfHosted ne bo zagnala ali ne bo delovala:
| Spremenljivka | Zakaj |
|---|---|
DATABASE_URL / NESSIE_DB_URL | Povezovalni niz za PostgreSQL. |
NESSIE_AUTH_SECRET | 32 bajtov v šestnajstiškem zapisu (openssl rand -hex 32). Podpisuje seje in zagonske žetone. Zagon se brez nje zunaj načina local ustavi; vrednost mora biti enaka na vsaki repliki in čez vse izdaje, sicer se ob vsaki izdaji vsaka seja prekine. |
NESSIE_ENCRYPTION_KEY_RING, NESSIE_ENCRYPTION_ACTIVE_KEY_VERSION | Obroč ključev v formatu JSON in oznaka, ki izbere aktivni koren, zahtevana zunaj načina local. To je ločen koren od podpisnega skrivnega ključa — obroč šifrira vsako trajno skrivnost, ki jo Nessie shrani. Enega ne uporabljajte kot drugega. |
NESSIE_STORAGE_PROVIDER | Mora biti s3. filesystem je privzeta vrednost in je zavrnjena v načinih hosted in selfHosted, tako da namestitev, ki tu ne nastavi ničesar, ne zažene, namesto da bi nalaganja pisala na disk, ki ga noben drug vsebnik ne more brati. |
NESSIE_CORS_ORIGINS | Izvor skrbniškega vmesnika. Skrbniški vmesnik in API sta ločena izvora, API pa mora dovoliti tistega, ki ga streže. |
NESSIE_API_PUBLIC_URL, NESSIE_ADMIN_PUBLIC_URL | Uporabljeno za ustvarjanje naslovov za preusmeritev OAuth zunaj HTTP zahteve. Brez prvega API ob zahtevi javi napako. |
NESSIE_MODEL_PROVIDER, _BASE_URL, _API_KEY | Kam gre sklepanje. Glejte spodaj. |
infrastructure/compose/.env.prod.example vsebuje natančno obliko vseh, z izbirnimi bloki — shramba objektov, trezor skrivnosti, SSO, povezana pošta — zakomentiranimi na mestu. Popoln katalog, vključno z vsemi neobveznimi nastavitvami, je v docs/deployment/configuration.md.
Namestitev z Docker Compose
Kopirajte .env.prod.example v .env poleg docker-compose.prod.yml in ga izpolnite, nato zaženite bazo, zgradite, migrirajte in zaženite storitve. Vrstni red je pomemben: migracije in začetni podatki se izvedejo nad bazo, ki je že zagnana, preden katera koli storitev sprejema zahteve.
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 -dProdukcijske Dockerfile datoteke pred gradnjo vsakega paketa zaženejo njegov lint, zato je napaka lint-a hkrati napaka gradnje.
Korak reconcile ni neobvezen
reconcile vnaprej napolni privzeta pravila politike vsake organizacije in dopolni dovoljenja za zaščitena orodja MCP ter orodja osebnega pomočnika. API je to nekoč naredil ob zagonu na vsaki repliki; zdaj se samo poveže, začne poslušati in nič več. Brez tega koraka prva organizacija nima pravil politike in vsaka vezava agenta je zavrnjena. Korak je idempotenten, zato ga zagon pri vsaki izdaji ne stane nič — in nadgradnja, izvedena ročno, ga mora prav tako zagnati.
Prvi račun lastnika
Nova namestitev selfHosted nima uporabnikov, zato API izda enkratni zagonski žeton in zabeleži naslov za nastavitev. Žeton živi v PostgreSQL, ne v procesu, zato se vse replike strinjajo o njem.
docker compose -f infrastructure/compose/docker-compose.prod.yml logs nessie-api 2>&1 | grep bootstrapOdprite https://<your-admin-host>/bootstrap?token=<token> in ustvarite račun lastnika. Žeton poteče po 15 minutah; za nov žeton znova zaženite storitev API.
Če nastavite SSO, zagonskega koraka sploh ni. Zagonski način se ukine v trenutku, ko je omogočen zunanji ponudnik prijave — sicer bi ugrabil prijavni zaslon — prva oseba, ki se prijavi prek SSO, pa zažene privzeto ekipo in postane njen lastnik.
Nastavitev sklepanja
Klepet je združljiv z OpenAI. NESSIE_MODEL_BASE_URL je krajišče, NESSIE_MODEL_API_KEY bearer ključ, NESSIE_MODEL_PROVIDER pa poimenuje adapter — Nessie ima prevedene adapterje za openai, kimi in deepseek, vse drugo pa gre prek splošnega priključka, združljivega z OpenAI. NESSIE_MODEL_NAME nastavi privzeti model namestitve, ki ga pa izbira modela pri posameznem agentu še vedno preglasi.
Vdelave so usmerjene ločeno, ker ponudnik klepeta morda sploh ne ponuja vdelav — DeepSeek na primer nima krajišča za vdelave. Vsako nenastavljeno polje NESSIE_EMBEDDING_* podeduje ponudnika klepeta, zato namestitev, ki jih ne nastavi nobenega, ustvarja vdelave prek krajišča klepeta. Kadar ponudnik klepeta ne more ustvarjati vdelav, nastavite NESSIE_EMBEDDING_PROVIDER, NESSIE_EMBEDDING_MODEL in — na posredniku, ki usmerja po storitvi — segment storitve. Napaka tu odpove tiho, ne glasno: priklic spomina in iskanje po bazi znanja se preklopita na leksikalni kanal in nadaljujeta, pri tem pa beležita kb_search: query embedding failed.
Lastno obračunavanje porabe Nessieja — knjiga stroškov žetonov po organizaciji in omejitev proračuna — je neodvisno od tega, na katero krajišče ga usmerite, in deluje enako, ne glede na to, ali je podpisovanje pripisov po posameznem klicu nastavljeno ali ne.
Prijava
Nessie preverja osebe prek UnlikeOtherAI, ki prav tako upravlja strukturo organizacij in ekip. Stran za prijavo v skrbniškem vmesniku prikazuje en gumb „Login / Register“.
Integracija je tok config-JWT, ne standardni OIDC: API na gostitelju API-ja streže podpisan konfiguracijski dokument RS256 na GET /api/auth/sso/config in ustrezni JWKS na GET /.well-known/jwks.json. Vzpostavitev je enkratno zaporedje — ustvarite par ključev RSA-2048 in nastavite UOA_CONFIG_JWT_PRIVATE_KEY_B64, UOA_CONFIG_JWT_KID, UOA_DOMAIN, UOA_CONFIG_URL, UOA_JWKS_URL, UOA_REDIRECT_URL in UOA_CONTACT_EMAIL; enkrat kliknite gumb, ki sproži zahtevo za integracijo; zahtevo odobrite, kar na kontaktni naslov pošlje enkratno povezavo s skrivnostjo odjemalca; nastavite UOA_CLIENT_SECRET in znova zaženite API. Vrednost kid mora biti v domeni edinstvena.
Postavitev za domeno, s TLS
Namestitev streže tri imena: javno spletno stran, skrbniški vmesnik in API. Izvora skrbniškega vmesnika in API-ja nista zamenljiva. Dockerfile.admin ob gradnji vgradi VITE_API_BASE_URL v paket, zato mora biti vsak zgrajen skrbniški artefakt — vključno z namiznim paketom, ki ga vdela — zgrajen za izvor API-ja. Če ga zgradite za lasten izvor skrbniškega vmesnika, se /api/auth/providers razreši v HTML lupino skrbniškega vmesnika in prijava obtiči na „Loading providers...“.
Produkcija konča TLS na Caddyju, ki pridobi certifikate za posamezna imena prek HTTP-01 in za to ne potrebuje vtičnika za ponudnika DNS. Usmerite posrednika na skrbniški in spletni vsebnik na vratih 80 ter na API na njegovih notranjih vratih.
Nastavite NESSIE_API_TRUSTED_PROXY_HOPS na število posrednikov pred API-jem — 1 za enim obratnim posrednikom. Privzeta vrednost je 0, ki X-Forwarded-For povsem prezre. To je ena odločitev z dvema posledicama: z njo se določijo tudi omejitve hitrosti prijave, zato je pri prenizki vrednosti vsak odjemalec v skupnem košu posrednika, pri previsoki pa lahko odjemalec ponaredi svoj naslov. Raje nizko in izmerite.
Vsaka organizacija in ekipa na lastni poddomeni je mogoča in privzeto izklopljena. Ureja jo NESSIE_TEAM_HOST_BASE_DOMAIN: če ni nastavljena, najemniki po imenu gostitelja sploh niso usmerjeni, vrata za izdajo certifikatov NESSIE_TLS_CHECK_KEY pa zavrnejo vse, dokler ni nastavljena — kar je pravilna privzeta vrednost za namestitev, ki te funkcije ne uporablja.
Preverjanja stanja
| Krajišče | Vprašanje, na katero odgovarja |
|---|---|
GET /api/health | Je ta proces živ? Odpove šele, ko začne zaključevati delo. |
GET /api/health/ready | Sme ta replika sprejemati nove zahteve? To je tisto, na katero naj kaže uravnoteževalnik obremenitve. |
GET /api/ops/health | Kako gre namestitvi? Poročilo za osebo — srčni utripi delavcev, globina čakalne vrste, mrtva opravila — ne sonda. |
Ob SIGTERM API zaključi delo, namesto da bi takoj ugasnil. NESSIE_SHUTDOWN_TIMEOUT_MS omeji to zaključevanje, privzeto je 25 sekund. Ohranite jo pod časom, ki ga vaš orkestrator da vsebniku, sicer izvajalno okolje proces ubije prej in zaključevanje nič ne pomaga.
Nadgradnja
Nadgradnja je prisma migrate deploy nad obstoječo bazo, nato začetni podatki in nato reconcile. Isti štirje ukazi kot pri prvi namestitvi.
Pot je preizkušena za pot, ki jo dejansko ubere samostojni upravitelj, in ne na sveži bazi: CI obnovi posnetek, vzet dvajset migracij za njim, ga migrira do trenutnega vrha, preveri shemo in zažene preverjanje delovanja nad osnovnimi tabelami. Vsaka izdaja znotraj tega zadnjega okna je dokazan vir nadgradnje. Mape migracij so po potrditvi (commit) nespremenljive, korak lint pa gradnjo prekine, če je katera preimenovana, preštevilčena, izbrisana ali spremenjena, ker vse štiri pokvarijo migrate deploy za bazo, ki je stari zapis že zabeležila.
Ena neuspela migracija zaustavi vse izvedbe za njo. migrate deploy se ustavi pri prvi napaki in vsako naslednjo migracijo zavrne s P3009, zato namestitev ostane na stari izdaji, dokler je nekdo ročno ne počisti. Produkcija samega projekta je tako cel dan zavračala vsako izvedbo. Počistiti jo pomeni potrditi, da je neuspela migracija res v celoti povrnjena — nobenega od objektov, ki jih ustvari, ne sme biti, vse, kar spremeni, pa mora imeti prvotno obliko — in šele nato jo razrešiti kot povrnjeno. Migracija, ki je bila le delno uveljavljena, ni kandidat.
Varnostno kopiranje in obnova za samostojno namestitev z Docker Compose v repozitoriju nista dokumentirana, zato ta stran ne opisuje postopka zanju.
En stroj ali upravljani oblak
Pot z enim gostiteljem in Docker Compose je tista, ki je preizkušena: na njej teče produkcija projekta na enem strežniku, z bazo, shrambo objektov, API-jem, delavcem, skrbniškim vmesnikom in spletnim mestom kot vsebniki za skupnim obratnim posrednikom.
Širitev čez en stroj spremeni tri stvari, vse pa so uveljavljene in ne le priporočene. Zunaj načina local Nessie zažene API in delavca kot ločena procesa in kot več kopij vsakega, zato je vsaka zmožnost, ki predpostavlja, da en proces lasti disk stroja, zavrnjena: shramba objektov na datotečnem sistemu (napaka pri zagonu), predloge izvajalnega okolja s ponudnikom docker (neučinkovite, priprava pa glasno odpove) in vgrajena orodja file_read, file_write ter file_glob (neuspešen rezultat orodja, ki ga agent lahko prebere). Vsaka zavrnitev imenuje nastavitev, način in to, kar naj uporabite namesto nje.
Za upravljani oblak repozitorij vsebuje drevo Terraform v infrastructure/terraform/, namenjeno Google Cloud: API kot storitev Cloud Run z najmanj eno instanco — drži trajni odjemalec PostgreSQL LISTEN in izvaja vzdrževalna opravila, zato ga zmanjšanje na nič ustavi dostavo v realnem času — delavca kot bazen delavcev Cloud Run, ker nima vrat in bi ga storitev nikoli ne označila kot pripravljenega; opravilo migracije, ki pogojuje vsako uvedbo; Cloud SQL za PostgreSQL 17 in vedro GCS, do katerega se dostopa prek zaledja, združljivega s S3.
Ta pot je napisana, ne preizkušena. Repozitorij to jasno pove in tudi ta stran: za to ne obstaja projekt v Google Cloud, v drevesu ni ničesar, kar bi bilo načrtovano ali uveljavljeno nad pravim projektom, pot za nalaganje večdelnih datotek v GCS ni preizkušena na pravem vedru, vrsta bazena delavcev ni potrjena, število skokov zaupanja posredniku pa je nadomestna vrednost, ki jo je treba izmeriti, ne meritev. Skrbniški vmesnik in javno spletno mesto tam sploh nista modelirana. Obravnavajte jo kot izhodišče, ki ga preverite, ne kot podprto namestitev.
Kje živijo podatki namestitve, kaj programska oprema hrani in česa namerno ne hrani, je ločena stran: Narejeno v EU in kje so vaši podatki.