Update ghcr.io/patchmon/patchmon-server Docker tag to v2.1.3
No problems upgrading the Docker container with a Docker compose yaml file by means of Watchtower DevOps resp. GitOps with dependency update facilitated by Mend's Renovate Bot.
This MR contains the following updates:
| Package | Update | Change |
|---|---|---|
| ghcr.io/patchmon/patchmon-server | minor | 2.0.2 → 2.1.3 |
Release Notes
PatchMon/PatchMon (ghcr.io/patchmon/patchmon-server)
v2.1.3: Version 2.1.3
A bug-fix release: single sign-on with ADFS, Mattermost and Rocket.Chat webhooks, compliance content on installs outside the official Docker image, and laptops that showed as stale after waking.
Upgrading
docker compose pull
docker compose up -d
No compose changes, no new settings, no database changes. Nothing to do on your agents.
Fixes
Single sign-on failing with no email in UserInfo or id_token. Two causes, both fixed: ADFS sends single-valued claims as JSON arrays, which were not read, and an empty email in a provider's UserInfo response hid a valid one in the signed ID token. If you still see this on 2.1.3, there is a troubleshooting entry in Setting up OIDC SSO.
Mattermost and Rocket.Chat webhook destinations failed every delivery with HTTP 400. Both are now detected from their /hooks/<token> URL and sent a compatible payload. Existing destinations start working on upgrade, with nothing to configure.
Compliance content was not being served on installs outside the official Docker image, the Proxmox LXC script in particular. Agents asking for a datastream got a 503 while Compliance Settings reported the directory as empty, so this was broken rather than mislabelled. The release is now read from the datastreams themselves. If you saw that message and moved on, check your fleet's compliance versions after upgrading.
Laptops and other machines that suspend showed as stale for days after waking. The server now asks for a report when an agent reconnects past its update interval. If you shortened your update interval to work around this, you can put it back.
Worth knowing
- Generic webhook destinations: the JSON body has gained a top-level
textkey so any Slack-compatible receiver works without configuration. Existing fields are unchanged, but a receiver that rejects unknown keys will start returning 400. - A single host reporting a malformed compliance version could stop SSG update checks for every host on that server, with only a logged warning. This is not new in 2.1.3.
- Downloads carry
SHA256SUMS, an SBOM and a provenance attestation again. A packaging fault meant v2.1.0, v2.1.1 and v2.1.2 shipped without them.
Every change in this release
| Issue | MR | Change |
|---|---|---|
| #805 | #1061 | ADFS logins failed because single-valued claims arrive as JSON arrays and only plain strings were accepted. Array-encoded string and boolean claims are now read |
| #805 | #1061 | An empty email in a provider's UserInfo response hid the address in the signed ID token and failed the login. Empty and whitespace-only values now count as absent |
| #805 | #1061 | Verified-email claims are now read from whichever source supplied the email, so an unverified assertion cannot override a signed one |
| #851 | #1061 | Mattermost and Rocket.Chat webhook destinations failed every delivery with HTTP 400. Both are now detected by their /hooks/<token> path and sent a compatible payload |
| #851 | #1061 | The generic webhook body gained a top-level text key, so any Slack-compatible receiver on a non-standard path works without configuration. Existing fields are unchanged |
| #1060 | #1061 | Servers whose SSG content lacked the .ssg-version marker could not distribute compliance content at all, and reported the directory as empty. The release is now read from the datastreams |
| #1060 | #1061 | One host reporting a malformed SSG version stopped compliance update checks for every host on the server |
| #351 | #1061 | Hosts that suspend showed as stale long after waking. The server now requests a report when an agent reconnects past its update interval |
What is coming next
Bug fixes are tracked in GitHub milestones. Feature requests live on feedback.patchmon.net, where you can propose an idea, vote on existing ones, and see what has been accepted onto the roadmap.
Questions about this release
This release has its own thread under New Release Discussions. Open a new issue for a reproducible bug not already covered.
v2.1.2: Version 2.1.2
A small release that fixes single sign-on for Microsoft Entra ID, and adds a documented way out for any provider that cannot confirm email addresses.
Upgrading
docker compose pull
docker compose up -d
No compose changes and no new settings you have to touch. One new database column is added automatically on start.
If your SSO broke on v2.1.0 or v2.1.1
From v2.1.0, when PatchMon has to work out who you are from your email address rather than from an identity it has already stored, it requires your provider to confirm that address is verified. Otherwise anyone able to set their own email address at your provider could sign in as an existing PatchMon user. This applies when linking to an existing account and when creating one on first login, and stops applying once an account is linked.
Two widely used providers could not satisfy that. Here is where each now stands.
Microsoft Entra ID. Entra never sends the standard email_verified claim and there is no way to make it, so there was no fix short of turning off auto-creation. PatchMon now reads xms_edov instead, which is Microsoft's own "Email Domain Owner Verified" signal, added by Microsoft in response to nOAuth, the same account-takeover attack this check exists to prevent. Add it as an ID token optional claim on your app registration and sign in again. The verified email requirement has the steps, including the manifest route for when the portal marks the claim unrecognised. Nothing has to be relaxed.
Because the claim is Microsoft-proprietary, it is only accepted from a Microsoft issuer and only from the ID token, which is signature verified. Azure AD B2C and Entra External ID are not currently on that list. If a sign-in is still refused, the server log now says which check failed and why, rather than only reporting the outcome.
Authentik. Unchanged, and the answer is still to replace the default email scope mapping with one that reports the address as verified. Full steps are in The verified email requirement.
Keycloak, Okta and Google Workspace were never affected and need no action.
If your provider cannot confirm addresses at all
Some directories have no notion of a verified email address. There is now an explicit opt-in for those: Trust unverified email in Settings > OIDC, or OIDC_TRUST_UNVERIFIED_EMAIL=true. It is off by default.
Be clear about what it does. With it on, anyone who can set their own email address at your identity provider can sign in as an existing PatchMon user with that address. It is only a reasonable choice when you control who can change addresses in your directory. Every login it allows through is written to the log, so you can see whether it is being used.
If a real fix exists for your provider, use that instead. This is the fallback. Full detail in If your provider cannot assert verification at all.
Also in this release
- A provider that simply omitted the verified-email claim was treated the same as one that actively denied it. Those are now told apart, which is what makes the Entra fix possible.
- The rejection in the log now names the claims PatchMon looked for and points at the relevant guide section, rather than just stating the outcome.
Every change in this release
| Issue | MR | Change |
|---|---|---|
| #1048 | #1057 | Entra ID logins were refused whenever PatchMon identified the user by email, because Entra never sends email_verified. xms_edov is now read when email_verified is absent |
| #1048 | #1057 | A missing verified-email claim was recorded as an explicit denial, making the two indistinguishable. Only a positive assertion is recorded now |
| #1048 | #1057 | New OIDC_TRUST_UNVERIFIED_EMAIL setting, off by default, for providers that cannot assert verification. Settable in Settings > OIDC, and logged whenever it permits a login |
What is coming next
Bug fixes are tracked in GitHub milestones. Each milestone lists the issues targeted at that release, so you can follow anything you have reported through to the version it lands in.
Feature requests live on feedback.patchmon.net, where you can propose an idea, vote on existing ones, and see what has been accepted onto the roadmap.
Questions about this release
This release has its own discussion thread, filed under New Release Discussions. If something is unclear or an upgrade step has not gone to plan, check there first. Open a new issue for a reproducible bug not already covered.
v2.1.1: Version 2.1.1
A patch release. It clears the upgrade crash loop some installs hit on the way to v2.1.0, makes failed sign-ins visible in the log, stops antivirus quietly breaking Windows agent installs, and gives internal mail relays that offer no TLS a working configuration.
Upgrading
docker compose pull
docker compose up -d
Nothing in your docker-compose.yml changes and there are no new settings.
Two exceptions, both below: a stuck migration 42, and single sign-on with Authentik or Microsoft Entra ID. If neither applies, the two commands above are all there is to do.
If your server has been crash-looping since v2.1.0
You will see cannot set path in scalar (22023) and migration 42 marked dirty. It affects installs whose host_down alert config stored its metadata as the JSON value null. Nothing was left half applied.
Recovery, in this order:
1. Upgrade to v2.1.1 first. The fix has to be in place, or migration 42 fails again on the next boot.
2. Rewind the marker. The server will still be crash-looping, which is fine, the database container is up:
docker compose exec database psql -U patchmon_user -d patchmon_db
UPDATE schema_migrations SET version = 41, dirty = false;
Then docker compose restart server. Adjust the service name and credentials if you changed them from the stock compose file.
Full recovery guide: Server Troubleshooting.
If you use single sign-on
This one arrived in v2.1.0, not v2.1.1, It can stop SSO login working entirely, so it is worth reading before you upgrade from v2.0.x.
When PatchMon has to identify you by email address rather than by an identity it has already stored, it now requires your provider to confirm that the address is verified. Otherwise anyone who can set their own email address at your provider could sign in as an existing PatchMon user. It applies when linking to an existing account and when creating one on first login, and stops applying once an account is linked.
If your provider does not send that confirmation you get "Unable to sign in with this account", and the server log shows oidc login rejected: unverified email claim.
| Provider | Affected |
|---|---|
| Authentik | Yes. Its default email scope mapping always reports the address as unverified. Replace the mapping |
| Microsoft Entra ID | Yes. It does not send the claim at all |
| Keycloak, Okta, Google Workspace | No, no change needed |
Step-by-step instructions for both providers: The verified email requirement.
Thanks to the people on #1048 who worked out the Authentik fix and posted it before we had documented any of it.
What else changed
Sign-in
- Failed sign-ins are now logged. Previously a stock install recorded nothing at all when a login was rejected, so you could not tell a wrong password from a mistyped username, or see that anyone was trying.
- Guessing a username that does not exist now counts toward the account lockout. Previously only a real username could reach a
429, and that difference confirmed which accounts existed.
Windows agent
- Installs no longer die with
Access is deniedwhen antivirus holds the freshly downloaded binary. The installer waits for the scan, clears the download marker, and if it still fails it prints how to fix it instead of a stack trace. Troubleshooting on Windows
- Relays that require authentication but offer no TLS now have a working configuration, as an explicit per-destination opt-in. It sends your credentials in the clear, so only enable it on a network you control. Enabling STARTTLS on the relay, even with your own internal CA, remains the better answer. Notification Destinations
Under the hood
- A dirty migration now prints the exact recovery SQL instead of leaving you to work it out.
- Built with Go 1.26.6, closing seven Go standard library vulnerabilities.
Documentation
- A complete plain-manifest Kubernetes deployment path alongside the Helm chart, for Argo CD, Flux and k3s. Includes the PostgreSQL volume mistake that silently empties your database on every redeploy. Installing PatchMon on Kubernetes
- Windows troubleshooting for the access-denied install failure.
- A "Failed Login Attempts in the Log" section, and a rewritten Account Lockout section.
- Removed an instruction to run migrations with
docker compose run --rm --entrypoint migrate server up. Nomigratebinary exists in the image, so that could never have worked.
Every change in this release
Changes since v2.1.0.
| Issue | MR | Change |
|---|---|---|
| #1042 | #1045 | Migration 42 aborted on installs storing host_down alert metadata as JSON null, wedging the upgrade to v2.1.0. The down migration had the same fault |
| #1042 | #1045 | A dirty migration now names the database and prints the exact recovery SQL, with a separate variant for version 1 |
| #1043 | #1051 | Failed sign-ins were not logged at all. Each rejection now writes one warn line with the reason, client IP, user agent, and username where known |
| #1043 | #1051 | Unknown usernames, disabled accounts and SSO-only accounts now all consume a lockout attempt and lock on the same one, so the responses no longer differ |
| #1043 | #1051 | The lockout counter treated admin and Admin as separate accounts while the user lookup did not, granting a fresh allowance of guesses per spelling |
| #1043 | #1051 | A lookup failing because the database is unreachable is now logged at error and does not consume a lockout attempt |
| #1043 | #1051 | An oversized username is rejected before the lookup, and the lockout key no longer embeds the submitted username |
| #1049 | #1051 | The Windows installer died with Access is denied and a stack trace when antivirus held the new binary, leaving a half-installed machine and no explanation |
| #817 | #1047 | Relays requiring SMTP AUTH with no TLS had no working configuration. A per-destination opt-in now permits it, off by default and inert in the TLS modes |
| #1048 | #1052 | Documented the verified email requirement for SSO, with provider-specific fixes for Authentik and Entra ID |
| - | #1051 | Built with Go 1.26.6 instead of 1.26.5, closing seven Go standard library vulnerabilities |
| - | #1051 | Plain-manifest Kubernetes deployment path added to the operator guide |
| - | #1051 | Unreleased migrations 000041 to 000046 renamed from v2-0-3 to v2-1-0. Renames only, no change to sequence numbers, SQL or applied state |
What is coming next
Bug fixes are tracked in GitHub milestones. Each milestone lists the issues targeted at that release, so you can follow anything you have reported through to the version it lands in.
Feature requests live on feedback.patchmon.net, where you can propose an idea, vote on existing ones, and see what has been accepted onto the roadmap.
Questions about this release
This release has its own discussion thread, filed under New Release Discussions. If something is unclear or an upgrade step has not gone to plan, check there first. Open a new issue for a reproducible bug not already covered.
v2.1.0: Version 2.1.0
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.
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
PORTsetting 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 | MR | 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 | MR | 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 | MR | 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 | MR | 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 | MR | 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 | MR | 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 | MR | 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 | MR | 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 |
| Issue | MR | 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 | MR | 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
| MR | 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.