Configuration¶
DiagramaHub is configured with environment variables. The backend reads them from
backend/.env (mounted into the container with env_file) and the frontend receives them
from the Docker Compose file. This page is the complete reference: anything not listed here
is not configurable through the environment.
After changing a variable
The backend reads its configuration at startup. Recreate the container to apply
changes: docker-compose up -d backend (or frontend). A restart does not re-read
env_file.
Backend (backend/.env)¶
Variables are defined in backend/app/core/config.py and are case-sensitive.
Database¶
| Variable | Default | Required | Description |
|---|---|---|---|
MONGO_URI |
mongodb://mongodb:27017 |
Yes in external-mongodb mode |
MongoDB connection string. In local-full the default points to the mongodb container. Accepts mongodb+srv:// (Atlas). |
DATABASE_NAME |
diagramahub |
No | Database name. |
Security¶
| Variable | Default | Required | Description |
|---|---|---|---|
JWT_SECRET |
— | Yes | Secret used to sign session tokens. The backend does not start without it. At least 32 random characters. Changing it signs everyone out. |
JWT_ALGORITHM |
HS256 |
No | JWT signing algorithm. |
ACCESS_TOKEN_EXPIRE_MINUTES |
30 |
No | No effect. Accepted so existing .env files keep working, but each sign-in sets the session lifetime (see Authentication). |
AI_ENCRYPTION_KEY |
empty | Yes, in practice | Fernet key that encrypts in the database the AI providers' API keys, the integrations' configuration (Resend, Stripe, Google) and the MFA TOTP secrets. If missing, those operations fail. |
Generate both secrets like this:
# JWT_SECRET
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
# AI_ENCRYPTION_KEY (requires the cryptography package)
python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
Back up AI_ENCRYPTION_KEY together with the database
What was encrypted with one key can only be decrypted with that same key. If you lose or change it, every user's AI API keys, integrations and authenticator-app MFA become unreadable and must be configured again.
install.sh generates AI_ENCRYPTION_KEY
The installer writes backend/.env with MONGO_URI, DATABASE_NAME, JWT_SECRET,
AI_ENCRYPTION_KEY and API_V1_PREFIX. Running it again keeps an existing
AI_ENCRYPTION_KEY. On installations made with versions before 0.8.4, add it by hand if
it's missing and recreate the backend.
URLs and CORS¶
| Variable | Default | Required | Description |
|---|---|---|---|
FRONTEND_URL |
http://localhost:5173 |
Yes in production | Public frontend URL. Used in Stripe Checkout redirects, the password-reset link and the URL of shared links. When BACKEND_CORS_ORIGINS is empty, it is also the only allowed CORS origin. |
BACKEND_CORS_ORIGINS |
empty | No | Allowed CORS origins, comma-separated: https://diagrams.example.com,https://www.example.com. |
API_V1_PREFIX |
/api/v1 |
No | API route prefix. The frontend assumes /api/v1: don't change it. |
BACKEND_CORS_ORIGINS format
Write the origins comma-separated, without brackets or quotes. Since 0.8.4 the bracketed
format (["http://localhost:5173"]) that earlier example files shipped is accepted too:
the brackets and quotes are dropped.
Environment and server¶
| Variable | Default | Required | Description |
|---|---|---|---|
APP_ENV |
production |
No | production disables Swagger/ReDoc/OpenAPI, hides error traces, enables HSTS and CSP on API responses and starts with gunicorn. development (or dev) starts uvicorn with hot reload. |
PORT |
8000 (image) |
No | Port the backend listens on inside the container. Both compose files (local-full and external-mongodb) set it to 5172, the published port, and that value takes precedence over backend/.env. |
WORKERS |
2 |
No | gunicorn processes in production mode. Request limits are counted per process (see Production). |
FORWARDED_ALLOW_IPS |
127.0.0.1,::1 |
Yes behind a proxy | Proxies whose X-Forwarded-For and X-Forwarded-Proto the backend accepts (comma-separated IPs or CIDR networks). Only those connections can change the client IP used by request limits, account lockout and the audit log. See Production. |
Diagram rendering¶
| Variable | Default | Required | Description |
|---|---|---|---|
KROKI_URL |
http://kroki:8000 |
No | URL of the Kroki service that renders PlantUML, D2 and DBML. Change it only if Kroki runs on another host. |
Request limits¶
| Variable | Default | Description |
|---|---|---|
MAX_REQUEST_BODY_BYTES |
5242880 (5 MB) |
Maximum body size for any request; above it the API answers 413. Generous because freehand drawings are stored as JSON. It is also the maximum size of each file inside an import. |
MAX_IMPORT_UPLOAD_BYTES |
20971520 (20 MB) |
Maximum size of a project import upload (ZIP or loose files). |
MAX_IMPORT_FILES |
500 |
Maximum number of files in one import. |
MAX_IMPORT_UNCOMPRESSED_BYTES |
52428800 (50 MB) |
Maximum size a ZIP may expand to. |
Monitoring (optional)¶
| Variable | Default | Description |
|---|---|---|
SENTRY_DSN |
empty | Sentry DSN for the backend. Empty = Sentry disabled. |
SENTRY_TRACES_SAMPLE_RATE |
0.1 |
Fraction of transactions sent for performance monitoring (0.0–1.0). |
SENTRY_ENABLE_LOGS |
True |
Sends logs to Sentry. |
Events are sanitized before they are sent (see Maintenance).
Stripe through environment variables (alternative)¶
The recommended way to connect Stripe is the Integrations panel. When no active gateway is configured there, the backend uses these variables:
| Variable | Description |
|---|---|
STRIPE_SECRET_KEY |
Secret key (sk_...). Required together with the webhook secret. |
STRIPE_WEBHOOK_SECRET |
Webhook signing secret (whsec_...). |
STRIPE_PUBLISHABLE_KEY |
Publishable key (pk_...). |
Variables you should not set¶
PROJECT_NAME and VERSION are configuration fields too, but the code sets them. If
backend/.env defines VERSION (the backend/.env.template template shipped
VERSION=1.0.0 up to 0.8.3), the API reports a false version at / and to Sentry. Remove it
from your .env.
Minimal example¶
Frontend¶
The frontend reads its configuration in this order:
/config.js(window.__DH_CONFIG__), which the production image generates when the container starts from the environment variables. Changing a value only requires recreating the container, not rebuilding the image.- The
VITE_*variables baked into the build (the development image, or static hosting without a container, where changing a value requires a rebuild).
| Variable | Default | Description |
|---|---|---|
VITE_API_URL |
http://localhost:5172 |
Public API URL, as the user's browser sees it (not the internal Docker URL). |
VITE_SENTRY_DSN |
empty | Sentry DSN for the frontend. Empty = disabled. |
VITE_APP_ENV |
production (prod image) |
Environment reported to Sentry. |
VITE_APP_VERSION |
package.json version |
Version reported to Sentry as the release. Usually not needed. |
In external-mongodb mode the compose file takes VITE_API_URL, VITE_SENTRY_DSN and
VITE_APP_ENV from the shell or from a .env file next to docker-compose.yml:
# .env at the repository root (next to docker-compose.yml)
VITE_API_URL=https://api.diagrams.example.com
In local-full, VITE_API_URL is fixed to http://localhost:5172 in the compose file.
Next steps¶
- Production: what changes when you expose the instance to the internet.
- Integrations: email, payments and Google OAuth.