Environment Variables
IntegraMon uses multiple configuration layers. The important point is that not every setting is read the same way:
- container bootstrap values are assembled by
deploy/scripts/boot.py deploy/start.shsources the generated.env- Django applies additional per-setting fallbacks from
backend/src/monitorx/settings.py - some runtime behavior is then further shaped by database-backed settings such as
cMetricSettings,cWorkerTuningSettings, andcConfigExt
This page documents the real runtime behavior, not only the intended one.
Effective precedence
For container bootstrapping, the order is:
CONFIG_JSON_B64if present/run/secrets/app-config.jsonif present- an already existing
/app/backend/src/.env boot.pyhardcoded defaults
After that, start.sh sources /app/backend/src/.env into the shell. That means keys written into .env can overwrite same-named variables that were passed into the container shell before sourcing.
Inside Django, every setting then has its own fallback. Example:
- if
DB_BACKENDis absent in.env, Django still falls back tosqlite - if
CHANNELS_REDIS_URLis absent, Django still falls back toredis://127.0.0.1:6379/0 - if
DJANGO_ALLOWED_HOSTSis absent, Django still falls back to*
Secret decoding conventions
core/env_secrets.py supports the following formats for secret-like values such as DB_PASSWORD and EMAIL_HOST_PASSWORD:
plain:secretkeeps the literal textb64:c2VjcmV0decodes base64 first<NAME>_B64=trueforces base64 decode for<NAME>- autodetect tries to decode values that look like base64 and round-trip cleanly
This is relevant for:
DB_PASSWORDEMAIL_HOST_PASSWORD- mount credentials such as
SMB_PASS,SSHFS_PASS,KOOFR_APP_PASSWORD
Bootstrap and file handling
| Variable | Default | Required | Real behavior |
|---|---|---|---|
CONFIG_JSON_B64 | none | no | Base64 encoded JSON payload. If present, it becomes the primary container config source. Invalid base64 or invalid JSON aborts boot. |
ENV_OUT_PATH | /app/backend/src/.env | no | Output file written by boot.py. Mostly relevant for custom container layouts. |
ENV_FILE | .env relative to backend/src | no | Optional override for Django load_dotenv. If the path does not load, Django falls back to backend/src/.env. |
APP_VERSION | none | no | Optional PDF version label fallback. |
RELEASE_VERSION | none | no | Optional PDF version label fallback. |
BUILD_VERSION | none | no | Optional PDF version label fallback. |
DOCS_PDF_VERSION | image build arg or none | no | Preferred version string printed into PDF exports. |
DOCS_PDF_LOGO | frontend logo fallback | no | Optional custom logo path for PDF exports. |
Database configuration
| Variable | Default | Required | Real behavior |
|---|---|---|---|
DB_BACKEND | Django fallback sqlite; boot.py default postgresql | effectively yes for predictable Docker setups | Controls the branch in settings.py. Supported values are sqlite, postgresql, postgres, postgres_neon, postgresql_neon, and neon. |
DB_ENGINE | django.db.backends.sqlite3 or django.db.backends.postgresql | no | Usually does not need manual override unless experimenting with custom Django backends. |
DB_NAME | db.sqlite3 for SQLite path logic, default_db_name for Postgres fallback, monitorx in sample JSON | SQLite: no, Postgres: yes | For SQLite it becomes a filename under DATA_DIR. For Postgres it is the database name used by Django. |
DB_USER | default_user in Django Postgres fallback, postgres in sample JSON | Postgres: yes | Login user for PostgreSQL connections. |
DB_PASSWORD | default_password in Django Postgres fallback, sample JSON values elsewhere | Postgres: yes | Can use plain: or b64: conventions. |
DB_HOST | postgres in Django Postgres fallback, 127.0.0.1 in local sample JSON | Postgres: yes | Hostname of the PostgreSQL service or pooler. |
DB_PORT | 5432 | no | Used by Django and by migration helper scripts. |
DB_SSLMODE | require for Neon-style backends | no | Only applied when DB_BACKEND is one of the Neon variants. |
DB_CHANNEL_BINDING | unset | no | Optional PostgreSQL channel binding mode for Neon-style deployments. |
DJANGO_DB_FILE | db.sqlite3 | SQLite only | Relative file name stored under DATA_DIR. |
SQLITE_TIMEOUT | 20 | SQLite only | Busy timeout in seconds for SQLite writes. |
DB_LOCAL | normalized to true in start.sh | no | Controls whether the internal PostgreSQL service is started by Supervisor. It does not change Django connection logic by itself. |
DB_CONNECT_TIMEOUT | 2 | no | Used by wait_for_db.py as PGCONNECT_TIMEOUT. Good for fast failover. |
DB_WAIT_ATTEMPTS | 60 | no | Retry count for wait_for_db.py. |
DB_WAIT_INTERVAL | 2 | no | Sleep interval in seconds for wait_for_db.py. |
DB_ALIAS | default | no | Database alias used by wait_for_db.py. |
Redis, cache, broker, and channels
| Variable | Default | Required | Real behavior |
|---|---|---|---|
CELERY_BROKER_URL | redis://localhost:6379/1 in Django, redis://localhost:6379/0 in boot.py defaults | yes for worker-based production | Broker URL for Celery transport. rediss:// automatically enables CA-based TLS settings. |
CELERY_RESULT_BACKEND | redis://localhost:6379/2 in Django, redis://localhost:6379/1 in boot.py defaults | recommended | Used for Celery task result storage. |
REDIS_CACHE_URL | redis://127.0.0.1:6379/0 in Django, redis://localhost:6379/2 in boot.py defaults | recommended | Django cache backend plus several application caches. |
CHANNELS_REDIS_URL | redis://127.0.0.1:6379/0 | required for websocket usage | Used by Django Channels for websocket fan-out. |
CELERY_RESULT_EXPIRES | 600 | no | Result expiry in seconds. |
REDIS_LOCAL | normalized to true in start.sh | no | Controls whether the internal Redis service is started by Supervisor. It does not provide an automatic external fallback by itself. |
HTTP, reverse proxy, and URL generation
| Variable | Default | Required | Real behavior |
|---|---|---|---|
PORT | 80 in start.sh | no | Nginx listen port for the HTTP template. |
APP_BASE_PATH | empty | no | Normalized to either empty string or /subpath. Used by Nginx path rewrites, frontend base href rewriting, and Django URL generation helpers. |
FRONTEND_URL | http://localhost:3000 | no | Base frontend URL without subpath. If FRONTEND_BASE_URL is absent, code may combine this with APP_BASE_PATH. |
FRONTEND_BASE_URL | empty | recommended for mail links | Best source for absolute links inside emails and templates. |
DJANGO_ALLOWED_HOSTS | * | recommended in production | Comma-separated Django ALLOWED_HOSTS. |
ENABLE_SSL | false unless explicitly set | no | Only affects which Nginx template is rendered. It does not toggle Django secure mode settings. |
SERVER_NAME | empty | HTTPS only | Injected into the HTTPS Nginx template as server_name. |
SSL_CERT | empty | HTTPS only | Path to the TLS certificate file used by Nginx. |
SSL_KEY | empty | HTTPS only | Path to the TLS private key file used by Nginx. |
NGINX_CONF_OVERRIDE | empty | no | If it points to an existing file, start.sh copies it directly and skips template rendering. |
Storage, mounts, and logging
| Variable | Default | Required | Real behavior |
|---|---|---|---|
DATA_DIR | /app/data in container runtime, <install_home>/data in local Django fallback | recommended | Main persistent root for SQLite, tenant archives, tenant logs, and storage snapshots. |
LOG_DIR | ${DATA_DIR}/logs | no | Supervisor logs go here. Django also writes login_activity.log here. |
LOG_RETENTION_DAYS | 3 if archive cleanup falls back to env | no | Used by archive cleanup when tenant-specific jobs.logs config does not override retention. |
SMB_HOST | none | optional | Enables CIFS mount attempts through mount.py. |
SMB_SHARE | none | optional | Share name for CIFS mount. |
SMB_USER | none | optional | CIFS user. |
SMB_PASS | none | optional | CIFS password, secret helpers supported. |
SMB_MOUNT | none | optional | Local mount path. |
SMB_VERS | 3.1.1 | no | SMB protocol version. |
SSHFS_HOST | none | optional | Enables SSHFS mount attempts when SMB is not mounted. |
SSHFS_USER | none | optional | SSHFS user. |
SSHFS_PASS | none | optional | SSHFS password if key auth is not used. |
SSHFS_KEY | none | optional | SSH private key for SSHFS. |
SSHFS_MOUNT | none | optional | Local mount path. |
KOOFR_EMAIL | none | optional | Koofr account used by rclone. |
KOOFR_APP_PASSWORD | none | optional | Koofr app password, secret helpers supported. |
KOOFR_REMOTE | koofr | no | rclone remote name to create or use. |
KOOFR_SUBPATH | empty | no | Optional subpath inside the Koofr remote. |
KOOFR_MOUNT | none | optional | Local mount path used by rclone mount. |
Email and notification delivery
| Variable | Default | Required | Real behavior |
|---|---|---|---|
EMAIL_HOST | empty | yes for SMTP delivery | SMTP host for Django mail backend. |
EMAIL_HOST_USER | empty | usually | SMTP login user. |
EMAIL_HOST_PASSWORD | empty | usually | SMTP password, secret helpers supported. |
DEFAULT_FROM_EMAIL | empty | recommended | Sender fallback when profiles do not override it. |
Important implementation detail:
EMAIL_PORTis currently hardcoded to587EMAIL_USE_TLSis currently hardcoded toTrue
The base .env files in the repository mention EMAIL_PORT, but the active settings module does not read it.
AI and integration related variables
| Variable | Default | Required | Real behavior |
|---|---|---|---|
OLLAMA_BASE_URL | http://192.168.178.84:11434 | only if Ollama-backed AI is used | Default Ollama endpoint in settings.py. |
OLLAMA_MODEL | llama3 | only if Ollama-backed AI is used | Default model name. |
OLLAMA_API_URL | none | optional | Referenced in code outside settings.py; useful when AI modules expect an explicit API endpoint. |
GROQ_API_KEY | none | optional | Referenced by Groq-related management commands and AI code paths. |
AGENT_DISPATCH_BATCH_SIZE | 50 | no | Maximum scheduled report dispatches per periodic run. |
CPI_HOST | none | tenant-driven in most cases | Present in code search, but most current CPI connection data is stored in cConfigExt and encrypted there. |
CPI_USER | none | tenant-driven in most cases | Same note as above. |
CPI_PASS | none | tenant-driven in most cases | Same note as above. |
FERNET_KEY | boot default exists, but production should override | effectively yes | Used to encrypt tenant connection passwords inside core/services/config_ext.py. Without a stable production key, encrypted tenant secrets become unsafe or incompatible across deployments. |
Worker concurrency overrides
The following variables are read by Supervisor rather than Django. They control the number of worker processes per queue group:
CELERY_LIGHT_CONCURRENCYdefault2CELERY_LIGHT_COLD_CONCURRENCYdefault2CELERY_API_DETAILS_CONCURRENCYdefault3CELERY_API_DETAILS_COLD_CONCURRENCYdefault2CELERY_ALERT_DETAILS_CONCURRENCYdefault1CELERY_ALERTS_CONCURRENCYdefault1CELERY_PERIODIC_CONCURRENCYdefault1CELERY_AI_CONCURRENCYdefault1CELERY_PROCESS_BATCH_CONCURRENCYdefault2CELERY_PROCESS_BATCH_COLD_CONCURRENCYdefault2CELERY_MEDIUM_CONCURRENCYdefault2
These values are also mirrored by the worker tuning UI in superadmin scope.
Variables that are often expected but are not wired today
These points are especially important during production hardening:
DEBUGis not read from the environment.settings.pycurrently hardcodesDEBUG = True.SECRET_KEYis not read from the environment. The Django secret key is currently hardcoded in source.- JWT signing uses Django defaults, so it also inherits the hardcoded secret key unless custom signing settings are added later.
ALLOWED_HOSTSis not the active env name. The active key isDJANGO_ALLOWED_HOSTS.EMAIL_PORTandEMAIL_USE_TLSare not environment driven in the active settings module.
Production recommendations
- Set
DJANGO_ALLOWED_HOSTSexplicitly. Do not keep*in production. - Override
FERNET_KEYwith a stable secret managed outside the image. - Use PostgreSQL for shared or high-write environments.
- Use explicit external Redis URLs when
REDIS_LOCAL=false. - Set
FRONTEND_BASE_URLwhenever the system sends links by email. - Use
NGINX_CONF_OVERRIDEonly for deliberate custom reverse proxy behavior, because it bypasses the standard templates. - Treat
CONFIG_JSON_B64and/run/secrets/app-config.jsonas the supported Docker bootstrap inputs.