---
title: "Authentication"
description: "The password and none modes, server-side sessions, invites and resets, and admin recovery through the CLI."
---

# Authentication

Authentication in Notarium is built in and runs entirely on the metadata database — no external IdP, no JWT, no SMTP. The mode is chosen by the `AUTH_MODE` variable and decides whether there's a login at all.

## The `password` mode (default)

Secure by default: full multi-user authentication.

- **First run.** On a clean instance, the first visitor creates the owner through the first-run setup screen (host-admin plus owner of the configured spaces). There's no preset password; once that account is registered, setup closes for good.
- **Sessions.** A login creates a **server-side session** — a row in the database, not a JWT. It lives in the HttpOnly `nt_session` cookie with a sliding 30-day TTL and the `Secure` flag behind HTTPS. Revocation is instant: disabling a user or changing a password tears down live sessions immediately.
- **A metadata database is required.** It's there by default — SQLite under `DATA_DIR`, nothing to configure. You only touch `META_DB_URL` to move to an external Postgres. See [Database](/docs/self-hosting/database/).

## The `none` mode

A single all-access principal — the operator turns this mode on deliberately, for the desktop, local development, or a trusted intranet. Auth routes return `404`, there is no login UI, and no metadata database is needed for auth.

> [!danger] Don't expose a `none` instance to the network
> In `none` mode, anyone who can reach the port gets full access to all data — including the agents' MCP endpoint. Use it only on an isolated or trusted network.

## Roles and access

Access to data is granted by space membership, and there are three roles:

| Role | Permissions |
|---|---|
| `reader` | Reads everything in the space. |
| `writer` | Edits notes. |
| `owner` | Manages the membership. |

The **host-admin** flag grants control over users and spaces, but to **read the data** of a specific space you still need membership in it. More on the model — [Access Model](/docs/concepts/access-model/).

## Invites and password resets

There's no SMTP in Notarium — the initial handoff of an account is a **one-time link** the administrator passes along by hand. One mechanism, two purposes:

- **Invite** — adds a user with no password; the link lives for 7 days.
- **Password reset** — the link lives for 24 hours; accepting it ends old sessions.

The token rides in the URL fragment (`/invite#<token>`), so it never lands in access logs. A user has only one such link active at a time, and the administrator never knows anyone else's password.

## Tokens for agents

AI agents authenticate with a personal access token (PAT) of the form `Authorization: Bearer ntp_…`, with a `read` or `write` scope, optionally narrowed to specific spaces. The secret is shown **exactly once**. Issuing tokens and other management actions are available only within a session — a leaked PAT can't escalate. Details — [Connect an agent](/docs/agents/connect/) and [Security and visibility](/docs/agents/security/).

## Recovering access

Since only the administrator issues a reset link, losing the only admin's password would mean losing access. The way out is the **admin CLI**, working directly against the metadata database. It's one of the image's built-in commands, so the call is short and goes straight into the running container:

```bash
docker compose exec notarium admin create-admin <user> --random

# for a bare docker run:
docker exec -it notarium admin create-admin <user> --random
```

There's no need to stop the server: SQLite in WAL mode tolerates a second writer, and Postgres all the more so. The CLI locates the metadata database on its own, by the same logic the server uses (`META_DB_URL`, or the root derived from `DATA_DIR`); on a wrong path it exits with an error rather than silently creating an empty database where "there are no users."

Available commands:

| Command | Action |
|---|---|
| `list` | Lists users. |
| `passwd <user> [--password <pw> \| --random]` | Changes a password. |
| `create-admin <user> [--random] [--display "Name"]` | Creates an administrator. |
| `grant <user> <space> <owner\|writer\|reader>` | Grants a role in a space. |

Without a flag, the password is read from stdin with echo suppressed, so it never lands in command history. `setPassword`/`createAdmin` are available **only from the CLI** — there's no HTTP path for them: this is the host's operator boundary. The image's other commands are covered on the [Image CLI](/docs/self-hosting/cli/) page.
