Trilium Notes Self-Hosted Installation

Trilium Notes is a hierarchical note-taking application designed for building a large personal knowledge base, featuring a tree-structured note organization, rich text and markdown editing, scripting with JavaScript, and end-to-end encrypted desktop sync. Self-hosting Trilium on a Linux server lets you access your entire knowledge base from any browser while keeping all notes on your own infrastructure.

Prerequisites

  • Ubuntu 20.04+, Debian 11+, or CentOS/Rocky 8+
  • Docker and Docker Compose, or Node.js 18+
  • Root or sudo access
  • A domain name for HTTPS access (recommended for desktop sync)

Installing Trilium Server

Method 1: Docker (recommended):

# Create Trilium directory
sudo mkdir -p /opt/trilium/data

# Create docker-compose.yml
sudo tee /opt/trilium/docker-compose.yml <<'EOF'
version: '3.8'

services:
  trilium:
    image: zadam/trilium:latest
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - /opt/trilium/data:/home/node/trilium-data
    environment:
      - TRILIUM_DATA_DIR=/home/node/trilium-data
EOF

cd /opt/trilium
sudo docker compose up -d

# Monitor startup
sudo docker compose logs trilium

Method 2: Binary installation:

# Download the latest server release
TRILIUM_VERSION="0.63.7"
curl -LO "https://github.com/zadam/trilium/releases/download/v${TRILIUM_VERSION}/trilium-linux-x64-server-${TRILIUM_VERSION}.tar.xz"

# Extract
sudo mkdir -p /opt/trilium-app
sudo tar -xf trilium-linux-x64-server-${TRILIUM_VERSION}.tar.xz \
  -C /opt/trilium-app --strip-components=1

# Create systemd service
sudo useradd -r -m -d /opt/trilium-data -s /bin/false trilium

sudo tee /etc/systemd/system/trilium.service <<'EOF'
[Unit]
Description=Trilium Notes Server
After=network.target

[Service]
User=trilium
WorkingDirectory=/opt/trilium-app
ExecStart=/opt/trilium-app/trilium.sh
Restart=always
RestartSec=5
Environment=TRILIUM_DATA_DIR=/opt/trilium-data

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now trilium

Access Trilium at http://your-server:8080.

Initial Setup

First launch wizard:

  1. Navigate to http://your-server:8080
  2. Set up a new document or sync from existing desktop app
  3. Create an admin password (this encrypts the database)
  4. Wait for Trilium to initialize the demo notes

Nginx reverse proxy:

# /etc/nginx/sites-available/trilium
server {
    listen 80;
    server_name notes.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    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;

    # Allow larger note content
    client_max_body_size 50M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
sudo ln -s /etc/nginx/sites-available/trilium /etc/nginx/sites-enabled/
sudo certbot --nginx -d notes.example.com
sudo systemctl reload nginx

Desktop Sync Configuration

Trilium Desktop (available for Windows, macOS, Linux) can sync with your server:

Download the desktop app:

# Linux desktop installation
TRILIUM_VERSION="0.63.7"
curl -LO "https://github.com/zadam/trilium/releases/download/v${TRILIUM_VERSION}/trilium-linux-x64-${TRILIUM_VERSION}.tar.xz"
tar -xf trilium-linux-x64-${TRILIUM_VERSION}.tar.xz
cd trilium-linux-x64
./trilium

Configure sync in the desktop app:

  1. Open Trilium Desktop
  2. If no notes exist: Options > Sync > Sync Server
  3. Set Server address: https://notes.example.com
  4. Click Test connection
  5. On success, click Set up sync — all notes from the server are downloaded

Enable sync on the server (required for desktop sync):

The server's sync is enabled by default. Verify in config.ini:

sudo cat /opt/trilium/data/config.ini
# Look for:
# [Network]
# host=0.0.0.0
# port=8080

Markdown Editing and Formatting

Trilium supports multiple note types:

Note types:

  • Text: Rich text editor (default, supports formatting)
  • Code: Syntax-highlighted code notes (select language)
  • Markdown: Pure Markdown with live preview
  • Canvas: Freehand drawing
  • Web View: Embed external URLs
  • Relation Map: Visual relationship diagrams

Use Markdown for notes:

  1. Create a new note
  2. Right-click the note title → Note type > Markdown
  3. Write in standard Markdown syntax

Useful keyboard shortcuts:

Ctrl+E              Edit/view toggle (in text notes)
Ctrl+Enter          Create a new child note
Ctrl+Backspace      Delete note
Alt+Home            Navigate to root note
Ctrl+F              Search notes
Ctrl+Shift+F        Full-text search
Ctrl+L              Insert link to another note

Scripting and Automation

Trilium supports JavaScript scripting directly in notes for automation:

Create a script note:

  1. Create a new note
  2. Change note type to Code > JavaScript backend or JavaScript frontend
  3. Write your script

Example: Create a daily journal note automatically:

// Script type: JavaScript backend
// Run on: server startup, or manually

const dateNote = await api.createNewNote({
  parentNoteId: "root",
  title: new Date().toISOString().split("T")[0],
  content: "## Daily Journal\n\n### Tasks\n\n### Notes\n",
  type: "text",
});

// Add a label to the created note
await api.toggleNoteLabel(dateNote.noteId, "journal");

Example: Auto-tag notes by content:

// Script type: JavaScript backend
// Trigger: note created event

const note = await api.getNote(api.originEntity.noteId);
const content = await note.getContent();

if (content.includes("TODO")) {
  await api.addLabel(note.noteId, "todo");
}

Scheduled script execution:

// Add a #interval:daily label to the note to run it daily
// Or #run:always to run on every startup

Web Clipper

The Trilium Web Clipper browser extension saves web content directly to your notes:

Install the extension:

Configure the extension:

  1. Click the extension icon → Settings
  2. Set Trilium server URL: https://notes.example.com
  3. Set Password: your Trilium password
  4. Test connection and confirm

Clip web content:

  • Full page: Saves entire page as a note
  • Selection: Saves selected text only
  • Screenshot: Saves a screenshot of the current view

Backup Configuration

# Trilium automatically creates backups in the data directory
ls /opt/trilium/data/backup/
# trilium-2024-01-15.db
# trilium-2024-01-14.db

# Configure backup retention in Options > Backup
# Default: keeps last 10 backups

Manual database backup:

# Stop Trilium for a consistent backup
sudo docker compose stop trilium

# Copy the database file
sudo cp /opt/trilium/data/document.db \
  /backup/trilium-$(date +%Y%m%d).db

sudo docker compose start trilium

Automated backup script:

sudo tee /opt/trilium/backup.sh <<'EOF'
#!/bin/bash
BACKUP_DIR="/backup/trilium"
mkdir -p "$BACKUP_DIR"

# Create a compressed backup without stopping the server
# SQLite WAL mode allows safe reads while writing
cp /opt/trilium/data/document.db "${BACKUP_DIR}/trilium-$(date +%Y%m%d).db"
gzip "${BACKUP_DIR}/trilium-$(date +%Y%m%d).db"

# Keep only last 30 backups
find "$BACKUP_DIR" -name "trilium-*.db.gz" -mtime +30 -delete
EOF

chmod +x /opt/trilium/backup.sh

# Schedule daily backup at 2 AM
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/trilium/backup.sh") | crontab -

Troubleshooting

Desktop sync fails with "Cannot connect to server":

# Verify server is accessible
curl -I https://notes.example.com/api/app-info

# Check Trilium is running
sudo docker compose ps
sudo docker compose logs trilium -n 20

# Verify SSL certificate is valid
curl -v https://notes.example.com 2>&1 | grep -i "SSL\|TLS\|certificate"

Notes not loading (blank page or spinning):

# Check server logs for JavaScript errors
sudo docker compose logs trilium | grep -i error

# Clear browser cache and reload
# Or try incognito mode to rule out extension conflicts

# Check database integrity
sudo docker compose exec trilium \
  sqlite3 /home/node/trilium-data/document.db "PRAGMA integrity_check;"

Database corruption recovery:

# Stop Trilium
sudo docker compose stop trilium

# Check integrity
sqlite3 /opt/trilium/data/document.db "PRAGMA integrity_check;"

# Restore from latest backup
sudo cp /opt/trilium/data/backup/trilium-YYYYMMDD.db \
  /opt/trilium/data/document.db

sudo docker compose start trilium

Conclusion

Trilium Notes provides a powerful hierarchical knowledge base platform with scripting, encrypted sync, and web clipping capabilities that scale from simple note-taking to complex personal information management systems. The combination of self-hosted server sync, JavaScript automation, and flexible note types makes it particularly valuable for developers and power users who need a programmable, private alternative to Notion or Roam Research.