Backup & migration
There is one file
Everything monoki knows lives in monoki.db inside the state directory:
accounts, the shared app catalog, everyone's boards and groups, private
resources, the icon images themselves, and the audit log.
That is the whole reason icons are stored as blobs in SQLite rather than as files on disk — one artifact to back up, with no chance of the database and an image directory drifting out of sync.
/var/lib/monoki/
├── monoki.db
├── monoki.db-wal
└── monoki.db-shm
Backing up
monoki runs SQLite in WAL mode, so copying monoki.db while the server is
running can capture a torn state. Use SQLite's own backup, which is consistent
and does not require stopping anything:
sqlite3 /var/lib/monoki/monoki.db ".backup '/backups/monoki-$(date +%F).db'"
Or stop the service and copy all three files together.
A gzipped backup of a few hundred apps is well under a megabyte, so daily is entirely reasonable:
# /etc/cron.daily/monoki-backup
#!/bin/sh
set -eu
sqlite3 /var/lib/monoki/monoki.db ".backup '/backups/monoki.db.tmp'"
gzip -c /backups/monoki.db.tmp > "/backups/monoki-$(date +%F).db.gz"
rm -f /backups/monoki.db.tmp
find /backups -name 'monoki-*.db.gz' -mtime +30 -delete
Restoring
Stop monoki, put the file back, start it:
systemctl stop monoki
gunzip -c /backups/monoki-2026-08-01.db.gz > /var/lib/monoki/monoki.db
rm -f /var/lib/monoki/monoki.db-wal /var/lib/monoki/monoki.db-shm
systemctl start monoki
Delete the -wal and -shm files: they belong to the database you just
replaced, and leaving them beside a different one is how you get corruption.
Moving to another machine
Copy the binary and the database. Nothing is tied to the host — no machine id, no absolute paths inside the database, no key file living somewhere else.
systemctl stop monoki
scp /var/lib/monoki/monoki.db newhost:/var/lib/monoki/
Upgrading
Replace the binary and restart. Schema migrations run automatically at startup, inside a transaction, and are recorded so they never run twice.
Migrations are forward-only: there is no downgrade path. Take a backup before upgrading, which is the actual rollback.
Upgrading 0.1.0 → 0.2.0
Take a backup before you start — the sqlite3 … ".backup" above, not a bare
cp. In WAL mode most of a busy database can be sitting in monoki.db-wal
rather than in monoki.db, so copying that one file can capture almost nothing.
This migration reshapes the database: bookmarks
become catalog apps, groups become private tags, and bookmarks,
bookmark_icons and group_access are dropped at the end. A failure part-way
rolls the whole thing back untouched, but a success is permanent.
What it does with your data:
- Bookmarks on the same host collapse into one catalog app. The earliest one wins and keeps its icon — or inherits an icon from one of the others if it had none. Two bookmarks added in the same second tie, and which title survives is then arbitrary; both describe the same app, so it is cosmetic.
- A non-default port keeps them apart:
nas.lan:5000andnas.lan:8123stay two apps. - Every group becomes a private tag on its owner's board, with the same items.
- Whoever added a bookmark becomes responsible for the app it became. Remove yourself in one click if you would rather not be.
- People a group was shared with keep those apps, added to their own boards, ungrouped. Sharing itself is gone — see Apps, resources & groups.
- The per-user ordering is approximate where one host appeared in several of your groups. It is always a clean sequence; it may not be the one you remember. One drag fixes it.
Reading the database directly
It is ordinary SQLite, and nothing is encrypted at rest:
sqlite3 /var/lib/monoki/monoki.db \
"SELECT u.username, a.title, a.url
FROM board_items bi
JOIN users u ON u.id = bi.user_id
JOIN apps a ON a.id = bi.app_id
ORDER BY u.username, bi.position;"
That is a convenient way to export your links if you ever want to leave — which is a property worth having, not a gap.