Configuration¶
All settings are environment variables prefixed MONSTEROPS_, read from .env (production:
/opt/monsterops/.env; development: the project root) or the process environment. Only
DATABASE_URL and SECRET_KEY are required in practice — everything else has a sensible default.
System → Settings renders the current effective config and can generate a starter .env.
Restart the service after changing any variable: sudo systemctl restart monsterops.
Core¶
| Variable | Default | Purpose |
|---|---|---|
MONSTEROPS_DATABASE_URL |
postgresql+asyncpg://radius:radius@localhost/radius |
Async SQLAlchemy DSN — must use the +asyncpg driver |
MONSTEROPS_SECRET_KEY |
change-me-before-production |
Signs JWTs and derives the key that encrypts stored credentials — change this; rotate later with monsterops rotate-secret-key |
MONSTEROPS_ACCESS_TOKEN_EXPIRE_MINUTES |
30 |
Access-token lifetime; the refresh cookie rotates a new one silently |
MONSTEROPS_COOKIE_SECURE |
(auto) | Force Secure on session cookies; unset derives it from the request scheme (X-Forwarded-Proto aware) |
MONSTEROPS_DEBUG |
false |
Enables /api/docs and verbose errors — never on in production |
MONSTEROPS_LOG_LEVEL |
INFO |
DEBUG / INFO / WARNING / ERROR |
MONSTEROPS_ALLOWED_ORIGINS |
"" |
Comma-separated CORS origins (empty = CORS disabled) |
MONSTEROPS_ENABLED_MODULES |
"" (all) |
Comma-separated allow-list; disabled modules are never imported |
MONSTEROPS_PLUGINS |
"" |
Comma-separated third-party plugin entry-point names to load |
Database pool¶
| Variable | Default | Purpose |
|---|---|---|
MONSTEROPS_DB_POOL_SIZE |
10 |
Steady-state connections |
MONSTEROPS_DB_MAX_OVERFLOW |
20 |
Burst connections above pool size |
MONSTEROPS_DB_POOL_TIMEOUT |
30 |
Seconds to wait for a free connection |
MONSTEROPS_DB_POOL_RECYCLE |
1800 |
Recycle connections older than N seconds |
Paths & integrations¶
| Variable | Default | Purpose |
|---|---|---|
MONSTEROPS_RADIUS_LOG_FILES |
/var/log/freeradius/radius.log |
Comma-separated log paths shown in the log viewer |
MONSTEROPS_GEOIP_DB |
"" |
Path to a MaxMind GeoLite2-City.mmdb (empty = geolocation off) |
MONSTEROPS_BACKUP_DIR |
/var/backups/monsterops |
Where named DB/config snapshots are stored |
MONSTEROPS_FREERADIUS_PROXY_CONF |
/etc/freeradius/3.0/proxy.conf |
Where Realms writes generated proxy config |
MONSTEROPS_VPN_CONFIG_DIR |
/etc/monsterops/vpn |
Where VPN writes wg-quick configs (0600) |
MONSTEROPS_FIREWALL_RULESET_PATH |
/etc/monsterops/firewall.nft |
Confirmed ruleset re-applied at boot by the firewall unit |
MONSTEROPS_RADIUS_SERVER_IP |
"" (auto) |
Advertised address for the NAS RADIUS Setup deploy; blank auto-detects the egress IP toward each NAS |
NAS reachability & Server Console¶
| Variable | Default | Purpose |
|---|---|---|
MONSTEROPS_NAS_PROBE_ENABLED |
true |
Background ICMP probe for the dashboard up/down state |
MONSTEROPS_NAS_PROBE_INTERVAL_SECONDS |
60 |
Seconds between probe sweeps |
MONSTEROPS_NAS_PROBE_TIMEOUT_SECONDS |
3 |
Per-probe timeout |
MONSTEROPS_CONSOLE_ENABLED |
false |
Enable the Server Console (opt-in: its palette restarts FreeRADIUS / runs migrations from the browser) |
MONSTEROPS_REQUIRE_2FA |
false |
Require two-factor (TOTP) for every admin; unenrolled admins must set it up at next sign-in |
Log retention¶
Applied by the scheduled Log Retention job. 0 disables pruning for that table (keep forever).
| Variable | Default (days) | Table |
|---|---|---|
MONSTEROPS_RETENTION_AUTH_LOG_DAYS |
90 |
radpostauth |
MONSTEROPS_RETENTION_AUDIT_LOG_DAYS |
365 |
audit_log |
MONSTEROPS_RETENTION_NOTIFICATION_DAYS |
90 |
mr_notification_history |
MONSTEROPS_RETENTION_DISPATCH_LOG_DAYS |
180 |
mr_nas_dispatch_log |
Email (scheduled reports & notifications)¶
MONSTEROPS_SMTP_HOST, MONSTEROPS_SMTP_PORT (587), MONSTEROPS_SMTP_USER,
MONSTEROPS_SMTP_PASSWORD, MONSTEROPS_SMTP_FROM, MONSTEROPS_SMTP_TLS (false).
Rotating the secret key¶
MONSTEROPS_SECRET_KEY does double duty: it signs session tokens and derives the key that
encrypts credentials at rest — NAS Manager SSH/Telnet secrets and directory
(AD/LDAP) bind passwords. So you can't just change it — the old ciphertext would no longer decrypt.
Rotate, don't replace
Changing MONSTEROPS_SECRET_KEY directly orphans every stored credential. Rotate with the CLI
while the old key is still configured:
# Dry run first — reports how many credentials would be re-encrypted, writes nothing
monsterops rotate-secret-key --new-key "<new-key>" --dry-run
# Then rotate for real (old key read from the current MONSTEROPS_SECRET_KEY)
monsterops rotate-secret-key --new-key "<new-key>"
It re-encrypts every stored credential in one pass and is abort-safe — if any value fails to
decrypt with the old key it stops and changes nothing. When it finishes, set MONSTEROPS_SECRET_KEY
to the new value and restart.
Related¶
- CLI · Installation · Settings
MonsterOps