Skip to content

Docker

Run Calends on your own machine with Docker, including persistent storage, HTTPS and backups.

The official image ghcr.io/imetn/calends runs the same Worker inside the container on workerd (the open-source Cloudflare Workers runtime), with data stored as a SQLite file in the data directory. It’s built for linux/amd64 and linux/arm64.

  1. Start the container using either method below, always mounting /data.
  2. Read the setup token from the logs and set a password at /admin.
  3. Configure HTTPS and SITE_URL before public use.
  4. Add a subscription and notification channel, test reminders and arrange backups.
终端窗口
docker run -d --name calends --restart unless-stopped \
-p 8787:8787 -v calends-data:/data \
ghcr.io/imetn/calends:latest
docker logs calends

Open http://localhost:8787/admin and set your password with the setup token from the logs.

  1. Migrations are applied to the database in the data directory (idempotent; checked on every start).

  2. The setup token is prepared: SETUP_TOKEN from the environment if set; otherwise a random one is generated on first start, saved as setup-token in the data directory and reused after that.

  3. The Worker starts and listens on PORT (8787 by default).

  4. If no password has been set yet, the setup token is printed to the logs:

    [calends] first run: create your password at /admin with this setup token:
    [calends] <token>
  5. A scheduled job fires at minute 5 of every hour (UTC), just like the cron on Cloudflare: reminders go out at your configured hour and stale exchange rates are refreshed.

The container has a health check that requests /api/auth/status.

Variable Default Details
SETUP_TOKEN generated Setup token for setting the first password.
SITE_URL the address you open the app from Links in reminders and the calendar feed.
TRUST_PROXY unset Set to 1 behind a reverse proxy so sign-in rate limiting sees real visitor IPs.
DATA_DIR /data Data directory.
PORT 8787 Listening port.
LOG_LEVEL warn Worker log level.

Only SETUP_TOKEN, SITE_URL and TRUST_PROXY (plus the legacy OWNER_PASSCODE) are passed to the Worker. The container’s TZ doesn’t affect reminders; they follow Settings → General → Time zone.

On the public internet, put Calends behind a reverse proxy for HTTPS and set TRUST_PROXY=1. Passkeys only work over HTTPS. With Caddy:

calends.example.com {
reverse_proxy 127.0.0.1:8787
}

More in Custom domain and HTTPS.

Everything lives in the calends-data volume (/data in the container), including the SQLite database and the setup-token file. Removing the container keeps your data; removing the volume doesn’t.

Two ways to back up:

  • Settings → Data → Export full backup gives you a JSON file you can restore on any deployment; see Backup and restore;

  • or archive the volume with the container stopped:

    终端窗口
    docker stop calends
    docker run --rm -v calends-data:/data -v "$PWD":/backup alpine tar czf /backup/calends-data.tgz -C /data .
    docker start calends
终端窗口
git clone https://github.com/imetn/calends && cd calends
docker build -t calends .
docker run -d -p 8787:8787 -v calends-data:/data calends

In compose, replace image: with build: ..

Tag Meaning
latest Latest build of the main branch.
1.2.3, 1.2 Releases. Use these to control when you upgrade.
main The main branch, same as latest.

See Upgrading.