Instalace Nessie
Provozujte Nessie na infrastruktuře, kterou si zvolíte, od jednoho počítače po spravovaný cloud.
Co musíte mít připravené, než začnete
Nessie je pnpm monorepo, tedy sada služeb v Node a dva statické balíčky. Ať ho spustíte jakkoli, musí nejdřív existovat těchto čtyři věci.
- PostgreSQL s
pgvector. Není to volitelné a nedá se to nahradit jiným řešením. Migrace spouštíCREATE EXTENSION vectora vytvářejí sloupcevector(1024). Produkce běží napgvector/pgvector:pg17. - Node 22 a pnpm. Každý Dockerfile v
infrastructure/docker/staví nanode:22-slima repozitář v kořenovémpackage.jsonpřipíná správce balíčků (pnpm@10.22.0). - Koncový bod modelu kompatibilní s OpenAI a klíč k němu. Agenti i vektorové vkládání (embeddings) přes něj procházejí. Viz „Nastavení inference“ níže.
- Objektové úložiště kompatibilní s S3 pro každé nasazení, které není lokální vývojářské. Nahrávání na lokální disk se mimo režim
localodmítá a toto odmítnutí je chyba při startu, ne omezený běh — viz „Jeden stroj, nebo spravovaný cloud“.
Docker a reverzní proxy jsou potřeba pro kontejnerovou variantu popsanou níže, doména a TLS pak pro cokoli dostupného z internetu.
Požadavky na hardware — minimální procesor, paměť a disk pro daný počet lidí — nejsou nikde v repozitáři uvedeny, proto je ani tato stránka neuvádí.
Komponenty a jak spolu souvisejí
| Komponenta | Co to je | Přístup z internetu |
|---|---|---|
api/ | HTTP/WebSocket API postavené na Fastify. Každý klient komunikuje pouze s ním. | Ano |
worker/ | Orchestrace agentů a práce na pozadí. Dotazuje frontu úloh; nenaslouchá na žádném portu. | Ne |
admin/ | Uživatelské rozhraní produktu — statický balíček sestavený nástrojem Vite a podávaný přes nginx. | Ano |
web/ | Veřejný web. Statický, volitelný a se samotným během produktu nesouvisí. | Ano |
| PostgreSQL | Databáze, fronta úloh i sběrnice pro sdílení v reálném čase — všechny tři zároveň. | Ne |
| Objektové úložiště | Přílohy, avatary a soubory znalostní báze. Kompatibilní s S3; v produkci MinIO. | Ne |
gateway/ | Volitelné předávací místo pro APNs a FCM. Vypnuté, dokud ho výslovně nezapnete. | Ano |
API a worker jsou jeden obraz. Oba balíčky jsou úzce propojené, takže Dockerfile.app sestaví celý tým jednou a kontejner workeru přepíše příkaz na node worker/dist/index.js. V režimu local žádný kontejner workeru neexistuje: API spouští worker vnořený ve svém vlastním procesu.
Redis tu není. Fronta úloh i přenos v reálném čase stojí na Postgresu. Je to rozhodnutí, ne opomenutí — stejného důvodu strom pro Google Cloud maže své moduly Pub/Sub a Redis.
Porty
Při místním vývoji je ve výchozím nastavení API na 5454 a administrace na 5455. Každý checkout si může vzít vlastní dvojici nastavením NESSIE_API_PORT a NESSIE_ADMIN_PORT, v prostředí nebo v souboru .env repozitáře; všechny nástroje v repozitáři, včetně testovacích sad pro prohlížeč, čtou tytéž dvě hodnoty. Dvojici zvolte před spuštěním a držte se jí: přesunutí běžící služby na jiný port způsobí, že administrace komunikuje s nesprávným API.
Produkce je jiná věc a toto pravidlo se na ni nevztahuje. Kontejner API naslouchá interně na 5554 (připnuto přes NESSIE_API_PORT) a předávací služba pro push na 5556, obojí za reverzní proxy.
Spuštění na jednom stroji pro vývoj
Repozitář obsahuje soubor Compose jen s databází, a to je vše, co lokální vývoj potřebuje.
pnpm install
docker compose -f infrastructure/compose/docker-compose.yml up -d postgresTento kontejner publikuje Postgres na 55432; uživatel, heslo i databáze se jmenují nessie. Připojovací řetězec vložte do souboru .env v kořeni repozitáře — čte ho vývojový skript API — a potom jednou aplikujte migrace a sestavte worker, protože v režimu local načítá API worker z jeho sestaveného dist:
DATABASE_URL=postgresql://nessie:nessie@localhost:55432/nessie
pnpm --filter @nessie/api prisma:migrate:deploy
pnpm --filter @nessie/worker build
pnpm devpnpm dev spustí API a administraci paralelně s hot reloadem, na portech 5454 a 5455. Ověřte, že API odpovídá na GET /api/health.
Postgres a požadavek pgvector
Tři rozšíření vytvářejí samy migrace — vector, pg_trgm a pgcrypto — takže role, která je spouští, musí mít oprávnění vytvářet rozšíření. U spravovaného Postgresu je to první věc, kterou zkontrolujte.
Šířka vektoru je součástí schématu, nejde o nastavení. Sloupce thoughts.embedding, thought_recalls.query_embedding a knowledge_page_chunks.embedding jsou sloupce vector(N) a N je jednou uvedeno jako EMBEDDING_DIMENSIONS v packages/schemas/src/embedding.ts — aktuálně 1024, nativní šířka modelu pro vektorové vkládání, který produkce používá. Každý požadavek na vložení tuto šířku posílá, takže poskytovatel, který by odpověděl jinou šířkou, selže hlasitě, místo aby zapsal vektory, které databáze odmítne. Přechod na model s jinou šířkou znamená upravit tuto konstantu, napsat migraci, která přetypuje tyto tři sloupce, a vektory znovu vložit: vektory různých šířek se převést nedají, takže je migrace nuluje místo toho, aby je zkracovala.
Pokud Nessie provozujete vedle jiných aplikací na sdílené síti Dockeru, dejte jejímu databázovému kontejneru odlišný název. Služba Compose projektu se jmenuje nessie-postgres a nikdy postgres, protože název služby se stává DNS aliasem na sdílené síti a kolize by způsobila, že postgres:5432 střídavě (round-robin) směřuje na dvě databáze.
Konfigurace
Konfigurace za běhu je vrstvená: soubor nessie.config.json připojený jen pro čtení do API a workeru, nad nímž mají přednost proměnné prostředí. Mapování mezi nimi je ConfigEnvMap v packages/config, který je závazným seznamem.
NESSIE_MODE určuje podobu nasazení: local (výchozí a cesta pro vývojáře), hosted, nebo selfHosted — což nastavuje vlastní instalace. Vypíná přihlášení pro vývojáře a vyžaduje seznam povolených původů CORS.
Toto jsou nastavení, bez kterých se nasazení selfHosted nespustí, nebo nebude fungovat:
| Proměnná | Proč |
|---|---|
DATABASE_URL / NESSIE_DB_URL | Připojovací řetězec k Postgresu. |
NESSIE_AUTH_SECRET | 32 bajtů v hexadecimálním zápisu (openssl rand -hex 32). Podepisuje relace a bootstrap tokeny. Mimo režim local se bez něj start přeruší. Musí být stejná hodnota na každé replice i napříč nasazeními, jinak každá relace zanikne při každém vydání. |
NESSIE_ENCRYPTION_KEY_RING, NESSIE_ENCRYPTION_ACTIVE_KEY_VERSION | JSON klíčový kruh a označení aktivního kořene, vyžadované mimo režim local. Jde o oddělený kořen od podpisového tajemství — klíčový kruh šifruje každé trvalé tajemství, které Nessie ukládá. Nepoužívejte jeden jako druhý. |
NESSIE_STORAGE_PROVIDER | Musí být s3. filesystem je výchozí a v režimech hosted a selfHosted je odmítnut, takže nasazení, které tu nic nenastaví, se nespustí, místo aby zapisovalo nahrané soubory na disk, ke kterému žádný jiný kontejner nemá přístup. |
NESSIE_CORS_ORIGINS | Původ administrace. Administrace a API jsou oddělené původy a API musí povolit ten, který obsluhuje. |
NESSIE_API_PUBLIC_URL, NESSIE_ADMIN_PUBLIC_URL | Slouží k vytvoření OAuth přesměrovacích URI mimo HTTP požadavek. API bez prvního z nich vyhodí chybu při požadavku. |
NESSIE_MODEL_PROVIDER, _BASE_URL, _API_KEY | Kam směřuje inference. Viz níže. |
infrastructure/compose/.env.prod.example ukazuje přesný tvar všech z nich, s volitelnými bloky — objektové úložiště, trezor tajemství, SSO, připojená pošta — zakomentovanými na svém místě. Úplný přehled včetně každého volitelného nastavení je v docs/deployment/configuration.md.
Nasazení přes Docker Compose
Zkopírujte .env.prod.example do .env vedle docker-compose.prod.yml a vyplňte ho. Potom spusťte databázi, sestavení, migrace a start. Pořadí je důležité: migrace a seedy běží na databázi, která už je spuštěná, dřív než cokoli začne obsluhovat.
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 -dProdukční Dockerfily před sestavením každého balíčku spustí jeho lint, takže chyba lintu znamená selhání sestavení.
Krok reconcile není volitelný
reconcile nasazuje výchozí pravidla zásad každé organizace a doplňuje oprávnění k chráněným MCP nástrojům a nástrojům osobního asistenta (Personal Assistant). API to dřív dělalo při startu na každé replice; nyní se jen připojí, naslouchá a nic dalšího nedělá. Bez tohoto kroku proto první organizace nemá žádná pravidla zásad a každé přiřazení agenta je zamítnuto. Je idempotentní, takže spouštět ho při každém nasazení nic nestojí. Upgrade provedený ručně musí spustit také.
První účet vlastníka
Čerstvá instalace selfHosted nemá žádné uživatele, takže API vytvoří jednorázový bootstrap token a zaloguje adresu pro nastavení. Token je uložen v Postgresu, ne v procesu, takže se všechny repliky shodnou na jeho hodnotě.
docker compose -f infrastructure/compose/docker-compose.prod.yml logs nessie-api 2>&1 | grep bootstrapOtevřete https://<your-admin-host>/bootstrap?token=<token> a vytvořte účet vlastníka. Token vyprší po 15 minutách; restartujte službu API, aby vytvořila nový.
Pokud nastavíte SSO, žádný bootstrap krok vůbec není. Režim bootstrapu se potlačí ve chvíli, kdy je zapnutý externí poskytovatel přihlášení — jinak by přebral přihlašovací obrazovku — a první člověk, který se přihlásí přes SSO, založí výchozí tým a stane se jeho vlastníkem.
Nastavení inference
Chat je kompatibilní s OpenAI. NESSIE_MODEL_BASE_URL je koncový bod, NESSIE_MODEL_API_KEY nosný token (bearer) a NESSIE_MODEL_PROVIDER pojmenovává adaptér. Nessie má zkompilované adaptéry pro openai, kimi a deepseek a na cokoli jiného se připojuje přes obecný konektor kompatibilní s OpenAI. NESSIE_MODEL_NAME nastavuje výchozí model nasazení, který však výběr modelu u jednotlivého agenta přebíjí.
Vektorové vkládání (embeddings) se směruje zvlášť, protože chatovací poskytovatel je nemusí nabízet vůbec — DeepSeek například žádný koncový bod pro vkládání nemá. Každé nenastavené pole NESSIE_EMBEDDING_* převezme chatovacího poskytovatele, takže nasazení, které žádné nenastaví, vkládá přes chatovací koncový bod. Když chatovací poskytovatel vkládat neumí, nastavte NESSIE_EMBEDDING_PROVIDER, NESSIE_EMBEDDING_MODEL a na proxy, která směruje podle služby, také segment služby. Chyba se projeví tiše, ne hlasitě: vyhledávání v paměti a ve znalostní bázi přejde na lexikální kanál a pokračuje dál, přičemž zapisuje kb_search: query embedding failed.
Vlastní účetnictví výdajů Nessie — tokenový účet na úrovni organizace a rozpočtová brána — na tom, na který koncový bod ho nasměrujete, nezávisí. Funguje stejně, ať je podepisování atribuce pro každé volání nastavené, nebo ne.
Přihlašování
Nessie ověřuje lidi přes UnlikeOtherAI, které také spravuje strukturu organizací a týmů. Přihlašovací stránka administrace ukazuje jediné tlačítko „Login / Register“.
Integrace je spíš config-JWT tok než standardní OIDC: API podává podepsaný RS256 konfigurační dokument na GET /api/auth/sso/config a odpovídající JWKS na GET /.well-known/jwks.json, obojí na hostiteli API. Nastavení je jednorázový postup. Vygenerujte pár klíčů RSA-2048 a nastavte UOA_CONFIG_JWT_PRIVATE_KEY_B64, UOA_CONFIG_JWT_KID, UOA_DOMAIN, UOA_CONFIG_URL, UOA_JWKS_URL, UOA_REDIRECT_URL a UOA_CONTACT_EMAIL. Jednou klikněte na tlačítko, které založí žádost o integraci. Nechte ji schválit; na kontaktní adresu přijde jednorázový odkaz s klientským tajemstvím. Nastavte UOA_CLIENT_SECRET a restartujte API. kid musí být jedinečné v rámci domény.
Provoz za doménou s TLS
Nasazení obsluhuje tři názvy: veřejný web, administraci a API. Původy administrace a API nejsou zaměnitelné. Dockerfile.admin zapéká VITE_API_BASE_URL do balíčku už při sestavení, takže každý sestavený artefakt administrace — včetně desktopového sestavení, které ho obsahuje — musí být sestaven vůči původu API. Když ho sestavíte vůči vlastnímu původu administrace, /api/auth/providers se přeloží na HTML kostru administrace a přihlášení uvízne na „Loading providers...“.
Produkce ukončuje TLS na Caddy, který získává certifikáty pro jednotlivé názvy hostitelů přes HTTP-01 a pro to nepotřebuje zásuvný modul pro DNS poskytovatele. Nasměrujte proxy na kontejnery administrace a webu na portu 80 a na API na jeho interním portu.
Nastavte NESSIE_API_TRUSTED_PROXY_HOPS na počet proxy před API — 1 za jednou reverzní proxy. Výchozí je 0, což ignoruje X-Forwarded-For úplně. Je to jedno rozhodnutí se dvěma důsledky: podle něj se určují i limity pokusů o přihlášení. Příliš nízká hodnota znamená, že všichni klienti sdílejí kbelík proxy; příliš vysoká umožní klientovi zfalšovat vlastní adresu. Raději nastavte nižší hodnotu a ověřte ji měřením.
Obsluhovat každou organizaci a tým na vlastní subdoméně je možné a ve výchozím stavu vypnuté. Řídí to NESSIE_TEAM_HOST_BASE_DOMAIN. Pokud není nastaveno, směrování podle názvu hostitele se pro organizace a týmy vůbec neuplatní. Brána pro vydávání certifikátů NESSIE_TLS_CHECK_KEY odmítá všechno, dokud není nastavena — což je správný výchozí stav pro nasazení, které tuto funkci nepoužívá.
Kontroly stavu
| Koncový bod | Na jakou otázku odpovídá |
|---|---|
GET /api/health | Běží tento proces? Selže až ve chvíli, kdy začne ukončování. |
GET /api/health/ready | Smí tato replika přijímat nové požadavky? Na tento koncový bod nasměrujte load balancer. |
GET /api/ops/health | Jak si nasazení vede? Přehled pro člověka — heartbeaty workerů, délka fronty, mrtvé úlohy — nikoli sonda. |
Při SIGTERM API nezemře na místě, ale dokončí rozpracované požadavky. NESSIE_SHUTDOWN_TIMEOUT_MS tuto dobu omezuje a výchozí je 25 sekund. Držte ji pod lhůtou na ukončení, kterou orchestrátor kontejneru poskytne; jinak runtime proces ukončí dřív a dokončování nemá smysl.
Aktualizace
Aktualizace znamená prisma migrate deploy nad existující databází, potom seedy a pak reconcile. Stejné čtyři příkazy jako při prvním nasazení.
Postup je testován pro cestu, kterou skutečně jde self-hoster, a ne proti čerstvé databázi: CI obnoví snímek pořízený o dvacet migrací zpět, migruje ho na aktuální head, ověří schéma a spustí kontrolu funkčnosti nad hlavními tabulkami. Každé vydání uvnitř tohoto posledního okna je ověřeným zdrojem upgradu. Složky migrací jsou po potvrzení neměnné a krok lintu selže sestavení, pokud je některá přejmenována, přečíslována, smazána nebo upravena, protože všechny čtyři věci rozbijí migrate deploy u databáze, která už starý záznam zapsala.
Jedna neúspěšná migrace zablokuje každé nasazení po ní. migrate deploy se zastaví na první chybě a všechny pozdější migrace odmítne s P3009, takže instalace zůstane na staré verzi, dokud ji někdo ručně neuvolní. Vlastní produkce projektu strávila den tím, že každé nasazení odmítala touto cestou. Uvolnění znamená potvrdit, že neúspěšná migrace se skutečně vrátila zpět: žádný z objektů, které vytváří, nesmí existovat a to, co mění, musí mít původní tvar. Teprve potom ji lze označit jako vrácenou. Migrace, která se provedla jen napůl, kandidátem není.
Zálohování a obnova pro self-hosted nasazení přes Docker Compose nejsou v repozitáři zdokumentovány, proto tato stránka žádný postup pro ně nepopisuje.
Jeden stroj, nebo spravovaný cloud
Jednostrojová cesta přes Docker Compose výše je ta ověřená: na ní běží vlastní produkce projektu na jednom serveru, s databází, objektovým úložištěm, API, workerem, administrací a webem jako kontejnery za sdílenou reverzní proxy.
Škálování za jeden stroj mění tři věci a všechny jsou vynucené, ne jen doporučené. Mimo režim local Nessie běží API a worker jako oddělené procesy a několik kopií každého, takže každá schopnost, která předpokládá, že jeden proces vlastní disk stroje, je odmítnuta: souborové objektové úložiště (chyba při startu), šablony prováděcího prostředí s poskytovatelem docker (neúčinné a provisioning hlasitě selže) a vestavěné nástroje file_read, file_write a file_glob (neúspěšný výsledek nástroje, který agent může přečíst). Každé odmítnutí pojmenuje nastavení, režim a to, co použít místo něj.
Pro spravovaný cloud repozitář obsahuje strom Terraformu v infrastructure/terraform/ cílící na Google Cloud: API jako službu Cloud Run s minimem jedné instance — drží trvalého klienta Postgres LISTEN a spouští údržbové úlohy, takže škálování na nulu zastaví doručování v reálném čase; worker jako worker pool Cloud Run, protože nenaslouchá na žádném portu a služba by nikdy nebyla připravena; migrační úlohu, která zastavuje každé vydání, dokud neprojde; Cloud SQL pro PostgreSQL 17 a bucket GCS připojený přes backend kompatibilní s S3.
Tato cesta je napsaná, ale ne vyzkoušená. Repozitář to říká přímo a tato stránka také: pro ni neexistuje žádný projekt v Google Cloud, nic v stromu nebylo naplánováno ani aplikováno proti skutečnému projektu, cesta multipart nahrávání do GCS není otestovaná na skutečném bucketu, typ zdroje worker poolu není ověřený a počet hopů důvěryhodné proxy je v něm zástupná hodnota, která se má změřit, ne změřená hodnota. Administrace a veřejný web tam nejsou vůbec modelovány. Berte to jako výchozí bod, který ověříte, ne jako podporované nasazení.
Kde žijí data nasazení, co software drží a co záměrně nedrží, je na samostatné stránce: Vyrobeno v EU a kde jsou vaše data.