Skip to main content
PathMon

Chapter 11 of 15

Agent config.yml Reference

Updated Read the full guide

Overview

The PatchMon agent is configured through a YAML file. On Linux the default path is /etc/patchmon/config.yml. On Windows it is C:\ProgramData\PatchMon\config.yml. This file controls how the agent communicates with the PatchMon server, where logs are stored, which integrations are active, and other runtime behaviour. A separate credentials file stores the host's API authentication details (/etc/patchmon/credentials.yml on Linux, C:\ProgramData\PatchMon\credentials.yml on Windows).

On Linux, these files are owned by root and set to 600 permissions (read/write by owner only) to protect sensitive information.

File Locations

File Default Path Purpose
Configuration Linux: /etc/patchmon/config.yml Windows: C:\ProgramData\PatchMon\config.yml Agent settings, server URL, integrations
Credentials Linux: /etc/patchmon/credentials.yml Windows: C:\ProgramData\PatchMon\credentials.yml API ID and API Key for host authentication
Log File Linux: /etc/patchmon/logs/patchmon-agent.log Windows: C:\ProgramData\PatchMon\patchmon-agent.log Agent log output
Cron File /etc/cron.d/patchmon-agent Scheduled reporting (fallback for non-systemd systems)

Quoting Windows paths

YAML treats a backslash inside double quotes as the start of an escape sequence, so a double-quoted Windows path is either rejected or silently altered. "C:\ProgramData\PatchMon\credentials.yml" fails to parse, because \c is not a valid escape. "C:\ProgramData\PatchMon\Notes" is worse: it parses, but \N is a valid escape and becomes a control character, so the path you get is not the path you wrote.

Use single quotes, or no quotes at all, for any value containing a backslash:

credentials_file: 'C:\ProgramData\PatchMon\credentials.yml'
log_file: C:\ProgramData\PatchMon\patchmon-agent.log

If config.yml cannot be parsed, the agent service refuses to start rather than falling back to its built-in defaults, and writes the parse error to the agent log. This is deliberate: an agent running on defaults has no server URL, so it reports nothing, and its first save would overwrite your file with those defaults. One-off commands such as report and ping, including the cron fallback on hosts without systemd, still run, but they will fail against that empty server URL.

The same applies to a config.yml that is present but empty, which is what a write interrupted by a full disk or a power cut leaves behind.

To recover, repair the file, or run patchmon-agent config set-api <API_ID> <API_KEY> <SERVER_URL> (patchmon-agent.exe on Windows) to write a fresh one. Note that this writes a complete new file, so any other settings the old one held are lost.

Full Configuration Reference

Below is a complete config.yml with all available parameters, their defaults, and descriptions:

# PatchMon Agent Configuration
# Location: /etc/patchmon/config.yml

# ─── Server Connection ───────────────────────────────────────────────
# The URL of the PatchMon server this agent reports to.
# Required. Must start with http:// or https://
patchmon_server: "https://patchmon.example.com"

# API version to use when communicating with the server.
# Default: "v1". Do not change unless instructed.
api_version: "v1"

# ─── Host Identity (agent 2.1.4 and later) ───────────────────────────
# ID of this host's record in PatchMon. Written by the installer, or
# learned from the server on the first successful ping. Do not copy it
# to another machine.
host_id: "3b0c2f7e-6a1d-4c55-9a0e-2f1f7d9e8c41"

# Version of the config file layout. Written by the agent only; it
# equals the agent version once the agent has loaded this file.
config_version: "2.1.4"

# ─── File Paths ──────────────────────────────────────────────────────
# Path to the credentials file containing api_id and api_key.
# Default: "/etc/patchmon/credentials.yml"
credentials_file: "/etc/patchmon/credentials.yml"

# Path to the agent log file. Logs are rotated automatically
# (max 10 MB per file, 5 backups, 14-day retention, compressed).
# Default: "/etc/patchmon/logs/patchmon-agent.log"
log_file: "/etc/patchmon/logs/patchmon-agent.log"

# ─── Logging ─────────────────────────────────────────────────────────
# Log verbosity level.
# Options: "debug", "info", "warn", "error"
# Default: "info"
log_level: "info"

# ─── SSL / TLS ───────────────────────────────────────────────────────
# Skip SSL certificate verification when connecting to the server.
# Set to true only if using self-signed certificates.
# Default: false
skip_ssl_verify: false

# ─── Reporting Schedule ──────────────────────────────────────────────
# How often (in minutes) the agent sends a full report to the server.
# This value is synced from the server on startup. If the server has
# a different value, the agent updates config.yml automatically.
# Default: 60
update_interval: 60

# Report offset (in seconds). Automatically calculated from the host's
# api_id to stagger reporting across hosts and avoid thundering-herd.
# You should not need to set this manually. The agent calculates and
# persists it automatically.
# Default: 0 (auto-calculated on first run)
report_offset: 0

# ─── Integrations ────────────────────────────────────────────────────
# Integration toggles control optional agent features.
# Most integrations can be toggled from the PatchMon UI and the server
# will push the change to the agent via WebSocket. The agent then
# updates config.yml and restarts the relevant service.
#
# EXCEPTION: ssh-proxy-enabled and rdp-proxy-enabled CANNOT be pushed from the server.
# It must be manually set in this file (see below).
integrations:
  # Docker integration: monitors containers, images, volumes, networks.
  # Can be toggled from the PatchMon UI (Settings → Integrations).
  # Default: false
  docker: false

  # Compliance integration: OpenSCAP and Docker Bench security scanning.
  #   enabled: false | "on-demand" | true
  #     false       - Disabled. No scans run.
  #     "on-demand"  - Scans only run when triggered from the PatchMon UI.
  #     true        - Enabled with automatic scheduled scans every report cycle.
  #   openscap_enabled: enable/disable OpenSCAP scanning (default: true)
  #   docker_bench_enabled: enable/disable Docker Bench scanning (default: false)
  # Can be toggled from the PatchMon UI.
  compliance:
    enabled: "on-demand"
    openscap_enabled: true
    docker_bench_enabled: false

  # SSH Proxy: allows browser-based SSH sessions through the agent.
  #     SECURITY: This setting can ONLY be enabled by manually editing
  #     this file. It cannot be pushed from the server to the agent.
  #     This is intentional. Enabling remote shell access should require
  #     deliberate action by someone with root access on the host.
  # Default: false
  ssh-proxy-enabled: false

  # RDP Proxy: allows browser-based RDP sessions through the agent.
  #     SECURITY: Same as SSH proxy. Requires manual configuration.
  #     Cannot be pushed from the server. Requires guacd sidecar on
  #     the server and RDP enabled on the Windows host.
  # Default: false
  rdp-proxy-enabled: false

# ─── Docker Image Update Check ───────────────────────────────────────
# Checks each image's registry for a newer image behind the same tag.
# Only runs when integrations.docker is true. Not pushed from the server.
docker_update_check:
  # Default: true
  enabled: true
  # Hours between automatic checks. Values below 1 use the default.
  # Default: 6
  interval_hours: 6

# ─── Alpine Security Database ────────────────────────────────────────
# Alpine hosts only. Flags security updates using secdb.alpinelinux.org.
# Not pushed from the server.
apk_secdb:
  # Default: true
  enabled: true

# ─── Apt Download Retries ────────────────────────────────────────────
# apt-based hosts only. Set from Settings → Agent Updates.
apt:
  # Default: true
  disable_retries: true

Parameters In Detail

patchmon_server

Type String (URL)
Required Yes
Default None (required)
Example https://patchmon.example.com

The full URL of the PatchMon server. Must include the protocol (http:// or https://). Do not include a trailing slash or path.

api_version

Type String
Required No
Default v1

The API version string appended to API calls. Leave as v1 unless directed otherwise by PatchMon documentation or release notes.

credentials_file

Type String (file path)
Required No
Default /etc/patchmon/credentials.yml

Path to the YAML file containing the host's api_id and api_key. The credentials file has this structure:

api_id: "patchmon_abc123def456"
api_key: "your_api_key_here"

log_file

Type String (file path)
Required No
Default /etc/patchmon/logs/patchmon-agent.log

Path to the agent's log file. The directory is created automatically if it does not exist. Logs are rotated using the following policy:

  • Max file size: 10 MB
  • Max backups: 5 rotated files
  • Max age: 14 days
  • Compression: Enabled (gzip)

log_level

Type String
Required No
Default info
Options debug, info, warn, error

Controls the verbosity of agent logging. Use debug for troubleshooting: it includes detailed execution flow and extra diagnostics. Enable it briefly and disable it again once you have the logs you need. Can also be overridden at runtime with the --log-level CLI flag.

skip_ssl_verify

Type Boolean
Required No
Default false

When true, the agent skips TLS certificate verification when connecting to the PatchMon server. Use this only for internal or testing environments with self-signed certificates. Not recommended for production.

update_interval

Type Integer (minutes)
Required No
Default 60

How frequently the agent sends a full system report (installed packages, updates, etc.) to the server. This value is synced from the server: if you change the global or per-host reporting interval in the PatchMon UI, the agent will update this value in config.yml automatically on its next startup or when it receives a settings update via WebSocket.

If the value is 0 or negative, the agent falls back to the default of 60 minutes.

report_offset

Type Integer (seconds)
Required No
Default 0 (auto-calculated)

A stagger offset calculated from the host's api_id and the current update_interval. This ensures agents across your fleet do not all report at the same moment (avoiding a thundering-herd problem on the server).

You should not set this manually. The agent calculates it on first run and saves it. If the update_interval changes, the offset is recalculated automatically.

host_id

Type String
Required No
Default None (omitted when empty)
Written by Installer, or the agent (learned from the server)
Example 3b0c2f7e-6a1d-4c55-9a0e-2f1f7d9e8c41

The ID of this host's record in PatchMon, the same ID that appears in the host's URL in the web UI. Added in agent 2.1.4.

  • Installer: the install command from a host's page writes that host's ID.
  • Agent: when host_id is empty, the agent records the ID the server returns on its next successful ping or report. Agents upgraded from an earlier release fill it in this way on their first start.
  • Never overwritten automatically: if config.yml already holds a different value, the agent keeps it, logs a warning once per run, and keeps reporting it, so PatchMon flags the host with a Host ID mismatch. Credentials still decide which host the data belongs to. To replace the value, run config sync-host-id or config set-api with --host-id, or reinstall the agent.

Enrolment scripts read host_id when they are run again on a machine whose agent is broken, so they can repair the existing host instead of creating a second one. See the Auto-Enrollment chapter of the API and integrations guide.

Valid values are 1 to 64 letters, digits or hyphens. An invalid value is discarded when the agent first loads the file after upgrading to 2.1.4.

config_version

Type String
Required No
Default The running agent's version
Written by Agent only
Example 2.1.4

The version of the config file layout. Added in agent 2.1.4. Do not edit it; neither the installer nor the server writes it.

Every time the agent loads config.yml and finds a config_version different from its own version, it applies any config changes introduced in later releases, in order, and then sets config_version to its own version. This happens on upgrade (auto-update or update-agent), on downgrade, and on the first start of a fresh install. Each change is written so that running it twice does no harm, which is why a release candidate's config is processed again when the final release loads it.

The agent reports config_version to the server, and the host page shows it next to the agent version. See Config version out of date if they differ.

integrations

A map of integration names to their enabled/disabled state. See the Integrations section below for details on each.

Integrations

Docker (docker)

Type Boolean
Default false
Server-pushable Yes

When enabled, the agent monitors Docker containers, images, volumes, and networks on the host. It sends an inventory snapshot at check-in whenever the inventory has changed, and again within seconds of any container being created, started, stopped or removed. It also runs the image update check described under Docker image update check below.

Requirements: Docker must be installed and the Docker socket must be accessible.

Toggle from UI: Go to a host's detail page, then Integrations tab, and toggle Docker on or off. The server pushes the change to the agent via WebSocket, the agent updates config.yml, and the service restarts automatically.

Compliance (compliance)

Type Boolean or String
Default "on-demand"
Server-pushable Yes
Valid values false, "on-demand", true

Controls OpenSCAP and Docker Bench security compliance scanning.

Value Behaviour
false Compliance scanning is fully disabled. No scans run.
"on-demand" Scans only run when manually triggered from the PatchMon UI. Tools are installed but no automatic scheduled scans occur.
true Fully enabled. Scans run automatically on every report cycle in addition to being available on-demand.

When first enabled, the agent automatically installs the required compliance tools (OpenSCAP, SSG content packages, Docker Bench image if Docker is also enabled).

SSH Proxy (ssh-proxy-enabled)

Type Boolean
Default false
Server-pushable No (manual edit required)

Enables browser-based SSH terminal sessions proxied through the PatchMon agent. When a user opens the SSH terminal in the PatchMon UI, the server sends the SSH connection request to the agent via WebSocket, and the agent establishes a local SSH connection on behalf of the user.

Why SSH Proxy Requires Manual Configuration

This is a deliberate security design decision. Enabling SSH proxy allows remote shell access to the host through the PatchMon agent. Unlike Docker or compliance integrations, this has direct security implications:

  • It opens an SSH connection path through the agent.
  • It could be exploited if a PatchMon server or user account were compromised.
  • The host administrator should make an informed, deliberate choice to enable it.

For these reasons, ssh-proxy-enabled cannot be toggled from the PatchMon UI or pushed from the server. If the server attempts to initiate an SSH proxy session while this is disabled, the agent rejects the request and returns an error message explaining how to enable it.

How to Enable SSH Proxy
  1. SSH into the host where the PatchMon agent is installed.
  2. Open the config file:
sudo nano /etc/patchmon/config.yml
  1. Find the integrations section and change ssh-proxy-enabled to true:
integrations:
  docker: false
  compliance:
    enabled: "on-demand"
    openscap_enabled: true
    docker_bench_enabled: false
  ssh-proxy-enabled: true    # ← Change from false to true
  1. Save the file and restart the agent:
# Systemd
sudo systemctl restart patchmon-agent.service

# OpenRC (Alpine)
sudo rc-service patchmon-agent restart
  1. The SSH terminal feature is now available for this host in the PatchMon UI.
How to Disable SSH Proxy

Set ssh-proxy-enabled back to false in config.yml and restart the agent service. Existing SSH sessions will be terminated.

RDP Proxy (rdp-proxy-enabled)

Type Boolean
Default false
Server-pushable No (manual edit required)

Enables browser-based RDP (Remote Desktop Protocol) sessions proxied through the PatchMon agent. When a user opens the RDP tab for a Windows host in the PatchMon UI, the server sends the RDP connection request to the agent via WebSocket, and the agent establishes a local RDP connection (default: localhost:3389) on behalf of the user via guacd (Apache Guacamole) running on the PatchMon server.

Why RDP Proxy Requires Manual Configuration

Same security rationale as SSH proxy. Enabling RDP proxy allows remote desktop access to the host through the PatchMon agent. This requires a deliberate decision by the host administrator:

  • It opens an RDP connection path through the agent to port 3389.
  • It could be exploited if a PatchMon server or user account were compromised.
  • The Windows host must have RDP enabled and guacd must be available on the PatchMon server.

For these reasons, rdp-proxy-enabled cannot be toggled from the PatchMon UI or pushed from the server. If the server attempts to initiate an RDP proxy session while this is disabled, the agent rejects the request and returns an error message explaining how to enable it.

Prerequisites
  • The PatchMon server must have guacd available (the default Docker Compose stack includes guacamole/guacd:1.6.0 as a sidecar). If your Docker install predates 2.1.4, apply the guacd compose change first.
  • The Windows host must have Remote Desktop enabled.
  • The PatchMon agent must be installed on the Windows host.
  • PatchMon only needs RDP listening on localhost:3389 on the Windows host. You do not need to expose RDP publicly.
  • If the browser reaches the host but the session still fails, retry with explicit Windows credentials first. The PatchMon UI distinguishes port-unreachable, auth, security-negotiation, and generic post-connect setup failures when guacd provides an explicit upstream message.
How to Enable RDP Proxy
  1. Connect to the host where the PatchMon agent is installed.
  2. Open the config file on the host:
# Windows (PowerShell as Administrator)
notepad "C:\ProgramData\PatchMon\config.yml"
  1. Find the integrations section and change rdp-proxy-enabled to true:
integrations:
  docker: false
  compliance:
    enabled: "on-demand"
    openscap_enabled: true
    docker_bench_enabled: false
  ssh-proxy-enabled: false
  rdp-proxy-enabled: true    # ← Change from false to true
  1. Save the file and restart the agent:
# Systemd
sudo systemctl restart patchmon-agent.service

# Windows (PowerShell as Administrator)
Restart-Service -Name PatchMonAgent
  1. The RDP tab is now available for this host in the PatchMon UI.
How to Disable RDP Proxy

Set rdp-proxy-enabled back to false in config.yml and restart the agent service. Existing RDP sessions are terminated: restarting the agent drops its connection to the server, which ends every open RDP session to that host with an error in the browser.

Docker Image Update Check (docker_update_check)

Controls the Docker image update check. The check asks each image's registry which image its tag points at now and compares that with the image on the host, so PatchMon can show Update available, Up to date and the other statuses described in the Admin Guide (Docker Inventory Tour, Image Update Checks). It only requests the image digest: it never pulls an image, and the requests do not count towards Docker Hub pull rate limits. It does not look for newer version tags.

Key Type Default Description
enabled Boolean true Runs the check whenever integrations.docker is true. Set to false to stop all checks on this host, including ones requested with Check for updates in the UI.
interval_hours Integer (hours) 6 Time between automatic checks. The first check runs about 2 minutes after the agent service starts. A value below 1 falls back to 6.

These settings are not server-pushable: edit config.yml and restart the agent service to change them. The agent writes the block into config.yml with its current values whenever it saves its configuration, so it appears after an agent update even if you never added it.

Network access

The check runs from the host, not from the PatchMon server. Each host needs outbound HTTPS (TCP/443, or the registry's own port) to the registries its images come from, and to their login (token) service. For Docker Hub that is registry-1.docker.io and auth.docker.io. The agent honours the standard HTTPS_PROXY, HTTP_PROXY and NO_PROXY environment variables.

A registry served over plain HTTP is only contacted if the Docker daemon on the host lists it under insecure-registries. For those registries the agent first tries HTTPS without certificate verification, then plain HTTP.

Registry credentials

Private registries use the logins already on the host. The agent reads $DOCKER_CONFIG/config.json when DOCKER_CONFIG is set in the agent's environment, otherwise the root user's /root/.docker/config.json, because the agent runs as root. Run sudo docker login <registry> on the host so the login lands in that file. Stored logins and identity tokens are supported, as are credential helpers configured with credHelpers or credsStore (the matching docker-credential-<name> program must be on the agent's PATH).

On macOS and Windows the agent runs as a system service, so it does not see a desktop user's ~/.docker/config.json. Point it at the right file by setting DOCKER_CONFIG in the agent service's environment, otherwise private registries report Unknown because the registry rejected the request.

Credentials are only sent to the registry they belong to, or to the login service that registry names. They are never written to the agent log and never sent to PatchMon. A registry with no login on the host is checked anonymously.

Alpine Security Database (apk_secdb)

Alpine's apk has no security metadata of its own, so on Alpine hosts the agent marks security updates using the Alpine security database. It reads the release branch (for example v3.23 or edge) from the untagged lines in /etc/apk/repositories, downloads that branch's main.json and community.json from https://secdb.alpinelinux.org/, and marks an update as a security update when it moves the package past a version that fixed a published issue. Other operating systems ignore this block.

Key Type Default Description
enabled Boolean true Set to false to stop the lookup. Updates on the host are then never marked as security updates.

The files are cached in /var/cache/patchmon/apk-secdb/ and fetched again at most every 6 hours. The cache is only used while that directory is owned by root and not writable by group or others. Each request times out after 20 seconds, follows redirects only over HTTPS to the same host, and accepts at most 8 MiB. If the database cannot be reached, the agent waits an hour before trying it again and meanwhile uses its last cached copy, or, with none, sends the report without security flags; the report itself never fails because of it. The agent logs a warning about it at most once every 6 hours. The host needs outbound HTTPS (TCP/443) to secdb.alpinelinux.org, and the agent honours the standard HTTPS_PROXY, HTTP_PROXY and NO_PROXY environment variables.

Like docker_update_check, this block is not server-pushable: edit config.yml and restart the agent service to change it. The agent writes the block into config.yml with its current value whenever it saves its configuration.

Apt Download Retries (apt)

apt-based hosts (Debian, Ubuntu and derivatives) only, from agent 2.1.8. Other operating systems ignore this block.

Key Type Default Description
disable_retries Boolean true When true, PatchMon patch runs call apt-get upgrade and apt-get --only-upgrade install with -o Acquire::Retries=0. Set to false to restore apt's own retry behaviour. A missing key counts as true.

With retries off, apt does not retry a failed or redirected download, which protects PatchMon patch runs against CVE-2026-109518. A transient mirror failure then fails the patch run instead of being retried. apt-get update and dry runs keep apt's normal retries. The compliance scanner install always runs with retries off, whatever this key says. On Univention Corporate Server, Patch all runs univention-upgrade, which this setting does not cover; patching selected packages is covered.

This block is server-driven: the value comes from Settings → Agent Updates → Disable apt download retries. The agent saves the server's value when it starts and when the setting changes, so a hand edit is replaced. A server older than 2.1.8 sends no value and leaves the key as it is.

How config.yml Is Generated

Initial Generation (Installation)

The config.yml file is created during agent installation by the patchmon_install.sh script. The installer generates a fresh config with:

  • patchmon_server set to the server URL used during installation
  • host_id set to the ID of the host the install command was generated for (2.1.4 and later)
  • skip_ssl_verify set based on whether -k curl flags were used
  • All integrations defaulted to false (Docker, SSH proxy, RDP proxy) or "on-demand" (compliance)
  • Standard file paths for credentials and logs
# What the installer generates:
cat > /etc/patchmon/config.yml << EOF
# PatchMon Agent Configuration
# Generated on $(date)
host_id: "3b0c2f7e-6a1d-4c55-9a0e-2f1f7d9e8c41"
patchmon_server: "https://patchmon.example.com"
api_version: "v1"
credentials_file: "/etc/patchmon/credentials.yml"
log_file: "/etc/patchmon/logs/patchmon-agent.log"
log_level: "info"
skip_ssl_verify: false
integrations:
  docker: false
  compliance:
    enabled: "on-demand"
    openscap_enabled: true
    docker_bench_enabled: false
  ssh-proxy-enabled: false
  rdp-proxy-enabled: false
EOF

chmod 600 /etc/patchmon/config.yml

The installer does not write config_version. The agent adds it the first time it loads the file, which is during the installer's own connectivity check, before the service starts. The Windows installer writes the same host_id key, and passes --host-id to config set-api when it updates an existing configuration.

Reinstallation Behaviour

If the agent is reinstalled on a host that already has a working configuration:

  1. The installer checks if the existing configuration is valid by running patchmon-agent ping.
  2. If the ping succeeds, the installer exits without overwriting. The existing configuration is preserved.
  3. If the ping fails (or the binary is missing), the installer:
    • Creates a timestamped backup: config.yml.backup.YYYYMMDD_HHMMSS
    • Keeps only the last 3 backups (older ones are deleted)
    • Writes a fresh config.yml

A reinstall on a healthy agent is safe and will not destroy your configuration.

How config.yml Is Regenerated / Updated at Runtime

The agent updates config.yml automatically in several scenarios. These are in-place updates: the agent reads the file, modifies the relevant field, and writes it back. Your other settings (including ssh-proxy-enabled) are preserved.

Server-Driven Updates

Trigger What Changes How
Agent startup update_interval, report_offset Agent fetches the current interval from the server. If it differs from config, the agent updates config.yml.
Agent startup integrations.docker, integrations.compliance Agent fetches integration status from the server. If it differs from config, the agent updates config.yml.
Agent startup apt.disable_retries Agent fetches the global apt retries setting from the server. If it differs from config, the agent updates config.yml.
WebSocket: settings_update update_interval, report_offset Server pushes a new interval. Agent saves it and recalculates the report offset.
WebSocket: settings_update apt.disable_retries Server pushes the apt retries setting when it changes. Agent saves it; the next patch run uses it.
WebSocket: apply_config integrations.docker, integrations.compliance.enabled, integrations.compliance.openscap_enabled, integrations.compliance.docker_bench_enabled Toggling an integration in the UI is staged, not sent. The server holds it as a pending change until you press Apply on the host detail page, then pushes the whole integration block in one message. The agent saves it to config.yml and restarts itself.

Agent-Calculated Updates

Trigger What Changes How
First run report_offset Calculated from api_id hash and update_interval to stagger reports.
Interval change report_offset Recalculated whenever update_interval changes.
Any load where the version differs config_version Set to the running agent's version after any newer config changes have been applied.
Ping or report response host_id Recorded from the server's response, only when config.yml has no host_id yet.
CLI: config set-api patchmon_server, credentials, host_id Running patchmon-agent config set-api overwrites the server URL and saves new credentials. host_id is set from --host-id, kept when the API ID is unchanged, and cleared then re-learned when the API ID changes.
CLI: config sync-host-id host_id Replaced with the server's value, even when a different value is present.

What Is Never Changed Automatically

Parameter Why
ssh-proxy-enabled Security: requires manual host-level action
rdp-proxy-enabled Security: requires manual host-level action
log_level Only changed by manual edit or --log-level CLI flag
log_file Only changed by manual edit
credentials_file Only changed by manual edit or config set-api
skip_ssl_verify Only changed by manual edit
host_id (when set) A different value from the server is reported, not adopted. Only config set-api, config sync-host-id, or a reinstall replaces it
docker_update_check Only changed by manual edit (the agent writes the defaults into the file if the block is missing)
apk_secdb Only changed by manual edit (the agent writes the default into the file if the block is missing)

Important: How SaveConfig Works

When the agent calls SaveConfig() internally, it writes all parameters back to the file. This means:

  • Your ssh-proxy-enabled and rdp-proxy-enabled settings are preserved across server-driven updates.
  • New integrations added in agent updates are automatically added to the file with their defaults (you will see them appear after an agent update).
  • The file format may be slightly reorganised by the YAML serialiser (key ordering may change), but all values are preserved.
  • The agent rewrites the file every time it loads it, from the settings it knows about. Comments, and keys the agent does not recognise, are not kept. The installer's # Generated on header disappears on the agent's first start; keep notes about a host elsewhere.
  • A pre-2.1.4 agent does not know host_id or config_version, so if you downgrade to one (or serve an older binary through agent binary overrides), its first load removes both keys. Nothing breaks: when the agent is upgraded again, it stamps config_version and re-learns host_id from the server on its first ping.

CLI Configuration Commands

The agent provides CLI commands for configuration management:

View Current Configuration

sudo patchmon-agent config show

Output:

Configuration:
  Server: https://patchmon.example.com
  Agent Version: 2.1.4
  Config Version: 2.1.4
  Host ID: 3b0c2f7e-6a1d-4c55-9a0e-2f1f7d9e8c41
  Config File: /etc/patchmon/config.yml
  Credentials File: /etc/patchmon/credentials.yml
  Log File: /etc/patchmon/logs/patchmon-agent.log
  Log Level: info

Docker Update Check:
  Enabled: true (requires integrations.docker)
  Interval: 6 hours

Credentials:
  API ID: patchmon_abc123def456
  API Key: Set ✅

Set API Credentials

sudo patchmon-agent config set-api <API_ID> <API_KEY> <SERVER_URL>

Avoid pasting a real API key into a shell with persistent history or session recording. If your environment records command lines, use a temporary shell with history disabled, or update credentials.yml directly.

This command:

  1. Validates the server URL format
  2. Saves the server URL to config.yml
  3. Saves the credentials to credentials.yml
  4. Tests connectivity with a ping to the server
  5. Reports success or failure

Add --host-id <HOST_ID> to set host_id at the same time. Without it, host_id is kept if the API ID is unchanged and cleared (then re-learned from the server) if it changes. See config set-api.

Custom Config File Path

All commands support a --config flag to use an alternative config file:

sudo patchmon-agent --config /path/to/custom/config.yml serve

Credentials File (credentials.yml)

The credentials file is separate from the config file for security isolation. It contains:

api_id: "patchmon_abc123def456"
api_key: "your_api_key_here"
  • Permissions: 600 (root read/write only)
  • Written using atomic rename: The agent writes to a temp file first, then atomically renames it. This prevents partial writes or race conditions.
  • Never contains the hashed key: The plain-text API key is stored here; the server stores only the bcrypt hash.

Troubleshooting

Config File Missing

If /etc/patchmon/config.yml does not exist, the agent uses built-in defaults. This means it will not know which server to connect to. Reinstall the agent or create the file manually.

Config File Permissions

# Check permissions (should be 600, owned by root)
ls -la /etc/patchmon/config.yml

# Fix if needed
sudo chmod 600 /etc/patchmon/config.yml
sudo chown root:root /etc/patchmon/config.yml

SSH Proxy Not Working

If the SSH terminal in the PatchMon UI shows an error like:

SSH proxy is not enabled. To enable SSH proxy, edit the file /etc/patchmon/config.yml...

This means ssh-proxy-enabled is set to false (the default). Follow the How to Enable SSH Proxy instructions above.

Config Gets Overwritten

If you notice settings being changed unexpectedly, check:

  1. Server sync: The update_interval and integration toggles (Docker, compliance) are synced from the server on startup and via WebSocket. Changes made in the PatchMon UI will override local values for these fields.
  2. Agent updates: After an agent update, new integration keys may appear in the file with default values.
  3. Reinstallation: A reinstall only overwrites config if the existing ping test fails.
  4. Comments and unknown keys: the agent rewrites the file from the settings it knows about every time it loads it, so comments and unrecognised keys are removed. This is expected.

Your ssh-proxy-enabled, rdp-proxy-enabled, log_level, skip_ssl_verify, and file path settings are never overwritten by server sync.

Viewing Debug Logs

# Temporarily enable debug logging
sudo patchmon-agent --log-level debug serve

# Or set permanently in config.yml
sudo nano /etc/patchmon/config.yml
# Change: log_level: "debug"
# Then restart the service
sudo systemctl restart patchmon-agent.service

Only enable debug briefly for troubleshooting. Avoid it during active SSH or RDP sessions, since remote-access traffic is more sensitive than normal agent telemetry. Switch back to info once you have captured what you need.

Example Configurations

Minimal Configuration

patchmon_server: "https://patchmon.example.com"

All other values use defaults. The agent will function with just the server URL (and valid credentials in credentials.yml).

Full Configuration with SSH and RDP Proxy Enabled

patchmon_server: "https://patchmon.internal.company.com"
api_version: "v1"
credentials_file: "/etc/patchmon/credentials.yml"
log_file: "/etc/patchmon/logs/patchmon-agent.log"
log_level: "info"
skip_ssl_verify: false
update_interval: 30
report_offset: 847
integrations:
  docker: true
  compliance:
    enabled: "on-demand"
    openscap_enabled: true
    docker_bench_enabled: false
  ssh-proxy-enabled: true
  rdp-proxy-enabled: true

Self-Signed SSL with Debug Logging

patchmon_server: "https://patchmon.lab.local"
api_version: "v1"
credentials_file: "/etc/patchmon/credentials.yml"
log_file: "/etc/patchmon/logs/patchmon-agent.log"
log_level: "debug"
skip_ssl_verify: true
update_interval: 60
integrations:
  docker: false
  compliance:
    enabled: false
    openscap_enabled: true
    docker_bench_enabled: false
  ssh-proxy-enabled: false
  rdp-proxy-enabled: false