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.
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.
| Variable | Default | Required | Description |
|---|---|---|---|
PROXIMA_AGENT_DATA_DIR | /var/lib/proxima-agent | No | Directory for persisted agent state (state.json, config cache, file-hash DB, log cursors, etc.) |
PROXIMA_AGENT_HEARTBEAT_INTERVAL | 30s | No | Heartbeat interval (Go duration format) |
PROXIMA_AGENT_INVENTORY_INTERVAL | 15m | No | Inventory collection interval (Go duration format) |
PROXIMA_AGENT_METRICS_INTERVAL | 60s | No | Metrics collection interval (Go duration format) |
PROXIMA_AGENT_PROCESS_INTERVAL | 30s | No | Process snapshot interval (Go duration format) |
PROXIMA_LOG_LEVEL | info | No | Log level (debug, info, warn, error) |
PROXIMA_BACKEND_URL | -- | Yes | Backend HTTPS URL for enrollment and renewal |
PROXIMA_INSTALL_TOKEN | -- | Yes (first run) | One-time install token for enrollment |
PROXIMA_AGENT_LABELS | -- | No | Static labels as JSON (merges over YAML labels) |
PROXIMA_AGENT_MEMORY_LIMIT_MB | -- | No | Go soft memory limit in MB via debug.SetMemoryLimit (disabled if unset) |
PROXIMA_AGENT_COLLECTOR_TIMEOUT | 30s | No | Per-collector context deadline (Go duration format) |
PROXIMA_PG_DSN | -- | No | PostgreSQL DSN for metrics collection; auto-creates a collectors entry (empty = disabled) |
PROXIMA_DOCKER_SOCKET | /var/run/docker.sock | No | Docker 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:
- Environment variables (highest priority)
- 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 seconds15m-- 15 minutes1h-- 1 hour1h30m-- 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:
nameis required and becomes the label keycommandmust be a non-empty arrayperiodminimum 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.
| Service | Detection Signals | Result |
|---|---|---|
| Docker | Socket at /var/run/docker.sock, dockerd process | Auto-configure with socket path |
| Nginx | nginx process + probe stub_status URLs, fallback to nginx -T parse | Auto-configure with discovered URL |
| PostgreSQL | postgres process, TCP 127.0.0.1:5432, /etc/postgresql dir | Detect-only -- log config suggestion |
| Redis | redis-server process, TCP 127.0.0.1:6379 | Detect-only -- log "not yet available" |
Precedence Rules
- Explicit config always wins -- if a collector type is defined in the
collectorsarray (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:
| Field | Required | Default | Description |
|---|---|---|---|
type | Yes | -- | Collector type (postgresql, nginx, docker) |
name | No | Same as type | Instance name (must be unique across all collectors) |
enabled | No | true | Set to false to skip this collector |
dsn | Yes (for postgresql) | -- | Connection string |
url | Yes (for nginx) | -- | HTTP endpoint URL (e.g., stub_status URL) |
socket_path | No (for docker) | /var/run/docker.sock | Path 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.
| Metric | Type | Labels | Source |
|---|---|---|---|
pg_connections_active | gauge | collector | pg_stat_activity |
pg_connections_idle | gauge | collector | pg_stat_activity |
pg_connections_max | gauge | collector | pg_settings |
pg_cache_hit_ratio | gauge | collector | pg_stat_database |
pg_xact_commit_total | counter | collector | pg_stat_database |
pg_xact_rollback_total | counter | collector | pg_stat_database |
pg_deadlocks_total | counter | collector | pg_stat_database |
pg_replication_lag_seconds | gauge | collector | pg_stat_replication |
pg_database_size_bytes | gauge | collector | pg_database |
pg_dead_tuples | gauge | collector | pg_stat_user_tables |
pg_stat_statements_count | gauge | collector | pg_stat_statements |
pg_stat_statements_calls_total | counter | collector | pg_stat_statements |
pg_stat_statements_time_seconds_total | counter | collector | pg_stat_statements |
pg_stat_statements_slow_queries | gauge | collector | pg_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):
| Parameter | Category |
|---|---|
max_connections | Connections and Authentication |
shared_buffers | Resource Usage / Memory |
effective_cache_size | Query Tuning / Planner Cost Constants |
work_mem | Resource Usage / Memory |
maintenance_work_mem | Resource Usage / Memory |
max_wal_size | Write-Ahead Log / Checkpoints |
checkpoint_timeout | Write-Ahead Log / Checkpoints |
random_page_cost | Query Tuning / Planner Cost Constants |
effective_io_concurrency | Resource Usage / Asynchronous Behavior |
max_worker_processes | Resource Usage / Worker Processes |
max_parallel_workers | Resource Usage / Worker Processes |
max_parallel_workers_per_gather | Resource Usage / Worker Processes |
wal_level | Write-Ahead Log / Settings |
max_wal_senders | Replication / Sending Servers |
log_statement | Reporting and Logging |
log_min_duration_statement | Reporting and Logging |
autovacuum | Autovacuum |
autovacuum_max_workers | Autovacuum |
data_directory | File 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.
| Metric | Type | Source |
|---|---|---|
nginx_connections_active | gauge | stub_status line 1 |
nginx_connections_accepted_total | counter | stub_status line 3 |
nginx_connections_handled_total | counter | stub_status line 3 |
nginx_requests_total | counter | stub_status line 3 |
nginx_connections_reading | gauge | stub_status line 4 |
nginx_connections_writing | gauge | stub_status line 4 |
nginx_connections_waiting | gauge | stub_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
| Field | Default | Description |
|---|---|---|
enabled | false | Enable file change detection |
interval | 60s | Scan 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_size | 1048576 (1 MB) | Maximum file size in bytes. Files larger than this are hashed but content is not collected. |
max_message_size | 0 | Maximum NATS message size in bytes. Large payloads are split into batches. |
Environment Variables
| Variable | Description |
|---|---|
PROXIMA_AGENT_CHANGE_DETECTION_ENABLED | Set to true or 1 to enable (overrides YAML) |
PROXIMA_AGENT_CHANGE_DETECTION_INTERVAL | Scan interval (Go duration format, overrides YAML) |
How It Works
- 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_filesrecords but no change events. - 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.
- Diff computation -- the backend computes unified diffs between file versions using the Myers diff algorithm. Diffs are stored in both
file_versions.diff_textandchange_events.details.diff_text. - Change events -- each detected change creates a
change_eventrecord 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_patternsonly
Severity Levels
| Event Type | Default Severity |
|---|---|
file_created | info |
file_modified | info |
file_deleted | warning |
file_metadata_changed | info |
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:
| Phase | Strategy | Behavior |
|---|---|---|
| Startup | Selective merge | Remote config fields override YAML only when non-empty. Empty or missing remote fields fall back to YAML values. |
| Runtime | Full overwrite | The NATS command replaces paths, exclude_patterns, sensitive_files, and max_file_size entirely. YAML is not re-read. |
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
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
| Field | Type | Default | Description |
|---|---|---|---|
log_collection.enabled | bool | false | Enable log collection |
log_collection.journald.enabled | bool | true | Enable 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[].path | string | required | Absolute path to the log file |
log_collection.files[].name | string | basename | Display name for the log source |
log_collection.files[].parser | string | auto | Parser type: auto, json, plain |
log_collection.buffer_size | int | 1000 | Maximum entries to buffer before flush |
log_collection.max_line_len | int | 8192 | Maximum line length (truncates longer lines) |
log_interval | duration | 10s | Log flush interval |
Environment Variable Overrides
| Variable | Description |
|---|---|
PROXIMA_AGENT_LOG_COLLECTION_ENABLED | Enable log collection (true or 1) |
PROXIMA_AGENT_LOG_INTERVAL | Log flush interval (Go duration format, e.g. 10s) |
How It Works
- Journald: Spawns
journalctl --output=json --followas a subprocess, reads log entries in real-time. Supports cursor persistence for resume after restart. - File tailing: Poll-based file tailing with inode rotation detection. Persists read offset for resume after restart.
- Publishing: Buffered entries are flushed at the configured interval via NATS on the
proxima.{client}.{env}.{host}.logssubject. - 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.