Skip to main content
PathMon

Chapter 5 of 15

PatchMon Environment Variables Reference

Updated Read the full guide

Applies to: PatchMon 2.0+ (Go server)

This document is the authoritative reference for all environment variables supported by the PatchMon server. Configure these in your .env file, which Docker reads and passes into the server container via env_file:.

Variables are loaded from .env in the working directory by default. To use a different file, set the ENV_FILE variable to the path you want the server to read at startup.

How values are resolved

PatchMon resolves configuration in this order, highest to lowest priority:

  1. Environment variable (set in .env or in your container/Pod spec)
  2. Database value (set via the Settings UI; only for values marked Editable in UI below)
  3. Built-in default

This means: if a variable is set in .env, editing it in Settings → Environment has no effect until you remove the env value. The UI flags overridden values with a yellow "env" badge so you can tell at a glance why your change is being ignored. See Settings in the web UI for more on runtime tuning.


Table of Contents

  1. Required Variables
  2. Server Configuration
  3. Database Connection Pool
  4. Authentication and Sessions
  5. Redis Configuration
  6. Rate Limiting
  7. Password Policy
  8. Logging and Profiling
  9. OIDC / SSO
  10. Compliance / SSG
  11. RDP / Remote Access
  12. Body Limits
  13. Timezone
  14. Encryption Keys
  15. Agent Binary Overrides
  16. Telemetry
  17. File Loading

1. Required Variables

The server will refuse to start if either of these is missing or empty.

Variable Default Required Description
DATABASE_URL (none) Yes PostgreSQL connection string.
JWT_SECRET (none) Yes Secret key used to sign JWT tokens. Must be a strong, randomly generated value.

Examples:

DATABASE_URL="postgresql://patchmon_user:strongpassword@localhost:5432/patchmon_db"
JWT_SECRET="$(openssl rand -hex 64)"

Keep JWT_SECRET stable across restarts. Changing it invalidates all active sessions and forces every user to log in again.


2. Server Configuration

General HTTP server and network settings.

Variable Default Required Description
PORT 3000 No TCP port the server listens on. In the Docker Compose stack the published port mapping follows this value, so you only need to update CORS_ORIGIN to match.
APP_ENV production No Runtime environment. Accepted values: production, development. NODE_ENV is also read as a backward-compatibility alias; APP_ENV takes precedence when both are set.
CORS_ORIGIN http://localhost:3000 No Allowed CORS origin(s). Must match the exact URL you use to access PatchMon in your browser (protocol, hostname, and port; no path, no trailing slash). To allow multiple origins, separate them with a comma and no spaces (e.g. https://patchmon.example.com,https://patchmon.internal.lan).
ENABLE_HSTS false No When true, the server adds an HTTP Strict Transport Security header to responses. Enable this only when PatchMon is served over HTTPS.
TRUST_PROXY true No When true, the server trusts X-Forwarded-For / X-Forwarded-Proto and related headers from a reverse proxy (Traefik, Caddy, nginx, NPM, etc.). Required for accurate client IP detection, correct rate limiting, and OIDC's HTTPS check when TLS is terminated at the proxy. Default is true because the officially supported deployment is Docker behind a reverse proxy; set to false explicitly only if PatchMon is exposed directly to the internet without a proxy.
TRUSTED_PROXY_RANGES (empty) No Comma-separated CIDRs or bare IPs of the reverse proxies in front of PatchMon, for example 10.0.0.0/8,172.16.0.0/12. Used together with TRUST_PROXY to work out the real client IP from X-Forwarded-For, which drives rate limiting, login lockout, and audit logging. Leave it empty when there is a single reverse proxy, which is the usual setup: PatchMon then uses the address your proxy appended to the header, which a client cannot forge. Set it only when proxies are chained (for example Cloudflare in front of Nginx Proxy Manager), listing the intermediate hops so the original client IP is resolved rather than your CDN's egress address. Configured via environment only, and shown read-only in the settings UI, because widening it would allow clients to spoof their own IP.

Production example:

PORT=3000
APP_ENV=production
CORS_ORIGIN=https://patchmon.example.com
ENABLE_HSTS=true
TRUST_PROXY=true

Set CORS_ORIGIN to the full URL your users type in their browser. A mismatch here is the most common cause of CORS errors after a fresh deployment. If PatchMon is accessed from multiple URLs (e.g. an external domain and an internal LAN address), list them comma-separated with no spaces: CORS_ORIGIN=https://patchmon.example.com,https://patchmon.internal.lan.


3. Database Connection Pool

These variables control how the server manages its PostgreSQL connection pool. The defaults work well for most deployments; adjust them if you are running a large number of monitored hosts or see connection timeout errors.

All timeout values are in seconds unless otherwise noted.

Variable Default Required Description
PM_DB_CONN_MAX_ATTEMPTS 30 No How many times the server will retry connecting to the database on startup before giving up. Useful in containerised environments where the database may not be ready immediately.
PM_DB_CONN_WAIT_INTERVAL 2 No Seconds to wait between each connection retry attempt on startup.
DB_CONNECTION_LIMIT 30 No Maximum number of concurrent database connections in the pool.
DB_POOL_TIMEOUT 20 No Seconds to wait for an available connection from the pool before returning a timeout error.
DB_CONNECT_TIMEOUT 10 No Seconds to wait when establishing a new individual connection to PostgreSQL.
DB_IDLE_TIMEOUT 300 No Seconds an idle connection is kept open before being closed and removed from the pool.
DB_MAX_LIFETIME 1800 No Maximum lifetime in seconds of any connection in the pool, regardless of activity. Connections are recycled after this time to prevent stale connections.
DB_TRANSACTION_MAX_WAIT 10000 No Milliseconds to wait for a transaction to acquire a database lock before giving up.
DB_TRANSACTION_TIMEOUT 30000 No Milliseconds allowed for a standard database transaction to complete.
DB_TRANSACTION_LONG_TIMEOUT 60000 No Milliseconds allowed for long-running operations (for example, bulk package imports or compliance scans). Increase this if those operations are timing out.

Sizing guidance:

Deployment size DB_CONNECTION_LIMIT
Small (1–10 hosts) 15
Medium (10–50 hosts) 30 (default)
Large (50+ hosts) 50 or higher

If you see connection pool exhausted errors in the server logs, increase DB_CONNECTION_LIMIT in increments of 10 and monitor until the errors stop.


4. Authentication and Sessions

Settings for JWT tokens, browser sessions, account lockout, two-factor authentication, and user roles.

JWT and Tokens

Variable Default Required Description
JWT_SECRET (none) Yes See Required Variables.
JWT_EXPIRES_IN 1h No How long an access token is valid. Accepts duration strings: 30m, 1h, 2h, 1d. The web interface renews the token automatically in the background, so a short value is not visible to signed-in users; it only controls how quickly a stolen token becomes useless.
AUTH_BROWSER_SESSION_COOKIES false No When set to true, the token and refresh_token cookies are issued without a Max-Age attribute, making them session cookies that are cleared when the browser is closed rather than persisting across browser restarts.

Account Lockout

Lockout is applied per user account after repeated failed login attempts.

Variable Default Required Description
MAX_LOGIN_ATTEMPTS 5 No Number of consecutive failed login attempts before the account is temporarily locked.
LOCKOUT_DURATION_MINUTES 15 No How long (in minutes) an account stays locked after exceeding MAX_LOGIN_ATTEMPTS.

Session Inactivity

Variable Default Required Description
SESSION_INACTIVITY_TIMEOUT_MINUTES 30 No Minutes without user activity before a session is invalidated and the browser returns to the login screen. Set to 0 to disable the inactivity timeout entirely.

"Activity" means someone actually using the interface: clicking, typing, scrolling, moving the pointer, or switching back to the tab. Pages that refresh data on a timer do not count, so a browser left open on an unattended machine still times out.

The timer is enforced by the server and evaluated when the next request arrives, so a session that has been idle past the limit ends at the next click or background refresh rather than at the exact second the limit passes. Signing out, or an administrator revoking the session, ends it immediately either way.

This setting is independent of JWT_EXPIRES_IN. Access tokens are renewed in the background for as long as the session stays active, so a value larger than JWT_EXPIRES_IN works as expected.

Two-Factor Authentication (TFA)

These settings apply only to users who have TFA enabled on their accounts.

Variable Default Required Description
MAX_TFA_ATTEMPTS 5 No Number of consecutive failed TFA code entries before the account is temporarily locked.
TFA_LOCKOUT_DURATION_MINUTES 30 No How long (in minutes) a TFA lockout lasts.
TFA_REMEMBER_ME_EXPIRES_IN 30d No How long a "remember this device" TFA exemption is valid. Accepts duration strings such as 7d, 30d, 90d.
TFA_MAX_REMEMBER_SESSIONS 5 No Maximum number of remembered devices per user. When the limit is reached, the oldest remembered session is removed.

User Defaults

Variable Default Required Description
DEFAULT_USER_ROLE user No Role assigned to newly created users. Accepted values: user, admin, readonly. This does not affect existing users.

5. Redis Configuration

Redis is used for background job queues (asynq), bootstrap tokens, and TFA lockout state. A running Redis instance is required.

Variable Default Required Description
REDIS_HOST localhost No Hostname or IP address of the Redis server.
REDIS_PORT 6379 No Port the Redis server listens on.
REDIS_PASSWORD (none) No Redis authentication password. Strongly recommended in any non-local deployment.
REDIS_USER (none) No Redis username for ACL-based authentication (Redis 6.0+). Leave empty to use password-only authentication.
REDIS_DB 0 No Redis logical database number (0–15). Change this if you share a Redis instance with other applications.
REDIS_TLS false No When true, the server connects to Redis over TLS.
REDIS_TLS_VERIFY true No When set to false, the server skips Redis TLS certificate verification. Only use this in testing against self-signed certificates.
REDIS_TLS_CA (none) No Path to a custom CA certificate file for verifying the Redis TLS connection. Only used when REDIS_TLS=true.
REDIS_CONNECT_TIMEOUT_MS 60000 No Milliseconds to wait when establishing a new connection to Redis before timing out.
REDIS_COMMAND_TIMEOUT_MS 60000 No Milliseconds to wait for a Redis command to complete before timing out.

Required Redis permissions when using ACLs:

If you set REDIS_USER and restrict that user with an ACL command allowlist, the user must be able to run server-side Lua scripts. Rate limiting evaluates a small script so that a counter and its expiry are set together, which stops a dropped expiry stranding a client on HTTP 429 indefinitely.

Grant at least:

ACL SETUSER patchmon on >yourpassword ~* +@read +@write +@keyspace +eval +evalsha +script

Without +eval and +evalsha, rate limiting fails. Sign-in and password endpoints deliberately fail closed when the rate limiter is unavailable, so the visible symptom is 503 Service temporarily unavailable on login rather than a rate limiting warning. If you see that after tightening an ACL, check these permissions first.

Redis users with no ACL restrictions, and deployments using REDIS_PASSWORD alone, need no change.

Generating a secure Redis password:

openssl rand -hex 32

6. Rate Limiting

Rate limits protect the API from abuse. Limits are applied per IP address, split across three endpoint categories. All window values are in milliseconds.

Variable Default Required Description
RATE_LIMIT_WINDOW_MS 900000 No Time window for the general API rate limit (default: 15 minutes).
RATE_LIMIT_MAX 5000 No Maximum requests per window for general API endpoints (dashboards, hosts, packages, settings).
AUTH_RATE_LIMIT_WINDOW_MS 600000 No Time window for authentication endpoints (login, token refresh) (default: 10 minutes).
AUTH_RATE_LIMIT_MAX 500 No Maximum requests per window for authentication endpoints.
AGENT_RATE_LIMIT_WINDOW_MS 60000 No Time window for agent check-in and reporting endpoints (default: 1 minute).
AGENT_RATE_LIMIT_MAX 1000 No Maximum requests per window for agent endpoints. Increase this if you have a large number of agents checking in frequently.
PASSWORD_RATE_LIMIT_WINDOW_MS 900000 No Time window for password change and reset operations (default: 15 minutes).
PASSWORD_RATE_LIMIT_MAX 5 No Maximum password change attempts per window. Kept deliberately low to limit brute-force attacks on password reset flows.

Quick reference: window conversions

Milliseconds Human-readable
60000 1 minute
600000 10 minutes
900000 15 minutes

7. Password Policy

Rules applied when a user sets or changes a local account password. These do not apply to OIDC users, who authenticate against their identity provider.

Variable Default Required Description
PASSWORD_MIN_LENGTH 8 No Minimum number of characters required in a password.
PASSWORD_REQUIRE_UPPERCASE true No Require at least one uppercase letter. Set to false to disable.
PASSWORD_REQUIRE_LOWERCASE true No Require at least one lowercase letter. Set to false to disable.
PASSWORD_REQUIRE_NUMBER true No Require at least one numeric digit. Set to false to disable.
PASSWORD_REQUIRE_SPECIAL true No Require at least one special character (e.g. !, @, #). Set to false to disable.

All four complexity options default to true. To disable a rule you must explicitly set it to false: omitting the variable leaves the rule enabled.


8. Logging and Profiling

Variable Default Required Description
ENABLE_LOGGING true No Structured application logging to stdout. Setting this to false silences the server completely. Not reduced logging: none at all, which leaves every instruction in this guide that asks you to check the server logs with nothing to show. Changed in 2.0.3; it previously defaulted to false. An explicit false, in either .env or Settings > Environment, is still honoured.
LOG_LEVEL info No Minimum log level to output. Accepted values: debug, info, warn, error. Must be one of these exact strings. The server will fail to start if an invalid value is provided.
ENABLE_PPROF false No When true, serves Go pprof profiling endpoints on a separate loopback-only listener (see PPROF_PORT). For diagnostics only. Do not enable in production unless actively investigating a performance issue.
PPROF_PORT 6060 No Port for the profiling listener when ENABLE_PPROF=true. Binds to 127.0.0.1 only, so nothing needs opening in a firewall or reverse proxy.
MEMSTATS_INTERVAL_SEC 60 No How often (in seconds) the server logs Go runtime memory statistics when profiling is active. Only relevant when ENABLE_PPROF=true.

Log level guide:

Level When to use
debug Active troubleshooting: very verbose, includes internal operations
info Normal production operation
warn Quieter production operation; only non-critical issues and errors
error Minimal output; critical errors only

9. OIDC / SSO

OpenID Connect configuration for Single Sign-On. When OIDC_ENABLED=true, the four marked variables below become required and the server will refuse to start without them.

Core Settings

Variable Default Required Description
OIDC_ENABLED false No Set to true to activate OIDC authentication.
OIDC_ISSUER_URL (none) If OIDC enabled The issuer URL of your identity provider (e.g. https://auth.example.com). The server fetches the OIDC discovery document from this URL.
OIDC_CLIENT_ID (none) If OIDC enabled The client ID registered in your identity provider.
OIDC_CLIENT_SECRET (none) If OIDC enabled The client secret from your identity provider.
OIDC_REDIRECT_URI (none) If OIDC enabled The callback URL registered in your identity provider. Must be: https://your-patchmon-url/api/v1/auth/oidc/callback
OIDC_SCOPES openid email profile groups No Space-separated list of OAuth scopes to request. The groups scope is required for group-to-role mapping to work.
OIDC_ENFORCE_HTTPS true No When true (the default), the server rejects OIDC configurations using a non-HTTPS issuer URL. Set to false only in a local development environment with a non-TLS identity provider.

User Provisioning

Variable Default Required Description
OIDC_AUTO_CREATE_USERS false No When true, a PatchMon account is automatically created the first time an OIDC user logs in. When false, an administrator must create the account first.
OIDC_DEFAULT_ROLE user No Role assigned to automatically created OIDC users when no group mapping matches. Accepted values: superadmin, admin, host_manager, user, readonly.
OIDC_DISABLE_LOCAL_AUTH false No When true, local username/password authentication is disabled. Only OIDC login is accepted. Useful when enforcing SSO organisation-wide.

Login Page

Variable Default Required Description
OIDC_BUTTON_TEXT Login with SSO No Text displayed on the SSO login button on the PatchMon login page.
OIDC_POST_LOGOUT_URI Derived from FRONTEND_URL, then CORS_ORIGIN No URL the user is redirected to after logging out of the identity provider. Defaults to the login page of your PatchMon instance.

Session

Variable Default Required Description
OIDC_SESSION_TTL 600 No Lifetime in seconds of the temporary OIDC session state stored during the OAuth flow. Increase this only if users on very slow networks experience session-expired errors mid-login.

Group-to-Role Mapping

Map groups from your identity provider directly to PatchMon roles. Set OIDC_SYNC_ROLES=true to keep role assignments in sync with group membership on every login.

Variable Default Required Description
OIDC_SYNC_ROLES false No When true, the user's PatchMon role is updated on every login to match their current IdP group membership. When false, roles are managed locally in PatchMon and OIDC login does not change them.
OIDC_ADMIN_GROUP (none) No Name of the IdP group whose members are granted the admin role.
OIDC_SUPERADMIN_GROUP (none) No Name of the IdP group whose members are granted the superadmin role.
OIDC_HOST_MANAGER_GROUP (none) No Name of the IdP group whose members are granted the host_manager role.
OIDC_READONLY_GROUP (none) No Name of the IdP group whose members are granted the readonly role.
OIDC_USER_GROUP (none) No Name of the IdP group whose members are granted the standard user role.

Example: Authentik

OIDC_ENABLED=true
OIDC_ISSUER_URL=https://authentik.example.com/application/o/patchmon/
OIDC_CLIENT_ID=patchmon
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=https://patchmon.example.com/api/v1/auth/oidc/callback
OIDC_SCOPES=openid email profile groups
OIDC_AUTO_CREATE_USERS=true
OIDC_DEFAULT_ROLE=user
OIDC_BUTTON_TEXT=Login with Authentik
OIDC_SYNC_ROLES=true
OIDC_ADMIN_GROUP=PatchMon Admins
OIDC_USER_GROUP=PatchMon Users

Example: Keycloak

OIDC_ENABLED=true
OIDC_ISSUER_URL=https://keycloak.example.com/realms/your-realm
OIDC_CLIENT_ID=patchmon
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=https://patchmon.example.com/api/v1/auth/oidc/callback
OIDC_SCOPES=openid email profile groups
OIDC_AUTO_CREATE_USERS=true
OIDC_DEFAULT_ROLE=user
OIDC_BUTTON_TEXT=Login with Keycloak

10. Compliance / SSG

Settings for SCAP Security Guide content used by the compliance scanning feature.

Variable Default Required Description
SSG_CONTENT_DIR ./ssg-content No Path to the directory holding SCAP Security Guide datastream files (ssg-*-ds.xml), which agents download from. The official image already contains this content at /app/ssg-content and sets this variable for you, so leave it alone unless you are deliberately supplying your own content. Do not mount an empty volume at this path. Doing so hides the bundled content and leaves every host in your fleet unable to update its compliance content.

11. RDP / Remote Access

Configuration for the Guacamole daemon (guacd) that powers in-browser RDP sessions.

Variable Default Required Description
GUACD_PATH (none) No Absolute path to the guacd binary. When empty, the server locates guacd using the system PATH. Set this if guacd is installed in a non-standard location.
GUACD_ADDRESS 127.0.0.1:4822 No Host and port the server uses to connect to the running guacd process. Change this if guacd is running on a different host or non-default port.

Patching

Variable Default Required Description
PATCH_RUN_STALL_TIMEOUT_MIN 30 No Minutes a patch run can stay in running state before the periodic cleanup (every 10 minutes) marks it as timed_out. Minimum 5; values below 5 are clamped at startup with a warning. Also editable via Settings → Environment in the web UI; the env var still wins if set. Changes made in the UI take effect on the next cleanup sweep without a restart.

Reporting

Variable Default Required Description
AGENT_REPORTS_RETENTION_DAYS 30 No Days to retain Agent Activity rows (every ping, full report, partial report, Docker upload, and compliance scan submission writes one row). The daily cleanup sweep at 02:00 deletes anything older. Range 7..365; values outside the range are clamped at startup with a warning. Also editable via Settings → Environment in the web UI; the env var still wins if set. Changes made in the UI take effect on the next cleanup sweep without a restart.

12. Body Limits

Maximum sizes for request bodies accepted by the API. Increase these only if you encounter HTTP 413 errors caused by legitimate large payloads.

Accepted suffixes: b, kb, mb, gb. Examples: 10mb, 512kb.

Variable Default Required Description
JSON_BODY_LIMIT 5mb No Maximum size of JSON request bodies for standard API endpoints (user management, settings, host actions, etc.).
AGENT_UPDATE_BODY_LIMIT 5mb No Maximum size of request bodies on agent check-in and package reporting endpoints. Increase this if agents managing a very large number of packages hit the limit.

13. Timezone

Variable Default Required Description
TZ UTC No IANA timezone name used for timestamps in server logs and scheduled operations. If TZ is not set, the server also checks TIMEZONE before falling back to UTC. All timestamps stored in the database remain in UTC regardless of this setting.

Common values:

TZ=UTC                    # Recommended for servers
TZ=Europe/London
TZ=Europe/Paris
TZ=America/New_York
TZ=America/Chicago
TZ=America/Los_Angeles
TZ=Asia/Tokyo

14. Encryption Keys

PatchMon encrypts sensitive values at rest: AI provider credentials, bootstrap enrolment tokens, OIDC client secrets, notification destination secrets. The encryption key is resolved from the first non-empty value in this list:

  1. AI_ENCRYPTION_KEY
  2. SESSION_SECRET
  3. Derived from DATABASE_URL (fallback; not recommended for production)

If you rotate this value, every encrypted secret in the database becomes unreadable. Set it once at install time and treat it with the same care as JWT_SECRET.

Variable Default Required Description
AI_ENCRYPTION_KEY (none) Recommended 32+ byte random secret used to encrypt AI provider keys, bootstrap tokens, OIDC client secrets, and notification destination credentials. Configure via .env only (not editable from the Settings UI).
SESSION_SECRET (none) No Fallback encryption key used if AI_ENCRYPTION_KEY is not set. Exists for backward compatibility with early 1.x installs; prefer AI_ENCRYPTION_KEY for new deployments.

Generating a secure value:

openssl rand -hex 32

If neither AI_ENCRYPTION_KEY nor SESSION_SECRET is set, the server derives an encryption key from DATABASE_URL. This works but means your encryption key is only as strong as your database connection string. Any change to the DB host, port, or password rotates the encryption key and invalidates every encrypted value. Always set AI_ENCRYPTION_KEY explicitly in production.


15. Agent Binary Overrides

Advanced deployments that want to replace the bundled agent binaries (for example, to ship a custom build or host binaries on a different volume) can override the directory the install script serves from. Normally you should leave these unset. The server embeds all supported agent binaries in the image at build time.

Variable Default Required Description
AGENT_BINARIES_DIR (none) No Absolute path to a directory containing replacement agent binaries (e.g. patchmon-agent-linux-amd64). Takes precedence over AGENTS_DIR when both are set.
AGENTS_DIR (none) No Alternative name for AGENT_BINARIES_DIR. Kept for compatibility with installs that set this variable before 2.0.

When both are empty, the server serves binaries from the static/ path embedded in its binary.


16. Telemetry

PatchMon can send anonymous usage heartbeats (version, host count, rough OS distribution) to the upstream metrics endpoint once a day. This is fully opt-in. See Metrics and telemetry for what is sent and the Settings → Metrics page to toggle it.

Variable Default Required Description
METRICS_API_URL (none) No Override the upstream metrics endpoint. Leave empty to send to the default PatchMon telemetry service. Set to an internal URL to collect telemetry privately.

17. File Loading

Variable Default Required Description
ENV_FILE .env No Path to the .env file the server reads at startup. If the file does not exist at the given path, startup continues silently and only actual process environment variables are used.
FRONTEND_URL (none) No Optional alias used by OIDC when computing OIDC_POST_LOGOUT_URI. If set and OIDC_POST_LOGOUT_URI is not set, the post-logout redirect defaults to <FRONTEND_URL>/login. Otherwise the server falls back to <CORS_ORIGIN>/login. Most deployments can ignore this; set CORS_ORIGIN correctly and it's not needed.

Complete Minimal Configuration

The smallest valid .env for a production deployment:

# Required
DATABASE_URL="postgresql://patchmon_user:strongpassword@database:5432/patchmon_db"
JWT_SECRET="paste-output-of-openssl-rand-hex-64-here"

# Encryption (strongly recommended in production)
AI_ENCRYPTION_KEY="paste-output-of-openssl-rand-hex-32-here"

# Server
PORT=3000
APP_ENV=production
CORS_ORIGIN=https://patchmon.example.com
ENABLE_HSTS=true
TRUST_PROXY=true

# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD="paste-output-of-openssl-rand-hex-32-here"

# Logging
ENABLE_LOGGING=true
LOG_LEVEL=info

# Timezone
TZ=UTC

Everything else defaults to a sensible production value and does not need to be set unless you want to change the behaviour described in this document.

The setup-env.sh script shipped with the Docker compose generates a valid .env with all three secrets (JWT_SECRET, REDIS_PASSWORD, and POSTGRES_PASSWORD) pre-populated. See Installing PatchMon Server on Docker. For day-to-day changes to rate limits, logging, password policy, timezone, and similar runtime-tunable values, prefer the Settings UI. See Settings in the web UI.


Troubleshooting

Server fails to start with "DATABASE_URL is required" or "JWT_SECRET is required" These two variables have no default. Verify they are present in your .env file and that the file is being loaded (check the ENV_FILE variable if you use a custom path).

CORS errors in the browser CORS_ORIGIN must exactly match the URL in your browser's address bar, including the protocol (http vs https) and port. A common mistake is setting it to https://patchmon.example.com while accessing the site on http://. If you access PatchMon from multiple URLs, list all of them comma-separated with no spaces (e.g. CORS_ORIGIN=https://patchmon.example.com,https://patchmon.internal.lan).

Rate limit errors (HTTP 429) Increase the relevant *_RATE_LIMIT_MAX value for the endpoint category hitting the limit. For large agent fleets, AGENT_RATE_LIMIT_MAX is the most common one to raise.

Database connection pool exhausted Increase DB_CONNECTION_LIMIT. Check your PostgreSQL max_connections setting to ensure the total across all PatchMon instances does not exceed it.

OIDC login fails immediately after enabling Verify that OIDC_ISSUER_URL, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, and OIDC_REDIRECT_URI are all set. The server validates these on startup and will not start if any are missing when OIDC_ENABLED=true. Also confirm that OIDC_REDIRECT_URI is registered as an allowed callback URL in your identity provider.

Sessions lost after server restart Verify JWT_SECRET has not changed. Rotating this value invalidates all existing tokens.


PatchMon 2.0+ (Go server)