Skip to content
Development documentation
This describes Keydra as it is being built and is not a released version. What it documents can change before a release.

Configuration

What a deployment must set, what to set before exposing Keydra, and the shared store that turns one instance into several.

How Keydra is configured#

Configuration is Quarkus configuration: properties, with environment variables overriding them. Almost everything a deployment sets has an environment variable named for it in application.properties, which is where the mapping is written down rather than guessed.

Three profiles:

%dev

./mvnw quarkus:dev. Points at the containers in deploy/keydra-dev.yaml.

%test

The test suite. PostgreSQL, Redis and Valkey come from Testcontainers.

%prod

The packaged runtime, which is what the image runs.

What a deployment must set#

Only two things have no useful default:

properties
KEYDRA_DB_URL=postgresql://db.internal:5432/keydra
KEYDRA_DB_USERNAME=keydra
KEYDRA_DB_PASSWORD=<the password>
KEYDRA_SECRET_KEY=<32 random bytes, base64>

Everything else has a default that is either correct or explicitly a development convenience.

What to set before exposing it#

properties
# Where Keydra is, as a browser sees it. A provider's redirect comes back here.
KEYDRA_PUBLIC_URL=https://keydra.example.com

# Behind a reverse proxy: believe the forwarded headers, from these proxies only.
KEYDRA_BEHIND_PROXY=true
KEYDRA_TRUSTED_PROXIES=10.0.0.0/8

See the configuration reference for everything.

Keydra’s own store#

With nothing configured, Keydra is one instance with one memory and no dependency to install — which is the deployment most people have.

KEYDRA_STORE_URL points at a Redis that several instances share. It is used for two things: re-broadcasting notifications so a change made on one instance reaches a browser attached to another, and caching the three reads every request would otherwise make.

Important:Important

The store must be its own server, never one of your targets. A cache living in a server somebody is browsing is a cache somebody empties with a bulk delete.

Everything it writes is namespaced and carries a TTL. A cache without an expiry is a memory leak with better manners.

Configuring outgoing mail#

One relay, configured once, used by invitations, password resets and anything after them.

Procedure

Set the four settings a relay needs:

properties
KEYDRA_MAIL_HOST=smtp.example.com
KEYDRA_MAIL_PORT=587
KEYDRA_MAIL_TLS=true
KEYDRA_MAIL_USERNAME=<username>
KEYDRA_MAIL_API_KEY=<password or API key>
KEYDRA_MAIL_FROM=keydra@example.com
Verification

Invite an account and check that the link arrives.

Note:Note

With nothing configured, an invitation is still created and its link is returned to the administrator who asked for it. That is worse than mail and much better than refusing: an instance with no relay must not be an instance where nobody can be given an account.

What the letter looks like

An invitation is the first thing somebody ever sees of Keydra, so it goes out as HTML with a plain text part beside it — the plain part first, which is the order MIME asks for and what a client that reads only what it understands shows.

It is written in the language the account reads, when the account has said. An account that has used Keydra has a language preference and that answer wins; a brand-new one has expressed nothing, and an address does not carry a language — so the fallback is KEYDRA_MAIL_LANGUAGE, what the installation itself is run in. The link carries the choice, so the page it opens speaks the same language as the letter.

Edit this page