Repository navigation
Releases: r0073d-l053r/ProxMate
Release list
v1.3.4
ProxMate 1.3.4 closes a tenant-isolation gap on a Proxmox node that is also a Tailscale subnet router, says when the ProxMate IDE installed but can't be reached, and fixes the text console. If one of your nodes is a subnet router, run the new guard on it (below); otherwise no configuration changes are needed to upgrade from 1.3.x.
- Security: the Tailscale subnet-router guard. On a node that routes your tailnet to the LAN, Tailscale's own firewall rules accepted tailnet traffic to the guests on that node before the Proxmox firewall ran, so every port of those guests was reachable from the tailnet whatever ProxMate's isolation rules said. The same traffic was also masqueraded twice, so replies were lost and the IDE on those guests never opened. Guests on other nodes were not affected.
- Run
deploy/proxmox-tailscale-guard.shas root on the subnet-router node. It installs a small service that clears Tailscale's mark on bridged traffic at boot, whenevertailscaledrestarts, and every 2 minutes, so each guest's own firewall decides again. --checkreports whether a node needs it and whether it is in place;--uninstallremoves it.- Afterwards, tailnet devices reach guests on that node only through ports their firewall allows, as on every other node. See SECURITY.md → 3c and docs/proxmate-ide.md → Tailscale subnet router on a Proxmox node.
- Run
- "Installed, but ProxMate can't reach it." When an IDE install times out after the install itself finished in the guest, the VM page now says the IDE installed but ProxMate can't reach it over the network, instead of "the last install didn't finish". The admin reachability test names the subnet-router case.
- The text console connects again. Opening a VM's text console could end at once without a login prompt: the browser's sign-in to the console arrived while ProxMate was still looking up the VM's node and was dropped, so Proxmox closed the session. It happened more often the slower ProxMate's link to Proxmox is. ProxMate now keeps what the browser sends until the console is ready. The graphical console was not affected.
1.3.3
ProxMate 1.3.3 fixes creating a machine behind a reverse proxy or a Cloudflare Tunnel, and the setup banners that stayed up until the page was reloaded. No configuration changes are needed to upgrade from 1.3.x.
- Creating a machine answers at once. Deploying from a template, installing from an ISO, creating a container and restoring an uploaded backup answer as soon as the machine is recorded, so the wizard opens its page right away, even behind a proxy or tunnel that cuts requests off after about 100 seconds. The page shows Creating until the machine is running, or why it couldn't be created. Quota, validation and placement errors still show in the wizard. The tenant email and the audit entry follow once the machine is running.
- Setup banners clear on their own. "Finishing setup on this VM…" and "Installing the ProxMate IDE…" clear without a reload: a VM page request that takes longer than 15 seconds is dropped and retried, and opening a VM also picks up a finished IDE install.
1.3.2
ProxMate 1.3.2 removes bulk deploys from a template from the Community Edition: deploying several copies at once, or one copy into each of several users' accounts, is now part of ProxMate Pro and EDU. Nothing else changes, and machines already deployed in a batch are ordinary machines and keep working. No configuration changes are needed to upgrade from 1.3.0 or 1.3.1; the rest of these notes describe 1.3.0 and 1.3.1 without that feature.
1.3.1
ProxMate 1.3.1 is ProxMate 1.3.0 with its version numbers corrected. The v1.3.0 tag was cut just before the version bump, so an install from it reports itself as 1.2.0 and keeps offering an update. 1.3.1 has the same features and fixes as 1.3.0, described below. Upgrading from 1.3.0 needs no steps beyond the update itself; upgrading from 1.2.x follows the 1.3.0 notes.
1.3.0
ProxMate 1.3.0 adds projects, a native Android app, view-only consoles for Viewer shares, tenant notifications and importing existing Proxmox guests. It also settles operations a backend restart interrupted, takes a snapshot before risky changes, and checks every restored backup before it is used. An optional pool-scoped Proxmox token limits what ProxMate's token can reach.
New in 1.3.0
- Projects. A Projects page groups your VMs by a
project:<name>tag. Each project shows its VM and running counts, allocated vCPU, RAM and disk, and average CPU and RAM use over 1, 7 or 14 days. It has Start all, Stop all and Restart all. Set a project on the VM page or with Move to project… on the VM list (owner or admin). VMs shared with you are listed separately, without their owner's tags. Admins see every owner's projects. - Android app. A native app for Android 8 and later. Enter your ProxMate address and sign in with email and password, including 2FA. Passkey and SSO accounts sign in through the web login inside the app. You then get the full ProxMate interface, consoles included.
- A self-signed certificate is trusted only after you check and accept its SHA-256 fingerprint. You are asked again if it changes.
- The APK is built by the Android workflow for every change, and a signed release APK is built for version tags once the signing secrets are set (see
android/README.md).
- View-only console for Viewer shares. A Viewer share can now watch a VM's graphical and text consoles, but not type into them.
- ProxMate's console relay drops keyboard, mouse, clipboard, resize and power messages before they reach Proxmox, and keeps the VNC session shared so a viewer never disconnects anyone else.
- Every console open is recorded in the audit log:
vm.console_open, orvm.console_view_openfor a view-only session. - A viewer's text console can't be resized.
- View the IDE install log. While the ProxMate IDE installs, or after it failed, the VM's owner or an admin can open View install log on the VM page. It shows the end of the install log, read through the guest agent, with Refresh and Download.
- Push a file into a VM. The owner, an admin or a Manager share can upload a small file into a QEMU VM through the guest agent, choosing its path, mode and owner. No SSH is needed.
- The default limit is 1 MiB per file (
GUEST_FILE_PUSH_MAX_BYTES, up to 8 MiB), and 30 pushes per 10 minutes per user. - Each push is recorded with its path, size and SHA-256.
- Into a folder other users can write to, the file is written as the chosen owner. Without an owner, such a push is refused.
- The default limit is 1 MiB per file (
- Tenant notifications.
- A tenant is emailed when an admin sets up a VM in their account.
- A user is emailed when a VM is shared with them or their access level changes, at most once a day per VM.
- Each user can turn these emails off under Security → Email preferences.
- Admin-managed badge. A VM an admin set up for a tenant shows "Set up by your admin — only an admin can resize or rebuild it." instead of silently missing controls.
- ntfy and Telegram for admin notifications, alongside the webhook and email. Tokens are stored encrypted and only shown masked, and each channel has its own Send test.
- Weekly usage digest. Users can opt in (it is off by default, behind an admin switch) to a weekly email with their machines, running hours, average CPU and memory, and quota in use. It is sent on Mondays at 08:00 (
USAGE_DIGEST_CRON). Admins can send themselves a preview. - Import existing Proxmox guests (admin). Settings → Maintenance → Import existing guests lists the QEMU and LXC guests ProxMate doesn't manage.
- Importing one for an owner applies the default bridge and the isolation firewall, tags it as that owner's, and counts it against their quota or as a grant.
- A guest is refused if it uses another guest's disks, host devices or host-level settings, or is a privileged container, including inside any of its snapshots.
- Automatic snapshots before risky changes. Before a resize, a data-disk resize or a rescue boot, ProxMate takes a disk-only
pm-auto-…snapshot of the VM, and refuses the change if the snapshot fails.- It keeps the newest 3 per VM (1–10, Admin → Settings → Maintenance) and only ever deletes snapshots it took itself.
- Containers and storage without snapshot support are skipped.
- A rebuild isn't covered, because deleting the guest deletes its snapshots: take a backup first.
- Interrupted operations are settled. A backend restart used to leave machines stuck in "creating". At startup and every 5 minutes, ProxMate now settles them from what Proxmox shows.
- A finished create is completed and left stopped.
- A create that produced no guest is removed and its quota freed.
- Anything part-way is held and admins are told which guest to check.
- ProxMate writes to a guest only when it can prove the guest came from that machine's own operation. It never deletes a backup.
- An operation still running, or younger than
RECONCILE_STUCK_MINUTES(15 minutes), is left alone.
ENCRYPTION_KEYbackup reminder. Admins see a banner on every page until one of them confirms the key is backed up off the host. A changed key brings the banner back. The key itself is never shown or stored.- Pool-scoped Proxmox token (optional). Set a Proxmox pool in the setup wizard or Admin → Settings, and every guest ProxMate creates, clones, restores or imports is placed in it.
deploy/proxmox-token.sh --pool <name>grants ProxMate's guest privileges on that pool only, instead of the whole cluster. Use--dry-runto see the plan first.- The connection test checks the pool and what the token can still reach, and Move managed guests into the pool moves existing machines.
- This mode has not yet been run end to end on a live cluster. Try it on a test cluster first, and see DEPLOYMENT.md → Pool-scoped token.
...
v1.3.3
ProxMate 1.3.3 fixes creating a machine behind a reverse proxy or a Cloudflare Tunnel, and the setup banners that stayed up until the page was reloaded. No configuration changes are needed to upgrade from 1.3.x.
- Creating a machine answers at once. Deploying from a template, installing from an ISO, creating a container and restoring an uploaded backup answer as soon as the machine is recorded, so the wizard opens its page right away, even behind a proxy or tunnel that cuts requests off after about 100 seconds. The page shows Creating until the machine is running, or why it couldn't be created. Quota, validation and placement errors still show in the wizard. The tenant email and the audit entry follow once the machine is running.
- Setup banners clear on their own. "Finishing setup on this VM…" and "Installing the ProxMate IDE…" clear without a reload: a VM page request that takes longer than 15 seconds is dropped and retried, and opening a VM also picks up a finished IDE install.
1.3.2
ProxMate 1.3.2 removes bulk deploys from a template from the Community Edition: deploying several copies at once, or one copy into each of several users' accounts, is now part of ProxMate Pro and EDU. Nothing else changes, and machines already deployed in a batch are ordinary machines and keep working. No configuration changes are needed to upgrade from 1.3.0 or 1.3.1; the rest of these notes describe 1.3.0 and 1.3.1 without that feature.
1.3.1
ProxMate 1.3.1 is ProxMate 1.3.0 with its version numbers corrected. The v1.3.0 tag was cut just before the version bump, so an install from it reports itself as 1.2.0 and keeps offering an update. 1.3.1 has the same features and fixes as 1.3.0, described below. Upgrading from 1.3.0 needs no steps beyond the update itself; upgrading from 1.2.x follows the 1.3.0 notes.
1.3.0
ProxMate 1.3.0 adds projects, a native Android app, view-only consoles for Viewer shares, tenant notifications and importing existing Proxmox guests. It also settles operations a backend restart interrupted, takes a snapshot before risky changes, and checks every restored backup before it is used. An optional pool-scoped Proxmox token limits what ProxMate's token can reach.
New in 1.3.0
- Projects. A Projects page groups your VMs by a
project:<name>tag. Each project shows its VM and running counts, allocated vCPU, RAM and disk, and average CPU and RAM use over 1, 7 or 14 days. It has Start all, Stop all and Restart all. Set a project on the VM page or with Move to project… on the VM list (owner or admin). VMs shared with you are listed separately, without their owner's tags. Admins see every owner's projects. - Android app. A native app for Android 8 and later. Enter your ProxMate address and sign in with email and password, including 2FA. Passkey and SSO accounts sign in through the web login inside the app. You then get the full ProxMate interface, consoles included.
- A self-signed certificate is trusted only after you check and accept its SHA-256 fingerprint. You are asked again if it changes.
- The APK is built by the Android workflow for every change, and a signed release APK is built for version tags once the signing secrets are set (see
android/README.md).
- View-only console for Viewer shares. A Viewer share can now watch a VM's graphical and text consoles, but not type into them.
- ProxMate's console relay drops keyboard, mouse, clipboard, resize and power messages before they reach Proxmox, and keeps the VNC session shared so a viewer never disconnects anyone else.
- Every console open is recorded in the audit log:
vm.console_open, orvm.console_view_openfor a view-only session. - A viewer's text console can't be resized.
- View the IDE install log. While the ProxMate IDE installs, or after it failed, the VM's owner or an admin can open View install log on the VM page. It shows the end of the install log, read through the guest agent, with Refresh and Download.
- Push a file into a VM. The owner, an admin or a Manager share can upload a small file into a QEMU VM through the guest agent, choosing its path, mode and owner. No SSH is needed.
- The default limit is 1 MiB per file (
GUEST_FILE_PUSH_MAX_BYTES, up to 8 MiB), and 30 pushes per 10 minutes per user. - Each push is recorded with its path, size and SHA-256.
- Into a folder other users can write to, the file is written as the chosen owner. Without an owner, such a push is refused.
- The default limit is 1 MiB per file (
- Tenant notifications.
- A tenant is emailed when an admin sets up a VM in their account.
- A user is emailed when a VM is shared with them or their access level changes, at most once a day per VM.
- Each user can turn these emails off under Security → Email preferences.
- Admin-managed badge. A VM an admin set up for a tenant shows "Set up by your admin — only an admin can resize or rebuild it." instead of silently missing controls.
- ntfy and Telegram for admin notifications, alongside the webhook and email. Tokens are stored encrypted and only shown masked, and each channel has its own Send test.
- Weekly usage digest. Users can opt in (it is off by default, behind an admin switch) to a weekly email with their machines, running hours, average CPU and memory, and quota in use. It is sent on Mondays at 08:00 (
USAGE_DIGEST_CRON). Admins can send themselves a preview. - Import existing Proxmox guests (admin). Settings → Maintenance → Import existing guests lists the QEMU and LXC guests ProxMate doesn't manage.
- Importing one for an owner applies the default bridge and the isolation firewall, tags it as that owner's, and counts it against their quota or as a grant.
- A guest is refused if it uses another guest's disks, host devices or host-level settings, or is a privileged container, including inside any of its snapshots.
- Automatic snapshots before risky changes. Before a resize, a data-disk resize or a rescue boot, ProxMate takes a disk-only
pm-auto-…snapshot of the VM, and refuses the change if the snapshot fails.- It keeps the newest 3 per VM (1–10, Admin → Settings → Maintenance) and only ever deletes snapshots it took itself.
- Containers and storage without snapshot support are skipped.
- A rebuild isn't covered, because deleting the guest deletes its snapshots: take a backup first.
- Interrupted operations are settled. A backend restart used to leave machines stuck in "creating". At startup and every 5 minutes, ProxMate now settles them from what Proxmox shows.
- A finished create is completed and left stopped.
- A create that produced no guest is removed and its quota freed.
- Anything part-way is held and admins are told which guest to check.
- ProxMate writes to a guest only when it can prove the guest came from that machine's own operation. It never deletes a backup.
- An operation still running, or younger than
RECONCILE_STUCK_MINUTES(15 minutes), is left alone.
ENCRYPTION_KEYbackup reminder. Admins see a banner on every page until one of them confirms the key is backed up off the host. A changed key brings the banner back. The key itself is never shown or stored.- Pool-scoped Proxmox token (optional). Set a Proxmox pool in the setup wizard or Admin → Settings, and every guest ProxMate creates, clones, restores or imports is placed in it.
deploy/proxmox-token.sh --pool <name>grants ProxMate's guest privileges on that pool only, instead of the whole cluster. Use--dry-runto see the plan first.- The connection test checks the pool and what the token can still reach, and Move managed guests into the pool moves existing machines.
- This mode has not yet been run end to end on a live cluster. Try it on a test cluster first, and see DEPLOYMENT.md → Pool-scoped token.
Fixes and changes in 1.3.0
- Restoring an uploaded backup checks what Proxmox restored. As soon as the restore ends, autostart, startup order and protection are removed. ProxMate then reads the restored guest's configuration, including pending changes and snapshots, and checks it before the machine can be used. It also clears the firewall rules, IP sets and aliases that came with the backup before applying isolation.
- A restored guest that doesn't pass is deleted.
- If Proxmox refuses the delete, the guest is held for an admin with its network links down.
- Adopt checks the guest's configuration before tagging it or lifting a hold. Adopting a restored or untagged guest also clears its autostart flags and restored firewall, and brings its network links back up.
- Number fields can be cleared and retyped. Emptying a numeric field no longer leaves a stuck
0that turns the next digit into "02". Min and max apply when you leave the field. - Rollback refuses a snapshot that holds host-level settings or another guest's disks.
- Machines still being created refuse every action except delete.
- Reserved VMIDs are honoured by every create path, including cloud-image builds and upload restores.
Upgrading from 1.2.x
No configuration changes are needed. Two database migrations run on first start:
-
one adds the email preferences (
User.activityEmailOptOut,User.usageDigestOptIn); -
one adds the operation-tracking fields and the automatic-snapshot table.
-
Back up
ENCRYPTION_KEYand confirm it when the banner asks. -
Automatic snapshots are on by default. They use storage that isn't counted against quotas, and on node-local storage a VM with snapshots may not live-migrate. Turn them off or lower the count under Admin → Settings → Maintenance if that matters to you.
-
File push on PVE 9 needs
VM.GuestAgent.FileWrite.deploy/proxmox-token.shnow always includes it; re-run the script if you use its token. -
The usage digest is off until an admin enables it and users opt in. Set
USAGE_DIGEST_CRONto change when it is sent (UTC in the Docker image).
...
v1.3.2
ProxMate 1.3.2 removes bulk deploys from a template from the Community Edition: deploying several copies at once, or one copy into each of several users' accounts, is now part of ProxMate Pro and EDU. Nothing else changes, and machines already deployed in a batch are ordinary machines and keep working. No configuration changes are needed to upgrade from 1.3.0 or 1.3.1; the rest of these notes describe 1.3.0 and 1.3.1 without that feature.
1.3.1
ProxMate 1.3.1 is ProxMate 1.3.0 with its version numbers corrected. The v1.3.0 tag was cut just before the version bump, so an install from it reports itself as 1.2.0 and keeps offering an update. 1.3.1 has the same features and fixes as 1.3.0, described below. Upgrading from 1.3.0 needs no steps beyond the update itself; upgrading from 1.2.x follows the 1.3.0 notes.
1.3.0
ProxMate 1.3.0 adds projects, a native Android app, view-only consoles for Viewer shares, tenant notifications and importing existing Proxmox guests. It also settles operations a backend restart interrupted, takes a snapshot before risky changes, and checks every restored backup before it is used. An optional pool-scoped Proxmox token limits what ProxMate's token can reach.
New in 1.3.0
- Projects. A Projects page groups your VMs by a
project:<name>tag. Each project shows its VM and running counts, allocated vCPU, RAM and disk, and average CPU and RAM use over 1, 7 or 14 days. It has Start all, Stop all and Restart all. Set a project on the VM page or with Move to project… on the VM list (owner or admin). VMs shared with you are listed separately, without their owner's tags. Admins see every owner's projects. - Android app. A native app for Android 8 and later. Enter your ProxMate address and sign in with email and password, including 2FA. Passkey and SSO accounts sign in through the web login inside the app. You then get the full ProxMate interface, consoles included.
- A self-signed certificate is trusted only after you check and accept its SHA-256 fingerprint. You are asked again if it changes.
- The APK is built by the Android workflow for every change, and a signed release APK is built for version tags once the signing secrets are set (see
android/README.md).
- View-only console for Viewer shares. A Viewer share can now watch a VM's graphical and text consoles, but not type into them.
- ProxMate's console relay drops keyboard, mouse, clipboard, resize and power messages before they reach Proxmox, and keeps the VNC session shared so a viewer never disconnects anyone else.
- Every console open is recorded in the audit log:
vm.console_open, orvm.console_view_openfor a view-only session. - A viewer's text console can't be resized.
- View the IDE install log. While the ProxMate IDE installs, or after it failed, the VM's owner or an admin can open View install log on the VM page. It shows the end of the install log, read through the guest agent, with Refresh and Download.
- Push a file into a VM. The owner, an admin or a Manager share can upload a small file into a QEMU VM through the guest agent, choosing its path, mode and owner. No SSH is needed.
- The default limit is 1 MiB per file (
GUEST_FILE_PUSH_MAX_BYTES, up to 8 MiB), and 30 pushes per 10 minutes per user. - Each push is recorded with its path, size and SHA-256.
- Into a folder other users can write to, the file is written as the chosen owner. Without an owner, such a push is refused.
- The default limit is 1 MiB per file (
- Tenant notifications.
- A tenant is emailed when an admin sets up a VM in their account.
- A user is emailed when a VM is shared with them or their access level changes, at most once a day per VM.
- Each user can turn these emails off under Security → Email preferences.
- Admin-managed badge. A VM an admin set up for a tenant shows "Set up by your admin — only an admin can resize or rebuild it." instead of silently missing controls.
- ntfy and Telegram for admin notifications, alongside the webhook and email. Tokens are stored encrypted and only shown masked, and each channel has its own Send test.
- Weekly usage digest. Users can opt in (it is off by default, behind an admin switch) to a weekly email with their machines, running hours, average CPU and memory, and quota in use. It is sent on Mondays at 08:00 (
USAGE_DIGEST_CRON). Admins can send themselves a preview. - Import existing Proxmox guests (admin). Settings → Maintenance → Import existing guests lists the QEMU and LXC guests ProxMate doesn't manage.
- Importing one for an owner applies the default bridge and the isolation firewall, tags it as that owner's, and counts it against their quota or as a grant.
- A guest is refused if it uses another guest's disks, host devices or host-level settings, or is a privileged container, including inside any of its snapshots.
- Automatic snapshots before risky changes. Before a resize, a data-disk resize or a rescue boot, ProxMate takes a disk-only
pm-auto-…snapshot of the VM, and refuses the change if the snapshot fails.- It keeps the newest 3 per VM (1–10, Admin → Settings → Maintenance) and only ever deletes snapshots it took itself.
- Containers and storage without snapshot support are skipped.
- A rebuild isn't covered, because deleting the guest deletes its snapshots: take a backup first.
- Interrupted operations are settled. A backend restart used to leave machines stuck in "creating". At startup and every 5 minutes, ProxMate now settles them from what Proxmox shows.
- A finished create is completed and left stopped.
- A create that produced no guest is removed and its quota freed.
- Anything part-way is held and admins are told which guest to check.
- ProxMate writes to a guest only when it can prove the guest came from that machine's own operation. It never deletes a backup.
- An operation still running, or younger than
RECONCILE_STUCK_MINUTES(15 minutes), is left alone.
ENCRYPTION_KEYbackup reminder. Admins see a banner on every page until one of them confirms the key is backed up off the host. A changed key brings the banner back. The key itself is never shown or stored.- Pool-scoped Proxmox token (optional). Set a Proxmox pool in the setup wizard or Admin → Settings, and every guest ProxMate creates, clones, restores or imports is placed in it.
deploy/proxmox-token.sh --pool <name>grants ProxMate's guest privileges on that pool only, instead of the whole cluster. Use--dry-runto see the plan first.- The connection test checks the pool and what the token can still reach, and Move managed guests into the pool moves existing machines.
- This mode has not yet been run end to end on a live cluster. Try it on a test cluster first, and see DEPLOYMENT.md → Pool-scoped token.
Fixes and changes in 1.3.0
- Restoring an uploaded backup checks what Proxmox restored. As soon as the restore ends, autostart, startup order and protection are removed. ProxMate then reads the restored guest's configuration, including pending changes and snapshots, and checks it before the machine can be used. It also clears the firewall rules, IP sets and aliases that came with the backup before applying isolation.
- A restored guest that doesn't pass is deleted.
- If Proxmox refuses the delete, the guest is held for an admin with its network links down.
- Adopt checks the guest's configuration before tagging it or lifting a hold. Adopting a restored or untagged guest also clears its autostart flags and restored firewall, and brings its network links back up.
- Number fields can be cleared and retyped. Emptying a numeric field no longer leaves a stuck
0that turns the next digit into "02". Min and max apply when you leave the field. - Rollback refuses a snapshot that holds host-level settings or another guest's disks.
- Machines still being created refuse every action except delete.
- Reserved VMIDs are honoured by every create path, including cloud-image builds and upload restores.
Upgrading from 1.2.x
No configuration changes are needed. Two database migrations run on first start:
-
one adds the email preferences (
User.activityEmailOptOut,User.usageDigestOptIn); -
one adds the operation-tracking fields and the automatic-snapshot table.
-
Back up
ENCRYPTION_KEYand confirm it when the banner asks. -
Automatic snapshots are on by default. They use storage that isn't counted against quotas, and on node-local storage a VM with snapshots may not live-migrate. Turn them off or lower the count under Admin → Settings → Maintenance if that matters to you.
-
File push on PVE 9 needs
VM.GuestAgent.FileWrite.deploy/proxmox-token.shnow always includes it; re-run the script if you use its token. -
The usage digest is off until an admin enables it and users opt in. Set
USAGE_DIGEST_CRONto change when it is sent (UTC in the Docker image).
1.2.0
ProxMate 1.2.0 adds sharing with people who haven't signed up yet, spreads template deploys across the cluster, and ships a least-privilege Proxmox token. Coming from 1.0.x? Read the 1.1.0 notes below first: they include the upgrade steps.
New in 1.2.0
- Share a VM before someone signs up. Sharing with an address that has no account keeps a pending share. It starts when an account is created with that address and the address is confirmed: registration through an invite sent to that address, or SSO sign-up with an email the identity provider verified. A self-typed address on an open invite never picks it up. Pending and live shares look the same in the owner's list, so sharing still doesn't reveal who has an account, and either kind can be revoked. A pending share doesn't invite anyone: send an invite to the same address. A VM can hold up to 100 shares.
- Template deploys spread across the cluster. A deploy that is a full clone, with the template's disks and the destination...
v1.2.0
ProxMate 1.2.0 adds sharing with people who haven't signed up yet, spreads template deploys across the cluster, and ships a least-privilege Proxmox token. Coming from 1.0.x? Read the 1.1.0 notes below first: they include the upgrade steps.
New in 1.2.0
- Share a VM before someone signs up. Sharing with an address that has no account keeps a pending share. It starts when an account is created with that address and the address is confirmed: registration through an invite sent to that address, or SSO sign-up with an email the identity provider verified. A self-typed address on an open invite never picks it up. Pending and live shares look the same in the owner's list, so sharing still doesn't reveal who has an account, and either kind can be revoked. A pending share doesn't invite anyone: send an invite to the same address. A VM can hold up to 100 shares.
- Template deploys spread across the cluster. A deploy that is a full clone, with the template's disks and the destination storage on shared storage (Ceph, NFS), goes to the node with the most free capacity instead of the template's node. It only picks nodes that can serve the deploy's cloud-init snippet. Linked clones and anything on node-local storage stay on the template's node as before.
- Least-privilege Proxmox token.
deploy/proxmox-token.shcreates aproxmate@pveuser, aProxMaterole holding only the privileges ProxMate uses, and a privilege-separated token. It picks the guest-agent privileges for your Proxmox release and can be re-run safely. It was run end to end on a 7-node Proxmox VE 9.2 cluster with every feature working through it. See DEPLOYMENT.md §2.2. - Connection test checks every privilege. It now warns about each privilege ProxMate uses, including backups, migration, the cluster firewall and the guest-agent privileges that changed in Proxmox VE 9.
Fixes in 1.2.0
- Start and restart report what Proxmox did. Like stop in 1.1.0, they wait up to 45 seconds for Proxmox to confirm the task. A failed start now returns its error instead of marking the VM running, and a restart the guest ignores returns advice to wait or stop it forcibly. Bulk start, stop and restart run side by side.
Upgrading from 1.1.x
No configuration changes are needed. A database migration adds the pending-shares table on first start.
- Admins using a narrower Proxmox token than root or Administrator may see new connection-test warnings: each names a privilege a feature needs. Re-run
deploy/proxmox-token.sh, or grant the named privileges. - On clusters with shared VM storage, new template deploys may land on a different node from the template.
1.1.1
- API tokens and ended access. A personal API token whose owner's compute access window has ended now answers 403 with
code: "access_expired", the same as a browser session. It used to answer 401, which looked like a bad token. Unknown, revoked or expired tokens still answer 401. - Docker Compose settings.
ALERT_COOLDOWN_MIN,PUBLIC_TOKEN_RATE_LIMIT_MAXandPUBLIC_TOKEN_RATE_LIMIT_WINDOW_MSare now passed through to the backend, so setting them in.envtakes effect. - Settings that aren't numbers.
PORTandRESTORE_UPLOAD_MAX_GBfall back to their defaults when set to something that isn't a number. A badRESTORE_UPLOAD_MAX_GBused to turn the upload size limit off. - Docs. The README, deployment guide, admin guide, API and IDE docs, and the security guide are updated for 1.1.0.
SECURITY.mdnow says which versions get security fixes and how to report a problem privately.
No configuration changes are needed to upgrade from 1.1.0.
1.1.0
ProxMate 1.1.0 is a security and reliability release. It follows a full review of the codebase and closes every issue that review found, and it fixes the setup wizard on SDN-only clusters (#126). Every 1.0.x install should upgrade. Read Upgrading below first: a few changes need a step from the admin, and some behaviour changes on purpose.
Security
- Guest ownership. Every guest ProxMate manages now carries a Proxmox tag naming its machine. Start, stop, console, IDE, backups, restores, resize and delete act only on a guest carrying its own machine's tag, so a stale or reused VMID can never point an action at someone else's guest. Existing guests are tagged on first start; see Upgrading.
- ProxMate IDE. The IDE opens only for the machine's owner. Before connecting, ProxMate confirms it is talking to that machine's own guest using a per-machine secret, and ProxMate's cookies are never passed to the guest or accepted back from it.
- Setup wizard. Once the admin account exists, every remaining setup step requires that admin's session.
- Sign-in and account security. Failed logins and 2FA codes are counted reliably under concurrent attempts, and 2FA codes are limited per account and per challenge. Passkey challenges are kept on the server and are single-use. Download links, password-reset links and recovery codes work exactly once. A password reset revokes the account's API tokens and signs it out everywhere. Replacing an existing authenticator needs a current code. Required 2FA also applies to password logins on SSO-linked accounts.
- API tokens (
pm_…) are refused on routes that change how an account signs in or is secured; those need a browser session. - SSO and invites. SSO links to an existing local account only when the identity provider marks the email verified and the account's email was confirmed by an invite. An invite sent to an address can be used only with that address.
- Backups and restores. Restoring an uploaded backup accepts only a guest's own configuration (no host devices or paths, raw arguments, hook scripts or privileged containers; containers always restore unprivileged). Restores, rollbacks and backups check that every disk belongs to that guest. Restores and rollbacks re-apply the guest's network isolation before it starts, and count against the owner's quota.
- Quotas are enforced when several creates or resizes for the same owner run at once.
- Sharing. Sharing a machine by email answers the same whether or not the address has an account, and is rate-limited per user. The share list shows only the address and access level.
- Admin settings and the audit log. Settings changes are audited without recording secret values, the notification webhook URL is shown only masked, and the audit log trusts a client-IP header only behind a configured proxy.
- Deployment. App-database snapshots are created readable by their owner only. The host updater no longer leaves root-owned files in the checkout and keeps its control files out of the app's reach. The backend refuses to start in production without a saved
ENCRYPTION_KEY, and images move to Node 22.
Fixes
- SDN and OVS networks (#126). The setup wizard and network settings list SDN VNets and Open vSwitch bridges, not only Linux bridges. A network name can be typed in when discovery finds nothing, and the connection test warns when the token lacks
SDN.UseorSDN.Audit. - Stop reports what Proxmox did. Stop waits for Proxmox to confirm the guest is down (up to 45 seconds). A guest that ignores a shutdown now returns an error asking you to wait or force-stop, instead of being marked stopped while it keeps running. Bulk and scheduled stops run side by side, so several slow guests don't add up.
- Migration no longer reports every possible target node as blocked.
- Resize grows the root disk by the requested change, not to the requested total, so data disks are no longer counted twice. Machines need at least 64 MB of RAM.
- Failed creates no longer leave orphaned rows or untagged guests behind. A machine that didn't finish creating, rebuilding or restoring is held, and its page says why.
- Locked machines. Bulk actions, migrations, the Cluster Balancer and node drains skip a machine while its IDE installs or its cloud-init deploy finishes, and report it.
- Schedules. Invalid stored power and backup schedules are reported to admins at startup. Per-VM backups missed while the backend was down run after it restarts.
- Alerts are capped at 20 rules per machine, duplicates are refused, and simultaneous firings are delivered once.
- Dashboard. While the API is unreachable the dashboard retries with a clear retry state instead of bouncing between pages. Bulk actions apply only to the selected machines visible under the active filter. Resize and quota dialogs keep RAM sizes exact. A rejected kiosk-exit PIN keeps the kiosk signed in.
- Settings. Numeric settings that aren't numbers fall back to their defaults instead of breaking. The Docker backend receives every setting documented in
.env. code-server listens onIDE_GUEST_PORT. - Updater. Local
docker-compose.ymlchanges now live indocker-compose.override.yml, and the updater refuses to run over local edits instead of discarding them.
Upgrading
Upgrading from 1.0.x and earlier
Read DEPLOYMENT.md §14.4 before updating. In short:
- Before updating, move local
docker-compose.ymledits intodocker-compose.override.yml. The update into this release is run by the updater already on the host, which force-checks-out the release and discards edits to tracked files — including uncommented/control, private-CA, snippets and backup-download mounts. Copy those mounts intodocker-compose.override.yml(aftergit fetch --tags, take the template withgit show <new-tag>:docker-compose.override.example.yml), rungit checkout -- docker-compose.yml, then update. From this release on, optional mounts live only in the override, and the updater refuses to run over local edits instead of discarding them. - Re-install the updater units after updating: copy
deploy/proxmate-updater.serviceanddeploy/proxmate-updater.pathto/etc/systemd/system/and run `systemctl ...
v1.1.1
ProxMate 1.1.1 is a small follow-up to 1.1.0. Coming from 1.0.x? Read the 1.1.0 notes below first: they include the upgrade steps.
Changes in 1.1.1
- API tokens and ended access. A personal API token whose owner's compute access window has ended now answers 403 with
code: "access_expired", the same as a browser session. It used to answer 401, which looked like a bad token. Unknown, revoked or expired tokens still answer 401. - Docker Compose settings.
ALERT_COOLDOWN_MIN,PUBLIC_TOKEN_RATE_LIMIT_MAXandPUBLIC_TOKEN_RATE_LIMIT_WINDOW_MSare now passed through to the backend, so setting them in.envtakes effect. - Settings that aren't numbers.
PORTandRESTORE_UPLOAD_MAX_GBfall back to their defaults when set to something that isn't a number. A badRESTORE_UPLOAD_MAX_GBused to turn the upload size limit off. - Docs. The README, deployment guide, admin guide, API and IDE docs, and the security guide are updated for 1.1.0.
SECURITY.mdnow says which versions get security fixes and how to report a problem privately.
No configuration changes are needed to upgrade from 1.1.0.
1.1.0
ProxMate 1.1.0 is a security and reliability release. It follows a full review of the codebase and closes every issue that review found, and it fixes the setup wizard on SDN-only clusters (#126). Every 1.0.x install should upgrade. Read Upgrading below first: a few changes need a step from the admin, and some behaviour changes on purpose.
Security
- Guest ownership. Every guest ProxMate manages now carries a Proxmox tag naming its machine. Start, stop, console, IDE, backups, restores, resize and delete act only on a guest carrying its own machine's tag, so a stale or reused VMID can never point an action at someone else's guest. Existing guests are tagged on first start; see Upgrading.
- ProxMate IDE. The IDE opens only for the machine's owner. Before connecting, ProxMate confirms it is talking to that machine's own guest using a per-machine secret, and ProxMate's cookies are never passed to the guest or accepted back from it.
- Setup wizard. Once the admin account exists, every remaining setup step requires that admin's session.
- Sign-in and account security. Failed logins and 2FA codes are counted reliably under concurrent attempts, and 2FA codes are limited per account and per challenge. Passkey challenges are kept on the server and are single-use. Download links, password-reset links and recovery codes work exactly once. A password reset revokes the account's API tokens and signs it out everywhere. Replacing an existing authenticator needs a current code. Required 2FA also applies to password logins on SSO-linked accounts.
- API tokens (
pm_…) are refused on routes that change how an account signs in or is secured; those need a browser session. - SSO and invites. SSO links to an existing local account only when the identity provider marks the email verified and the account's email was confirmed by an invite. An invite sent to an address can be used only with that address.
- Backups and restores. Restoring an uploaded backup accepts only a guest's own configuration (no host devices or paths, raw arguments, hook scripts or privileged containers; containers always restore unprivileged). Restores, rollbacks and backups check that every disk belongs to that guest. Restores and rollbacks re-apply the guest's network isolation before it starts, and count against the owner's quota.
- Quotas are enforced when several creates or resizes for the same owner run at once.
- Sharing. Sharing a machine by email answers the same whether or not the address has an account, and is rate-limited per user. The share list shows only the address and access level.
- Admin settings and the audit log. Settings changes are audited without recording secret values, the notification webhook URL is shown only masked, and the audit log trusts a client-IP header only behind a configured proxy.
- Deployment. App-database snapshots are created readable by their owner only. The host updater no longer leaves root-owned files in the checkout and keeps its control files out of the app's reach. The backend refuses to start in production without a saved
ENCRYPTION_KEY, and images move to Node 22.
Fixes
- SDN and OVS networks (#126). The setup wizard and network settings list SDN VNets and Open vSwitch bridges, not only Linux bridges. A network name can be typed in when discovery finds nothing, and the connection test warns when the token lacks
SDN.UseorSDN.Audit. - Stop reports what Proxmox did. Stop waits for Proxmox to confirm the guest is down (up to 45 seconds). A guest that ignores a shutdown now returns an error asking you to wait or force-stop, instead of being marked stopped while it keeps running. Bulk and scheduled stops run side by side, so several slow guests don't add up.
- Migration no longer reports every possible target node as blocked.
- Resize grows the root disk by the requested change, not to the requested total, so data disks are no longer counted twice. Machines need at least 64 MB of RAM.
- Failed creates no longer leave orphaned rows or untagged guests behind. A machine that didn't finish creating, rebuilding or restoring is held, and its page says why.
- Locked machines. Bulk actions, migrations, the Cluster Balancer and node drains skip a machine while its IDE installs or its cloud-init deploy finishes, and report it.
- Schedules. Invalid stored power and backup schedules are reported to admins at startup. Per-VM backups missed while the backend was down run after it restarts.
- Alerts are capped at 20 rules per machine, duplicates are refused, and simultaneous firings are delivered once.
- Dashboard. While the API is unreachable the dashboard retries with a clear retry state instead of bouncing between pages. Bulk actions apply only to the selected machines visible under the active filter. Resize and quota dialogs keep RAM sizes exact. A rejected kiosk-exit PIN keeps the kiosk signed in.
- Settings. Numeric settings that aren't numbers fall back to their defaults instead of breaking. The Docker backend receives every setting documented in
.env. code-server listens onIDE_GUEST_PORT. - Updater. Local
docker-compose.ymlchanges now live indocker-compose.override.yml, and the updater refuses to run over local edits instead of discarding them.
Upgrading
Upgrading from 1.0.x and earlier
Read DEPLOYMENT.md §14.4 before updating. In short:
- Before updating, move local
docker-compose.ymledits intodocker-compose.override.yml. The update into this release is run by the updater already on the host, which force-checks-out the release and discards edits to tracked files — including uncommented/control, private-CA, snippets and backup-download mounts. Copy those mounts intodocker-compose.override.yml(aftergit fetch --tags, take the template withgit show <new-tag>:docker-compose.override.example.yml), rungit checkout -- docker-compose.yml, then update. From this release on, optional mounts live only in the override, and the updater refuses to run over local edits instead of discarding them. - Re-install the updater units after updating: copy
deploy/proxmate-updater.serviceanddeploy/proxmate-updater.pathto/etc/systemd/system/and runsystemctl daemon-reload. - Images move to Node 22 (
node:22-alpine); Node 20 is end-of-life. TRUST_PROXY≥ 1 is required for the audit log's real-IP header (REAL_IP_HEADER, defaultcf-connecting-ip);x-forwarded-foris resolved through the trusted hop count. Behind Caddy, nginx or a Cloudflare Tunnel keepTRUST_PROXY=1.- The backend refuses to start in production without
ENCRYPTION_KEY. Docker installs already require it; barenode/npm startruns no longer generate a key in memory.
What changes for admins and users after upgrading from 1.0.x
Guest ownership tags and the Unconfirmed machines card
- Every guest ProxMate manages now carries a Proxmox tag naming its machine (
proxmate-<id>; templatesproxmate-template-<id>). Start, stop, console, IDE, backups, restores, resize and delete act only on a guest that carries its own machine's tag. The Proxmox API token must be allowed to set guest tags (VM.Config.Options); the recommended privilege-separation-off token, or one with the Administrator role, is. - At first start the upgrade tags existing guests. A machine is tagged only when exactly one machine references its VMID, its status is not
errororcreating, its guest has no ProxMate tag yet, and the guest's Proxmox name matches the machine's name. Everything else stays unmatched: machines left inerrororcreatingby 1.0.x, machines renamed in Proxmox (or in ProxMate) so the names differ, and VMIDs referenced by more than one machine. - If Proxmox can't be reached at boot, or a guest can't be read, the tagging pass is retried every 15 minutes until a pass completes. When a completed pass leaves machines unmatched, admins get one
vm.errornotification with the count. - Unmatched machines are refused (start, console, IDE, backups, delete) until an admin settles them in Settings → Maintenance → Unconfirmed machines: Adopt tags the guest at the VMID as that machine's. On an
erroror held machine it then puts the guest on the current bridge with isolation applied and re-reads its CPU, RAM and disk sizes, as a restore does, and only then clears the hold so the machine can be started; disks over the owner's quota keep it held, Remove row deletes only the ProxMate record and leaves the guest alone. Adopt is refused for a guest that carries another machine's tag, is a Proxmox or Template Store template, has another machine on the same VMID, or references disks that aren't its own. - Removing or refreshing a template deletes the ...
v1.1.0
ProxMate 1.1.0 is a security and reliability release. It follows a full review of the codebase and closes every issue that review found, and it fixes the setup wizard on SDN-only clusters (#126). Every 1.0.x install should upgrade. Read Upgrading below first: a few changes need a step from the admin, and some behaviour changes on purpose.
Security
- Guest ownership. Every guest ProxMate manages now carries a Proxmox tag naming its machine. Start, stop, console, IDE, backups, restores, resize and delete act only on a guest carrying its own machine's tag, so a stale or reused VMID can never point an action at someone else's guest. Existing guests are tagged on first start; see Upgrading.
- ProxMate IDE. The IDE opens only for the machine's owner. Before connecting, ProxMate confirms it is talking to that machine's own guest using a per-machine secret, and ProxMate's cookies are never passed to the guest or accepted back from it.
- Setup wizard. Once the admin account exists, every remaining setup step requires that admin's session.
- Sign-in and account security. Failed logins and 2FA codes are counted reliably under concurrent attempts, and 2FA codes are limited per account and per challenge. Passkey challenges are kept on the server and are single-use. Download links, password-reset links and recovery codes work exactly once. A password reset revokes the account's API tokens and signs it out everywhere. Replacing an existing authenticator needs a current code. Required 2FA also applies to password logins on SSO-linked accounts.
- API tokens (
pm_…) are refused on routes that change how an account signs in or is secured; those need a browser session. - SSO and invites. SSO links to an existing local account only when the identity provider marks the email verified and the account's email was confirmed by an invite. An invite sent to an address can be used only with that address.
- Backups and restores. Restoring an uploaded backup accepts only a guest's own configuration (no host devices or paths, raw arguments, hook scripts or privileged containers; containers always restore unprivileged). Restores, rollbacks and backups check that every disk belongs to that guest. Restores and rollbacks re-apply the guest's network isolation before it starts, and count against the owner's quota.
- Quotas are enforced when several creates or resizes for the same owner run at once.
- Sharing. Sharing a machine by email answers the same whether or not the address has an account, and is rate-limited per user. The share list shows only the address and access level.
- Admin settings and the audit log. Settings changes are audited without recording secret values, the notification webhook URL is shown only masked, and the audit log trusts a client-IP header only behind a configured proxy.
- Deployment. App-database snapshots are created readable by their owner only. The host updater no longer leaves root-owned files in the checkout and keeps its control files out of the app's reach. The backend refuses to start in production without a saved
ENCRYPTION_KEY, and images move to Node 22.
Fixes
- SDN and OVS networks (#126). The setup wizard and network settings list SDN VNets and Open vSwitch bridges, not only Linux bridges. A network name can be typed in when discovery finds nothing, and the connection test warns when the token lacks
SDN.UseorSDN.Audit. - Stop reports what Proxmox did. Stop waits for Proxmox to confirm the guest is down (up to 45 seconds). A guest that ignores a shutdown now returns an error asking you to wait or force-stop, instead of being marked stopped while it keeps running. Bulk and scheduled stops run side by side, so several slow guests don't add up.
- Migration no longer reports every possible target node as blocked.
- Resize grows the root disk by the requested change, not to the requested total, so data disks are no longer counted twice. Machines need at least 64 MB of RAM.
- Failed creates no longer leave orphaned rows or untagged guests behind. A machine that didn't finish creating, rebuilding or restoring is held, and its page says why.
- Locked machines. Bulk actions, migrations, the Cluster Balancer and node drains skip a machine while its IDE installs or its cloud-init deploy finishes, and report it.
- Schedules. Invalid stored power and backup schedules are reported to admins at startup. Per-VM backups missed while the backend was down run after it restarts.
- Alerts are capped at 20 rules per machine, duplicates are refused, and simultaneous firings are delivered once.
- Dashboard. While the API is unreachable the dashboard retries with a clear retry state instead of bouncing between pages. Bulk actions apply only to the selected machines visible under the active filter. Resize and quota dialogs keep RAM sizes exact. A rejected kiosk-exit PIN keeps the kiosk signed in.
- Settings. Numeric settings that aren't numbers fall back to their defaults instead of breaking. The Docker backend receives every setting documented in
.env. code-server listens onIDE_GUEST_PORT. - Updater. Local
docker-compose.ymlchanges now live indocker-compose.override.yml, and the updater refuses to run over local edits instead of discarding them.
Upgrading
Upgrading from 1.0.x and earlier
Read DEPLOYMENT.md §14.4 before updating. In short:
- Before updating, move local
docker-compose.ymledits intodocker-compose.override.yml. The update into this release is run by the updater already on the host, which force-checks-out the release and discards edits to tracked files — including uncommented/control, private-CA, snippets and backup-download mounts. Copy those mounts intodocker-compose.override.yml(aftergit fetch --tags, take the template withgit show <new-tag>:docker-compose.override.example.yml), rungit checkout -- docker-compose.yml, then update. From this release on, optional mounts live only in the override, and the updater refuses to run over local edits instead of discarding them. - Re-install the updater units after updating: copy
deploy/proxmate-updater.serviceanddeploy/proxmate-updater.pathto/etc/systemd/system/and runsystemctl daemon-reload. - Images move to Node 22 (
node:22-alpine); Node 20 is end-of-life. TRUST_PROXY≥ 1 is required for the audit log's real-IP header (REAL_IP_HEADER, defaultcf-connecting-ip);x-forwarded-foris resolved through the trusted hop count. Behind Caddy, nginx or a Cloudflare Tunnel keepTRUST_PROXY=1.- The backend refuses to start in production without
ENCRYPTION_KEY. Docker installs already require it; barenode/npm startruns no longer generate a key in memory.
What changes for admins and users after upgrading from 1.0.x
Guest ownership tags and the Unconfirmed machines card
- Every guest ProxMate manages now carries a Proxmox tag naming its machine (
proxmate-<id>; templatesproxmate-template-<id>). Start, stop, console, IDE, backups, restores, resize and delete act only on a guest that carries its own machine's tag. The Proxmox API token must be allowed to set guest tags (VM.Config.Options); the recommended privilege-separation-off token, or one with the Administrator role, is. - At first start the upgrade tags existing guests. A machine is tagged only when exactly one machine references its VMID, its status is not
errororcreating, its guest has no ProxMate tag yet, and the guest's Proxmox name matches the machine's name. Everything else stays unmatched: machines left inerrororcreatingby 1.0.x, machines renamed in Proxmox (or in ProxMate) so the names differ, and VMIDs referenced by more than one machine. - If Proxmox can't be reached at boot, or a guest can't be read, the tagging pass is retried every 15 minutes until a pass completes. When a completed pass leaves machines unmatched, admins get one
vm.errornotification with the count. - Unmatched machines are refused (start, console, IDE, backups, delete) until an admin settles them in Settings → Maintenance → Unconfirmed machines: Adopt tags the guest at the VMID as that machine's. On an
erroror held machine it then puts the guest on the current bridge with isolation applied and re-reads its CPU, RAM and disk sizes, as a restore does, and only then clears the hold so the machine can be started; disks over the owner's quota keep it held, Remove row deletes only the ProxMate record and leaves the guest alone. Adopt is refused for a guest that carries another machine's tag, is a Proxmox or Template Store template, has another machine on the same VMID, or references disks that aren't its own. - Removing or refreshing a template deletes the old Proxmox guest only while it still carries that template's tag. Otherwise it is left in place and admins are notified.
Machines that can't run
- A machine in
error, or held after a create, rebuild or restore that didn't finish (or a restore that left it over quota), can't be started and its console and IDE don't open. Its page says why. It can be restored, rebuilt, adopted by an admin, or deleted. - Backups are refused for a machine whose config references a disk that isn't one of its own storage volumes. That includes disks that are not volumes at all, such as an iSCSI LUN or a host disk passed through by path; such a guest can't be adopted either. Detach the disk in Proxmox first.
- Restore from an uploaded backup accepts only archives whose config describes the guest itself. Host devices and paths, raw QEMU or LXC keys, hook scripts, custom cloud-init snippets, CPU/NUMA host pinning, container features beyond nesting, a template flag and privileged containers are refused. Containers are always restored unprivileged.
- Machines need at least 64 MB of RAM: a create, deploy or resize asking for less is refused with 400.
- A r...
v1.0.0
Security
- Cloud-init login passwords are no longer given to cloud-init. The crypt hash was written to the seed drive (
/dev/sr0) and to the guest's/var/lib/cloudcache, both readable by the VM's own user for its lifetime. The password is now held encrypted until first boot, applied in-guest via the QEMU guest agent, then discarded.cipasswordwas removed fromsetCloudInitConfig's signature. - Axios client error objects are sanitized before logging. An axios error carries the request that produced it, including the
Authorizationheader, soconfigandrequestare now replaced with sanitized copies at the client, on both the error and its response. - Guests can be placed on a per-tenant VLAN. The per-VM firewall operates at L3 and above and could not prevent ARP poisoning, rogue DHCP, or IPv6 router advertisement between tenants sharing a bridge. Verified on a live cluster: cross-VLAN blocked at ARP resolution, same-VLAN control passes.
- Outbound DHCP server replies (
udp dport 68) and IPv6 router advertisements are dropped per guest. Clients still obtain leases. - The compute-access window is enforced on passkey and SSO login, not only password. All three paths share one refusal; a source-scan test fails if a new login path skips it.
testProxmoxConnectionrejects a token that authenticates but holds no permissions. A--privsep 1token answers/versionand returns every node, so the previous check reported success. It now reads/access/permissionsand names the missing privilege and the command that grants it.
Fixes
- The default network bridge and default storage are applied to guests deployed from a template. A template deploy is a clone, so both were inherited from the template and the configured defaults never applied. Storage additionally reverted the migratability fix from 0.9.0 — new guests kept landing on node-local storage. Applied on deploy, duplicate and restore, preserving MAC, firewall flag and VLAN tag.
- A linked-clone template that is not on the configured storage is now full-cloned. Proxmox cannot place a linked clone on a different storage; the link is dropped rather than the setting, and the reason is logged.
- Cloud-image templates built by ProxMate now include
qemu-guest-agent. The importer converted the downloaded image to a template without booting it, so no package could be installed — and since login passwords are applied through the agent, those templates could not serve a password-only deploy. The build boots the image once, installs and verifies the agent, clears the cloud-init cache and build logs, then converts. A build without network access still produces a usable template, recorded as agentless and flagged in Template Store. deploy.agent_missingnotification when a deploy's guest agent never responds. Previously the only signals were a log line and a tenant unable to log in.GET /api/admin/storage-pinninglists guests that cannot migrate, using Proxmox's own migration preflight.
Modules
Self-hosted installs can add API routes and database tables without patching app.ts. A module is a directory exporting an Express router, enabled by name in PROXMATE_MODULES and served under /api/ext/<name>.
Modules supply a router rather than the application, so they cannot reorder middleware or replace the error handler. All modules mount under one reserved path segment and cannot shadow a built-in route. requireAuth is applied by default; opting out is logged by name at boot. Modules may own a Prisma schema and migrations, applied after core migrations.
With no module configured no import is attempted and no route is added. See backend/src/modules/README.md.
Upgrading
No configuration changes required.
- Rebuild cloud-image templates to pick up the guest agent. Password-only deploys from templates built before this release produce machines their owner cannot log into. Template Store flags them.
- Guests created before this release keep their existing storage.
GET /api/admin/storage-pinninglists any that cannot migrate as a result.
What's Changed
- Feat/tenant network segmentation and hardening by @r0073d-l053r in #112
- fix(deploy): the EDU dev stack's "never fire" crons crash-looped the … by @r0073d-l053r in #113
- fix(cloud-init): never put the login password on the seed — set it via the guest agent by @r0073d-l053r in #114
- chore(deploy): rename the second-instance stack to be edition-neutral by @r0073d-l053r in #115
- fix: apply the default bridge and storage to cloned guests (B-37 / B-38) by @r0073d-l053r in #116
- Guest-agent templates, a connection test that means something, and a migration-pinning report by @r0073d-l053r in #117
- fix: scrub the build boot out of a baked template (B-42) by @r0073d-l053r in #118
- feat: a minimal seam for mounting optional module routers (B-35) by @r0073d-l053r in #119
- ci: fix the Security workflow on private forks, and pass PROXMATE_MODULES to the dev stack by @r0073d-l053r in #120
- release: v1.0.0 by @r0073d-l053r in #121
- refactor(proxmox): sanitize axios client error objects by @r0073d-l053r in #122
- docs: rewrite the v1.0.0 release notes by @r0073d-l053r in #123
Full Changelog: v0.9.1...v1.0.0
v0.9.1
Highlights
A fix release, and one of the fixes is the kind worth reading about: on some
installs the nightly backup of ProxMate's own database had never once succeeded,
and nothing said so.
- The installer now installs what your machine is missing — Docker, Compose
v2, git, curl, openssl — after asking. Declining changes nothing. - Fixed: app-database backups could fail silently, forever. Any install done
withsudoleft the backup directory unwritable by the container. The job ran
every night at 02:30, failed, and reported nothing. - Fixed: migrations that Proxmox permits but the guest cannot survive are now
refused, with the reason and the way round it. - Fixed: an HTTPS deployment could silently lose
upgrade-insecure-requests
depending on how its image was built.
No breaking changes. Upgrading from v0.9.0 is a normal update.
The installer installs what's missing
Previously it stopped at "docker is not installed" with a link to Docker's
documentation. For a command shared publicly that is the most likely first
failure, and it handed a newcomer three more guides to read before they could
try the product.
It now detects everything missing in one pass, explains what each piece is for,
and offers to install it:
! ProxMate needs some things this machine doesn't have yet:
Docker engine runs ProxMate's two containers
Docker Compose v2 builds and orchestrates them
git fetches the ProxMate source
These are required — ProxMate is a containerised application and cannot
run without them. Nothing here is optional or cosmetic.
Install them now? [y/N]:
Declining is a first-class outcome, not an error path: it says why they are
required, confirms nothing on the machine was changed, points at the official
documentation, and exits.
Docker is installed through Docker's own get.docker.com, downloaded to a file
whose path is printed before it runs — never piped into a root shell. That is the
same reasoning that keeps the installer from being a curl | sudo bash one-liner,
and it matters more here than usual, because ProxMate ends up holding a Proxmox
token that is effectively root on your cluster.
Debian, Ubuntu, Fedora, RHEL, CentOS and Rocky go through get.docker.com.
openSUSE and Alpine use their own repositories, because get.docker.com rejects
them outright. Arch deliberately stops and prints the two commands to run:
installing there without a full system upgrade is the partial-upgrade state Arch
declares unsupported, and turning the installer into an unattended pacman -Syu
of someone else's machine is not acceptable.
Installing Docker guarantees the very next check fails, because group membership
only applies to new sessions. The installer adds you to the docker group and
continues in the same session rather than telling you to log out and back in.
Fixed: app-database backups could fail silently, forever
Check this one if you installed with sudo.
ProxMate backs up its own database nightly. The backup directory is bind-mounted
into the backend container, which drops to the unprivileged node user before it
runs anything. If that directory was created by root — which is exactly what
sudo bash install.sh, or a hand-rolled mkdir, produces — node cannot write
to it.
What made this bad is how quiet it was. The backup service logs a warning and
returns; the scheduler only logs successes; the admin API reports the configured
directory with no last-run status. So the job failed at 02:30 every night and
nothing surfaced it. Meanwhile the installer printed a cheerful
+ created ./backups.
The fix is in the container entrypoint, which already runs as root to make the
data volume writable: it now does the same for the backup directory. That covers
every install path, including hand-rolled ones, not just the installer's.
It is deliberately non-recursive — the directory holds your existing snapshots
and a recursive chown of someone's backup archive is not ours to perform — and
non-fatal, since a read-only (:ro) mount is a legitimate deliberate setup.
The installer additionally works out who is really running it (via SUDO_USER)
and hands back the checkout, the .env and the backup directory, so you can read
the ENCRYPTION_KEY you are told to back up, and run the compose commands it
prints, without sudo.
After upgrading, confirm a backup actually lands. If the directory is still
root-owned from before, the entrypoint corrects it on the next container start.
Fixed: migrations that crash the guest
Proxmox will happily permit two migrations that break the guest. Both are now
refused, with the reason.
A running guest configured cpu: host cannot cross CPU models. That setting
hands the guest the host's CPUID verbatim. Live-migrating it to a node with a
different CPU pulls features out from under a kernel already running on them, and
the next instruction needing a missing one takes a fatal exception. On a mixed
cluster this kills the guest mid-flight. The migrate dialog now says:
different CPU model (…) and this guest uses cpu=host — a live migration would
crash it. Stop the guest first, then it can move here safely.
Note the second sentence: this is refused only while the guest is running. A
stopped guest cold-boots on the target perfectly happily, so the restriction
lifts rather than pretending the node is permanently ineligible.
A guest whose cloud-init cicustom snippet lives on a node-restricted storage
migrates fine and then cannot be started. A running guest never re-reads that
file, so Proxmox sees no obstacle — and the damage stays invisible until someone
stops the guest, possibly weeks later, with no apparent connection to the move.
Proxmox's own preflight does not consider cicustom at all.
Both checks fail open: an unreadable config, an undetectable CPU model, or a
storage the cluster does not report all leave the node allowed. Wrongly pinning a
guest is worse than a warning that was not given.
Because the cluster balancer and node-drain resolve their targets through the
same code, they inherit this automatically — which is the point. With the
balancer in automatic mode, these migrations would otherwise have been performed
on tenant VMs on a schedule, unattended.
Fixed: HTTPS deployments could lose upgrade-insecure-requests
v0.9.0 stopped sending this directive on plain-HTTP deployments, which was
correct — it rewrites the page's own CSS and JavaScript to https:// and nothing
is listening there. But it decided that from NEXT_PUBLIC_SITE_URL, and Next
inlines NEXT_PUBLIC_* at build time. The value in play was therefore
whatever was baked in as a build argument, and docker-compose.yml defaults that
to http://localhost:3000. An operator running HTTPS who never set the build
argument got an image that silently omitted the directive — and could not fix it
by editing .env, only by rebuilding.
It is now decided per request from the scheme the browser actually used:
X-Forwarded-Proto first (set by any reverse proxy, and correct regardless of
build arguments), then NEXT_PUBLIC_SITE_URL, then the request's own scheme.
Also in this release
.env.*is now ignored. The installer writes its new.envthrough
mktemp .env.XXXXXXinside the checkout it just cloned, and that temp file
holds a freshly generatedENCRYPTION_KEY. The cleanup trap removes it on any
ordinary exit, but aSIGKILL, an out-of-memory kill or a power loss left it
behind — untracked, in a git tree, onegit add -Afrom being published.- Better failure messages for the situations people actually hit:
usermod
lives in/usr/sbinand is missing from some users'PATH, which produced
Alpine advice on an Ubuntu box;sudobeing installed is not the same as being
allowed to use it, which is now checked immediately after you consent rather
than partway through; and a low-disk warning that printed "only 0 GB free" now
reports "only 99 MB free in /srv" and names the directory it measured. - The README leads with installing ProxMate rather than a two-terminal
development setup.DEPLOY_WITH_CLAUDE.mdis presented as a supported
alternative — some people would rather have an agent walk the deploy with them,
and that route is not going away. - CI writes its Docker build cache only from
main. Exporting every
intermediate layer from every branch filled the 10 GB Actions cache quota, at
which point builds fail witherror writing layer blob: failed to reserve cache
on code that is perfectly fine. Pull requests still read the cache.
Upgrade notes
Standard update. No database migration beyond what the backend applies on boot,
and no configuration changes required.
git pull
docker compose up -d --buildTwo things worth checking afterwards:
- If you ever installed or created directories with
sudo, confirm the next
nightly app-database backup actually produces a file. The entrypoint fixes the
ownership on container start, but it is worth seeing a snapshot appear. - If you migrate guests between nodes, expect the migrate dialog to offer
fewer targets than before on a mixed-CPU cluster. That is the guardrail, not a
regression — and the message tells you how to move the guest anyway.
Verification
- Backend: 740 tests across 84 files, plus typecheck and lint.
- Frontend: lint, production build, Playwright smoke.
- CodeQL, Trivy,
npm auditand SBOM all pass. - The installer was exercised end to end on a clean Ubuntu 24.04 host: with
Docker present, with Docker absent (installed from scratch in 6m39s), as
root via sudo (ownership handed back, and the backup directory confirmed
writable by the unprivileged container user), in--domainmode behind Caddy
over HTTPS, and re-run over a live install holding real data — where the
ENCRYPTION_KEY...
v0.9.0
Highlights
ProxMate gets a real installer, and a long-standing bug that made plain-HTTP
deployments unusable is fixed.
install.sh— one command from a clean machine to the setup wizard.
Preflight checks, a generatedENCRYPTION_KEY, a correct.envfor either an
HTTP trial or an HTTPS domain, and the build. It stops at the browser wizard on
purpose.- Fixed: plain-HTTP deployments could not load the UI. Every release since
v0.6.8 sentupgrade-insecure-requestsunconditionally, which made the browser
rewrite the application's own CSS and JavaScript tohttps://. Without an HTTPS
reverse proxy in front, the interface never rendered. - The migrate dialog now says why a VM cannot move, instead of showing an
empty list, and a new admin diagnostic explains why automatic placement keeps
choosing the same node. - Optional settings documented in
.envnow actually take effect under Docker.
No breaking changes. Upgrading from v0.8.6 is a normal update.
A real installer
Until now there were two documented paths: edit .env by hand and run
docker compose up -d --build, or point an agent at DEPLOY_WITH_CLAUDE.md. The
hand-editing is where installs break, and it is easy to get wrong in ways that are
expensive to undo.
curl -fsSLO https://raw.githubusercontent.com/r0073d-l053r/ProxMate/main/install.sh
less install.sh
bash install.shOne question — HTTP trial, or HTTPS domain — and it handles the rest:
- Preflight that checks what actually fails. Not merely whether Docker is
installed, but whether the daemon is reachable at all (being outside the
dockergroup is the most common first-run failure), whether Compose is v2, and
whether there is enough memory for the frontend build, which otherwise gets
OOM-killed and surfaces as an unrelated-looking Compose error. --localdetects your LAN address instead of assuminglocalhost, because
a headless server is almost always browsed from a different machine.--domainvalidates the hostname. A URL, ahost:port, or a bare IP is
rejected with an explanation — certificates and passkeys both need a real DNS
name, and an IP would otherwise fail much later with an opaque browser error.- It never overwrites an existing
.env, so yourENCRYPTION_KEYis
preserved. Pointing an existing install at a different origin stops with
instructions rather than proceeding, becauseNEXT_PUBLIC_*values are baked
into the frontend at build time and a silent rebuild would produce a stack still
calling the old origin. - It stops at the setup wizard. The Proxmox API token is entered in the
browser, never as a shell argument where it would land in shell history and the
process list.
It is deliberately not a curl | sudo bash one-liner. ProxMate ends up
holding a Proxmox token that is effectively root on your cluster, so "download,
read, then run" is the right habit for this particular software.
Flags: --local, --host, --domain, --dir, --ref, --no-start, --yes.
DEPLOY_WITH_CLAUDE.md is unchanged and still supported. If you would rather
have a coding agent walk your deployment — reading your environment, adapting as
it goes — that route remains a first-class option. The installer is for people who
want the same result every time; the runbook is for people who want a
conversation. Neither replaces the other.
Fixed: the interface could not load over plain HTTP
The Content-Security-Policy included upgrade-insecure-requests on every
response. On an HTTPS deployment that is useful hardening. On a plain-HTTP one it
is fatal: the browser rewrites the page's own script, style, and font URLs to
https://, nothing is listening on port 3000 over TLS, and every asset fails with
ERR_SSL_PROTOCOL_ERROR before the application can render.
This affected every release from v0.6.8 through v0.8.6. It was invisible to
anyone running behind an HTTPS reverse proxy, which is the documented production
setup — but it meant a quick HTTP trial on a LAN address could never work at all.
The directive is now sent only when the public origin really is HTTPS, determined
from NEXT_PUBLIC_SITE_URL (which the operator controls, so a client cannot forge
it) and falling back to X-Forwarded-Proto or the request scheme when that is
unset. NEXT_PUBLIC_SITE_URL is now also passed to the frontend at runtime, not
only as a build argument.
If you pin CSP_CONNECT_SRC in .env, wrap the whole value in double quotes:
CSP_CONNECT_SRC="'self' https://proxmate.example.com wss://proxmate.example.com"
Docker Compose ends a value at the closing quote it opened, so the previously
documented unquoted form collapsed to just self — dropping your API origin, and
dropping the quotes that make 'self' a CSP keyword rather than a hostname. The
example in .env.docker.example showed the broken form and has been corrected.
Why a VM cannot migrate, and why placement keeps picking one node
Proxmox reports a per-node reason when it refuses a migration, but ProxMate read
only the list of allowed targets and discarded the explanations. When that list
came back empty — which is common — the dialog could only say "no eligible
nodes": true, and useless.
The migrate dialog now shows the actual reason per node, for example
"pve-1 — storage not available there: tank". Containers and guests with PCI
passthrough now explain why they are ineligible instead of presenting an empty
list.
Alongside it, GET /admin/placement-diagnostics reports which nodes actually
hold your configured ISO storage and disk pool, the resulting candidate set, and
whether placement is effectively pinned to a single node — with the remedy.
This matters more than it sounds. Automatic placement filters candidates to nodes
that have both the install image and the configured disk pool. If either lives on
node-local storage, the candidate set silently collapses to one node and the
scheduler never gets to compare load at all — so a cluster can look like it is
ignoring its own balancing while the scoring code is working perfectly. That
condition is now visible from the admin API instead of requiring an SSH session.
Administrative settings changes are now recorded
PUT /admin/settings/defaults wrote no audit entry — the only admin route without
one. The default storage set there decides where every future VM is placed, so it
could be changed with no record of who did it or when. It now writes an audit
entry with a before-and-after diff.
Docker: documented settings now actually work
docker-compose.yml never forwarded several variables the documentation told you
to set, so under Docker they silently did nothing:
SNIPPET_DIR,SNIPPET_STORAGE— on-demand cloud-init snippet writingBACKUP_DOWNLOAD_DIR,RESTORE_UPLOAD_MAX_GB— guest backup download and restoreMATESTATE_CRON,ACCESS_EXPIRY_CRON— background job schedules
All six are now passed through, with commented mount stubs for the two that are
container paths. A folder created on the host is unreachable unless it is
mounted in, and changing a mount requires docker compose up -d backend rather
than a plain restart.
Documentation corrections
A read-through of the deployment documentation against the actual code found a
number of claims that had drifted:
- The quickstart implied
cp .env.docker.example .envand straight on to
docker compose up. The example ships with its production block active,
pointing atproxmate.example.comand bound to127.0.0.1, so following it
verbatim builds a frontend that calls a domain you do not own, on ports only
reachable from the machine itself. This is now called out explicitly. - Tenant network isolation was described as unconditional. It does nothing until
the Proxmox cluster firewall is enabled, which is now stated everywhere it
appears. - Kiosk mode was still documented as having power controls. It has been
monitoring-only since v0.8.6. - Share levels were documented under old internal names rather than the shipped
Viewer / Operator / Manager. - The cloud image count was wrong — 20 ship, 16 x86-64 and 4 ARM64 — and
Share-a-VM, compute access windows, app-database backups, personal API tokens,
and admin deploy-for-tenant were missing from the feature list entirely. ENCRYPTION_KEYguidance now states plainly that a database backup without an
off-host copy of the key restores nothing.
Also in this release
.gitattributespins LF line endings for shell scripts, container
entrypoints, Dockerfiles and YAML. There was none, so the bytes committed for
install.shdepended on each contributor's local git configuration — and a CRLF
copy dies on its first executable line with
set: pipefail: invalid option name, where the stray carriage return is
invisible in the error message.- The README banner was redrawn to match the application's actual aesthetic.
Upgrade notes
Upgrading from v0.8.6 is a normal update. There are no schema changes beyond what
the backend applies automatically on boot, and no configuration changes are
required.
git pull
docker compose up -d --buildTwo things worth checking:
- If you set
CSP_CONNECT_SRCin.env, wrap the value in double quotes as
shown above. If you previously used the unquoted form it was silently reduced
toself, so this is a repair rather than a change in behaviour. - If you run over plain HTTP, the interface should now load. It could not
before.
Verification
- Backend: 730 tests across 84 files, plus typecheck and lint.
- Frontend: lint, production build, and the Playwright smoke suite.
- CodeQL, Trivy,
npm audit, and SBOM generation all pass. install.shwas run end to end on a clean Ubuntu 24.04.4 machine with Docker
29.7.1 and Compose 5.3.1: preflight, LAN address detection, clone and ref
resolution, `.en...
v0.8.6
Highlights
A hardening release. The kiosk wall panel becomes monitoring-only and stops
leaking who owns what, and app-database backups can finally be pointed at a
directory on the host without hitting a wall.
- Kiosk is monitoring only — the VMs tab no longer carries power controls,
and three separate ways out of the panel that skipped the passkey/PIN exit
gate are closed. - App-database backups: choose the host location in
.env— the setting
now works out of the box, and failures explain themselves instead of emitting
a bareEACCES.
No breaking changes. Upgrading from v0.8.5 is a normal update.
Kiosk mode: monitoring only
The wall panel's VMs tab was rendering the admin VM card verbatim, so anyone
walking past could start, gracefully shut down, hard power off, or reboot any
tenant's machine, and open its console. A rack panel should show state, not
change it. Those controls are now removed from the panel entirely — not
disabled, removed, because a greyed-out button still advertises an action that
doesn't belong there. Live status, sparklines, and per-node health are unchanged.
An adversarial review of the panel then found three more ways past the exit
lock, all now closed:
- The browser Back button left kiosk entirely. One gesture — Back, an
edge-swipe, orAlt+Left— landed on the admin dashboard with a live admin
session and every power control, without ever showing the passkey/PIN prompt.
Kiosk is now entered so that nothing sits behind it in history, and a
back-navigation opens the same unlock dialog as the corner exit button. - A long-press opened the browser context menu, offering Back again and
Inspect — a developer console on an authenticated admin session. Suppressed. - The VM name and console icon were links into the full dashboard, which
walked around the exit gate the same way.
Kiosk mode: what's on the glass
Two disclosure fixes, holding the panel to the standard the Activity tab already
set (show what happened, never who did it):
- The activity feed could print a tenant's email address. Sharing a VM
records an audit line beginning with the recipient's address, and the panel's
label logic took that leading word and displayed it styled as a machine name.
VM names are now resolved from the actual inventory, so a label is either a
real machine name or absent. This also stops node names and stray words being
dressed up as VMs. - The VMs tab no longer names each tenant. It listed every owner's display
name beside their machines and quota — a who-owns-what map readable from the
hallway. Groups now read "Tenant · 3 guests", with the crown icon still
distinguishing admin-owned guests from tenant-owned ones.
App-database backups: pick the host directory
Pointing the backup setting at a folder created on the host failed with:
EACCES: permission denied, mkdir '/srv/backups'
That reads like a file-permission problem and sends you off fixing ownership on
the host. It isn't one: ProxMate runs in a container and can only write to
directories mounted into it, so a host folder that was never mounted is
unreachable no matter what its permissions are.
The host location is now chosen where it has to be — when the container is
created:
# .env
PROXMATE_BACKUP_DIR=/mnt/backups/proxmateThe container-side path is fixed and is the default for the in-app setting, so
backups work out of the box rather than requiring you to discover which paths
are writable. An explicitly empty directory still means "disabled".
Failures now explain themselves. A permission error names the container-mount
cause and says creating the folder on the host isn't enough on its own; missing
directories, read-only (:ro) mounts, and full disks each get their own
message. The directory is also checked when you press Save, so a bad path is
rejected while you're looking at it instead of failing silently at 02:30.
DEPLOYMENT.md gains an App-database backups section covering the container
boundary, setup, restore steps, and the reminder that a snapshot is useless
without the matching ENCRYPTION_KEY.
Upgrade notes
Standard update — pull the release and rebuild. No database migration.
docker-compose.yml gains a backup mount that defaults to ./backups beside
the compose file, so existing installs get a working backup target without any
configuration. Set PROXMATE_BACKUP_DIR in .env to put it somewhere better —
ideally a different disk from the database, or an off-host share.
If you run a kiosk panel, its VM controls are gone by design. Power actions live
in Admin → Monitor and on each VM's page, behind a normal login.
Verification
718 backend tests, 12 frontend tests, typecheck and lint clean on both, frontend
production build green, Playwright smoke passing, CodeQL / Trivy / npm audit /
SBOM green.
The kiosk changes came out of an adversarial multi-agent review of the panel
that produced 11 candidate findings; the 4 that survived independent
verification are the ones fixed above. The backup change was verified end to end
on a live host: a mounted directory produces real snapshots from both the manual
button and the scheduled (non-root) path.
What's Changed
- feat(backups): choose the app-DB backup location on the host via .env by @r0073d-l053r in #100
- release: v0.8.6 by @r0073d-l053r in #101
Full Changelog: v0.8.5...v0.8.6