Chapter 10 of 15
Uninstalling the PatchMon Agent
Overview
There are two sides to decommissioning a host in PatchMon:
- Remove the agent from the host: stops the service, deletes the binary, config, credentials, logs, and service unit.
- Remove the host record from the PatchMon server: deletes the row in the database, its API credentials, historical reports, and any group memberships.
You almost always want to do both. This page covers the script-driven removal, the manual fallback for each platform, and how to clean up the UI side.
The agent binary does not have a built-in uninstall subcommand. Removal is driven by a server-generated shell script (Linux/FreeBSD) or PowerShell script (Windows). The Agent Removal section in Managing the PatchMon Agent contains the same commands in a more compact reference form: this page is the detailed walkthrough with manual fallbacks for when the script-driven approach is not viable.
What Gets Removed
The server-provided removal scripts delete everything the installer wrote:
| Artefact (Linux / FreeBSD) | Artefact (Windows) |
|---|---|
Running patchmon-agent processes |
Running patchmon-agent.exe processes |
systemd service + /etc/systemd/system/patchmon-agent.service |
PatchMonAgent Windows Service |
OpenRC service + /etc/init.d/patchmon-agent |
- |
FreeBSD rc.d script at /usr/local/etc/rc.d/patchmon_agent |
- |
Crontab entries containing patchmon-agent |
- |
Agent binary /usr/local/bin/patchmon-agent |
C:\Program Files\PatchMon\ |
Configuration directory /etc/patchmon/ (config, credentials, logs) |
C:\ProgramData\PatchMon\ |
Log file /var/log/patchmon-agent.log (legacy path, if present) |
- |
Backup files (*.backup.*), only when REMOVE_BACKUPS=1 is set |
Backup .exe.backup.* files |
Install path removed from system PATH |
The host record on the server is not removed by these scripts. Use the Delete Host button in the web UI (covered below).
Method 1: Server-Provided Removal Script (Recommended)
The server exposes a public, unauthenticated endpoint that returns the removal script: GET /api/v1/hosts/remove. Pass ?os=windows to get the PowerShell version.
Linux / FreeBSD
curl -s https://patchmon.example.com/api/v1/hosts/remove | sudo sh
The script is idempotent, running it twice is harmless. It prints a progress log and finishes with a "Removal Summary" block.
Options (environment variables set before sh):
| Variable | Default | Effect |
|---|---|---|
REMOVE_BACKUPS |
0 |
Set to 1 to also delete *.backup.* files (config backups, binary backups, log rotations). |
SILENT |
unset | Set to 1 for minimal output (useful in automation / Ansible). |
Examples:
# Standard removal, keep backups (safest)
curl -s https://patchmon.example.com/api/v1/hosts/remove | sudo sh
# Nuke everything including backups
curl -s https://patchmon.example.com/api/v1/hosts/remove | sudo REMOVE_BACKUPS=1 sh
# Silent removal (for Ansible / cron)
curl -s https://patchmon.example.com/api/v1/hosts/remove | sudo SILENT=1 sh
# Silent + full cleanup
curl -s https://patchmon.example.com/api/v1/hosts/remove | sudo REMOVE_BACKUPS=1 SILENT=1 sh
If your PatchMon server uses a self-signed certificate and the target host does not trust it, the server automatically serves the script with
-sk(insecure) baked in whenSettings → Server → Ignore SSL self-signedis enabled. If it is not, add-kto the initialcurlyourself:curl -sk https://patchmon.example.com/api/v1/hosts/remove | sudo sh.
Windows (elevated PowerShell)
$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest https://patchmon.example.com/api/v1/hosts/remove?os=windows -UseBasicParsing -OutFile "$env:TEMP\patchmon-remove.ps1"
powershell.exe -ExecutionPolicy Bypass -File "$env:TEMP\patchmon-remove.ps1"
Or download first, inspect, then run:
irm https://patchmon.example.com/api/v1/hosts/remove?os=windows -OutFile patchmon_remove.ps1
# inspect patchmon_remove.ps1
.\patchmon_remove.ps1 -RemoveAll -Force
Script parameters:
| Parameter | Default | Effect |
|---|---|---|
-RemoveConfig |
off | Remove C:\ProgramData\PatchMon\ (config, credentials, logs). |
-RemoveLogs |
off | Remove log files. |
-RemoveAll |
off | Shortcut for -RemoveConfig + -RemoveLogs. |
-Force |
off | Skip interactive confirmation prompts. |
-InstallPath |
C:\Program Files\PatchMon |
Override install location (rare). |
-ConfigPath |
C:\ProgramData\PatchMon |
Override config location (rare). |
By default the Windows script removes the service and the binary but keeps config and logs. Pass -RemoveAll to wipe everything.
Method 2: Manual Removal
Use the manual steps when:
- The PatchMon server is unreachable and you cannot pull the removal script.
- You are removing a legacy / corrupted install where the script is failing.
- You want to script removal yourself with a configuration management tool.
Linux: systemd
# 1. Stop and disable the service
sudo systemctl stop patchmon-agent
sudo systemctl disable patchmon-agent
sudo rm -f /etc/systemd/system/patchmon-agent.service
sudo systemctl daemon-reload
# 2. Kill any stragglers
sudo pkill -f patchmon-agent
# 3. Remove binary and timestamped backups
sudo rm -f /usr/local/bin/patchmon-agent
sudo rm -f /usr/local/bin/patchmon-agent.backup.*
# 4. Remove config, credentials, and logs
sudo rm -rf /etc/patchmon/
# 5. Remove any stale crontab entries
crontab -l 2>/dev/null | grep -v "patchmon-agent" | crontab -
# 6. Verify
which patchmon-agent # should print nothing
systemctl status patchmon-agent 2>&1 | head -1 # should show "not found"
ls /etc/patchmon/ 2>/dev/null # should be absent
Linux: OpenRC (Alpine)
# 1. Stop, remove from runlevel, delete init script
sudo rc-service patchmon-agent stop
sudo rc-update del patchmon-agent default
sudo rm -f /etc/init.d/patchmon-agent
# 2. Kill any stragglers
sudo pkill -f patchmon-agent
# 3. Remove binary and config
sudo rm -f /usr/local/bin/patchmon-agent /usr/local/bin/patchmon-agent.backup.*
sudo rm -rf /etc/patchmon/
# 4. Verify
rc-service patchmon-agent status 2>&1 | head -1
FreeBSD: rc.d
# 1. Stop the service
service patchmon_agent stop
# 2. Disable auto-start (remove or comment the enable line in rc.conf.local)
sysrc -x patchmon_agent_enable 2>/dev/null || true
sed -i '' '/patchmon_agent_enable/d' /etc/rc.conf.local 2>/dev/null || true
# 3. Remove the rc.d script
rm -f /usr/local/etc/rc.d/patchmon_agent
# 4. Kill any stragglers
pkill -f patchmon-agent || true
rm -f /var/run/patchmon_agent.pid
# 5. Remove binary, config, and backups
rm -f /usr/local/bin/patchmon-agent /usr/local/bin/patchmon-agent.backup.*
rm -rf /etc/patchmon/
# 6. Verify
service patchmon_agent status 2>&1 | head -1
The FreeBSD rc.d script name uses an underscore (
patchmon_agent), not a hyphen. This matches FreeBSD's rc convention. Do not be surprised by the inconsistency with Linux.
Crontab-Only Hosts (minimal containers)
On systems without systemd, OpenRC, or rc.d, the installer adds a @reboot crontab entry and starts the agent in the background. To remove:
# 1. Kill the running agent
sudo pkill -f 'patchmon-agent serve'
# 2. Strip the crontab entry
crontab -l 2>/dev/null | grep -v "patchmon-agent" | crontab -
# 3. Remove binary and config
sudo rm -f /usr/local/bin/patchmon-agent /usr/local/bin/patchmon-agent.backup.*
sudo rm -rf /etc/patchmon/
# 4. Verify no processes remain
pgrep -f patchmon-agent
Windows: elevated PowerShell
# 1. Stop and delete the service
Stop-Service -Name PatchMonAgent -Force -ErrorAction SilentlyContinue
sc.exe delete PatchMonAgent
# 2. Kill any stragglers
Get-Process -Name patchmon-agent -ErrorAction SilentlyContinue | Stop-Process -Force
# 3. Remove binary and data directories
Remove-Item -Recurse -Force 'C:\Program Files\PatchMon'
Remove-Item -Recurse -Force 'C:\ProgramData\PatchMon'
# 4. Strip the install path from the system PATH
$installPath = 'C:\Program Files\PatchMon'
$currentPath = [Environment]::GetEnvironmentVariable('Path', [EnvironmentVariableTarget]::Machine)
$newPath = ($currentPath -split ';' | Where-Object { $_ -and $_ -ne $installPath }) -join ';'
[Environment]::SetEnvironmentVariable('Path', $newPath, [EnvironmentVariableTarget]::Machine)
# 5. Verify
Get-Service -Name PatchMonAgent -ErrorAction SilentlyContinue # should print nothing
Test-Path 'C:\Program Files\PatchMon' # should be False
Test-Path 'C:\ProgramData\PatchMon' # should be False
Step 3: Delete the Host Record from PatchMon
Removing the agent from the host does not delete the host record in PatchMon's database. The host will show as offline / stale. To fully decommission:
- Log in as a user with
can_manage_hosts. - Navigate to Hosts.
- Find the host (or multi-select several) and click Delete Host (single) or the Delete bulk action (multi).
- Confirm in the modal. This removes:
- The host row
- Its API credentials (hashed
api_id/api_key) - Its report history, package inventory, repository list, compliance scans, and Docker inventory
- Its host-group memberships
- If you intend to re-enrol the same machine later, it will come back as a brand new host with a new
api_id.
Caveat for credential reuse. The agent's
credentials.ymlcontains the old API ID. If you removed the host record but left the binary installed, the agent will start logging401 Unauthorizedevery check-in because the server no longer knows that API ID. Always pair UI deletion with one of the removal methods above.
Troubleshooting Removal
Script fails with "Permission denied"
You forgot sudo:
curl -s https://patchmon.example.com/api/v1/hosts/remove | sudo sh
On Windows, open PowerShell with Run as Administrator: a non-elevated shell will error with This script must be run as Administrator.
Service is still running after removal
On systemd:
sudo systemctl status patchmon-agent
sudo systemctl stop patchmon-agent
sudo systemctl disable patchmon-agent
sudo rm -f /etc/systemd/system/patchmon-agent.service
sudo systemctl daemon-reload
sudo pkill -9 -f patchmon-agent # force-kill stragglers
On Windows, if sc.exe delete PatchMonAgent reports "The specified service has been marked for deletion" and the service is still listed, reboot once. SCM cannot purge a service while the binary's file handle is still open. Alternatively, close any Event Viewer / Services.msc windows and retry.
Config files still present after script ran
The Linux/FreeBSD script removes /etc/patchmon/ unconditionally. The Windows script only removes C:\ProgramData\PatchMon\ when -RemoveConfig (or -RemoveAll) is passed. Re-run the Windows script with -RemoveAll -Force.
Backups persist after removal
Backup files (config, credentials, binary, logs) are preserved by default on Linux as a safety net. They live under:
/etc/patchmon/credentials.yml.backup.*(removed with/etc/patchmon/directory)/etc/patchmon/config.yml.backup.*(removed with/etc/patchmon/directory)/usr/local/bin/patchmon-agent.backup.*- not removed unlessREMOVE_BACKUPS=1/etc/patchmon/logs/patchmon-agent.log.old.*(removed with/etc/patchmon/directory)
Pass REMOVE_BACKUPS=1 when invoking the removal script, or delete them manually:
sudo rm -f /usr/local/bin/patchmon-agent.backup.*
Host still appears as "Connected" briefly after uninstall
The WebSocket status can take up to ~60 seconds to reflect the disconnect. If you delete the host record in the UI while the agent is still running, the agent will immediately see 401 on its next ping and the UI will update. The residual "Connected" display is cosmetic and self-corrects.
See Also
- Managing the PatchMon Agent: especially the "Agent Removal" section for a condensed reference.
- Installing the PatchMon Agent: how to re-enrol a host after removal.
- Agent Configuration Reference (config.yml): what's in the config files that get deleted.
- Agent Troubleshooting: quick decision tree for agent-side problems.