Guides
Running the server
Once it's set up, the server mostly looks after itself. This page covers the things you'll do now and then: updating, backups, tokens, undoing a publish and putting Cloudflare in front.
All commands below are run on the server, in the folder with docker-compose.yml (~/kvist in Getting started).
Updating
docker compose pull
docker compose up -d
This fetches the newest kvist image (and Caddy's, if you use the Caddy setup) and restarts what changed. Your published site and settings are kept.
Update the server first, then the plugin. A newer plugin may send things an older server doesn't understand yet, and publishing fails until the server catches up. The plugin and the server also check each other's protocol version and tell you if one is too old.
Every build of kvist is also published with its own tag, ghcr.io/klppl/kvist:sha-<commit>. To stay on a known version, put that tag in docker-compose.yml instead of latest; to go back after a bad update, put the previous one there and run docker compose up -d.
Changing the settings
The site's title, menu and look are set in the settings note in your vault, which needs no restart. kvist.toml holds the rest, and kvist reads it when it starts. After editing it:
docker compose restart kvist
Then publish from Obsidian, so the site is rebuilt with the new settings. If the file has a mistake, kvist doesn't start; docker compose logs kvist says what's wrong.
Tokens
docker compose exec kvist kvist token create --name phone
docker compose exec kvist kvist token list
docker compose exec kvist kvist token revoke 3f9a1c2e
--name is a label that token list shows; without it, the token is named after today's date. A server with several sites also needs --site with the site's id. Use one token per device. If a device is lost, revoke its token (by the id from token list); the others keep working. Changes take effect immediately, without a restart. Anyone with a token can replace your site, so treat it like a password.
Undoing a publish
The server keeps the last 10 versions (revisions) of each site. The log names the revision each publish created:
docker compose logs kvist | grep commit
Make an earlier one live again:
docker compose exec kvist kvist rollback garden r000041
If you give an id that's no longer kept, kvist lists the ones that are. A rollback is undone by the next publish from your vault, so fix the vault first (or turn off automatic publishing for a while).
Starting over or removing a site
To put a different vault on a site, publish from the new vault with the site's token. Each publish replaces the whole site, so the old notes are gone from it at once; they stay in the stored history until they age out (see disk use).
To remove a site completely, first delete its [[site]] block from kvist.toml and restart, so kvist stops serving it. Then delete its stored data and tokens:
docker compose restart kvist
docker compose exec kvist kvist site list
docker compose exec kvist kvist site delete garden
site list shows each site with its stored data and tokens, including sites that are no longer in kvist.toml. site delete asks you to type the site's id before it deletes anything, and refuses a site that's still in kvist.toml. To start a site over from nothing under the same id, delete it this way, then add its block back and restart.
When a vault moves to another site, or its site was started over, press Reset settings at the bottom of the plugin's settings on each device, then enter the site and a new token. This makes the plugin forget the old site's history, so the first publish isn't stopped as “newer content on the server”.
Backups
Everything kvist stores is in the kvist-data Docker volume: what you published, the built site, the token fingerprints and the old addresses of moved notes. Your vault is the real original, so losing the server only means setting it up again and publishing; only the redirects from old addresses would start over. To keep a copy anyway:
docker run --rm -v kvist_kvist-data:/data -v "$PWD":/backup alpine \
tar czf /backup/kvist-data.tar.gz -C /data .
The volume's name starts with the folder name; check it with docker volume ls.
Disk use and history
Unpublished notes vanish from the site immediately, but stay on the server's disk inside older revisions until they age out. That's what makes rollbacks possible. Change how much history is kept in kvist.toml:
[site.retention]
revisions = 10 # versions of your notes kept for rollback
builds = 3 # built copies of the site
Set both to 1 to keep as little as possible. Unchanged files are shared between builds, so history costs little space. Old uploads are cleaned up automatically.
Logs
docker compose logs -f kvist
Every publish (commit), build and error is logged, with the device name that published.
Cloudflare
kvist works behind Cloudflare's proxy (the orange cloud). Set it up like this:
- SSL/TLS mode: Full (strict). Your server already has a valid certificate, from Caddy or your own proxy.
- Caching: leave Cloudflare's cache on “respect existing headers”. kvist tells it to keep pages for 60 seconds and images and styles for a year (their addresses change when they change). Don't add a “cache everything” rule with a long edge lifetime, or unpublished pages stay visible until it expires.
- The API: add a Cache Rule: URI Path starts with
/api/→ Bypass cache. - Upload size: Cloudflare's free plan accepts up to 100 MB per request. kvist's default file limit, 50 MiB, fits.
Clearing Cloudflare's cache on every publish
So that an unpublished page disappears from Cloudflare right away instead of within a minute:
- In Cloudflare, create an API token with only the permission Zone → Cache Purge, for your domain's zone.
- Add it to the server, next to
docker-compose.yml, in a file called.env:CF_API_TOKEN=your-token - Add the zone to
kvist.toml(the Zone ID is on your domain's overview page in Cloudflare):[site.cloudflare] zone_id = "your-zone-id" api_token_env = "CF_API_TOKEN" - Run
docker compose up -dso kvist picks up both.
If a purge fails, the publish still succeeds, and the warning shows in the plugin's report.
The command line
The same kvist program is the server and a set of tools. On the server, run them with docker compose exec kvist kvist …. To use them on your own computer (for example kvist dev to preview your vault), build it from the repository with Go installed: make build puts it in bin/kvist.
| Command | What it does |
|---|---|
kvist serve | Runs the server (what the Docker container does). |
kvist token create|list|revoke | Manages tokens. |
kvist site list|delete | Lists sites with their stored data and tokens; deletes a site that's no longer in kvist.toml (details). |
kvist rollback SITE REVISION | Makes an earlier revision live again. |
kvist gc | Cleans up unused uploads now (the server also does it by itself). |
kvist dev --dir VAULT --config kvist.toml | Previews a vault at http://127.0.0.1:1313, reloading on every change. --listen picks another address. Without a config, only notes tagged #public or with publish: true are shown; --public Kvist makes a folder public too. |
kvist build --dir VAULT --out DIR | Builds the site into a folder, without a server. --emit-model FILE writes what the theme receives as JSON instead (or as well), for debugging a theme. |
kvist push --server URL --site ID --dir VAULT | Publishes a folder from the terminal, like the plugin does. The token goes in KVIST_TOKEN, and KVIST_SERVER and KVIST_SITE can stand in for the flags; -v shows the decision for every note, --device sets the name shown in the server's log, and --no-wait returns without waiting for the build. --force publishes even when the server has newer content; check first. |
kvist version | Prints the version. |
Commands that need the config look for kvist.toml in the current folder, or the path in KVIST_CONFIG, or --config. On a server with several sites, dev, build and token create take --site. kvist <command> -h lists a command's flags.
Without Docker
kvist is a single program, so it also runs directly under systemd, behind Caddy or nginx. The deployment notes have a ready-made systemd unit and an nginx example that serves the built files directly.