Skip to main content

PatchMon Environment Variables Reference

This document provides a comprehensive reference for all environment variables available in PatchMon. These variables can be configured in your .env file (bare metal installations) or in your docker-compose.yml file (Docker deployments).

Table of Contents


Database Configuration

PostgreSQL database connection settings.

Variable Description Default Required Example
DATABASE_URL PostgreSQL connection string - ✅ Yes postgresql://user:pass@localhost:5432/patchmon_db
PM_DB_CONN_MAX_ATTEMPTS Maximum database connection attempts during startup 30 No 30
PM_DB_CONN_WAIT_INTERVAL Wait interval between connection attempts (seconds) 2 No 2

Usage Notes

  • The DATABASE_URL must be a valid PostgreSQL connection string
  • Connection retry logic helps handle database startup delays in containerized environments
  • Format: postgresql://[user]:[password]@[host]:[port]/[database]

Database Connection Pool (Prisma)

Connection pooling configuration for optimal database performance and resource management.

Variable Description Default Required Example
DB_CONNECTION_LIMIT Maximum number of database connections per instance 30 No 30
DB_POOL_TIMEOUT Seconds to wait for an available connection before timeout 20 No 20
DB_CONNECT_TIMEOUT Seconds to wait for initial database connection 10 No 10
DB_IDLE_TIMEOUT Seconds before closing idle connections 300 No 300
DB_MAX_LIFETIME Maximum lifetime of a connection in seconds 1800 No 1800

Sizing Guidelines

Small Deployment (1-10 hosts):

DB_CONNECTION_LIMIT=15
DB_POOL_TIMEOUT=20

Medium Deployment (10-50 hosts):

DB_CONNECTION_LIMIT=30  # Default
DB_POOL_TIMEOUT=20

Large Deployment (50+ hosts):

DB_CONNECTION_LIMIT=50
DB_POOL_TIMEOUT=30

Connection Pool Calculation

Use this formula to estimate your needs:

DB_CONNECTION_LIMIT = (expected_hosts * 2) + (concurrent_users * 2) + 5

Example: 20 hosts + 3 concurrent users:

(20 * 2) + (3 * 2) + 5 = 51 connections

Important Notes

  • Each backend instance maintains its own connection pool
  • Running multiple backend instances requires considering total connections to PostgreSQL
  • PostgreSQL default max_connections is 100 (ensure your pool size doesn't exceed this)
  • Connections are reused efficiently - you don't need one connection per host
  • Increase pool size if experiencing timeout errors during high load

Detecting Connection Pool Issues

When connection pool limits are hit, you'll see clear error messages in your backend console:

Typical Pool Timeout Error:

Host creation error: Error: Timed out fetching a new connection from the connection pool.
⚠️  DATABASE CONNECTION POOL EXHAUSTED!
⚠️  Current limit: DB_CONNECTION_LIMIT=30
⚠️  Pool timeout: DB_POOL_TIMEOUT=20s
⚠️  Suggestion: Increase DB_CONNECTION_LIMIT in your .env file

Frontend Error:

POST /api/v1/hosts/create 500 (Internal Server Error)
Response: { "error": "Failed to create host" }

If you see these errors frequently, increase DB_CONNECTION_LIMIT by 10-20 and monitor your system.

Monitoring Connection Pool Usage

You can monitor your PostgreSQL connections to determine optimal pool size:

Check Current Connections:

# Connect to PostgreSQL
psql -U patchmon_user -d patchmon_db

# Run this query
SELECT count(*) as current_connections, 
       (SELECT setting::int FROM pg_settings WHERE name='max_connections') as max_connections
FROM pg_stat_activity 
WHERE datname = 'patchmon_db';

View Connection Details:

SELECT 
    usename,
    application_name,
    client_addr,
    state,
    backend_start,
    state_change
FROM pg_stat_activity 
WHERE datname = 'patchmon_db'
ORDER BY backend_start DESC;
  • If current_connections frequently approaches DB_CONNECTION_LIMIT, increase the pool size
  • Monitor during peak usage (when multiple users are active, agents checking in)
  • Leave 20-30% headroom for burst traffic

Authentication & Security

JWT token configuration and security settings.

Variable Description Default Required Example
JWT_SECRET Secret key for signing JWT tokens - ✅ Yes your-secure-random-secret-key
JWT_EXPIRES_IN Access token expiration time 1h No 1h, 30m, 2h
JWT_REFRESH_EXPIRES_IN Refresh token expiration time 7d No 7d, 3d, 14d

Generating Secure Secrets

Linux/macOS:

openssl rand -hex 64

Node.js:

require('crypto').randomBytes(64).toString('hex')

Time Format

Supports the following formats:

  • s: seconds
  • m: minutes
  • h: hours
  • d: days

Examples: 30s, 15m, 2h, 7d

Development:

JWT_EXPIRES_IN=1h
JWT_REFRESH_EXPIRES_IN=7d

Production:

JWT_EXPIRES_IN=30m
JWT_REFRESH_EXPIRES_IN=3d

High Security:

JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=1d

Session Management

Control user session behavior and security.

Variable Description Default Required Example
SESSION_INACTIVITY_TIMEOUT_MINUTES Minutes of inactivity before automatic logout 30 No 30

Usage Notes

  • Sessions are tracked in the database with activity timestamps
  • Each authenticated request updates the session activity
  • Expired sessions are automatically invalidated
  • Users must log in again after timeout period
  • Lower values provide better security but may impact user experience
  • High Security Environment: 15 minutes
  • Standard Security: 30 minutes (default)
  • User-Friendly: 60 minutes

Server & Network Configuration

Server protocol, host, and CORS settings.

Variable Description Default Required Example
PORT Backend API server port 3001 No 3001
NODE_ENV Node.js environment mode production No production, development
SERVER_PROTOCOL Frontend server protocol http No http, https
SERVER_HOST Frontend server hostname/domain localhost No patchmon.example.com
SERVER_PORT Frontend server port 3000 No 3000, 443
CORS_ORIGIN Allowed CORS origin URL http://localhost:3000 No https://patchmon.example.com
ENABLE_HSTS Enable HTTP Strict Transport Security true No true, false
TRUST_PROXY Trust proxy headers (when behind reverse proxy) true No true, false, 1, loopback

Usage Notes

  • SERVER_PROTOCOL, SERVER_HOST, and SERVER_PORT are used to generate agent installation scripts
  • CORS_ORIGIN must match the URL you use to access the frontend
  • Set TRUST_PROXY to true when behind nginx, Apache, or other reverse proxies
  • ENABLE_HSTS should be true in production with HTTPS

Example Configurations

Local Development:

SERVER_PROTOCOL=http
SERVER_HOST=localhost
SERVER_PORT=3000
CORS_ORIGIN=http://localhost:3000
ENABLE_HSTS=false
TRUST_PROXY=false

Production with HTTPS:

SERVER_PROTOCOL=https
SERVER_HOST=patchmon.example.com
SERVER_PORT=443
CORS_ORIGIN=https://patchmon.example.com
ENABLE_HSTS=true
TRUST_PROXY=true

Production with Custom Port:

SERVER_PROTOCOL=https
SERVER_HOST=patchmon.example.com
SERVER_PORT=8443
CORS_ORIGIN=https://patchmon.example.com:8443
ENABLE_HSTS=true
TRUST_PROXY=true

Rate Limiting

Protect your API from abuse with configurable rate limits.

Variable Description Default Required Example
RATE_LIMIT_WINDOW_MS General rate limit window (milliseconds) 900000 No 900000 (15 min)
RATE_LIMIT_MAX Maximum requests per window (general) 5000 No 5000
AUTH_RATE_LIMIT_WINDOW_MS Authentication endpoints rate limit window (ms) 600000 No 600000 (10 min)
AUTH_RATE_LIMIT_MAX Maximum auth requests per window 500 No 500
AGENT_RATE_LIMIT_WINDOW_MS Agent API rate limit window (ms) 60000 No 60000 (1 min)
AGENT_RATE_LIMIT_MAX Maximum agent requests per window 1000 No 1000

Understanding Rate Limits

Rate limits are applied per IP address and endpoint category:

  • General API: Dashboard, hosts, packages, user management
  • Authentication: Login, logout, token refresh
  • Agent API: Agent check-ins, updates, package reports

Calculating Windows

The window is a sliding time frame. Examples:

  • 900000 ms = 15 minutes
  • 600000 ms = 10 minutes
  • 60000 ms = 1 minute

Default (Balanced):

RATE_LIMIT_WINDOW_MS=900000      # 15 minutes
RATE_LIMIT_MAX=5000              # ~5.5 requests/second
AUTH_RATE_LIMIT_WINDOW_MS=600000 # 10 minutes
AUTH_RATE_LIMIT_MAX=500          # ~0.8 requests/second
AGENT_RATE_LIMIT_WINDOW_MS=60000 # 1 minute
AGENT_RATE_LIMIT_MAX=1000        # ~16 requests/second

Strict (High Security):

RATE_LIMIT_WINDOW_MS=900000      # 15 minutes
RATE_LIMIT_MAX=2000              # ~2.2 requests/second
AUTH_RATE_LIMIT_WINDOW_MS=600000 # 10 minutes
AUTH_RATE_LIMIT_MAX=100          # ~0.16 requests/second
AGENT_RATE_LIMIT_WINDOW_MS=60000 # 1 minute
AGENT_RATE_LIMIT_MAX=500         # ~8 requests/second

Relaxed (Development/Testing):

RATE_LIMIT_WINDOW_MS=900000      # 15 minutes
RATE_LIMIT_MAX=10000             # ~11 requests/second
AUTH_RATE_LIMIT_WINDOW_MS=600000 # 10 minutes
AUTH_RATE_LIMIT_MAX=1000         # ~1.6 requests/second
AGENT_RATE_LIMIT_WINDOW_MS=60000 # 1 minute
AGENT_RATE_LIMIT_MAX=2000        # ~33 requests/second

Redis Configuration

Redis is used for BullMQ job queues and caching.

Variable Description Default Required Example
REDIS_HOST Redis server hostname localhost No localhost, redis, 10.0.0.5
REDIS_PORT Redis server port 6379 No 6379
REDIS_USER Redis username (Redis 6+) - No default
REDIS_PASSWORD Redis authentication password - ⚠️ Recommended your-redis-password
REDIS_DB Redis database number 0 No 0, 1, 2

Usage Notes

  • Redis authentication is highly recommended for security
  • Redis 6.0+ supports ACL with usernames; earlier versions use password-only auth
  • If no password is set, Redis will be accessible without authentication (not recommended)
  • Database number allows multiple applications to use the same Redis instance

Docker Deployment

In Docker, the Redis password must be set in two places:

  1. Redis service command:

    command: redis-server --requirepass your-redis-password-here
    
  2. Backend environment:

    REDIS_PASSWORD: your-redis-password-here
    

Generating Secure Passwords

openssl rand -hex 32

Logging

Control application logging behavior and verbosity.

Variable Description Default Required Example
LOG_LEVEL Logging level info No debug, info, warn, error
ENABLE_LOGGING Enable/disable application logging true No true, false
PRISMA_LOG_QUERIES Log all Prisma database queries false No true, false

Log Levels

Ordered from most to least verbose:

  1. debug: All logs including database queries, internal operations
  2. info: General information, startup messages, normal operations
  3. warn: Warning messages, deprecated features, non-critical issues
  4. error: Error messages only, critical issues

Development:

LOG_LEVEL=debug
ENABLE_LOGGING=true
PRISMA_LOG_QUERIES=true

Production:

LOG_LEVEL=info
ENABLE_LOGGING=true
PRISMA_LOG_QUERIES=false

Production (Quiet):

LOG_LEVEL=warn
ENABLE_LOGGING=true
PRISMA_LOG_QUERIES=false

Two-Factor Authentication (TFA)

Optional two-factor authentication settings (when TFA is enabled).

Variable Description Default Required Example
TFA_REMEMBER_ME_EXPIRES_IN "Remember this device" token expiration 30d No 30d, 7d, 90d
TFA_MAX_REMEMBER_SESSIONS Maximum remembered devices per user 5 No 5
TFA_SUSPICIOUS_ACTIVITY_THRESHOLD Failed attempts before flagging suspicious 3 No 3

Usage Notes

  • These variables only apply when users have TFA enabled
  • "Remember this device" allows users to skip TFA on trusted devices
  • Suspicious activity detection helps prevent brute force attacks
  • Remembered sessions can be revoked by users or admins

Time Format

Same as JWT expiration: s (seconds), m (minutes), h (hours), d (days)

Standard:

TFA_REMEMBER_ME_EXPIRES_IN=30d
TFA_MAX_REMEMBER_SESSIONS=5
TFA_SUSPICIOUS_ACTIVITY_THRESHOLD=3

High Security:

TFA_REMEMBER_ME_EXPIRES_IN=7d
TFA_MAX_REMEMBER_SESSIONS=3
TFA_SUSPICIOUS_ACTIVITY_THRESHOLD=2

User Management

Default settings for new users.

Variable Description Default Required Example
DEFAULT_USER_ROLE Default role assigned to new users user No user, admin, viewer

Available Roles

  • admin: Full system access, can manage users and settings
  • user: Standard access, can manage hosts and packages
  • viewer: Read-only access, cannot make changes

Usage Notes

  • Only applies to newly created users
  • Existing users are not affected by changes to this variable
  • First user created through setup is always an admin
  • Can be changed per-user through the user management interface

Frontend Configuration

Frontend-specific environment variables (used during build and runtime).

Variable Description Default Required Example
VITE_API_URL Backend API base URL /api/v1 No http://localhost:3001/api/v1
VITE_APP_NAME Application name displayed in UI PatchMon No PatchMon
VITE_APP_VERSION Application version displayed in UI (from package.json) No 1.3.1
BACKEND_HOST Backend hostname (Docker only) backend No backend, localhost
BACKEND_PORT Backend port (Docker only) 3001 No 3001
VITE_ENABLE_LOGGING Enable frontend debug logging false No true, false

Usage Notes

  • Frontend variables are prefixed with VITE_ for Vite build system
  • These are embedded during build time (except for Docker runtime variables)
  • VITE_API_URL can be relative (/api/v1) or absolute
  • Docker-specific variables (BACKEND_HOST, BACKEND_PORT) are used by the frontend server proxy

Complete Example Configuration

Bare Metal (Production)

# Database Configuration
DATABASE_URL="postgresql://patchmon_user:secure_db_password@localhost:5432/patchmon_db"
PM_DB_CONN_MAX_ATTEMPTS=30
PM_DB_CONN_WAIT_INTERVAL=2

# Database Connection Pool
DB_CONNECTION_LIMIT=30
DB_POOL_TIMEOUT=20
DB_CONNECT_TIMEOUT=10
DB_IDLE_TIMEOUT=300
DB_MAX_LIFETIME=1800

# JWT Configuration
JWT_SECRET="generated-secure-secret-from-openssl"
JWT_EXPIRES_IN=30m
JWT_REFRESH_EXPIRES_IN=3d

# Server Configuration
PORT=3001
NODE_ENV=production
SERVER_PROTOCOL=https
SERVER_HOST=patchmon.example.com
SERVER_PORT=443
CORS_ORIGIN=https://patchmon.example.com
ENABLE_HSTS=true
TRUST_PROXY=true

# Session Configuration
SESSION_INACTIVITY_TIMEOUT_MINUTES=30

# User Configuration
DEFAULT_USER_ROLE=user

# Rate Limiting
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX=5000
AUTH_RATE_LIMIT_WINDOW_MS=600000
AUTH_RATE_LIMIT_MAX=500
AGENT_RATE_LIMIT_WINDOW_MS=60000
AGENT_RATE_LIMIT_MAX=1000

# Redis Configuration
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=secure_redis_password
REDIS_DB=0

# Logging
LOG_LEVEL=info
ENABLE_LOGGING=true

# TFA Configuration (Optional)
TFA_REMEMBER_ME_EXPIRES_IN=30d
TFA_MAX_REMEMBER_SESSIONS=5
TFA_SUSPICIOUS_ACTIVITY_THRESHOLD=3

Docker Compose (Production)

See docker/docker-compose.yml for a complete Docker deployment example with all variables.


Troubleshooting

Common Issues

"timeout of 10000ms exceeded" when adding hosts:

  • Increase DB_CONNECTION_LIMIT (try 30 or higher)
  • Increase DB_POOL_TIMEOUT (try 20 or 30)
  • Check backend logs for "⚠️ DATABASE CONNECTION POOL EXHAUSTED!" messages
  • Monitor PostgreSQL connection count: SELECT count(*) FROM pg_stat_activity WHERE datname = 'patchmon_db';

Database connection failures on startup:

  • Increase PM_DB_CONN_MAX_ATTEMPTS
  • Increase PM_DB_CONN_WAIT_INTERVAL
  • Verify DATABASE_URL is correct

"Invalid or expired session" errors:

  • Check JWT_SECRET hasn't changed
  • Verify SESSION_INACTIVITY_TIMEOUT_MINUTES isn't too low
  • Ensure JWT_EXPIRES_IN is reasonable

Rate limit errors:

  • Increase RATE_LIMIT_MAX values
  • Increase window duration (*_WINDOW_MS variables)

CORS errors:

  • Verify CORS_ORIGIN matches your frontend URL exactly
  • Include protocol, domain, and port (if non-standard)

Security Best Practices

  1. Always set strong passwords:

    • Use openssl rand -hex 64 for JWT secrets
    • Use openssl rand -hex 32 for database/Redis passwords
  2. Enable HTTPS in production:

    • Set SERVER_PROTOCOL=https
    • Enable ENABLE_HSTS=true
    • Use proper SSL certificates
  3. Configure appropriate rate limits:

    • Adjust based on expected traffic
    • Monitor for rate limit violations
    • Lower limits for public-facing deployments
  4. Use session timeouts:

    • Don't set SESSION_INACTIVITY_TIMEOUT_MINUTES too high
    • Balance security with user experience
  5. Secure Redis:

    • Always set REDIS_PASSWORD
    • Use Redis ACLs in Redis 6+ for additional security
    • Don't expose Redis port publicly
  6. Connection pool sizing:

    • Monitor database connections under load
    • Adjust DB_CONNECTION_LIMIT based on actual usage
    • Ensure total connections don't exceed PostgreSQL limits

Version Information

  • Document Version: 1.0
  • Last Updated: October 2025
  • Applicable to PatchMon: v1.3.1+

For updates and additional documentation, see: https://github.com/PatchMon/PatchMon