# Navi — deployment .env template. # install.sh copies this to .env (repo root) on first run and fills in # NAVI_DB_PASSWORD. Edit the placeholders marked TODO, then restart: # systemctl restart navi # ── LLM: Ollama Cloud ──────────────────────────────────────────────── # Profiles' config.json already carry cloud-first model priority lists. OLLAMA_HOST=https://ollama.com # TODO: your Ollama Cloud API key (https://ollama.com/settings/keys) OLLAMA_API_KEY= OLLAMA_DEFAULT_MODEL=glm-5.3-flash:cloud OLLAMA_NUM_CTX=65536 OLLAMA_THINK=true OLLAMA_REQUEST_TIMEOUT=30 # Embeddings for memory vector search. Empty host falls back to OLLAMA_HOST # (ollama.com). If the cloud account has no embedding model, leave empty — # the server starts with a warning and memory search degrades gracefully. EMBEDDING_OLLAMA_HOST= EMBEDDING_OLLAMA_API_KEY= EMBEDDING_MODEL=nomic-embed-text:latest # ── Database (dockerized postgres, see deploy/docker-compose.yml) ──── # install.sh generates NAVI_DB_PASSWORD and keeps this URL in sync. DATABASE_URL=postgresql://navi:CHANGEME@127.0.0.1:5432/navi NAVI_DB_PASSWORD=CHANGEME # ── Deployment shape: terminal client only, web UI off ─────────────── # To re-enable the web panel later: set true and `systemctl restart navi`. NAVI_WEBCLIENT_ENABLED=false # navi_ui MCP serves the webclient only — off together with it. NAVI_UI_MCP_ENABLED=false # Trusted single-server module: auth off. The server is LAN-reachable # (NAVI_HOST below) for the swarm peer channel; it is still protected by # nothing else — the network must be trusted. NAVI_AUTH_ENABLED=false # Server bind (used by navi-server / the systemd unit). # 0.0.0.0 = reachable from the LAN: required for the swarm (peer ask/status # come INBOUND on 8099). Use 127.0.0.1 only on machines outside the swarm; # then remote terminals need an SSH tunnel. NAVI_HOST=0.0.0.0 NAVI_PORT=8099 # ─── Client profile ────────────────────────────────────────────────── NAVI_DEFAULT_PROFILE_ID=navi_code # ─── Misc ──────────────────────────────────────────────────────────── LOG_LEVEL=INFO SESSION_MESSAGES_WINDOW=1000 WS_REPLAY_BUFFER_SIZE=500 CONTEXT_COMPRESSION_ENABLED=true # ─── Swarm / hive registry (see hive/README.md) ───────────────────── # Empty HIVE_URL = standalone machine: no announcements, nothing blocked. # To join a swarm: copy .swarm-key from the hive host, uncomment, restart. #HIVE_URL=http://192.168.1.168:8087 ANNOUNCE_INTERVAL_SEC=120 PEER_ASK_PROFILE=server_admin PEER_ASK_TIMEOUT_SEC=120 # ─── Web push (PWA notifications) ──────────────────────────────────────── # Empty keys = push disabled (graceful). Generate once: # pip install py_vapid && python -m py_vapid gen NAVI_VAPID_PUBLIC_KEY= NAVI_VAPID_PRIVATE_KEY= NAVI_VAPID_SUBJECT=mailto:admin@navi.local NAVI_PUSH_COOLDOWN_SEC=30 # ─── Persona ───────────────────────────────────────────────────────── # Prepended to every profile's system prompt (identity, house rules). The # file ships with the repo; without this line the server runs with no persona. NAVI_PERSONA_FILE=persona.txt # ─── Web search (navi-web MCP server) ───────────────────────────────── # Optional. The server's primary search backend is a self-hosted SearXNG; # without it the chain starts at DuckDuckGo scraping (slower, first to be # rate-limited). The config maps this through ${SEARXNG_URL:-}, so a missing # value costs you the backend, not the server. See docs/mcp.md#navi-web-settings. #SEARXNG_URL=http://127.0.0.1:8888 # ─── MCP server credentials ────────────────────────────────────────── # mcp_servers.d/*.json is tracked in git and must never hold a live token: it # names the variable (e.g. "Authorization": "Bearer ${NAVI_MCP_GNTODO_TOKEN}") # and the value lives here. Canonical store is gnexus-creds — rotate there, # then update this file and restart. A blank value counts as missing and the # server refuses to connect. See docs/mcp.md#secrets. NAVI_MCP_GNEXUS_CREDS_TOKEN= NAVI_MCP_GNTODO_TOKEN= NAVI_MCP_HARD_PANEL_TOKEN= NAVI_MCP_SYNAPSE_TOKEN= NAVI_MCP_TGCLIENT_TOKEN= # ─── History export ────────────────────────────────────────────────── # Bulk snapshot of message text for an external consumer (n-gram tables). # The snapshot is age-encrypted to the recipient below; its private half stays # on the consumer, so Navi cannot decrypt what it exports. Both lines are # required — with either blank nothing is built and the endpoints answer 503. # Consumer setup: scripts/navi_export.py keygen #NAVI_EXPORT_AGE_RECIPIENT=age1... #NAVI_EXPORT_TOKEN= # Roles in the corpus. Tool output and system prompts are excluded on purpose: # they are scraped web text and boilerplate, and they drown real dialogue. #NAVI_EXPORT_ROLES=user,assistant #NAVI_EXPORT_INTERVAL_HOURS=4 # Rolling window over whole sessions, newest first. 0 = no cap. #NAVI_EXPORT_MAX_BYTES=157286400