Skip to Content
Deployment

Deployment

NavFlow is a single process writing to a single DuckDB file. There is no external database or broker to run. DuckDB is single-writer, so a deployment is exactly one navflowd and one data volume — do not run multiple replicas against the same data.

Local

Install the package and run navflow up:

uv tool install navflow # or: pipx install navflow navflow up # console on http://127.0.0.1:8787, data in ~/.navflow

navflow up accepts --host, --port, --data-dir, and --open. To expose the MCP endpoint for external agents, also run navflow mcp (see Connecting agents).

Docker

The published image runs the daemon by default:

docker run -p 8787:8787 -v navflow-data:/data \ ghcr.io/glassflow/navflow:latest

Self-hosted (compose)

For a server, run the daemon, the MCP server, and a reverse proxy that terminates TLS and routes one hostname. The image serves both processes (same image, different command):

# docker-compose.yml name: navflow services: navflowd: image: ghcr.io/glassflow/navflow:${NAVFLOW_VERSION:-latest} command: ["navflow", "up", "--host", "0.0.0.0", "--data-dir", "/data"] environment: NAVFLOW_AUTH_TOKEN: "${NAVFLOW_AUTH_TOKEN:?set NAVFLOW_AUTH_TOKEN}" volumes: [navflow-data:/data] expose: ["8787"] restart: unless-stopped mcp: image: ghcr.io/glassflow/navflow:${NAVFLOW_VERSION:-latest} command: ["navflow", "mcp", "--transport", "streamable-http", "--host", "0.0.0.0", "--port", "8788", "--navflowd", "http://navflowd:8787"] environment: NAVFLOW_AUTH_TOKEN: "${NAVFLOW_AUTH_TOKEN:?set NAVFLOW_AUTH_TOKEN}" expose: ["8788"] depends_on: [navflowd] restart: unless-stopped caddy: image: caddy:2 ports: ["80:80", "443:443"] environment: NAVFLOW_DOMAIN: "${NAVFLOW_DOMAIN:-:80}" volumes: ["./Caddyfile:/etc/caddy/Caddyfile:ro", "caddy-data:/data"] depends_on: [navflowd, mcp] restart: unless-stopped volumes: navflow-data: caddy-data:
# Caddyfile — one hostname; /mcp and /sse go to the MCP server, the rest to the daemon {$NAVFLOW_DOMAIN} { handle /mcp* { reverse_proxy mcp:8788 } handle /sse* { reverse_proxy mcp:8788 } handle { reverse_proxy navflowd:8787 } }

Set the domain and token, then start it:

export NAVFLOW_AUTH_TOKEN=$(openssl rand -hex 24) NAVFLOW_DOMAIN=navflow.example.com docker compose up -d

A real NAVFLOW_DOMAIN enables Caddy’s automatic HTTPS (point its DNS A record at the host first); unset, it serves plain HTTP on :80. The console is at https://<domain>; the MCP endpoint at https://<domain>/mcp.

Image versions

Images are published to ghcr.io/glassflow/navflow: :latest (the default branch) and a tag per release (:0.1.0, :0.1). Pin NAVFLOW_VERSION for reproducible deploys.

Configuration

navflowd is configured by environment variables.

variabledefaultdescription
NAVFLOW_DBnavflow.duckdbpath to the DuckDB file (navflow up uses ~/.navflow)
NAVFLOW_HOST127.0.0.1bind address (0.0.0.0 to expose)
NAVFLOW_PORT8787bind port
NAVFLOW_CATALOGcatalog.yamlcatalog YAML imported on first boot if the DB is empty
NAVFLOW_CATALOG_SYNCunsetif set, re-import the catalog YAML on every boot (file is source of truth)
NAVFLOW_AUTH_TOKENunsetrequire this bearer token on the API, console, and MCP
NAVFLOW_INGEST_TOKENunsetrequire this token on ingest endpoints (/ingest/*, /v1/*)
NAVFLOW_READONLYunsetrefuse the control plane; ingest stays open (see below)
NAVFLOW_VERCEL_VERIFYunsetvalue echoed in the x-vercel-verify header for Vercel drains
NAVFLOW_OTLP_GRPC_PORT4317OTLP/gRPC receiver port (off to disable; needs the otlp-grpc extra)
NAVFLOW_AGENT_MODELclaude-sonnet-4-6model used by the in-app Ask agent

The MCP server (navflow mcp / navflow-mcp) reads NAVFLOWD_URL, NAVFLOW_AUTH_TOKEN, and NAVFLOW_MCP_TRANSPORT / NAVFLOW_MCP_HOST / NAVFLOW_MCP_PORT.

Authentication and modes

NavFlow separates two surfaces:

  • Control plane — the API, console, and MCP (reads, authoring, source management).
  • Data plane — the ingest endpoints that push connectors deliver to.
settingeffect
NAVFLOW_AUTH_TOKENthe control plane requires this bearer token; the console prompts for it, agents send it. The data plane is unaffected.
NAVFLOW_INGEST_TOKENingest endpoints require this token (X-NavFlow-Token or Authorization: Bearer). Independent of the auth token — producers are not console users.
NAVFLOW_READONLYthe control plane refuses writes (the console and MCP go read-only); the data plane stays open so push sources keep delivering. Use for a public, read-only instance.

A token in NAVFLOW_AUTH_TOKEN is the same credential as the console login. For per-user SSO, put a proxy (oauth2-proxy, Tailscale, Caddy basic-auth) in front of the console; the machine paths (MCP, ingest) keep their bearer tokens.

Backups

The data is the DuckDB file in the volume. Back it up by snapshotting the volume (or the host) or copying /data/navflow.duckdb; restore by putting the file back before start.

Last updated on