Self-hosting
Deploy NoteGen Server with Docker Compose, then configure HTTPS, initialize the instance, connect clients, and maintain it.
NoteGen Server provides accounts, device pairing, realtime sync, team collaboration, and account administration for NoteGen. This guide is for users running an experimental instance on their own Linux server or trusted local network.
NoteGen Server is experimental. Deployment, configuration, and database structures may change. Always keep your local NoteGen Markdown files and never treat an experimental instance as the only copy of important data.
Choose a deployment method
| Method | Best for | Requirements |
|---|---|---|
| Docker Compose (recommended) | Quick trials and personal or small-team instances | Docker Engine and Docker Compose v2 |
| Run from source | Reading the implementation, debugging the protocol, and contributing | Node.js 22+, pnpm 10.20.0, and PostgreSQL 17 |
Use Docker Compose for production-like or long-running experiments. Source mode is primarily for development; do not expose pnpm dev directly as a production service.
Deploy with Docker Compose
The default Compose stack starts NoteGen Server and PostgreSQL 17. Two separate volumes store the database and attachments. The service listens only on 127.0.0.1:3789 on the host by default.
The official image is ghcr.io/codexu/note-gen-server and supports linux/amd64 and linux/arm64. Compose defaults to the latest image published from the release branch, so the server does not need Node.js, pnpm, or a local source build.
1. Prepare the server
Before starting, confirm that:
- Docker Engine and Docker Compose v2 are installed;
- the server can access
ghcr.io; - remote deployments have a domain pointed at the server;
- the firewall exposes only SSH, HTTP, and HTTPS, never PostgreSQL.
2. Download the deployment configuration
git clone https://github.com/codexu/note-gen-server.git
cd note-gen-server
cp .env.docker.example .envcompose.yaml defines the deployment topology. .env contains configuration for this instance. Never commit the real .env file to Git.
3. Configure environment variables
Run this command twice to generate two different random values:
openssl rand -hex 32Edit .env and verify at least these values:
| Variable | Value |
|---|---|
POSTGRES_PASSWORD | The first random value, used only by this PostgreSQL instance |
AUTH_SECRET | The second random value; do not casually rotate it after launch |
PUBLIC_BASE_URL | The exact address used by NoteGen clients, without a path or trailing slash |
SERVER_BIND_ADDRESS | Keep 127.0.0.1 and expose the service through a reverse proxy |
NOTEGEN_SERVER_IMAGE | Defaults to latest; pin a full version such as 0.1.0 for reproducible deployments |
For a local-only trial:
PUBLIC_BASE_URL=http://127.0.0.1:3789Remote deployments must use HTTPS:
PUBLIC_BASE_URL=https://sync.example.com4. Start the services
docker compose pull
docker compose up -d
docker compose psBy default, Compose pulls:
ghcr.io/codexu/note-gen-server:latestOn first startup, the server waits for PostgreSQL and applies pending database migrations. Once both services report healthy, check readiness:
curl --fail http://127.0.0.1:3789/health/readyA successful response means the containers and database can accept requests. If readiness fails, start with Troubleshooting.
5. Configure HTTPS
Remote access requires Caddy, Nginx, or Traefik in front of NoteGen Server. The proxy must support:
- WebSocket Upgrade;
- the
Authorization,Range, andX-Request-Idheaders; - request bodies larger than an attachment part;
- streaming responses from
/v1/sync/eventswithout response buffering.
Minimal Caddy configuration:
sync.example.com {
reverse_proxy 127.0.0.1:3789
}Caddy obtains and renews HTTPS certificates automatically. Continue only after the account page opens at https://sync.example.com.
Set TRUST_PROXY=true only when the proxy and containers are on a trusted network and external traffic cannot bypass the proxy to reach the server port directly.
6. Initialize the instance
Open PUBLIC_BASE_URL in a browser and follow the installer to:
- choose an instance name;
- create the first administrator account;
- sign in to the account portal;
- set registration to disabled, invitation-only, or public.
Public registration increases moderation and maintenance work. Keep personal instances closed and create time-limited invitations when another user needs access.
7. Connect NoteGen
In NoteGen sync settings, select NoteGen Server and enter the exact PUBLIC_BASE_URL, then register or sign in.
Validate the connection in this order:
- create a test note on device A;
- confirm that device B receives it;
- briefly take one device offline and edit the test content on both devices;
- reconnect and confirm sync continues while local Markdown remains available.
See Sync for Git, S3, WebDAV, and cloud-drive options.
Upgrade the instance
The latest image follows releases from the release branch and may still include configuration or database changes. Before upgrading, review repository notes and create a consistent backup of PostgreSQL and attachment data.
cd note-gen-server
git pull --ff-only
docker compose pull
docker compose up -d
docker compose psDatabase migrations run during service startup. Recheck the instance after an upgrade:
curl --fail http://127.0.0.1:3789/health/ready
docker compose logs --tail=200 serverTo pin the current version, replace latest in NOTEGEN_SERVER_IMAGE with a full version tag such as ghcr.io/codexu/note-gen-server:0.1.0. A sha-<commit> tag can also reproduce a specific build for troubleshooting.
Data and backups
The default deployment stores two groups of data:
| Data | Default location |
|---|---|
| Accounts, devices, sync cursors, and object versions | Docker postgres_data volume |
| Attachments, blobs, and server-generated files | Docker notegen_data volume |
A backup must cover PostgreSQL and notegen_data at a consistent point in time, and recovery must be verified in an isolated environment. Backing up only one part is incomplete.
Complete backup and restore tooling is still being developed. Until it is stable, use an externally audited backup process appropriate for your environment and continue keeping local Markdown on every device.
Stop containers while preserving data:
docker compose downDo not run docker compose down -v while the data is needed. -v requests deletion of the Compose-managed volumes.
Routine maintenance
Check container state and recent logs:
docker compose ps
docker compose logs --tail=200 server
docker compose logs --tail=200 postgresFollow server logs:
docker compose logs -f serverCheck readiness and advertised capabilities:
curl --fail http://127.0.0.1:3789/health/ready
curl --fail http://127.0.0.1:3789/v1/capabilitiesRun from source
Source mode is for debugging and contributions. Install Node.js 22 or newer, pnpm 10.20.0, and PostgreSQL 17, then run:
git clone https://github.com/codexu/note-gen-server.git
cd note-gen-server
createuser notegen
createdb -O notegen notegen
pnpm install
cp .env.example .env
pnpm devSet DATABASE_URL, AUTH_SECRET, and PUBLIC_BASE_URL in .env. In development, the API listens on 3789 and the account portal on 3790 by default.
See the contribution guide in the NoteGen Server repository for project structure, change boundaries, and contribution checks.
Troubleshooting
| Symptom | Check and action |
|---|---|
| Image pull fails | Confirm access to ghcr.io, then check proxy and DNS settings |
| PostgreSQL never becomes healthy | Inspect docker compose logs --tail=200 postgres, free disk space, and POSTGRES_PASSWORD |
| Server never becomes healthy | Inspect server logs and confirm PostgreSQL is ready and required .env values are set |
| Browser works but the client cannot connect | Match the client address exactly to PUBLIC_BASE_URL and validate the HTTPS certificate |
| Realtime sync does not trigger | Confirm the reverse proxy supports WebSocket Upgrade |
| Attachment upload returns 413 | Increase the reverse proxy request-body limit |
| Sign-in fails after restart | Confirm AUTH_SECRET was not changed and the server clock is correct |
When opening an issue, include the operating system and CPU architecture, deployment method, image tag, reverse proxy, reproduction steps, and redacted container logs. Never publish .env, tokens, passwords, or recovery keys.
Deployment checklist
POSTGRES_PASSWORDandAUTH_SECRETare different random values;PUBLIC_BASE_URLexactly matches the address used by clients;- public access uses a valid HTTPS certificate;
- PostgreSQL and internal service ports are not directly exposed;
- the reverse proxy supports WebSocket and large attachment requests;
- PostgreSQL and attachment data have a coordinated backup;
- local Markdown is retained and at least one multi-device sync check has passed.