Environment variables
Notarium is configured through environment variables. The defaults just work — for a local run you don't need to fill in anything: copy .env.example to .env and edit the lines you actually need. The Docker stack passes .env into the container as-is (values are not baked into the image), so the same file describes both your local and your production instance.
cp .env.example .env # the defaults work — edit only what you need
Below is the full reference. Some variables are set directly in .env.example; others (search fine-tuning) have defaults in code and aren't spelled out in the example — those are flagged separately.
Core
The basics: port, authentication mode, and the location of the metadata database and spaces.
| Variable | Purpose | Default | Example |
|---|---|---|---|
DATA_DIR | The single data knob: the root from which everything else is derived — the metadata database, indexes, notes, artifacts. Unset → a sensible default is used. | /data (Docker); ~/.local/share/notarium (host) | DATA_DIR=/srv/notarium |
PORT | The port the backend listens on; a single Fastify listener serves /api, /mcp, and the SPA's static assets. | 3000 | PORT=3000 |
AUTH_MODE | Authentication mode: password (login plus a first-run setup screen, requires the metadata database) or none (a single all-access principal for desktop/dev/trusted intranet, no login UI). | password | AUTH_MODE=none |
META_DB_URL | The metadata database: identity, revision log, space registry, authentication, projects. Defaults to sqlite under DATA_DIR, so password mode works with no setup. Optional: set it only to move metadata state into an external Postgres (shared state, HA). | sqlite:<DATA_DIR>/meta.db | META_DB_URL=postgres://user:pass@db:5432/notarium |
SPACES_ROOT | The root where each space is a folder; enables creating spaces from the UI at runtime. Optional: defaults to <DATA_DIR>/spaces, set it only if your notes live outside the data root. | <DATA_DIR>/spaces | SPACES_ROOT=/mnt/notes |
SPACES_CONFIG | Explicit space topology: inline JSON or a path to a JSON file. Overrides the single-space variables. | unset | SPACES_CONFIG=/data/spaces.json |
ENGINE_DATA_DIR | Where the engine keeps derived indexes — one file per space. The file name follows the space's folder name and doesn't change when the space is renamed. Deleting the directory → a reindex at startup; the index is recoverable. Optional: defaults to <DATA_DIR>/engine, set it to move the indexes onto another disk. | <DATA_DIR>/engine | ENGINE_DATA_DIR=/mnt/ssd/engine |
JOBS_DATA_DIR | The job directory: artifacts of async exports (derived, cleaned up by TTL) and the uploaded files of an unfinished import — those live exactly as long as their job does, which is why they belong in a backup. Optional: defaults to <DATA_DIR>/jobs, set it to move it onto another disk. | <DATA_DIR>/jobs | JOBS_DATA_DIR=/mnt/ssd/jobs |
SPACE_IDLE_EVICT_SECONDS | Evict the read model of an idle space. 0 — keep it warm; spaces with a live SSE connection are never evicted. | 0 | SPACE_IDLE_EVICT_SECONDS=900 |
SYNC_POLL_SECONDS | The polling interval for external on-disk changes (each poll is a full space rescan). 0 — disable polling. For unwatchable mounts (network volume, in-memory) the effective interval is capped at 60 s. | 120 | SYNC_POLL_SECONDS=0 |
PUBLIC_BASE_URL | The canonical external address of the instance behind a reverse proxy — for the OAuth metadata of MCP connectors. Without it, the address is derived from the proxy's forwarded headers. | unset | PUBLIC_BASE_URL=https://notes.example.com |
TRUST_PROXY | A comma-separated list of IPs/CIDRs of the immediate proxies — used to derive the real client IP for login rate limits and for admitting new OAuth clients. Unset means the safe default: X-Forwarded-For has no effect on the limits. Boolean values, hop counts, named ranges, and all-address ranges (/0) are rejected at startup. | unset | TRUST_PROXY=172.18.0.0/16 |
Two different things live on disk. SPACES_ROOT is the Markdown truth (your notes, one folder per space). META_DB_URL is the metadata database: what can't be derived from the files (users, access, version history). More in the Self-host section.
Single-space (bare-host, no Docker)
For running a single space without SPACES_CONFIG and without SPACES_ROOT (for example, a local bare run without Docker).
| Variable | Purpose | Default | Example |
|---|---|---|---|
ENGINE | The engine for a single space. The only value is notarium; you can leave it unset. | notarium | ENGINE=notarium |
NOTES_DIR | Absolute path to the notes folder of a single space (single-space mode). | unset | NOTES_DIR=/home/me/notes |
Semantic search
Lexical full-text search (FTS) always works, with no configuration. Semantic (vector) and hybrid search are opt-in: a heavy native stack (onnxruntime + sqlite-vec, ~660 MB on disk) plus the bge-m3 embedding model (~600 MB on disk, hundreds of MB of RAM). The variables below have defaults in code and aren't spelled out in .env.example.
| Variable | Purpose | Default | Example |
|---|---|---|---|
VECTOR_SEARCH | on/off — turns on semantics and hybrid fusion. When the native stack is missing, on falls back to full-text search — without error. | on (code), off (published image) | VECTOR_SEARCH=on |
EMBED_MODEL | The id of the embedding model (transformers.js/ONNX). Set it together with EMBED_DIMENSIONS. | Xenova/bge-m3 | EMBED_MODEL=Xenova/multilingual-e5-small |
EMBED_DIMENSIONS | The vector width; it must match the model (bge-m3 — 1024, e5-small — 384). A mismatch is fail-closed: the note stays FTS-only. | 1024 | EMBED_DIMENSIONS=384 |
EMBED_DTYPE | Model quantization: fp32 / fp16 / q8 / q4. | q8 | EMBED_DTYPE=fp16 |
EMBED_THREADS | The number of ONNX intra-op threads per background-indexing worker (a pool of EMBED_WORKERS workers). | 1 per worker (no-pool fallback — half the cores) | EMBED_THREADS=2 |
EMBED_WORKERS | The size of the embedding worker_threads pool = background-indexing parallelism across cores. Each worker holds its own copy of the model (this affects RAM). | max(1, min(cores−2, 4)) | EMBED_WORKERS=8 |
EMBED_QUERY_PREFIX / EMBED_PASSAGE_PREFIX | Prefixes for asymmetric models (e5). For the symmetric bge-m3, leave them unset — otherwise quality drops in ways you won't notice. | unset | EMBED_QUERY_PREFIX="query: " |
EMBED_CPU_MEM_ARENA | on/off. off keeps consumption flat at ~1.9 GB of RAM for bge-m3 — a guard against OOM on a tight, swapless machine (with on the arena can creep up to several GB). | on | EMBED_CPU_MEM_ARENA=off |
GRAPH_BOOST | on/off — a third RRF channel (a graph boost over links, 1-hop wikilink). Inert when VECTOR_SEARCH=off. | off | GRAPH_BOOST=on |
For semantics to work locally you need both: the native stack installed (make deps-vector; the default make deps does not install it, the published image always ships it) and VECTOR_SEARCH=on. If the stack is missing, on falls back to lexical full-text search — without error. More in the Search and Search setup sections.
Backup and restore
The built-in backup, backup verify, and restore commands work with no configuration. The variables below only matter when the container root is mounted read-only or your data is noticeably larger than typical. More in Backup and restore.
| Variable | Purpose | Default | Example |
|---|---|---|---|
NOTARIUM_BACKUP_TMPDIR | The directory for the intermediate files of a backup, a verify, or a restore. Set it if the container root is read-only or /tmp is short on space: a streaming backup may temporarily need room for the archive plus two expanded stages. | /tmp | NOTARIUM_BACKUP_TMPDIR=/mnt/scratch |
NOTARIUM_BACKUP_MAX_BYTES | The size ceiling — for both the compressed input and the expanded payload. A zip-bomb guard; only large, trusted installations raise it. | 64 GiB | NOTARIUM_BACKUP_MAX_BYTES=137438953472 |
NOTARIUM_BACKUP_MAX_ENTRIES | The ceiling on the number of entries in the archive. | 1000000 | NOTARIUM_BACKUP_MAX_ENTRIES=2000000 |
NOTARIUM_BACKUP_MAX_METADATA_BYTES | A separate memory ceiling for names, the ZIP's internal structures, and manifest.json. | 32 MiB | NOTARIUM_BACKUP_MAX_METADATA_BYTES=67108864 |
Docker and build
| Variable | Purpose | Default | Example |
|---|---|---|---|
IMAGE / TAG | The image reference for docker compose / make up. The main install path is the public image docouno/notarium:latest; override the coordinate to use your own registry or a specific tag. | docouno/notarium:latest | IMAGE=docouno/notarium TAG=latest |
GIT_SHA / BUILD_TIME | Build-args; inlined into GET /api/about and the Settings → About tab. Without them — null. | empty | GIT_SHA=$(git rev-parse --short HEAD) |
docouno/notarium:latest is the public image and the main install path; IMAGE / TAG set which image docker compose / make up will pull. If the image hasn't been pulled from the registry yet — build from source in the main repository: make up (the behavior is identical).
See also
- Self-host configuration — installation, volumes, production configuration.
- Search — lexical, semantic, hybrid fusion, and the fallback to full-text search without error.
- Keyboard shortcuts reference — layouts and presets.