Configuration
Application settings come from environment variables — set them in the shell, a systemd unit, or .env files (KEY=VALUE, one per line). No YAML or other config format.
Load order
- Defaults (in code)
- User config file (if present): see below
- Project / CWD .env (when running from source or from a deployment directory)
- Environment variables (always override)
So: env vars override .env; .env overrides user config file; user config overrides defaults.
User-level config (.env file)
When using the installed package (e.g. rediflow run), the app looks for a user config file and then for a .env in the current working directory.
- Explicit path: set
REDIFLOW_CONFIGto the full path of a .env file (e.g./etc/rediflow/config.envor~/my.env). - Default path (no env set):
- Linux / macOS:
$XDG_CONFIG_HOME/rediflow/config.envor, if that is unset,~/.config/rediflow/config.env - Windows:
%APPDATA%\rediflow\config.env
- Linux / macOS:
Create the directory and file if you want to use it (e.g. mkdir -p ~/.config/rediflow then create config.env with DATABASE_URL=..., SECRET_KEY=..., etc.). Only variables not already set in the environment are applied from the file.
Project / deployment directory (.env)
When you run from the source tree (e.g. python main.py run), the app loads from the project root: .env.<APP_ENV>, .env.dev, or .env (first found). When you run the installed rediflow CLI, it also loads from the current working directory in the same order. So in a deployment directory (or in Podman with WORKDIR /app), place .env, .env.qa, or .env.dev and the app will use it.
Deployment with compose: Place .env.qa or .env.prod in the same directory as the compose file. Compose reads env_file relative to the compose file location. Compose also loads .env by default for variable substitution; create .env with POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB matching your env file, or source the env file before running compose. See Deploy QA and production for the full guide.
Example .env files
- Dev: copy
.env.dev.example(in repo root) to.env.dev(or.env) and setDATABASE_URL,SECRET_KEY, etc. - QA: copy
.env.qa.exampleto.env.qa. When using Podman Compose, setDATABASE_URLso the host is the service namedb, e.g.postgresql://rediflow:rediflow@db:5432/rediflow_qa. Compose overrides this via theenvironmentsection if you use the same variable names.
Running migrations
After setting DATABASE_URL, run schema migrations before starting the app.
From source (local):
uv run python main.py migrate
Or: uv run rediflow migrate head.
From container (dev, with compose):
make migrate
Or explicitly: podman run --rm --network rediflow_default --env-file .env.dev -e DATABASE_URL=postgresql://...@db:5432/rediflow rediflow:latest rediflow migrate head. Use docker instead of podman if you use Docker.
From container (QA or production):
podman compose -f compose.deploy-qa.yml run --rm app-qa rediflow migrate head
For production, use compose.deploy-prod.yml and service app-prod. See Deploy QA and production for the full guide.
Main variables
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL URL (e.g. postgresql://user:pass@host:5432/dbname). Use postgresql+psycopg:// if you need the psycopg driver explicitly. |
SECRET_KEY |
Yes in prod | Flask secret; use a strong value in QA/prod. |
APP_ENV |
No | dev, qa, or prod (default dev). |
LANG |
No | Default UI locale (e.g. en, fi). |
SUPPORTED_LOCALES |
No | Comma-separated locales for the language dropdown. |
PERSON_CAPACITY_ENABLED |
No | true / false; enable People, Team, capacity (default false). |
ROLE_DEMAND_ENABLED |
No | When person capacity on, show Role demand / Roles capacity (default true). |
CAPACITY_REQUESTS_ENABLED |
No | When person capacity on, enable capacity requests (default true). |
SHARE_URL_FEATURE |
No | true / false; enable "Share" button to create short links and copy to clipboard (default true). |
SHARE_URL_FEATURE_STATS |
No | true / false; show Share link stats under Settings (default true). |
SHARE_URL_STATS_MIN_CLICKS |
No | Minimum click count to show a link in stats (default 10). |
DEMAND_DEVIATION_ENABLED |
No | true / false; show deviation of realised (EST/Actual) vs planned demand on Capacity and Graph (default false). |
DEMAND_DEVIATION_MINOR_PCT |
No | Normal/minor boundary in % (0–50, default 2.0). User can override in Settings → User preferences. |
DEMAND_DEVIATION_MAJOR_PCT |
No | Minor/major boundary in % (0–50, default 7.0). User can override in Settings → User preferences. |
REDIFLOW_LICENSE_FILE |
No | Path to a signed registration license file (Ed25519). If valid and not expired, the footer shows "Registered installation". |
REDIFLOW_LICENSE |
No | Inline signed license string (alternative to file). If both are set, the inline value is used. |
REGISTRATION_URL |
No | URL for the "Register (free)" link in the footer when the installation is unregistered (e.g. your form or landing page). |
DEFAULT_COUNTRY_CODE |
No | Default country for calendars (when org and its ancestors have no country code). ISO code e.g. FI, SE (default FI). Overridable in Settings → Calendars. Child orgs inherit from the nearest ancestor. |
SOURCE_URL |
No | Repository URL for the footer "Source" link (default: upstream GitLab). Set empty to hide. |
DOCS_URL |
No | Documentation site URL (GitLab Pages). Default derived from SOURCE_URL (e.g. https://rediflow_eu.gitlab.io/rediflow). Set empty to hide the docs link in Help and Settings. |
SESSION_TRACE_ENABLED |
No | true / false; when true, assign a correlation ID per session and log each request path. Enables "what did the user do before the error?" lookup for support (default false). |
Row Level Security (RLS)
When using Authentik (OIDC), the app sets the PostgreSQL session variable app.current_user_id per request. RLS policies on user_settings and shared_views restrict access by user. When no user is logged in (or OIDC is disabled), the variable is empty and policies allow full access for backward compatibility.
RLS policies apply only when the app connects as a non-owner role. By default, the app uses the same role that runs migrations (table owner), so RLS is bypassed. To enable RLS, use a two-role setup.
RLS variables
| Variable | Required | Description |
|---|---|---|
RLS_ENABLED |
No | true / false; when true, app connects as DATABASE_URL_APP role (default false). |
DATABASE_URL_APP |
When RLS | PostgreSQL URL for the app role (e.g. postgresql://rediflow_app:pass@host:5432/dbname). Must have SELECT/INSERT/UPDATE/DELETE on tables but not own them. |
POSTGRES_APP_USER |
When RLS | Username for the app role (e.g. rediflow_app). Used by compose to build DATABASE_URL_APP. |
POSTGRES_APP_PASSWORD |
When RLS | Password for the app role. |
Two-role setup
- Owner role (e.g.
rediflow): Runs migrations, owns tables. UseDATABASE_URLfor migrations. - App role (e.g.
rediflow_app): Has grants only. UseDATABASE_URL_APPfor the app whenRLS_ENABLED=true.
Steps to enable RLS:
- Run migrations as owner:
uv run python main.py migrate head(usesDATABASE_URL). - Create the app role and grant permissions:
uv run rediflow setup-rls-app-role(requiresDATABASE_URL,POSTGRES_APP_USER,POSTGRES_APP_PASSWORD). - Set
RLS_ENABLED=trueandDATABASE_URL_APPin your .env. - Restart the app.
See Authentik setup for the full RLS flow with Authentik and .env.test.
Registration and license: Providing no license or an expired/invalid license does not restrict use of the software or any feature. The app works fully in all cases. Only the footer text differs: "Unregistered installation · Register (free)" vs "Registered installation." See Registration and license for license format and how to obtain a license.
See .env.dev.example and .env.qa.example in the repo root for the full list and comments.