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.
- Start the container using either method below, always mounting
/data. - Read the setup token from the logs and set a password at
/admin. - Configure HTTPS and
SITE_URLbefore public use. - 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:latestdocker logs calendsdocker-compose.yml:
services: calends: image: ghcr.io/imetn/calends:latest restart: unless-stopped ports: - '8787:8787' volumes: - calends-data:/data environment: # Public address used in reminder and calendar links (optional) # SITE_URL: https://calends.example.com # Set to 1 behind a reverse proxy # TRUST_PROXY: "1" TZ: UTC
volumes: calends-data:docker compose up -ddocker compose logs calendsOpen http://localhost:8787/admin and set your password with the setup token from the logs.
What happens on start
Section titled “What happens on start”-
Migrations are applied to the database in the data directory (idempotent; checked on every start).
-
The setup token is prepared:
SETUP_TOKENfrom the environment if set; otherwise a random one is generated on first start, saved assetup-tokenin the data directory and reused after that. -
The Worker starts and listens on
PORT(8787 by default). -
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> -
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.
Environment variables
Section titled “Environment variables”| 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.
Data and backups
Section titled “Data and backups”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 calendsdocker run --rm -v calends-data:/data -v "$PWD":/backup alpine tar czf /backup/calends-data.tgz -C /data .docker start calends
Build from source
Section titled “Build from source”git clone https://github.com/imetn/calends && cd calendsdocker build -t calends .docker run -d -p 8787:8787 -v calends-data:/data calendsIn compose, replace image: with build: ..
Image tags
Section titled “Image tags”| 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.