SETUP.md
Rama main · réplica de lectura del repositorio original.
# Nabu Setup
This guide is written for agents.
If a human sends you the Nabu GitHub repo and says "set this up for me," this is the path.
Nabu is a self-hosted, markdown-native knowledge OS for humans and agents.
The app is disposable.
The knowledge is not.
That means your first job is not "get the app running."
Your first job is **put the knowledge on persistent storage and make the app point at it correctly**.
## What Nabu needs
Nabu needs three core runtime inputs for a production deployment:
- `KNOWLEDGE_PATH` — absolute path to the mounted knowledge directory
- `NABU_DATA_PATH` — absolute path to persistent application metadata
- `NABU_PASSWORD` — password required to access the app
Example:
```bash
KNOWLEDGE_PATH=/data/nabu/knowledge
NABU_DATA_PATH=/data/nabu/app-data
NABU_PASSWORD="set-a-real-password-here"
```
For a public native MCP endpoint, also set `NABU_PUBLIC_URL` to the canonical
HTTPS base URL (including any deployment path prefix):
```bash
NABU_PUBLIC_URL=https://nabu.example.com
```
Keep `NABU_DATA_PATH` on persistent storage. It contains lease metadata and
credential hashes, never raw invite, connection-link, or access-token secrets.
After deployment, an owner can open **Settings → Agents**, choose read or
read-write permissions, and generate a one-time connection link for an agent.
The link expires after 10 minutes and exchanges for a credential that expires
after 90 days; the link does not contain that credential.
## Local MCP access
Nabu includes an agent-first MCP server that runs as a local stdio process. The
process can access a directly mounted vault or proxy MCP calls to a deployed
Nabu service. The local process owns the MCP server setup; the browser app does
not need an MCP-specific route.
### Direct vault mode
Use this when the MCP client and the vault are on the same machine. The vault
path must be absolute, outside the Nabu checkout, and already exist unless
`NABU_MCP_CREATE_VAULT=true` is set.
```json
{
"mcpServers": {
"nabu": {
"command": "npm",
"args": ["run", "mcp"],
"env": {
"NABU_MCP_MODE": "direct",
"KNOWLEDGE_PATH": "/data/nabu/knowledge"
}
}
}
}
```
On Windows, use an absolute Windows path in `KNOWLEDGE_PATH` and make sure the
MCP client launches from the Nabu checkout containing `package.json`.
### Remote deployed-Nabu mode
Use this when Nabu is running on a VPS or another host. For a new owner agent,
use the connection link in **Settings → Agents** and set the returned durable
credential as `NABU_AGENT_TOKEN` in the local MCP client. Use HTTPS for
non-loopback URLs.
The legacy setup remains supported: configure the same `NABU_PASSWORD` in the
local MCP client that is set on the deployed service, and the local MCP process
derives the owner bearer credential internally.
```json
{
"mcpServers": {
"nabu": {
"command": "npm",
"args": ["run", "mcp"],
"env": {
"NABU_MCP_MODE": "remote",
"NABU_URL": "https://nabu.example.com",
"NABU_AGENT_TOKEN": "credential-returned-by-owner-connection-link"
}
}
}
}
```
The MCP process exposes traversal, search, note resources, and note
create/update/move/delete operations through stdio. Nabu also exposes the same
surface at `POST /mcp` over stateless Streamable HTTP. Send an issued owner-agent
credential, the password-derived owner bearer, or a scoped shared-space bearer
on every authenticated request:
```http
Authorization: Bearer <owner-agent-or-password-derived-credential>
```
The native endpoint deliberately keeps the agent flow small:
- no `Authorization` header opens a bootstrap surface with only
`redeem_shared_space_invite` and no resources;
- redeem the one-time invite URL, save the returned scoped access token in the
agent's secure credential profile, and reuse it across agents, sessions, and
chats;
- a scoped token can read or write only its shared root until the lease expires
or the owner revokes it; shared-space management remains owner-only;
- MCP redemption accepts an optional `Idempotency-Key`. If omitted, Nabu derives
a stable non-secret key, so agents do not need additional setup.
Configure `NABU_PUBLIC_URL` to the canonical HTTPS base URL in production. The
reverse proxy must preserve the trusted `Host` header and browser `Origin`; use
HTTPS for every non-loopback deployment. The v1 native endpoint uses a fixed
bearer header rather than OAuth. REST and stdio remain supported.
For remote stdio MCP, `NABU_AGENT_TOKEN` is preferred for owner-agent
connections. Existing clients may continue using `NABU_PASSWORD`, which remains
the backwards-compatible fallback.
## The non-negotiables
If you are the agent doing setup, do not screw these up:
1. **The filesystem is the source of truth**
- Notes live on disk as markdown files.
- Do not store the human's real notes inside the git checkout.
2. **`KNOWLEDGE_PATH` must be persistent**
- If using containers, mount a persistent bind mount or persistent volume.
- If using bare metal, point to a durable directory outside the repo.
3. **Back up the knowledge directory**
- This is where the actual notes live.
- The app can be rebuilt. The notes are the thing that matters.
- Recommend periodic archive/export/backup jobs.
4. **Set a real password**
- Never leave `NABU_PASSWORD` set to a placeholder value.
- Use a long random secret.
5. **Do not make the repo directory the vault**
- Bad: `/opt/nabu`
- Good: `/data/nabu/knowledge` or `/srv/nabu/knowledge`
## Questions to resolve before installation
If you do not already know these answers, ask the human:
1. What domain or subdomain should Nabu live on?
- Example: `nabu.example.com`
2. Are we deploying with Docker/container infra, or directly on the server with Node/Bun?
3. Where should persistent knowledge live?
- Recommended: `/data/nabu/knowledge`
4. Is there already an existing markdown vault we should mount?
5. What password should protect the app?
6. Is TLS/HTTPS already handled by a reverse proxy/platform?
7. Do they want backups enabled now or later?
If the environment already makes the answer obvious, resolve it yourself and move on.
Do not ask pointless questions when the platform already dictates the right answer.
## Recommended deployment shape
For most self-hosted installs, use this shape:
- app checkout or image: ephemeral
- knowledge directory: persistent
- application metadata directory: persistent
- reverse proxy: handles HTTPS
- `KNOWLEDGE_PATH`: points at the persistent mounted directory
- `NABU_DATA_PATH`: points at the persistent mounted application-data directory
Recommended paths:
```text
/opt/nabu # app checkout or deployment workspace
/data/nabu/knowledge # persistent markdown vault
/data/nabu/app-data # persistent shared-space metadata
/data/nabu/backups # optional backup output
```
## Container deployment: the right way
If Nabu runs in a container, **mount both the knowledge and application-data directories**.
That mount can be either:
- a bind mount to persistent server storage, or
- a named/persistent container volume
What matters is simple:
**the mounted paths must survive container replacement**
because that is where the real knowledge lives.
### Docker Compose example with bind mount
Use the repo directly and build the image from source:
```yaml
services:
nabu:
build:
context: .
restart: unless-stopped
ports:
- "3000:3000"
environment:
KNOWLEDGE_PATH: /data/nabu/knowledge
NABU_DATA_PATH: /data/nabu/app-data
NABU_PASSWORD: ${NABU_PASSWORD}
volumes:
- /data/nabu/knowledge:/data/nabu/knowledge
- /data/nabu/app-data:/data/nabu/app-data
```
This is good because:
- the host owns the real note storage
- container rebuilds do not wipe the vault
- backups are easy from the host path
### Docker Compose example with a named volume
```yaml
services:
nabu:
build:
context: .
restart: unless-stopped
ports:
- "3000:3000"
environment:
KNOWLEDGE_PATH: /data/nabu/knowledge
NABU_DATA_PATH: /data/nabu/app-data
NABU_PASSWORD: ${NABU_PASSWORD}
volumes:
- nabu_knowledge:/data/nabu/knowledge
- nabu_app_data:/data/nabu/app-data
volumes:
nabu_knowledge:
nabu_app_data:
```
This is acceptable if the platform manages volume persistence correctly.
A plain bind mount is often easier to reason about and back up.
### Docker build + run example
Build the image from the repo:
```bash
docker build -t nabu:local .
```
Then run it with a persistent mount:
```bash
docker run -d \
--name nabu \
--restart unless-stopped \
-p 3000:3000 \
-e KNOWLEDGE_PATH=/data/nabu/knowledge \
-e NABU_DATA_PATH=/data/nabu/app-data \
-e NABU_PASSWORD="set-a-real-password-here" \
-v /data/nabu/knowledge:/data/nabu/knowledge \
-v /data/nabu/app-data:/data/nabu/app-data \
nabu:local
```
### What not to do
Do **not** do this:
```yaml
volumes: []
```
or this:
```bash
KNOWLEDGE_PATH=/app/content
```
when `/app/content` is just container filesystem with no persistent mount behind it.
That is how people lose data and then act surprised.
## Source deployment on a server
If you are deploying from source on a Linux box:
```bash
git clone https://github.com/Timmyy3000/nabu.git /opt/nabu
cd /opt/nabu
npm install
npm run build
```
Then run with environment variables:
```bash
export KNOWLEDGE_PATH=/data/nabu/knowledge
export NABU_DATA_PATH=/data/nabu/app-data
export NABU_PASSWORD="set-a-real-password-here"
node .output/server/index.mjs
```
Create the knowledge directory if needed:
```bash
mkdir -p /data/nabu/knowledge
mkdir -p /data/nabu/app-data
```
## Dokploy / source-build platforms
Nabu already builds fine on source-build platforms.
If the platform supports environment variables and persistent mounts, that is enough.
On Dokploy-like platforms, make sure you configure:
- `KNOWLEDGE_PATH=/data/nabu/knowledge`
- `NABU_DATA_PATH=/data/nabu/app-data`
- `NABU_PASSWORD=<set-a-real-password-here>`
- persistent mounts for `/data/nabu/knowledge` and `/data/nabu/app-data`
- one application replica while metadata is file-backed SQLite
- a post-deploy `GET /api/health` check returning `{ "status": "ok" }`
If the platform builds from repo source, point it at this repo directly.
If the platform expects a Docker image, build and publish the included `Dockerfile` first.
The important bit is not the platform UI.
The important bit is that the runtime path inside the app matches the mounted persistent path.
## Local development setup
For local dev:
```bash
git clone https://github.com/Timmyy3000/nabu.git
cd nabu
cp .env.example .env
# edit .env before starting the app
npm install
```
Then set real values in `.env`:
```bash
KNOWLEDGE_PATH=/absolute/path/to/local/knowledge
NABU_PASSWORD=set-a-real-password-here
```
Then start the app:
```bash
npm run dev
```
You can also use Bun:
```bash
bun install
bun run dev
```
## Existing vault migration
If the human already has markdown notes:
1. Put the vault on persistent storage
2. Point `KNOWLEDGE_PATH` at that directory
3. Make sure file permissions allow the app to read it
4. If Nabu will write notes/folders, make sure the app user can write there too
Good example:
```bash
/data/nabu/knowledge
```
If migrating from Obsidian or a plain markdown repo, do **not** copy the notes into the Nabu app repo.
Mount or place them as a separate vault directory.
## Reverse proxy and HTTPS
If exposed publicly, put Nabu behind HTTPS.
Typical reverse proxy targets:
- Nginx
- Caddy
- Traefik
- Dokploy-managed ingress
Nabu itself just needs the app reachable.
The exact proxy is not sacred.
What matters:
- HTTPS enabled
- app forwarded correctly
- long random password set
## Backups
Back up the knowledge and application metadata directories, not just the app.
Minimum sane backup target:
```text
/data/nabu/knowledge
/data/nabu/app-data
```
Recommended backup habits:
- daily snapshot or archive
- occasional off-server copy
- test restore at least once
Example simple archive job:
```bash
tar -czf /data/nabu/backups/nabu-knowledge-$(date +%F).tar.gz /data/nabu/knowledge
```
If the human cares about their notes, this is not optional forever.
## Verification checklist after install
Before calling setup complete, verify all of this:
- app loads
- login works with `NABU_PASSWORD`
- a note in `KNOWLEDGE_PATH` appears in the UI
- creating or editing a note writes back to the mounted knowledge directory
- container/server restart does not lose notes
- mounted path is actually persistent
- `/api/health` reports storage readiness
- a shared-space invite, scoped access token, and read-link metadata survive an app restart
- `/agents.md` is reachable after auth
## Agent handoff checklist
If you are the agent finishing setup, leave the human with:
- live URL
- where the knowledge is stored
- how to change the password
- how to back up the vault
- whether writes are enabled and tested
- whether the deployment is source-based or container-based
## One-paragraph instruction a human can send to an agent
```text
Set up Nabu for me from this repo: https://github.com/Timmyy3000/nabu
Use a persistent knowledge directory outside the repo, mount it correctly if using containers, set a real NABU_PASSWORD, and verify that notes survive restarts. If anything about domain, hosting style, or storage location is unclear, ask me only the minimum necessary questions.
```
## Short version
If you remember only one thing, remember this:
**Nabu is easy to redeploy. The vault is not. Mount persistent storage correctly or you are doing a fake setup.**