Self-Host openvlt

Get openvlt running on your own hardware in minutes. Your notes stay on your machine as plain markdown files — no cloud, no third parties, no subscriptions.

Quick Install

The fastest way to get started. Works on macOS and Linux. This script installs all dependencies, builds the app, and starts the server.

terminal
curl -fsSL https://openvlt.com/install.sh | bash

The install script will:

  • Install Node.js 20+ and bun (if not present)
  • Clone the repository to ~/.openvlt/app/
  • Build the application
  • Start the server on port 3456 via pm2
  • Set up the openvlt CLI command

Once complete, open http://localhost:3456 to create your account.

Docker

Recommended for VPS and server deployments. The Docker image uses a multi-stage build with node:22-alpine and runs as a non-root user.

docker-compose.yml
services:
  openvlt:
    build: .
    ports:
      - "${OPENVLT_PORT:-3456}:3456"
    volumes:
      - ./data:/app/data
    environment:
      - NODE_ENV=production
    restart: unless-stopped
terminal
# Clone and start
git clone https://github.com/ericvaish/openvlt.git
cd openvlt
docker compose up -d

# Or build and run manually
docker build -t openvlt .
docker run -d -p 3456:3456 -v openvlt_data:/app/data openvlt

The ./data volume is critical — it contains your vault files and database. Mount it to persist data across container restarts.

Manual Setup

For full control over the setup. Requires Node.js 20+ and bun.

terminal
git clone https://github.com/ericvaish/openvlt.git
cd openvlt
bun install
bun run build
bun run start

The server starts on port 3456 by default. Set the PORT environment variable to change it. For production, use a process manager like pm2 to handle restarts.

terminal (pm2)
# Install pm2
bun add -g pm2

# Start with pm2
PORT=3456 pm2 start node -- .next/standalone/server.js
pm2 save

CLI Commands

If you used the quick install script, the openvlt CLI is available globally.

commands
openvlt start              # Start the server (default port 3456)
openvlt start 8080         # Start on a custom port
openvlt stop               # Stop the server
openvlt restart            # Restart the server
openvlt status             # Show status and check for updates
openvlt update             # Pull latest version, rebuild, restart
openvlt logs               # Show recent logs
openvlt logs -f            # Follow logs in real-time
openvlt uninstall          # Remove openvlt (keeps your data)

Configuration

openvlt is configured via environment variables. All settings have sensible defaults — no configuration file is required.

VariableDefaultDescription
PORT3456Server listening port
HOSTNAME0.0.0.0Bind address
OPENVLT_DB_PATHdata/.openvlt/openvlt.dbSQLite database file path
WEBAUTHN_ORIGINhttp://localhost:3456WebAuthn origin (must match your domain)
WEBAUTHN_RP_IDlocalhostWebAuthn relying party ID (your domain)
NODE_ENVproductionSet to production for deployments

For WebAuthn (biometric login) to work in production, set WEBAUTHN_ORIGIN to your full URL (e.g. https://notes.example.com) and WEBAUTHN_RP_ID to your domain (e.g. notes.example.com).

Directory Structure

All user data lives in the data/ directory. Notes are plain markdown files — you can browse, edit, and back them up with standard tools.

data/
├── vault/
│   └── {userId}/            # Each user gets an isolated directory
│       ├── notes/
│       │   ├── meeting.md   # Plain markdown files
│       │   └── ideas.md
│       └── attachments/
│           └── image.png
└── .openvlt/
    └── openvlt.db           # SQLite metadata & search index

Important: The markdown files on disk are always the source of truth. SQLite stores metadata, search indexes, and sync state only — never note content.

Database

openvlt uses SQLite in WAL mode with FTS5 for full-text search. The database is created and migrated automatically on first start — no manual setup required.

  • Schema is created automatically on first run
  • Migrations run automatically on startup
  • Default location: data/.openvlt/openvlt.db
  • Override with OPENVLT_DB_PATH env variable

Security

openvlt is designed for self-hosting with strong security defaults.

User Isolation

Each user's files are scoped to data/vault/{userId}/. The service layer enforces directory boundaries — users cannot access each other's files through the API.

Authentication

Passwords hashed with bcrypt. Optional WebAuthn for biometric login (Touch ID, Face ID, Windows Hello). 24-word recovery key generated at registration. Sessions stored as httpOnly cookies with signed tokens.

End-to-End Encryption

Lock sensitive notes with AES-256-GCM. The encryption key is derived from your lock password via PBKDF2 (100,000 iterations) and never leaves the browser.

Docker

The Docker container runs as a non-root user (UID 1001) with minimal permissions.

Reverse Proxy

For production, put openvlt behind a reverse proxy with HTTPS. Here are example configurations.

Caddy (recommended — automatic HTTPS)
notes.example.com {
    reverse_proxy localhost:3456
}
nginx
server {
    listen 443 ssl http2;
    server_name notes.example.com;

    ssl_certificate     /etc/letsencrypt/live/notes.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/notes.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3456;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket support (for HMR in dev, optional in prod)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Remember to set WEBAUTHN_ORIGIN and WEBAUTHN_RP_ID to match your domain when using a reverse proxy.

Backups

Since notes are plain files, backing up is straightforward. Back up two things:

terminal
# Back up everything
rsync -av data/ /path/to/backup/

# Or just the essentials
cp data/.openvlt/openvlt.db /path/to/backup/
rsync -av data/vault/ /path/to/backup/vault/

You can also use git, Syncthing, or any file sync tool on the data/vault/ directory since it's just markdown files.

Updating

If you used the quick install script:

terminal
openvlt update

For Docker:

terminal
git pull
docker compose up -d --build

For manual installs:

terminal
git pull
bun install
bun run build
bun run start  # or: pm2 restart openvlt

Database migrations run automatically on startup — no manual migration step needed.