nessie

Nessien asentaminen

Aja Nessietä valitsemassasi infrastruktuurissa, yksittäisestä koneesta hallittuun pilveen.

Mitä tarvitset ennen aloittamista

Nessie on pnpm-monorepo, jossa on Node-palveluita ja kaksi staattista pakettia. Tavasta riippumatta ensin tarvitaan nämä neljä asiaa.

  • PostgreSQL ja pgvector. Ei valinnainen, eikä sitä voi korvata toisella. Migraatiot suorittavat komennon CREATE EXTENSION vector ja luovat vector(1024)-sarakkeita. Tuotannossa käytetään kuvaa pgvector/pgvector:pg17.
  • Node 22 ja pnpm. Jokainen hakemiston infrastructure/docker/ Dockerfile rakentuu kuvan node:22-slim päälle, ja repositorio lukitsee paketinhallintansa juuren package.json-tiedostossa (pnpm@10.22.0).
  • OpenAI-yhteensopiva mallipäätepiste ja sen avain. Agentit ja upotukset kulkevat molemmat sen kautta. Katso kohta ”Päättelyn määrittäminen” alla.
  • S3-yhteensopiva objektitallennus jokaiseen käyttöönottoon, joka ei ole paikallinen kehitysympäristö. Paikallisen levyn lataukset hylätään muussa kuin local-tilassa, ja tuo hylkäys on käynnistysvirhe eikä heikennetty käynnistys — katso ”Yksi kone vai hallittu pilvi”.

Konttipolkua varten tarvitaan Docker ja käänteinen välityspalvelin, ja internetistä tavoitettavaa käyttöä varten verkkotunnus ja TLS.

Laitteiston mitoitusta — vähimmäismäärää suorittimelle, muistille ja levylle tietyn henkilömäärän mukaan — ei kerrota missään repositoriossa, joten tälläkään sivulla sitä ei kerrota.

Komponentit ja niiden yhteys toisiinsa

KomponenttiMitä se onSisääntulo
api/Fastify-pohjainen HTTP- ja WebSocket-rajapinta. Jokainen asiakas puhuu vain sille.Kyllä
worker/Agenttien orkestrointi ja taustatyöt. Kysyy työjonosta eikä sido porttia.Ei
admin/Tuotteen käyttöliittymä — Viten rakentama staattinen paketti, jota nginx tarjoaa.Kyllä
web/Julkinen sivusto. Staattinen, valinnainen eikä liity tuotteen ajamiseen.Kyllä
PostgreSQLTietokanta, työjono ja reaaliaikainen väylä — kaikki kolme.Ei
ObjektitallennusLiitteet, avatarit ja tietopankin tiedostot. S3-yhteensopiva; tuotannossa MinIO.Ei
gateway/Valinnainen push-välittäjä APNs- ja FCM-ilmoituksille. Pois päältä, ellei sitä oteta käyttöön tarkoituksella.Kyllä

API ja worker ovat yksi kuva. Kaksi pakettia ovat tiiviisti kytkeytyneet toisiinsa, joten Dockerfile.app rakentaa koko tiimin kerran, ja workerin kontti korvaa komennon ajamalla node worker/dist/index.js. local-tilassa workerin konttia ei ole lainkaan: API ajaa workerin upotettuna omassa prosessissaan.

Redisiä ei ole. Työjono ja reaaliaikainen väylä perustuvat molemmat Postgresiin. Tämä on päätös, ei unohdus — Google Cloud -puu poistaa Pub/Sub- ja Redis-moduulinsa samasta syystä.

Portit

Paikallisessa kehityksessä API on oletuksena portissa 5454 ja admin portissa 5455. Työkopio voi ottaa oman parinsa asettamalla NESSIE_API_PORT ja NESSIE_ADMIN_PORT ympäristössä tai repositorion .env-tiedostossa; jokainen repositorion työkalu, selaintestisarjat mukaan lukien, lukee samat kaksi arvoa. Valitse pari ennen käynnistystä ja pidä se: käynnissä olevan palvelun siirtäminen toiseen porttiin saa adminin puhumaan väärälle API:lle.

Tuotanto on eri asia, eikä edellinen sääntö muuta sitä. API-kontti kuuntelee sisäisesti portissa 5554 (kiinnitetty muuttujalla NESSIE_API_PORT) ja push-välittäjä portissa 5556, molemmat käänteisen välityspalvelimen takana.

Ajaminen yhdellä koneella kehitystä varten

Repositorion mukana tulee Compose-tiedosto, jossa on pelkkä tietokanta. Se riittää paikallisen kehityksen kierrokseen.

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

Kontti julkaisee Postgresin portissa 55432, ja käyttäjä, salasana ja tietokanta ovat kaikki nimeltään nessie. Lisää yhteysmerkkijono repositorion juuressa olevaan .env-tiedostoon — API:n dev-skripti lukee sen — aja sitten migraatiot ja rakenna worker kerran, sillä local-tilassa API lataa workerin rakennetusta dist-hakemistosta:

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

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

pnpm dev ajaa APIn ja adminin rinnakkain kuumalatauksella porteissa 5454 ja 5455. Varmista, että API vastaa kutsulla GET /api/health.

Postgres ja pgvector-vaatimus

Migraatiot luovat itse kolme laajennusta — vector, pg_trgm ja pgcrypto — joten roolilla, joka ne ajaa, on oltava oikeus luoda laajennuksia. Hallitussa Postgresissa tämä kannattaa tarkistaa ennen kaikkea muuta.

Vektorin leveys on osa skeemaa, ei asetus. thoughts.embedding, thought_recalls.query_embedding ja knowledge_page_chunks.embedding ovat vector(N)-sarakkeita, ja N on määritelty kerran nimellä EMBEDDING_DIMENSIONS tiedostossa packages/schemas/src/embedding.ts — tällä hetkellä 1024, tuotannon upotusmallin alkuperäinen leveys. Jokainen upotuspyyntö lähettää tämän leveyden, joten palveluntarjoaja, joka vastaisi toisella leveydellä, epäonnistuu äänekkäästi eikä kirjoita vektoreita, joita tietokanta hylkää. Toisen leveyden upotusmalliin siirtyminen tarkoittaa tämän vakion muokkaamista, migraation kirjoittamista, joka muuttaa kolmen sarakkeen tyypin, ja uudelleenupotusta: eri leveyksisiä vektoreita ei voi muuntaa, joten migraatio nollaa ne sen sijaan, että katkaisisi ne.

Jos ajat Nessietä muiden sovellusten rinnalla jaetussa Docker-verkossa, anna sen tietokantakontille oma nimi. Projektin oman Compose-palvelun nimi on nessie-postgres, ei koskaan postgres, koska palvelun nimi muuttuu DNS-aliakseksi jaetussa verkossa, ja nimen törmäys saa osoitteen postgres:5432 vaihtelemaan kahden tietokannan välillä.

Asetukset

Ajonaikainen asetus on kerroksellinen: API:lle ja workerille liitetään lukuoikeudella tiedosto nessie.config.json, ja ympäristömuuttujat ovat sen päällä. Näiden kahden välinen vastaavuus on ConfigEnvMap hakemistossa packages/config, ja se on ratkaiseva luettelo.

NESSIE_MODE valitsee käyttöönoton muodon: local (oletus ja kehittäjän polku), hosted tai selfHosted, jonka itse ylläpidetty asennus asettaa. Se poistaa kehityskirjautumisen käytöstä ja vaatii CORS-sallintalistan.

Nämä ovat asetukset, joita selfHosted-käyttöönotto ei käynnistä tai ei saa toimimaan ilman:

MuuttujaMiksi
DATABASE_URL / NESSIE_DB_URLPostgresin yhteysmerkkijono.
NESSIE_AUTH_SECRET32 tavua heksadesimaalina (openssl rand -hex 32). Allekirjoittaa istunnot ja käynnistystunnukset. Käynnistys epäonnistuu ilman sitä muussa kuin local-tilassa, ja arvon on oltava sama jokaisessa replikassa ja jokaisessa julkaisussa, muuten jokainen istunto katkeaa joka julkaisussa.
NESSIE_ENCRYPTION_KEY_RING, NESSIE_ENCRYPTION_ACTIVE_KEY_VERSIONJSON-avainrengas ja aktiivisen juuren valitseva tunniste, pakollinen muussa kuin local-tilassa. Tämä on erillinen juuri allekirjoitussalaisuudesta — avainrengas salaa jokaisen pysyvän salaisuuden, jonka Nessie tallentaa. Älä käytä samaa arvoa kummassakin.
NESSIE_STORAGE_PROVIDERArvon on oltava s3. filesystem on oletus, ja se hylätään tiloissa hosted ja selfHosted. Näin käyttöönotto, joka ei aseta tätä, ei käynnisty sen sijaan, että kirjoittaisi lataukset levylle, johon mikään muu kontti ei pääse.
NESSIE_CORS_ORIGINSAdmin-origin. Admin ja API ovat erilliset originit, ja APIn on sallittava listallaan se origin, jonka se palvelee.
NESSIE_API_PUBLIC_URL, NESSIE_ADMIN_PUBLIC_URLKäytetään OAuth-uudelleenohjausosoitteiden luomiseen HTTP-pyynnön ulkopuolella. API heittää virheen pyynnön aikana, jos ensimmäinen puuttuu.
NESSIE_MODEL_PROVIDER, _BASE_URL, _API_KEYMinne päättely menee. Katso alla.

infrastructure/compose/.env.prod.example näyttää kaikkien asetusten täsmällisen muodon, ja valinnaiset lohkot — objektitallennus, salaisuusvarasto, SSO ja yhdistetty sähköposti — ovat kommentoituina paikoillaan. Täydellinen luettelo, mukaan lukien kaikki valinnaiset asetukset, on docs/deployment/configuration.md.

Käyttöönotto Docker Composella

Kopioi .env.prod.example nimellä .env tiedoston docker-compose.prod.yml viereen ja täytä se. Käynnistä sitten tietokanta, rakenna, migroi ja käynnistä palvelut. Järjestyksellä on merkitystä: migraatiot ja siemenaineistot ajetaan jo käynnissä olevaa tietokantaa vasten, ennen kuin mikään palvelu vastaa.

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

Tuotannon Dockerfilet ajavat jokaisen paketin lintin ennen sen rakentamista, joten lintivirhe on rakennusvirhe.

Reconcile-vaihe ei ole valinnainen

reconcile siemenöi jokaisen organisaation oletuskäytännön säännöt ja täydentää suojattujen MCP-työkalujen ja Henkilökohtaisen avustajan työkaluoikeudet. API teki tämän aiemmin käynnistyksen yhteydessä jokaisessa replikassa; nyt se yhdistää, kuuntelee eikä tee muuta, joten ilman tätä vaihetta ensimmäisellä organisaatiolla ei ole käytäntösääntöjä, ja jokainen agentin sidonta evätään. Vaihe on idempotentti, joten sen ajaminen jokaisessa käyttöönotossa ei maksa mitään — ja käsin tehty päivitys on ajettava myös sen kautta.

Ensimmäinen omistajatili

Tuore selfHosted-asennus ei sisällä käyttäjiä, joten API luo kertakäyttöisen käynnistystunnuksen ja kirjaa asennusosoitteen lokiin. Tunnus on Postgresissa eikä prosessissa, joten jokainen replika on samaa mieltä siitä.

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

Avaa https://<your-admin-host>/bootstrap?token=<token> ja luo omistajatili. Tunnus vanhenee 15 minuutissa; käynnistä API-palvelu uudelleen, jos tarvitset uuden tunnuksen.

Jos määrität SSO:n, käynnistysvaihetta ei ole lainkaan. Käynnistystila poistuu käytöstä heti, kun ulkoinen tunnistuspalvelu otetaan käyttöön — muuten se kaappaisi kirjautumisnäkymän — ja ensimmäinen SSO:lla kirjautuva henkilö alustaa oletustiimin ja tulee sen omistajaksi.

Päättelyn määrittäminen

Chat on OpenAI-yhteensopiva. NESSIE_MODEL_BASE_URL on päätepiste, NESSIE_MODEL_API_KEY bearer-avain ja NESSIE_MODEL_PROVIDER nimeää sovittimen. Nessie sisältää sovittimet tarjoajille openai, kimi ja deepseek, ja kaikki muu kulkee yleisen OpenAI-yhteensopivan liittimen kautta. NESSIE_MODEL_NAME asettaa käyttöönoton oletusmallin, jonka yksittäisen agentin oma mallivalinta kuitenkin ohittaa.

Upotukset reititetään erikseen, koska chat-palveluntarjoaja ei välttämättä tarjoa niitä lainkaan — esimerkiksi DeepSeekillä ei ole upotuspäätepistettä. Jokainen asettamaton NESSIE_EMBEDDING_*-kenttä perii chat-palveluntarjoajan, joten käyttöönotto, joka ei aseta niitä, upottaa chat-päätepisteen kautta. Aseta NESSIE_EMBEDDING_PROVIDER, NESSIE_EMBEDDING_MODEL ja — välityspalvelimessa, joka reitittää palvelun mukaan — palvelun segmentti, kun chat-palveluntarjoaja ei osaa upottaa. Väärin asetettuna virhe on hiljainen eikä äänekäs: muistihaku ja tietopankin haku siirtyvät sanapohjaiseen kanavaan ja jatkavat työtään, ja lokiin kirjautuu kb_search: query embedding failed.

Nessien oma kulutuskirjanpito — organisaatiokohtainen tokenikirjanpito ja budjettiportti — ei muutu sen mukaan, mihin päätepisteeseen sen osoitat, ja toimii samalla tavalla riippumatta siitä, onko allekirjoitettu kutsukohtainen kohdennus määritetty.

Kirjautuminen

Nessie tunnistaa ihmiset UnlikeOtherAI:n kautta, joka hallitsee myös organisaation ja tiimien rakennetta. Admin-kirjautumissivulla on yksi painike: ”Login / Register”.

Integraatio on config-JWT-virta eikä vakio-OIDC. API tarjoaa allekirjoitetun RS256-konfiguraatioasiakirjan osoitteessa GET /api/auth/sso/config ja vastaavan JWKS:n osoitteessa GET /.well-known/jwks.json, molemmat API-isännällä. Pystytys on kertaluonteinen prosessi: luo RSA-2048-avainpari ja aseta UOA_CONFIG_JWT_PRIVATE_KEY_B64, UOA_CONFIG_JWT_KID, UOA_DOMAIN, UOA_CONFIG_URL, UOA_JWKS_URL, UOA_REDIRECT_URL ja UOA_CONTACT_EMAIL. Paina painiketta kerran, jolloin syntyy integraatiopyyntö. Hyväksytä pyyntö, jolloin yhteystietoon lähtee kertakäyttöinen linkki, jossa on asiakassalaisuus. Aseta UOA_CLIENT_SECRET ja käynnistä API uudelleen. kid-tunnisteen on oltava yksilöllinen verkkotunnuksen sisällä.

Verkkotunnus ja TLS

Käyttöönotto palvelee kolmea nimeä: julkista sivustoa, adminia ja APIa. Admin- ja API-originit eivät ole keskenään vaihdettavissa. Dockerfile.admin upottaa VITE_API_BASE_URL-muuttujan pakettiin rakennusaikana, joten jokainen rakennettu admin-artefakti — mukaan lukien työpöytäversio, johon se upotetaan — on rakennettava API-originia vastaan. Jos rakennat sen adminin omaa originia vastaan, /api/auth/providers ratkeaa adminin HTML-kuoreksi ja kirjautuminen jää tilaan ”Loading providers...”.

Tuotannossa TLS päätetään Caddyssä, joka hakee isäntäkohtaiset sertifikaatit HTTP-01-haasteella eikä tarvitse siihen DNS-palveluntarjoajan lisäosaa. Osoita välityspalvelin admin- ja web-konttien porttiin 80 ja API:lle sen sisäiseen porttiin.

Aseta NESSIE_API_TRUSTED_PROXY_HOPS APIn edessä olevien välityspalvelimien määrään — 1, kun takana on yksi käänteinen välityspalvelin. Oletus on 0, joka jättää X-Forwarded-For-otsikon kokonaan huomiotta. Tämä on yksi päätös kahdella seurauksella: sama arvo määrittää myös kirjautumisen nopeusrajat. Liian pieni arvo jakaa kaikki asiakkaat välityspalvelimen yhteiseen rajoitusryhmään, ja liian suuri antaa asiakkaan väärentää oman osoitteensa. Valitse mieluummin matala arvo ja mittaa.

Jokaisen organisaation ja tiimin palvelu omassa alidomainissaan on mahdollista, ja se on oletuksena pois päältä. Sitä ohjaa NESSIE_TEAM_HOST_BASE_DOMAIN. Jos se on asettamatta, vuokralaisia ei reititetä isäntänimen perusteella lainkaan. Sertifikaattien myöntämisen portti NESSIE_TLS_CHECK_KEY hylkää kaiken, kun se on asettamatta — mikä on oikea oletus käyttöönotolle, joka ei käytä tätä ominaisuutta.

Terveystarkistukset

PäätepisteKysymys, johon se vastaa
GET /api/healthOnko tämä prosessi elossa? Epäonnistuu vain, kun tyhjennys on alkanut.
GET /api/health/readySaako tämä replika ottaa vastaan uusia pyyntöjä? Tähän kannattaa osoittaa kuormantasaaja.
GET /api/ops/healthMiten käyttöönotto voi? Raportti ihmiselle — workerien sykkeet, jonon syvyys, kuolleet työt — ei koetin.

SIGTERM-signaalilla API tyhjentää työnsä eikä kuole siihen paikkaan. NESSIE_SHUTDOWN_TIMEOUT_MS rajaa tyhjennyksen, ja oletus on 25 sekuntia. Pidä arvo alle sen armoajan, jonka orkestraattorisi antaa kontille, muuten ajoympäristö tappaa prosessin ennen kuin tyhjennys ehtii tuottaa mitään.

Päivittäminen

Päivitys on prisma migrate deploy olemassa olevaa tietokantaa vasten, sitten siemenaineistot ja sitten reconcile. Samat neljä komentoa kuin ensimmäisessä käyttöönotossa.

Polkua testataan sillä reitillä, jota itse ylläpitävä asentaja oikeasti kulkee, ei tuoreella tietokannalla: CI palauttaa kuvan, joka on otettu kaksikymmentä migraatiota taaksepäin, migroi sen nykyiseen kärkeen, validoi skeeman ja ajaa savutarkistuksen ydintauluista. Mikä tahansa julkaisu tuon liukuvan ikkunan sisällä on todistettu päivityslähde. Migraatiokansiot ovat muuttumattomia, kun ne on commitoitu, ja lintvaihe hylkää buildin, jos kansio nimetään uudelleen, numeroidaan uudelleen, poistetaan tai muokataan, koska kaikki nämä rikkoisivat migrate deploy -komennon tietokannalle, joka on jo kirjannut vanhan rivin.

Yksi epäonnistunut migraatio pysäyttää jokaisen sitä seuraavan käyttöönoton. migrate deploy pysähtyy ensimmäiseen virheeseen ja hylkää jokaisen myöhemmän migraation virhekoodilla P3009, joten asennus jää vanhaan julkaisuun, kunnes joku tyhjentää tilan käsin. Projektin oma tuotanto hylkäsi jokaisen käyttöönoton tällä tavalla koko päivän. Tilan tyhjentäminen edellyttää, että varmistat migraation todella peruuntuneen — mikään sen luomista objekteista ei saa olla olemassa, ja kaiken, mitä se muuttaa, on oltava alkuperäisessä muodossaan — ja vasta sitten merkitset sen peruutetuksi. Puoliksi sovellettu migraatio ei ole ehdokas.

Varmuuskopiointia ja palautusta itse ylläpidettävälle Compose-käyttöönotolle ei ole dokumentoitu repositoriossa, joten tämä sivu ei kuvaa siihen menettelyä.

Yksi kone vai hallittu pilvi

Yhden palvelimen Docker Compose -polku, jota yllä kuvataan, on se, joka on todistettu: sitä projektin oma tuotanto ajaa yhdellä palvelimella, ja tietokanta, objektitallennus, API, worker, admin ja sivusto toimivat kontteina jaetun käänteisen välityspalvelimen takana.

Skaalaus useammalle koneelle muuttaa kolmea asiaa, ja ne kaikki pakotetaan eikä niitä vain suositella. Muussa kuin local-tilassa Nessie ajaa APIn ja workerin erillisinä prosesseina ja useampina kopioina kumpaakin, joten jokainen ominaisuus, joka olettaa yhden prosessin omistavan koneen levyn, evätään: tiedostopohjainen objektitallennus (käynnistysvirhe), docker-palveluntarjoajan ajoympäristömallit (eivät toimi, ja käyttöönotto epäonnistuu äänekkäästi) sekä sisäänrakennetut työkalut file_read, file_write ja file_glob (epäonnistunut työkalun tulos, jonka agentti voi lukea). Jokainen hylkäys nimeää asetuksen, tilan ja sen, mitä tilalle kannattaa käyttää.

Hallittua pilveä varten repositorio sisältää Terraform-puun hakemistossa infrastructure/terraform/, joka kohdistuu Google Cloudiin: API Cloud Run -palveluna, jossa on vähintään yksi instanssi — se ylläpitää pysyvää Postgres-LISTEN-asiakasta ja ajaa ylläpitosiivouksia, joten skaalaus nollaan pysäyttää reaaliaikaisen toimituksen. Worker on Cloud Run -työpoolina, koska se ei sido porttia eikä palvelu koskaan tulisi valmiiksi. Mukana on migraatiotyö, joka portittaa jokaisen julkaisun, Cloud SQL for PostgreSQL 17 ja GCS-säiliö, johon päästään S3-yhteensopivan taustajärjestelmän kautta.

Tämä polku on kirjoitettu, mutta sitä ei ole kävelty läpi. Repositorio sanoo sen suoraan, ja tämä sivu sanoo samoin: polulle ei ole olemassa Google Cloud -projektia, puuhun ei ole suunniteltu tai otettu käyttöön mitään oikeaa projektia vasten, moniosainen latauspolku GCS:ään on testaamatta oikealla säiliöllä, työpooliresurssin tyyppi on validoimaton, ja siinä oleva luotetun välityspalvelimen hyppyjen määrä on paikkamerkki eikä mitattu arvo. Adminia ja julkista sivustoa ei ole siinä mallinnettu lainkaan. Pidä sitä lähtökohtana, jonka varmistat itse, äläkä tuettuna käyttöönottona.

Missä käyttöönoton tiedot sijaitsevat, mitä ohjelmisto pitää ja mitä se tarkoituksella ei pidä, on erillisellä sivulla: EU:ssa tehty ja tietojesi sijainti.