Form K-00 · Installation
Install
One container, one volume, one port. All data lives in a single SQLite file.
Docker (recommended)
docker run -d --name keeyo \
-p 5390:5390 \
-v keeyo-data:/data \
--restart unless-stopped \
ghcr.io/ans-ib/keeyo:latest
Docker Compose
services:
keeyo:
image: ghcr.io/ans-ib/keeyo:latest
container_name: keeyo
restart: unless-stopped
ports:
- "5390:5390"
volumes:
- keeyo-data:/data
volumes:
keeyo-data:
Then open http://localhost:5390. Your first visit creates the admin account — there is no default password and no open registration.
Build from source
git clone https://github.com/ans-ib/keeyo.git && cd keeyo
docker compose up -d
Without Docker
Needs Node.js 22.13+ — Keeyo uses Node's built-in SQLite, so there are no native modules to compile.
git clone https://github.com/ans-ib/keeyo.git && cd keeyo
npm install
npm start # http://localhost:5390, data in ./data
Configuration
| Variable | Default | What it does |
|---|---|---|
PORT | 5390 | Web server port. |
DATA_DIR | /data | Where the SQLite database lives. |
SESSION_TTL_DAYS | 30 | How long sign-ins last. |
REGISTRY_REFRESH_DAYS | 7 | How often the FIDO device registry is re-fetched. |
KEEYO_OFFLINE | unset | Set 1 to block all outbound requests (registry updates off). |
TRUST_PROXY | unset | Set 1 only behind a reverse proxy so X-Forwarded-* headers are honored. |
KEEYO_DISABLE_MFA | unset | Set 1 to skip every sign-in second factor — security keys and authenticator codes (lockout recovery). |
KEEYO_OIDC_ISSUER | unset | OIDC issuer URL — setting this (plus client id/secret) enables single sign-on. See below. |
KEEYO_OIDC_CLIENT_ID | unset | OIDC client id. |
KEEYO_OIDC_CLIENT_SECRET | unset | OIDC client secret. Leave empty for public clients (PKCE-only) — Cosmos's built-in OpenID works this way. |
KEEYO_OIDC_ADMIN_BOOTSTRAP | unset | Set 1 on a fresh instance to skip the setup screen: the first person to sign in through SSO becomes the admin, and password setup is refused. Closes the first-visit race behind platforms like Cosmos. |
KEEYO_OIDC_NAME | SSO | Label on the sign-in button (e.g. Authentik). |
KEEYO_OIDC_AUTO_CREATE | 1 | Set 0 to refuse SSO sign-ins for usernames that don't already exist in Keeyo. |
KEEYO_OIDC_SCOPES | openid profile email | OIDC scopes to request. |
KEEYO_OIDC_USERNAME_CLAIM | preferred_username | ID-token claim used as the Keeyo username. |
KEEYO_OIDC_LOGOUT_URL | unset | Where SSO users are sent after signing out of Keeyo. |
KEEYO_OIDC_REQUIRE_VERIFIED | unset | Set 1 to require email_verified before auto-creating an account. |
KEEYO_OIDC_DISABLE_PASSWORD | unset | Set 1 to turn off password sign-in for everyone except admins. |
KEEYO_SMTP_HOST | unset | SMTP server — setting this (plus FROM) enables email and password-reset links. |
KEEYO_SMTP_PORT | 587/465 | SMTP port (default depends on security mode). |
KEEYO_SMTP_SECURITY | starttls | tls, starttls or none. |
KEEYO_SMTP_USER / KEEYO_SMTP_PASS | unset | SMTP credentials, if the server needs them. |
KEEYO_SMTP_FROM | unset | Sender address for outgoing mail. |
KEEYO_SMTP_FROM_NAME | Keeyo | Sender display name. |
Single sign-on (Authentik, Authelia, Keycloak, …)
Keeyo speaks standard OpenID Connect (authorization code flow with PKCE), so any self-hosted identity provider works. The easiest way is the admin panel: Settings → Single sign-on covers everything — provider name, client credentials, issuer (endpoints are auto-discovered; manual Auth/Token URL overrides exist for providers without discovery), scopes, the identifier claim, a logout URL, plus toggles for auto-creating users, requiring a verified email, and disabling password login (admins always keep password sign-in as the lockout hatch). Environment variables do the same headlessly and, when set, lock the panel. For Authentik:
- Create an OAuth2/OpenID provider (confidential client, authorization code flow) with redirect URI
https://keys.example.com/api/oidc/callback, and an application using it. - Set the environment variables:
KEEYO_OIDC_ISSUERto the provider's OpenID issuer URL (e.g.https://auth.example.com/application/o/keeyo/), plusKEEYO_OIDC_CLIENT_ID,KEEYO_OIDC_CLIENT_SECRET, andKEEYO_OIDC_NAME=Authentik. - Restart Keeyo — a Continue with Authentik button appears on the sign-in page.
SSO users are matched by username (preferred_username, falling back to the email's local part) and created automatically on first sign-in as regular users — admins are only ever appointed locally. SSO accounts have no Keeyo password, and Keeyo's own second factor is skipped for them: your identity provider owns their authentication, including MFA. Password sign-in keeps working alongside SSO for local accounts.
Email & password reset
Configure SMTP in Settings → Email (or via the KEEYO_SMTP_* variables, which lock the panel) and a Forgot password? link appears on the sign-in page. Users set their address under Settings → Account; reset links are single-use, expire after 45 minutes, and revoke every session of the account when used. Accounts created by SSO have no password and are excluded. The SMTP client is built in — no relay container needed — and speaks TLS, STARTTLS or plain.
Reverse proxy & HTTPS
Keeyo speaks plain HTTP; put your reverse proxy in front for TLS and set TRUST_PROXY=1. Caddy example:
keys.example.com {
reverse_proxy keeyo:5390
}
localhost or an HTTPS origin. On a plain-HTTP LAN IP they politely disable themselves. Browsers also refuse WebAuthn on raw IP addresses, so use a hostname.Backups
- Everything: back up the
/datavolume — the SQLite file is the complete state, file attachments included. - Portable: Settings → Account → Export data gives a JSON file with keys, services, registrations, catalog and secret notes (in plain text — guard it). Attachments are not in the JSON.
- Human-readable: CSV export and a printable register sheet exist for paper people.
Locked out?
On the server (or in the container):
docker exec -it keeyo node scripts/reset-password.js <username> <new-password>
This resets the password, signs out all sessions and removes every second factor on the account — sign-in security keys, the authenticator app, and recovery codes. Alternatively, start Keeyo once with KEEYO_DISABLE_MFA=1 to skip the second factor.