You need a machine with Docker and the Docker Compose plugin (docker compose version), plus
curl and openssl. Checky runs as one container; all data lives in one SQLite file in a Docker volume.
1. Get the Compose file
mkdir checky && cd checky
curl -fsSLO https://raw.githubusercontent.com/sonnenglas/checky/main/docker-compose.yml
2. Write the configuration
This creates .env with two fresh random secrets. BASE_URL is the address people open in the browser —
for a first try on your own machine that is http://localhost:3000.
cat > .env <<EOF
BASE_URL=http://localhost:3000
BETTER_AUTH_SECRET=$(openssl rand -base64 48)
APP_SECRET=$(openssl rand -base64 48)
EMAIL_FROM=Checky <[email protected]>
# SMTP_URL=smtps://user:[email protected]:465
EOF
chmod 600 .env
Keep the two secrets safe: BETTER_AUTH_SECRET signs sessions, APP_SECRET signs the one-tap links in
emails and encrypts SSO secrets. Without SMTP_URL, emails are only written to the container log — fine
for a test; set it up later in Email setup.
The image comes from ghcr.io/sonnenglas/checky. Compose uses :latest unless you pin a version with
CHECKY_IMAGE in .env, e.g. CHECKY_IMAGE=ghcr.io/sonnenglas/checky:2.0 (recommended for production:
x.y only receives patch releases). CHECKY_PORT changes the published port (default 3000).
3. Start Checky
docker compose up -d
Database migrations run on every start. Wait until the health check answers:
until curl -fsS http://localhost:3000/health; do sleep 2; done
It prints {"status":"ok","version":"…"}. docker compose logs checky shows the mode, the email transport
and the scheduler in its first line.
4. Set up your organization
Open http://localhost:3000. The first visit shows the setup: create your owner account and your
organization (or choose “Moving from another Checky?” to restore an export). The guided onboarding then
walks you through company details, sign-in options, your team, the first questions and the rhythm.
Only the first account can be created freely. Everyone else joins by invitation or — once you have verified your email domain — by signing in with a company address (SSO and verified domains).
5. Go to production
For real use, Checky needs a public https address: passkeys, secure cookies, OAuth for ChatGPT/Claude and SSO callbacks all depend on it.
- Point a DNS record (
A/AAAA) such aschecky.example.comat your server. - In
.env, setBASE_URL=https://checky.example.com,TRUST_PROXY=trueand your SMTP settings. - Put a reverse proxy with TLS in front. With Caddy (automatic certificates), add a
docker-compose.override.yml:
services:
checky:
ports: !reset []
caddy:
image: caddy:2
restart: unless-stopped
ports: ["80:80", "443:443"]
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
volumes:
caddy-data:
and a Caddyfile next to it:
checky.example.com {
reverse_proxy checky:3000 {
flush_interval -1
}
}
flush_interval -1 streams live updates (Server-Sent Events) immediately. With nginx, set
proxy_buffering off; for /api/v1/events; Traefik needs no extra settings.
- Run
docker compose up -dagain, then set up backups before you invite your team.
What’s in the box
- Image: distroless Node 24, amd64 + arm64, runs as uid 65532, no shell.
- Data: volume
checky-data, database at/data/checky.db. - Scheduler: in-process, every minute (check-ins, reminders, webhooks).
- Health:
GET /health, also used by the container health check.