Skip to main content

Configuration

The Proxima Agent is configured through environment variables. Startup tuning (intervals, data dir, log level, install token) is read from the process environment — typically set as Environment= lines in the systemd unit. Operational configuration (collectors, labels, change detection, log collection, healthcheck, etc.) is managed centrally from the Console and delivered over NATS at runtime; see Config Sync.

No YAML config file

The agent does not read a YAML config file. There is no /etc/proxima-agent/config.yaml and no PROXIMA_AGENT_CONFIG variable — the install script writes settings as Environment= lines in the systemd unit, and all operational config comes from the Console via Config Sync. The YAML snippets below describe the shape of each config block (as stored in the Console / delivered over NATS), not a file the agent loads from disk.

Environment Variables

Environment variables are the agent's startup configuration. This is well suited to container deployments and secrets management.

VariableDefaultRequiredDescription
PROXIMA_AGENT_DATA_DIR/var/lib/proxima-agentNoDirectory for persisted agent state (state.json, config cache, file-hash DB, log cursors, etc.)
PROXIMA_AGENT_HEARTBEAT_INTERVAL30sNoHeartbeat interval (Go duration format)
PROXIMA_AGENT_INVENTORY_INTERVAL15mNoInventory collection interval (Go duration format)
PROXIMA_AGENT_METRICS_INTERVAL60sNoMetrics collection interval (Go duration format)
PROXIMA_AGENT_PROCESS_INTERVAL30sNoProcess snapshot interval (Go duration format)
PROXIMA_LOG_LEVELinfoNoLog level (debug, info, warn, error)
PROXIMA_BACKEND_URL--YesBackend HTTPS URL for enrollment and renewal
PROXIMA_INSTALL_TOKEN--Yes (first run)One-time install token for enrollment
PROXIMA_AGENT_LABELS--NoStatic labels as JSON (merges over YAML labels)
PROXIMA_AGENT_MEMORY_LIMIT_MB--NoGo soft memory limit in MB via debug.SetMemoryLimit (disabled if unset)
PROXIMA_AGENT_COLLECTOR_TIMEOUT30sNoPer-collector context deadline (Go duration format)
PROXIMA_PG_DSN--NoPostgreSQL DSN for metrics collection; auto-creates a collectors entry (empty = disabled)
PROXIMA_DOCKER_SOCKET/var/run/docker.sockNoDocker Unix socket path; applies to all docker collectors without an explicit socket_path

Loading Order

Startup configuration is resolved in the following order, where higher priority sources override lower ones:

  1. Environment variables (highest priority)
  2. Hardcoded defaults (lowest priority)

Operational config (collectors, labels, change detection, etc.) is layered on top at startup: the agent fetches its Console-managed config over NATS (falling back to its on-disk cache), and continues to receive live updates at runtime. See Config Sync for the full resolution chain.

Intervals

The heartbeat_interval, inventory_interval, metrics_interval, and process_interval values use Go duration format:

  • 30s -- 30 seconds
  • 15m -- 15 minutes
  • 1h -- 1 hour
  • 1h30m -- 1 hour and 30 minutes

Labels

Labels attach custom metadata to hosts, stored in the tags JSONB column. They are included in both inventory and heartbeat messages.

Static Labels

Static labels are simple key-value pairs defined in the labels config section or via the PROXIMA_AGENT_LABELS environment variable (JSON format). The env var merges over YAML values.

# Override or add labels via environment variable
export PROXIMA_AGENT_LABELS='{"role":"web","datacenter":"us-east-1"}'

Dynamic Labels

Dynamic labels run a shell command on a schedule and use the output as the label value. Commands must be specified as arrays (no string shorthand).

dynamic_labels:
- name: kernel # label key
command: ["uname", "-r"] # command to run (array format only)
period: 1h # how often to re-evaluate

Dynamic label rules:

  • name is required and becomes the label key
  • command must be a non-empty array
  • period minimum is 1 second
  • Commands run with a 10-second timeout
  • Output is trimmed and truncated to 512 bytes
  • On error, the label is omitted from the host tags (the previous successful value is retained; first-run failures mean the label is absent)
  • Static labels take precedence over dynamic labels on key conflict

Auto-Discovery

When auto_discover is enabled, the agent automatically detects running services at startup and configures collectors without manual YAML entries. This is opt-in and startup-only (restart the agent to detect new services).

Configuration

agent:
auto_discover: true

Or via environment variable:

export PROXIMA_AGENT_AUTO_DISCOVER=true

How It Works

The agent probes for known services using multiple detection signals (process names, TCP ports, Unix sockets, HTTP endpoints, config files). Any single signal match is sufficient for detection.

ServiceDetection SignalsResult
DockerSocket at /var/run/docker.sock, dockerd processAuto-configure with socket path
Nginxnginx process + probe stub_status URLs, fallback to nginx -T parseAuto-configure with discovered URL
PostgreSQLpostgres process, TCP 127.0.0.1:5432, /etc/postgresql dirDetect-only -- log config suggestion
Redisredis-server process, TCP 127.0.0.1:6379Detect-only -- log "not yet available"

Precedence Rules

  • Explicit config always wins -- if a collector type is defined in the collectors array (even if disabled), auto-discovery skips it entirely.
  • Auto-configurable services (Docker, Nginx) are fully set up with sensible defaults.
  • Detect-only services (PostgreSQL, Redis) require credentials, so the agent logs a suggestion and reports status: "discovered" in the heartbeat. These appear as blue "discovered" badges in the UI.

Example Log Output

INFO auto-discovered service component=discovery type=docker
INFO auto-discovered service component=discovery type=nginx
INFO discovered service (needs configuration) component=discovery type=postgresql suggestion="configure with: collectors: [{type: postgresql, dsn: \"...\"}]"

Collectors

The agent supports pluggable metrics collectors configured via the collectors array. Each entry specifies a collector type, an optional name (for multi-instance setups), and type-specific settings like dsn.

Configuration

collectors:
- type: postgresql
dsn: "postgres://user:password@localhost:5432/mydb?sslmode=disable"

# Multiple instances with custom names:
- type: postgresql
name: analytics-db
dsn: "postgres://user:password@analytics:5432/analytics?sslmode=disable"

# Nginx stub_status collector:
- type: nginx
url: "http://127.0.0.1/nginx_status"

# Disable a collector without removing it:
- type: postgresql
name: staging-db
enabled: false
dsn: "postgres://user:password@staging:5432/staging?sslmode=disable"

Each collector entry supports:

FieldRequiredDefaultDescription
typeYes--Collector type (postgresql, nginx, docker)
nameNoSame as typeInstance name (must be unique across all collectors)
enabledNotrueSet to false to skip this collector
dsnYes (for postgresql)--Connection string
urlYes (for nginx)--HTTP endpoint URL (e.g., stub_status URL)
socket_pathNo (for docker)/var/run/docker.sockPath to Docker Unix socket

Legacy Configuration

The legacy postgresql.dsn YAML key and PROXIMA_PG_DSN environment variable are still supported. They are automatically normalized into a collectors entry:

# Legacy format — still works:
postgresql:
dsn: "postgres://user:password@localhost:5432/mydb?sslmode=disable"
# Also creates a collector entry:
export PROXIMA_PG_DSN="postgres://user:password@localhost:5432/mydb?sslmode=disable"

The environment variable takes precedence over the YAML value. If no collectors are configured, the agent runs with system metrics only.

PostgreSQL Collector

Required Permissions

The PostgreSQL user needs read access to system catalog views. The pg_monitor role is recommended:

GRANT pg_monitor TO your_monitoring_user;

Collected Metrics

All metrics are labeled with collector=<name> (e.g., collector=pg-main) to enable multi-instance differentiation and frontend filtering.

MetricTypeLabelsSource
pg_connections_activegaugecollectorpg_stat_activity
pg_connections_idlegaugecollectorpg_stat_activity
pg_connections_maxgaugecollectorpg_settings
pg_cache_hit_ratiogaugecollectorpg_stat_database
pg_xact_commit_totalcountercollectorpg_stat_database
pg_xact_rollback_totalcountercollectorpg_stat_database
pg_deadlocks_totalcountercollectorpg_stat_database
pg_replication_lag_secondsgaugecollectorpg_stat_replication
pg_database_size_bytesgaugecollectorpg_database
pg_dead_tuplesgaugecollectorpg_stat_user_tables
pg_stat_statements_countgaugecollectorpg_stat_statements
pg_stat_statements_calls_totalcountercollectorpg_stat_statements
pg_stat_statements_time_seconds_totalcountercollectorpg_stat_statements
pg_stat_statements_slow_queriesgaugecollectorpg_stat_statements

The pg_stat_statements metrics are optional -- if the extension is not installed, they are silently skipped.

Runtime Configuration Collection

In addition to metrics, the PostgreSQL collector queries pg_settings every 5 minutes to collect runtime configuration parameters. This data is sent as part of the heartbeat collector status and displayed in the Config tab on the Integration Detail Page.

Collected parameters (19 total):

ParameterCategory
max_connectionsConnections and Authentication
shared_buffersResource Usage / Memory
effective_cache_sizeQuery Tuning / Planner Cost Constants
work_memResource Usage / Memory
maintenance_work_memResource Usage / Memory
max_wal_sizeWrite-Ahead Log / Checkpoints
checkpoint_timeoutWrite-Ahead Log / Checkpoints
random_page_costQuery Tuning / Planner Cost Constants
effective_io_concurrencyResource Usage / Asynchronous Behavior
max_worker_processesResource Usage / Worker Processes
max_parallel_workersResource Usage / Worker Processes
max_parallel_workers_per_gatherResource Usage / Worker Processes
wal_levelWrite-Ahead Log / Settings
max_wal_sendersReplication / Sending Servers
log_statementReporting and Logging
log_min_duration_statementReporting and Logging
autovacuumAutovacuum
autovacuum_max_workersAutovacuum
data_directoryFile Locations

Each parameter includes value, unit (if applicable), source (e.g., configuration file, default), and category from PostgreSQL's pg_settings view.

Config collection is independent of metric collection -- if the config query fails, metrics continue unaffected. The 5-minute cache interval prevents excessive queries against pg_settings.

Nginx Collector

The Nginx collector scrapes the stub_status endpoint to collect connection and request metrics.

Configuration

collectors:
- type: nginx
url: "http://127.0.0.1/nginx_status"

The url field must point to a location block with stub_status enabled. See the Nginx Integration page for full setup instructions including the Nginx config block.

Collected Metrics

All metrics are labeled with collector=<name> (e.g., collector=nginx-main) for multi-instance differentiation and frontend filtering.

MetricTypeSource
nginx_connections_activegaugestub_status line 1
nginx_connections_accepted_totalcounterstub_status line 3
nginx_connections_handled_totalcounterstub_status line 3
nginx_requests_totalcounterstub_status line 3
nginx_connections_readinggaugestub_status line 4
nginx_connections_writinggaugestub_status line 4
nginx_connections_waitinggaugestub_status line 4

The collector uses an HTTP client with a 5-second timeout. If the endpoint is unreachable or returns a non-200 status code, the collector reports an error status in the heartbeat.

Change Detection

The agent can monitor files for changes using SHA-256 hash comparison. When enabled, the agent scans watched paths on a schedule, detects new/modified/deleted files, and publishes change events to the backend. The backend computes unified diffs between file versions and stores them for review in the UI.

Configuration

agent:
change_detection:
enabled: true
interval: 2m
paths:
- /etc/nginx/nginx.conf
- /etc/nginx/conf.d/
- /etc/nginx/sites-available/
- /etc/ssh/sshd_config
- /etc/passwd
- /etc/sudoers
- /etc/crontab
exclude_patterns:
- "*.swp"
- "*.tmp"
- "*~"
sensitive_files:
- /etc/ssh/sshd_config
- /etc/sudoers
- /etc/shadow
max_file_size: 1048576
FieldDefaultDescription
enabledfalseEnable file change detection
interval60sScan interval (Go duration format)
paths[]Files and directories to watch. Directories are scanned recursively.
exclude_patterns[]Glob patterns for files to skip (e.g., *.swp, *.tmp)
sensitive_files[]File paths to mark as sensitive in the UI (content is still collected but flagged)
max_file_size1048576 (1 MB)Maximum file size in bytes. Files larger than this are hashed but content is not collected.
max_message_size0Maximum NATS message size in bytes. Large payloads are split into batches.

Environment Variables

VariableDescription
PROXIMA_AGENT_CHANGE_DETECTION_ENABLEDSet to true or 1 to enable (overrides YAML)
PROXIMA_AGENT_CHANGE_DETECTION_INTERVALScan interval (Go duration format, overrides YAML)

How It Works

  1. Baseline scan -- on the first run, the agent scans all watched paths, computes SHA-256 hashes, and sends a baseline snapshot. The backend creates watched_files records but no change events.
  2. Delta scans -- on subsequent runs, the agent compares current file hashes against its local hash database (a JSON file). Only changed, created, or deleted files are published.
  3. Diff computation -- the backend computes unified diffs between file versions using the Myers diff algorithm. Diffs are stored in both file_versions.diff_text and change_events.details.diff_text.
  4. Change events -- each detected change creates a change_event record with event type (file_created, file_modified, file_deleted, file_metadata_changed), severity, and details.

Path Types

  • Individual files (e.g., /etc/nginx/nginx.conf) -- watched directly
  • Directories (trailing /, e.g., /etc/nginx/conf.d/) -- all files within the directory are watched recursively
  • Glob patterns are supported in exclude_patterns only

Severity Levels

Event TypeDefault Severity
file_createdinfo
file_modifiedinfo
file_deletedwarning
file_metadata_changedinfo

Sensitive files (matching sensitive_files paths) are elevated to warning severity for modifications.

Dynamic Configuration (Remote Override)

In addition to the YAML config, watch paths can be managed remotely from the backend API without restarting the agent. This is the recommended approach for managing watch paths across a fleet of agents.

Update via API:

curl -X PUT https://api-console.prxm.uz/api/v1/hosts/{hostID}/watch-config \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"paths": ["/etc/"],
"exclude_patterns": ["*.swp", "*.tmp"],
"sensitive_files": ["/etc/shadow", "/etc/sudoers"],
"max_file_size": 1048576
}'

The backend saves the config to the database and pushes it to the agent immediately via NATS. The agent applies the new config on its next scan cycle.

How overrides work:

PhaseStrategyBehavior
StartupSelective mergeRemote config fields override YAML only when non-empty. Empty or missing remote fields fall back to YAML values.
RuntimeFull overwriteThe NATS command replaces paths, exclude_patterns, sensitive_files, and max_file_size entirely. YAML is not re-read.
tip

When pushing a runtime update, include all fields you want to keep — not just the ones you're changing. Omitting exclude_patterns from a runtime update will clear any custom excludes.

Persistence: Remote config is stored in the backend database (host_configs table). On agent restart, the remote config is fetched again and merged with YAML, so changes survive restarts without modifying the YAML file.

See How It Works — Config Priority and Override Behavior for full details on the merge logic.

Hash Database

The agent persists file hashes as a JSON file at {data_dir}/file_hashes.json. This allows the agent to detect changes across restarts without re-sending baselines. If the file is deleted, the next scan produces a new baseline.

Log Collection

Added in v0.3.0

Log collection gathers logs from systemd journald and arbitrary log files, then ships them to the Proxima Console backend via NATS for storage in VictoriaLogs.

Configuration

agent:
log_collection:
enabled: true
journald:
enabled: true
units: [] # empty = all units
files:
- path: /var/log/syslog
- path: /var/log/nginx/access.log
name: nginx-access
parser: json
buffer_size: 1000
max_line_len: 8192
log_interval: 10s

Configuration Fields

FieldTypeDefaultDescription
log_collection.enabledboolfalseEnable log collection
log_collection.journald.enabledbooltrueEnable journald log collection (when log_collection is enabled)
log_collection.journald.units[]string[]Filter to specific systemd units (empty = all units)
log_collection.files[]object[]List of log files to tail
log_collection.files[].pathstringrequiredAbsolute path to the log file
log_collection.files[].namestringbasenameDisplay name for the log source
log_collection.files[].parserstringautoParser type: auto, json, plain
log_collection.buffer_sizeint1000Maximum entries to buffer before flush
log_collection.max_line_lenint8192Maximum line length (truncates longer lines)
log_intervalduration10sLog flush interval

Environment Variable Overrides

VariableDescription
PROXIMA_AGENT_LOG_COLLECTION_ENABLEDEnable log collection (true or 1)
PROXIMA_AGENT_LOG_INTERVALLog flush interval (Go duration format, e.g. 10s)

How It Works

  1. Journald: Spawns journalctl --output=json --follow as a subprocess, reads log entries in real-time. Supports cursor persistence for resume after restart.
  2. File tailing: Poll-based file tailing with inode rotation detection. Persists read offset for resume after restart.
  3. Publishing: Buffered entries are flushed at the configured interval via NATS on the proxima.{client}.{env}.{host}.logs subject.
  4. Storage: Backend LogsWorker consumes log messages and writes them to VictoriaLogs with tenant-scoped AccountID headers for multi-tenancy isolation.

File Permissions

There is no config file to protect — the install token is set as an Environment= line in the systemd unit. The install script creates the data directory (/var/lib/proxima-agent) with mode 0700, and the agent writes state.json (which holds the NATS credentials) with mode 0600. Ensure the data directory and its contents remain restricted to the user running the agent process.