Configuration
All configuration goes through environment variables, validated at startup. Immediate failure with an explicit message rather than a breakdown in use: a crisis tool does not discover its own misconfiguration on the day.
The variables
Instance identity
| Variable | Purpose |
|---|---|
KASTELL_URL_PUBLIQUE | The address your users type. It also builds the links sent by email. |
KASTELL_ENV | developpement or production. In production, no example value is tolerated. |
KASTELL_PORT | 8080 by default. |
SECRET_SESSION | 32 characters minimum. openssl rand -hex 32. |
SECRET_SESSIONIt also encrypts the credentials of your delivery gateways. Losing it makes them unreadable — that is intended, and it must be backed up somewhere other than the database it protects.
Source offer — AGPL, section 13
| Variable | Purpose |
|---|---|
KASTELL_SOURCE_URL | Where to find the code of this instance. If you modified it, point at your own repository. |
KASTELL_REVISION | The exact revision, stamped at build time. |
See Licence.
Database, cache, storage
DATABASE_URL, REDIS_URL, S3_ENDPOINT, S3_BUCKET, S3_ACCES,
S3_SECRET, S3_REGION.
Without Redis the real-time feed degrades: each screen refreshes on action, without immediate propagation. The instance stays usable.
Video
| Variable | Purpose |
|---|---|
LIVEKIT_URL | What the browser dials. |
LIVEKIT_URL_INTERNE | What the server dials — inside a Docker compose, http://livekit:7880. |
LIVEKIT_CLE, LIVEKIT_SECRET | The credentials. |
"localhost", seen from the application container, means the container itself.
Confusing the two yields an ECONNREFUSED that the interface would otherwise
report as a network failure.
In production, enable the TURN relay on port 443 in docker/livekit.yaml:
it is the only port every firewall lets through, and often the only route from
the hotel the team has fallen back to.
Antivirus scanning
CLAMAV_HOTE, CLAMAV_PORT. With no scanner, uploads are marked
"not scanned" — never "clean".
On first start, ClamAV downloads its signatures for a few minutes. Uploads remain possible meanwhile.
Mobile notifications
KASTELL_RELAIS_POUSSEE, KASTELL_RELAIS_CLE. Without a relay the instance is
whole: it simply wakes nobody, and says so.
Delivery channels, per organisation
Each organisation plugs in its own gateways from Settings → Delivery channels: OVHcloud for SMS, Brevo for email, or any HTTP provider described by a template.
Credentials are encrypted at rest and never come back out: not through the API, not through the root console. Administering an instance is not reading your customers' secrets.
A channel never tested is a hypothesis. The "Test" button sends a message to you, and only to you.
Mobile notifications: the knock relay
Apple's servers only accept messages signed with the app publisher's key. A self-hosted instance therefore cannot, on its own, make the Kastell app ring on a phone: it goes through a relay that holds that key.
Without a relay, the instance is still whole. Reading, logging, calling: nothing is lost. It wakes nobody, and says so — on its status probe, and therefore in the app at the moment someone picks their instance. SMS and voice calls remain the first-rank call-out channels.
To start it with the composition:
docker compose --profile mobile up -d
| Variable | Purpose |
|---|---|
KASTELL_RELAIS_POUSSEE | The relay's address, as seen from the instance. |
KASTELL_RELAIS_CLE | The key the instance presents to the relay. |
APNS_CLE, APNS_CLE_ID, APNS_EQUIPE_ID, APNS_PAQUET | The relay's Apple credentials. |
APNS_ALERTE_CRITIQUE | true only once Apple has granted the entitlement. |
The relay receives nothing but a device token, an opaque identifier and a
degree of urgency: no organisation, no crisis, no person. It stores nothing.
Its code and protocol live in apps/relais/ — you can run your own, or check
what the one you use actually does.