Docker · Linux · NAS

Deploy & configure

One binary with the frontend and SQLite built in. Get Diarum running on your server, NAS or laptop in five minutes.

Try it first

Not ready to deploy? Open the live demo and sign in with demo / demo@1234 to try every feature. The demo is public and reset from time to time, so please don’t write anything real there.

The official image songtianlun/diarum is built for linux/amd64 and linux/arm64, so it runs on a Raspberry Pi, Synology, QNAP and other ARM devices too.

docker run -d \
  --name diarum \
  -p 8090:8090 \
  -v /path/to/your/data:/app/data \
  -e TZ=Europe/London \
  --restart unless-stopped \
  songtianlun/diarum:latest

Then open http://your-server:8090.

Always mount the data directory. /app/data holds the database, images, audit logs — everything. Without a volume, removing the container removes your diary.

Tags: latest always points at the newest release, and every release also has its own tag (such as v0.9.9) when you want to pin a version.

Docker Compose

Create docker-compose.yml:

services:
  diarum:
    image: songtianlun/diarum:latest
    container_name: diarum
    ports:
      - "8090:8090"
    volumes:
      - ./data:/app/data
    environment:
      - DIARUM_DATA_PATH=/app/data
      - TZ=Europe/London
    restart: unless-stopped

Start it:

docker compose up -d

First run

  1. Open the page and register. The first account becomes the administrator; everyone after it is a regular user;
  2. After signing in you land on today’s entry — start writing;
  3. Visit Settings for language and visual style, the AI assistant, image storage, automatic backups, the API and MCP;
  4. Administrators can open /admin for the system overview, user management, audit log archiving and visitor statistics.

HTTPS and a domain

Put Diarum behind a reverse proxy with HTTPS. Installing the PWA and clipboard access need a secure context, and MCP clients work best with an HTTPS URL.

Caddy (automatic certificates):

diary.example.com {
    reverse_proxy 127.0.0.1:8090
}

Nginx:

server {
    listen 443 ssl http2;
    server_name diary.example.com;
    # ssl_certificate / ssl_certificate_key ...

    client_max_body_size 200m;   # large photos, Live Photo videos and import archives

    location / {
        proxy_pass http://127.0.0.1:8090;
        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_buffering off;     # the AI assistant streams its replies
    }
}

Configuration

Setting Description
--data-dir / DIARUM_DATA_PATH Data directory. Priority: flag > environment variable > default (./diarum_data for the binary, /app/data in the Docker image)
--http Listen address, :8090 by default; e.g. --http=127.0.0.1:8090 to listen locally only
TZ Time zone for scheduled jobs such as backups and log cleanup

Everything else — AI, image storage, backups, API, auditing — is configured in the web interface and stored per user. No config files to edit.

What is in the data directory

data/
├── diarum.db              # main SQLite database: users, entries, versions, settings, AI conversations…
├── storage/               # locally stored images and their thumbnails
├── logs/system-audit/     # system audit log, one JSON Lines file per day
└── visits/visits.db       # visitor statistics (when enabled), a separate SQLite file

Moving or cold backups: stop the server and copy the whole directory. For everyday backups, turn on automatic backups to S3 in Settings → Data management.

When upgrading from an old release, a legacy data.db without a diarum.db is migrated automatically at startup, leaving the old file untouched.

Upgrading

docker compose pull && docker compose up -d
# or
docker pull songtianlun/diarum:latest && docker rm -f diarum && docker run ... (as above)

The database schema migrates itself on startup. Taking a backup first is a good habit. See Releases for what changed in each version.

Managing users from the command line

diarum users list                    # users and roles
diarum users list --json
diarum users set-role alice admin    # <user>: username, email or ID; <role>: user or admin

# Inside Docker
docker exec -it diarum /app/diarum users list
docker exec -it diarum /app/diarum users set-role alice admin

This works while the server is running; role changes apply immediately and are audited. Handy if you forget which account is the admin.

Building from source

You need Go 1.23+ and Node.js 20+:

git clone https://github.com/songtianlun/diarum.git
cd diarum
make build          # builds the frontend, then embeds it in the Go binary
./diarum serve      # listens on :8090, stores data in ./diarum_data

For development, make dev-frontend and make dev-backend run each side, and make test runs the tests.

Getting help