- π Notes & Checklists - Create notes with rich text and interactive checklists
- π·οΈ Labels - Organize notes with customizable labels
- π Pin & Archive - Pin important notes, archive completed ones
- π Version History - Store file versions and restore/rollback to previous states
- π¨ Color Coding - 11 beautiful colors to categorize your notes
- π Secure Authentication - Local login or OIDC (Authentik, Authelia, PocketID, etc.)
- π End-to-End Encryption - Your notes are encrypted with a 24-word recovery phrase. Zero-knowledge - not even the server admin can read your data.
- π₯ Multi-user & Admin Panel - User management with admin/user roles
- π± Responsive Design - Works beautifully on desktop and mobile
- π² PWA Support - Install as a native app on your device
- π Offline Sync - Continue working without internet connection
- π½ Sorting Options - Sort notes by date or alphabetical order
# Clone and start
git clone https://github.com/bigtcze/noteer.git
cd noteer
# Edit environment variables in docker-compose.yaml
docker compose up -dOpen http://localhost:3000 and login with your admin credentials.
services:
postgres:
image: postgres:17
restart: unless-stopped
volumes:
- noteer-db:/var/lib/postgresql/data
environment:
POSTGRES_USER: noteer
POSTGRES_PASSWORD: noteer
POSTGRES_DB: noteer
healthcheck:
test: ["CMD-SHELL", "pg_isready -U noteer"]
interval: 5s
timeout: 5s
retries: 5
noteer:
image: ghcr.io/bigtcze/noteer:latest
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
ports:
- "3000:3000"
volumes:
- noteer-data:/var/lib/noteer
environment:
DB_HOST: postgres
DB_PORT: 5432
DB_NAME: noteer
DB_USER: noteer
DB_PASSWORD: noteer
ADMIN_EMAIL: admin@example.com
ADMIN_PASSWORD: your-secure-password
REGISTRATION_ENABLED: "true"
# APP_URL: "https://noteer.example.com" # Required in production!
# ALLOWED_HOSTS: "localhost,127.0.0.1" # Whitelist for non-prod
volumes:
noteer-db:
noteer-data:| Variable | Default | Description |
|---|---|---|
DB_HOST |
localhost |
PostgreSQL host |
DB_PORT |
5432 |
PostgreSQL port |
DB_NAME |
noteer |
Database name |
DB_USER |
noteer |
Database user |
DB_PASSWORD |
noteer |
Database password |
PORT |
3000 |
Application port |
ADMIN_EMAIL |
admin@example.com |
Admin user email |
ADMIN_PASSWORD |
changeme |
Admin user password |
REGISTRATION_ENABLED |
true |
Allow new user registration |
LOG_LEVEL |
warn |
Log level: error, warn, info, debug |
TRUST_PROXY |
1 |
Proxy trust config: number (hops) or CIDR |
SSL_ENABLED |
false |
Enable direct HTTPS |
SSL_CERT_PATH |
- | Path to SSL certificate |
SSL_KEY_PATH |
- | Path to SSL key |
APP_URL |
- | Public application URL (Required in production) |
ALLOWED_HOSTS |
- | Allowed hosts whitelist (e.g. localhost,10.0.0.1) for non-prod |
JWT_SECRET |
- | JWT secret (optional) |
NOTEER_INSTANCE_ENCRYPTION |
true |
Enable E2E encryption (see below) |
Noteer supports two encryption modes, configured at first startup via NOTEER_INSTANCE_ENCRYPTION:
| Mode | Value | Description |
|---|---|---|
| Encrypted (default) | true |
Full E2E encryption. Users must set up a 24-word recovery phrase. Notes, images, and labels are encrypted client-side. Zero-knowledge architecture. |
| Unencrypted | false |
No encryption. Simpler setup, no recovery phrase needed. Data stored in plaintext. |
IMPORTANT: This setting is immutable after first initialization. Once the instance starts, the value is stored in the database and cannot be changed. The environment variable is ignored on subsequent starts.
Example (unencrypted instance):
environment:
NOTEER_INSTANCE_ENCRYPTION: "false"Noteer supports OpenID Connect (OIDC) for single sign-on with providers like Authentik, Authelia, Keycloak, and more. You must configure it via Environment Variables.
| Variable | Description |
|---|---|
OIDC_ISSUER_URL |
OIDC Issuer URL (e.g., https://auth.example.com) |
OIDC_CLIENT_ID |
Client ID |
OIDC_CLIENT_SECRET |
Client Secret |
OIDC_ONLY |
Set to true to force SSO and disable password login (default: false) |
Callback URL for your Identity Provider:
[YOUR_APP_URL]/api/auth/callback
Examples:
- Local:
http://localhost:3000/api/auth/callback - Production:
https://notes.example.com/api/auth/callback
Traefik
labels:
- "traefik.enable=true"
- "traefik.http.routers.noteer.rule=Host(`notes.example.com`)"
- "traefik.http.routers.noteer.entrypoints=websecure"
- "traefik.http.routers.noteer.tls.certresolver=letsencrypt"
- "traefik.http.services.noteer.loadbalancer.server.port=3000"Nginx Proxy Manager
- Add new proxy host
- Domain:
notes.example.com - Forward Hostname:
noteer(container name) - Forward Port:
3000 - Enable SSL with Let's Encrypt
Caddy
notes.example.com {
reverse_proxy noteer:3000
}- π€ Android app (native)
- πΎ System Backup: Scheduled full system backup to filesystem
- π Reminders & notifications
- π Advanced search with filters
- π Duplicate note
- π¦ Export All (User Profile): Export all notes as PDF, CSV
- π€ Export (Markdown, PDF)
- Node.js 20+
- PostgreSQL 16+ (or use Docker)
To build the image locally:
git clone https://github.com/bigtcze/noteer.git
cd noteer
docker build -t noteer:local -f docker/Dockerfile .Prerequisites:
- Node.js 20+
- PostgreSQL 16+ (running locally or in Docker)
- Git
Backend Setup:
cd backend
npm install
cp ../docker/.env.example .env
npm run devFrontend Setup:
cd frontend
npm install
npm run devE2E Tests (Playwright):
# Run quick tests (Chromium only)
npm test
# Run full test suite (All browsers)
npm run test:full
# Run tests in debug mode
npm run test:debugBackend Tests:
cd backend
npm testLinting:
# Run all lint checks (Backend + Frontend)
npm run lint
# Run backend lint only
npm run lint:backend
# Run frontend lint only
npm run lint:frontendFrontend Tests:
cd frontend
npm testThank you to all our contributors!
- @RohitChavan16 - Integration tests for Notes API
Apache License 2.0 - see LICENSE for details.
Made with β€οΈ for the self-hosted community
