Skip to content

Version 2.1.0

Latest

Choose a tag to compare

@9technologygroup 9technologygroup released this 13 Aug 15:10
· 4 commits to main since this release
10b16f9

A performance, reliability and security release, tested against fleets of 1,000+ hosts.

Read this before upgrading

Three lines in your docker-compose.yml changed. docker compose pull will not apply them, because your compose file is yours.

In the server service:

    ports:
      - "${PORT:-3000}:${PORT:-3000}"   # was "3000:3000"
    hostname: patchmon-server           # new

In the guacd service:

    image: guacamole/guacd:1.6.0        # was :latest

Then:

docker compose pull
docker compose up -d

Skip those lines and PatchMon still starts, but changing PORT will break the healthcheck and remote console will not run on ARM.

Migrations run at startup and there are no other steps. Large fleets should expect a pause on first boot while the database rebuilds indexes: a few seconds on SSD or NVMe, a few minutes on slower storage. PatchMon does not serve requests while this runs, so give it time rather than assuming it has hung.

Afterwards, update your agents and set the TLS mode on each email destination.

Two dashboard numbers will change, both because they were wrong before:

  • Hosts PatchMon holds no package data for were counted as Up to date. They now appear under a new Awaiting data slice, so your "Up to date" figure may drop.
  • GetHomepage widget totals left out hosts you had created but not yet enrolled. The widget now counts the same way as the dashboard, so the total may rise.

The feedback portal is live

Ideas, voting, the roadmap and the changelog now live at feedback.patchmon.net. GitHub Issues stays for bug reports.

How the feedback portal works

Agents send far less, and you can see what they sent

  • Agents upload only what has actually changed. A routine check-in drops from around 2 MB to around 1 KB.
  • The Package Reports and Agent Queue tabs are replaced by a single Agent Activity timeline: every check-in, what kind it was, and which sections were updated or skipped. History is kept for 30 days by default and is configurable.
  • Update your agents to get the reduced traffic. Older agents keep working as they are.

You can tell at a glance what is actually wrong

  • Four separate status pills per host: connection, reporting, reboot pending and updates. A dropped connection no longer looks the same as a dead host.
  • Status reads correctly without relying on colour alone.
  • Uptime is live, rather than frozen at whatever the last report said.
  • The host down alert watches the live connection instead of inferring from how long ago a host last reported. It reacts in seconds and stops flagging hosts that are plainly still connected. It is now called Host Agent Down.

Large fleets are fast again

  • The Packages page loads in a fraction of a second where it previously took around ten.
  • Hosts, Packages, Repositories and Alerts are paginated, with a page size that sticks between visits.
  • The dashboard and sidebar no longer pull your entire host list just to show a count.
  • The package total is no longer capped at 10,000, so the figure matches your database.
  • Package search no longer errors out on Docker installs.

Patch runs no longer get stuck

  • Stalled runs are timed out and cleared automatically instead of sitting at "running" for ever, and the timeout is configurable.
  • A run is marked as disconnected if the agent drops mid-patch, and corrected if the agent comes back with a result.
  • Stop Run always stops the run, even when the agent is offline, unresponsive, or holding open output from a child process.
  • Long-running jobs that are genuinely still working are no longer marked as timed out.

Your distribution is read correctly

A large sweep through how the agent reads each package manager, so counts match what the host itself reports.

  • Fedora and RHEL family: correct upgrade commands rather than install, banner lines no longer parsed as packages, duplicate upgradable entries removed.
  • Rocky Linux: RLSA- security advisories are recognised, so security updates are classified correctly.
  • Debian and Ubuntu: deb822 sources files are read properly, security updates are identified from the origin rather than the whole line, and patch all applies upgrades that pull in new packages instead of leaving them pending for ever.
  • Raspberry Pi: security updates are no longer misfiled as ordinary updates, and multiple installed kernel variants no longer produce a false reboot required.
  • Arch and Manjaro: inventory is collected without needing pacman-contrib, kernel detection is fixed, and a broken pacman database is reported as an error rather than as no updates.
  • FreeBSD: the correct installer is served.
  • LXC containers: uptime is the container's own rather than the host's.
  • A host that failed to check for updates is reported as failed, rather than as fully patched.

Windows

  • Windows hosts that never appeared in PatchMon at all should now appear. Some installers write stray null characters into their registry entries, and a single one anywhere in a host's package list caused every report from that host to be rejected. MeshCentral's agent is a common source, so this may account for missing hosts in mixed fleets. The same protection now covers Docker and compliance data.
  • The agent no longer resets its own server address on first start.
  • Updating the agent no longer fails with "Access is denied".
  • The uninstall script works on PowerShell 5.1.
  • Non-English characters are handled correctly in reports, collectors and install scripts.
  • Reboot detection reads the registry consistently, and the agent reports its real version instead of 0.0.0.
  • Windows builds, linting and runtime tests now run in CI.

Email that tells you why it failed

  • SMTP destinations have a proper TLS choice (STARTTLS, SSL, none, or automatic) instead of a single toggle. Existing destinations keep working, but picking the right one means a broken or tampered relay fails rather than quietly sending anyway.
  • Port 465 servers requiring implicit TLS now work, instead of failing with an end-of-file error.
  • A new Send test email button does a real send and tells you which step failed, whether that is the connection, TLS, the login or delivery, with the mail server's own message.
  • Long lines and long subjects are encoded properly rather than being mangled in transit.

Security

  • Client IP addresses could be spoofed behind a reverse proxy, which affected rate limiting, login lockouts and activity log entries. A new trusted proxy setting controls which upstream addresses are believed, and the default is correct for standard deployments.
  • The rate limiter could leave a counter with no expiry, stranding an address at HTTP 429 with no way back.
  • Every issued token is bound to a session, and refresh tokens are no longer accepted in place of a sign-in token, so signing out, revoking a session, changing a password and deactivating an account take effect immediately.
  • Accounts created through the initial setup or the sign-up page could not be signed out remotely, because their session had no way to be revoked.
  • Linking a Discord or single sign-on identity to an existing account now requires a verified email address and explicit confirmation from the account owner, rather than happening automatically on an email match.
  • Two-factor verification requires the first sign-in step to be completed successfully before the code is accepted.
  • Sign-in messages are uniform, and no longer vary depending on whether an account exists for the address entered.
  • Single sign-on fixes: an error during sign-on could assign the wrong role to a new account, logins were rejected when the provider reported email verification in an unexpected format, and saving settings while a user was signing in applied the wrong auto-create behaviour to that login.
  • The idle session timeout setting now works.
  • Server address, port and package name inputs are validated more strictly before they reach the installer scripts or the system package manager.
  • Repository credentials are redacted from agent logs, including when an update check fails.
  • Images and release binaries are published with an SBOM and build provenance.

The API now agrees with the interface

If you have ever queried the API and found a host reported as active while the interface showed it as Inactive, that is fixed.

The status field was never a liveness signal. It records how far a host got through enrolment, so once a host has checked in it stays active for ever, even if it never reports again. The interface has always calculated liveness separately, on the fly, from when the host last reported.

Rather than change what status means and break anyone relying on it, host responses now carry an extra effective_status field holding exactly what the interface displays: pending, active or inactive. It is available on the scoped hosts API, the admin host list, the hosts-in-a-group listing and host detail. Alongside it, reporting_state tells you how fresh a host's data is (reporting, overdue, stale) and update_state tells you whether it needs patching.

The API documentation now sets out which of these four fields answers which question.

Also in this release

  • Compliance scanner installs complete reliably, including on Ubuntu 24.04 and Rocky Linux 8 and 9. Scan history and rules search and sort properly, timings are correct, and stalled scans are swept hourly rather than daily.
  • The daily compliance content check no longer re-downloads the same archive every day.
  • Remote console runs on ARM again.
  • Changing the PORT setting works, rather than breaking the healthcheck.
  • Background jobs honour Redis TLS and Redis usernames, so they no longer fail while the rest of the server connects fine.
  • A sweep through every filter, sort and clickable stat card in the app so they all do what they say.
  • Refresh now refreshes the whole screen rather than a single panel, and routine actions no longer wipe unsaved edits elsewhere on the page.
  • The legacy bare-metal installer is removed.
  • Dependency and toolchain updates across the server, agent and frontend.

New and changed settings

All new settings are optional and defaulted correctly. None needs setting on a standard install.

Setting Default Purpose
TRUSTED_PROXY_RANGES empty CIDRs of chained proxies, for real client IP resolution. Only needed when proxies are chained, for example Cloudflare in front of Nginx Proxy Manager.
PATCH_RUN_STALL_TIMEOUT_MIN 30 (minimum 5) Minutes before a stuck patch run is marked timed out.
AGENT_REPORTS_RETENTION_DAYS 30 (range 7 to 365) How long Agent Activity history is kept.
ENABLE_PPROF off Go profiling endpoints, on a loopback-only listener.
PPROF_PORT 6060 Profiling port. Never published by compose.
SESSION_INACTIVITY_TIMEOUT_MINUTES unset Existed already but had no effect. Now functional. 0 disables it.

One default has changed. ENABLE_LOGGING now defaults to true. The server previously wrote no application logs at all unless this was explicitly turned on, which made every "check the logs" instruction useless. If you have ENABLE_LOGGING=false in your .env, or logging turned off in Settings, that is still honoured. If you never set it, you will start seeing logs after upgrading.

Every fix in this release

Changes since v2.0.2. Numbers refer to issues and pull requests on github.com/PatchMon/PatchMon. Where a fix landed without a pull request, the commit is given instead.

Agent: package managers and OS detection

Issue PR Fix
#257 #1011 LXC containers reported the host's uptime rather than their own
#415 #967 dnf banner lines parsed as packages on the RHEL family, inflating outdated counts
#553 #949 Kernel detection broken on Arch
#647 #949 False reboot required on Raspberry Pi 5 with multiple kernel variants
#672 5dec92e9 Patch all now applies apt upgrades that pull in new packages, so kernel meta-packages stop reappearing as pending
#741 #965 Wrong update command on Fedora (install rather than upgrade)
#772 #949 Windows reboot registry key read inconsistently
#776 #988 Problem updating a VM
#782 #969 Raspberry Pi security updates classed as normal updates
#832 #990 Successful yum dry runs misread as patch validation failures
#849 #970 Agent behind an outgoing proxy
#850 #985 Manjaro and Arch needed pacman-contrib for the first report
#867 #964 Rocky Linux RLSA- security advisories not recognised
#872 #988 deb822 sources files required URIs
#896 c4e43497 Architecture token reported as the current version for newly seen packages
#946 #949 Installed kernel version regressed on Debian 13, masking a real pending reboot

Agent: Windows

Issue PR Fix
#701 7995b11b, 1263f83a Agent reported its version as 0.0.0
#769 #979 Uninstall script failed on PowerShell 5.1
#824, #1021 #979 A single null character in a registry-sourced package name caused every report from that host to be rejected, so the host never appeared in PatchMon at all
#873 5733fa90, e8bf40e1 Agent update failed with "Access is denied"
#884 #1008 Agent reset its own server address on first start
#941, #804 #979, adcbc589 Package names with non-English characters arrived mangled or cut short, for example "Microsoft Visual C++ 2015-2022 Redistributable (x64"
#1004 #1007 Wrong install command shown when setup was interrupted
#1029 #1031 Null character handling extended to the Docker and compliance endpoints

Agent: connectivity and reporting

Issue PR Fix
#615 #617 Unhandled curl exit code 6 (unknown host)
#773 #970 Agent did not reconnect over WSS, and the reconnect loop stalled silently
#866 - Report failing with status 429
#876 #981 Installer used a deprecated version subcommand
#936 #988 Auto-enrolment installer IP address and hostname handling
#1000 #999 Proxmox auto-enrolment script documented a SKIP_STOPPED=false option that did nothing, alongside two configuration variables it no longer read

Patching

Issue PR Fix
#657 #994 Patch all button not removed
#664 #994 Patching policy exclusions
#687, #718, #738, #810, #858, #907 - Patch runs stuck in Running indefinitely and never cleaned up
#991 #992 Stop and timeout had no effect while a child process held the output pipes

Compliance

Issue PR Fix
#676 #994 Incorrect timing shown
#688 - OpenSCAP install failed but reported ready
#809 #1017 Could not install OpenSCAP on Ubuntu 24.04
#842 #1022 Daily content check re-downloaded the same archive every day
#859 #988 No SCAP content found for Rocky Linux 8 and 9
#996 #998, #1010 Stalled scans were reaped after three hours but swept only daily
#1025 #1027 Bulk-scan host picker always showed a red status dot

Dashboard, hosts and interface

Issue PR Fix
#673 #988 Packages and Installations hover with no action
#674 492c09d7 Packages summary cards scoped to their heading, so the count and the list agree
#678 #988 Column picker
#698 #968 Several issues on the Automations page
#763 - Reporting and alerts not loading
#808 #994 Double scroll bar on Hosts and Packages
#916 - Package count capped at 10,000
#929 #956 Errored segment counted stale-reporting hosts rather than failed jobs
#930 #994 Errored segment navigated to the wrong filter
#952 #988 Connection status on Hosts not clickable
#995 #1009 Loading states overflowed the page
#1002 #1007 Host setup modal sat behind the sidebar
#1005 #1007 Group selection cut off
#1032 #1036 Hosts with no package data counted as Up to date, now shown under a new Awaiting data bucket with a matching list filter
- #1038 A host added but not yet enrolled showed green Reporting and Up to date pills. Never-reported hosts now read Awaiting report and No package data on host detail, the Hosts table and cards, and the compliance host picker, with a new Awaiting report option on the Reporting filter

Integration API

Issue PR Fix
#874 #1024 Scoped API reported status: active for hosts the interface showed as Inactive. New effective_status, reporting_state and update_state fields, with status unchanged
#1026 #1028 GetHomepage total_hosts excluded never-enrolled hosts, disagreeing with the dashboard
#1034 #1036 GetHomepage statistics query rewritten: around 277 ms to around 30 ms at 3,000 hosts and 3.74M package rows, with no spill to disk

Sign-in, users and settings

Issue PR Fix
#696 #988 Password rules not applied properly
#739, #794 - Single sign-on: provider unreachable
#730 #978 Last login not recorded on local sign-in
#787 - Admin users lost privileges after a full stack restart
#918 #1003 SESSION_INACTIVITY_TIMEOUT_MINUTES had no effect
#1020 #1037 A correct single sign-on configuration logged nothing at startup, so operators following the guide assumed it had failed. One confirmation line is now logged, and the operator guide documents that Authentik needs a Signing Key set on the provider

Email

Issue PR Fix
#714 - End-of-file error on port 465 implicit TLS
#845 #980 Email lines too long
#870 - Use TLS tickbox never persisted, so STARTTLS was skipped

Server, Docker and infrastructure

Issue PR Fix
#736 #737 Background jobs ignored REDIS_TLS, so all of them failed
#745 #785 Background jobs ignored REDIS_USER
#765 #988 guacd not running on arm64
#767 #988 Changing PORT broke the healthcheck and the app
#791 #792 Auto-enrolment docs linked to the wrong section
#840, #878 #819, #843 Dev Docker image showed "Build frontend first"
#868 #955 Rate limiter leaked Redis counters, stranding an address at HTTP 429

Changes without an issue number

PR Change
#722 Redis-backed distributed registry for agent presence
#827 Quoted paths in the agent Makefile
#836 Windows agent update
#862 Compliance scans rejected when the scanner is unavailable
#890 Autofocus on the login form
#931 Logic defect audit
#933, #935, #937 Version resolved from the git tag, release manifest parsing, pre-release numbering
#934 Filter and sort audit across the interface
#943 Compliance installation improvements
#948 Isolation and security improvements
#949 Reboot detection across Debian, Arch, Raspberry Pi and Windows
#973 Redis ACL, dnf makecache, apt only-upgrade, dev Dockerfile
#974 SMTP transport security resolved identically on all three send paths
#979 Windows text encoding across reports, collectors and install scripts
#982 Windows build, lint and runtime test coverage in CI
#984 Correct installer served for FreeBSD hosts
#986 Host OS sent when requesting the install script
#987 Broken pacman database no longer reported as no updates
#989 Both connection counts filter the host list
#993 Installer detects whether systemd is running, not merely installed
#1006 One copy of the agent scripts served, not two
#1012 SBOM and build provenance published for images and release binaries
#1013 Refresh refreshes the whole screen, not one query

What is coming next

Bug fixes are tracked in GitHub milestones. Each milestone lists the issues targeted at that release, so you can see which fixes are queued for the next version and follow anything you have reported through to the release it lands in. The milestone for this release records every fix that went into it.

Feature requests are not tracked on GitHub. They live on feedback.patchmon.net, where you can propose an idea, vote on the ones already there, and see what has been accepted onto the roadmap.

Please do note, that future releases will be small and in more of an agile format, the community got together and we discussed this and other project status / plans - the recording of this is on the YouTube channel.

We understand that there are still some bugs under Compliance, Windows integration and Docker integration. These are going to be addressed over the next few more minor releases.

Questions about this release

This release has its own discussion thread, linked at the top of this release page and filed under New Release Discussions.

If something here is unclear, an upgrade step has not gone to plan, or you think this release has changed behaviour you were relying on, please check that thread first. Others are likely to have hit the same thing, and answers about this specific release are collected there rather than spread across new issues.

Open a new issue for a bug you can reproduce that is not already covered in the thread.

Many thanks, from Iby and the PatchMon team.