mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 05:29:45 +00:00
Keep historical upgrade recovery non-destructive
Route current upgrades to current guidance; preserve existing login and monitoring state when diagnosing missing PVE backups. Require endpoint-specific access evidence rather than blanket ACL changes or setup-token rotation. Contract-Neutral: Documentation and regression checks only; no collector, permission, authentication or upgrade contract changes. Change-source: pulse-maintainer
This commit is contained in:
+45
-21
@@ -1,6 +1,9 @@
|
||||
# Upgrade to Pulse v5
|
||||
|
||||
This is a practical guide for upgrading an existing Pulse install to v5.
|
||||
This historical guide covers the v4-to-v5 transition. For an upgrade to a
|
||||
current release, follow [Updating Pulse](AUTO_UPDATE.md) and the
|
||||
[current installation and recovery guidance](INSTALL.md); do not downgrade
|
||||
to v5 to follow this page.
|
||||
|
||||
## Before You Upgrade
|
||||
|
||||
@@ -50,11 +53,21 @@ helm upgrade pulse pulse/pulse -n pulse
|
||||
|
||||
### Bootstrap token on fresh auth setup
|
||||
|
||||
If you reset auth (for example by deleting `.env`), Pulse may require a bootstrap token before you can complete setup.
|
||||
An upgrade is not a reason to reset authentication. **Do not delete `.env` or
|
||||
repeat first-time setup to recover an existing login.** Follow
|
||||
[password recovery](TROUBLESHOOTING.md#i-forgot-my-password), preserving the
|
||||
existing configuration and data.
|
||||
|
||||
A bootstrap token is for an installation that genuinely needs initial setup,
|
||||
not a replacement for an existing password. Retrieve it locally only when the
|
||||
setup screen asks for it:
|
||||
|
||||
- Docker: `docker exec pulse /app/pulse bootstrap-token`
|
||||
- systemd/LXC: `sudo pulse bootstrap-token`
|
||||
|
||||
Keep the token private and enter it in the setup screen; do not post it in a
|
||||
report or put it in a URL.
|
||||
|
||||
### Sensor proxy removal
|
||||
|
||||
The `pulse-sensor-proxy` from v4 is no longer needed — temperature monitoring is now handled by the unified agent. If you had the sensor proxy installed on your Proxmox hosts, remove it **on each host** after upgrading:
|
||||
@@ -89,25 +102,36 @@ Alternative option:
|
||||
|
||||
### Backups not showing (PVE)
|
||||
|
||||
If local PVE backups aren't appearing in Pulse, your API token may be missing the `PVEDatastoreAdmin` permission required for backup visibility.
|
||||
An empty backup table does not establish a permission failure. Pulse's server
|
||||
reads PVE backup inventory through the saved Proxmox API connection; a working
|
||||
host agent does not prove that this separate collection is current.
|
||||
|
||||
This can happen if:
|
||||
- You upgraded from v4 (older setup scripts didn't include this permission)
|
||||
- You set up nodes via the unified agent before v5.1.x (the agent wasn't granting this permission)
|
||||
- You created the API token manually without the storage permission
|
||||
1. Compare an **existing** archive in native PVE with **Proxmox → Backups →
|
||||
By date**, retaining its node, storage, guest type/ID and time. Check the
|
||||
selected connection and filters. Direct PBS and PVE passthrough are distinct
|
||||
sources, and Coverage posture is not the same as archive presence. A failed
|
||||
or partial read is not an empty inventory.
|
||||
2. Retain the existing collection status, original redacted error and time.
|
||||
Connection liveness and a successful connection test do not establish backup
|
||||
freshness. Do not run another backup, restore, guest-agent probe or restart
|
||||
just to obtain evidence. An OK backup task does not prove guest thaw; follow
|
||||
the [backup safety precaution](VM_DISK_MONITORING.md#backup-safety).
|
||||
3. If a request was rejected, have the Proxmox administrator check the **actual
|
||||
rejected endpoint**, installed PVE version and configured service user/token.
|
||||
With privilege separation, both user and token ACLs must permit that request
|
||||
at the relevant scope and inheritance. Authentication failure is not proof
|
||||
of a missing storage role, and audit-only access is not proof of access to
|
||||
every storage-content endpoint. Do not grant blanket storage-administrator
|
||||
access, disable privilege separation or substitute an administrator token
|
||||
merely because backups are missing.
|
||||
|
||||
**Quick fix** (run on each Proxmox host):
|
||||
```bash
|
||||
pveum aclmod /storage -user pulse-monitor@pve -role PVEDatastoreAdmin
|
||||
pveum aclmod /storage -token 'pulse-monitor@pve!<token-name>' -role PVEDatastoreAdmin
|
||||
```
|
||||
Replace `pulse-monitor@pve!<token-name>` with the full token ID shown in Pulse,
|
||||
for example `pulse-monitor@pve!pulse-example`. Privilege-separated PVE tokens
|
||||
need the storage ACL on the token as well as the service user.
|
||||
**Do not delete the monitored node, remove registration state or rerun setup as
|
||||
a diagnostic.** Setup can rotate an existing API token and change permissions.
|
||||
Preserve the connection, credentials, registration state and backup/history data.
|
||||
Make any evidenced repair through normal maintenance outside backups, then
|
||||
observe ordinary polling rather than repeating **Test Connection**.
|
||||
|
||||
**Alternative** (re-run setup):
|
||||
1. Delete the node from Pulse Settings
|
||||
2. Re-run the setup (either the UI-generated script or agent with `--enable-proxmox`)
|
||||
3. The new token will have correct permissions
|
||||
|
||||
Note: The "re-run setup" option only works on v5.1.x or later, which includes the fix for agent-based setups.
|
||||
Use the [complete missing-PVE-backup checks](UNIFIED_AGENT.md#pve-backups-not-showing-recovery)
|
||||
and [Proxmox permission guidance](TROUBLESHOOTING.md#check-permissions-proxmox).
|
||||
Keep token secrets, full ACL listings and private infrastructure details out of
|
||||
public reports; follow [Getting Help](TROUBLESHOOTING.md#-getting-help).
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Upgrade to Pulse v5
|
||||
|
||||
This is a practical guide for upgrading an existing Pulse install to v5.
|
||||
This historical guide covers the v4-to-v5 transition. For an upgrade to a
|
||||
current release, follow [Updating Pulse](AUTO_UPDATE.md) and the
|
||||
[current installation and recovery guidance](INSTALL.md); do not downgrade
|
||||
to v5 to follow this page.
|
||||
|
||||
## Before You Upgrade
|
||||
|
||||
@@ -50,11 +53,21 @@ helm upgrade pulse pulse/pulse -n pulse
|
||||
|
||||
### Bootstrap token on fresh auth setup
|
||||
|
||||
If you reset auth (for example by deleting `.env`), Pulse may require a bootstrap token before you can complete setup.
|
||||
An upgrade is not a reason to reset authentication. **Do not delete `.env` or
|
||||
repeat first-time setup to recover an existing login.** Follow
|
||||
[password recovery](TROUBLESHOOTING.md#i-forgot-my-password), preserving the
|
||||
existing configuration and data.
|
||||
|
||||
A bootstrap token is for an installation that genuinely needs initial setup,
|
||||
not a replacement for an existing password. Retrieve it locally only when the
|
||||
setup screen asks for it:
|
||||
|
||||
- Docker: `docker exec pulse /app/pulse bootstrap-token`
|
||||
- systemd/LXC: `sudo pulse bootstrap-token`
|
||||
|
||||
Keep the token private and enter it in the setup screen; do not post it in a
|
||||
report or put it in a URL.
|
||||
|
||||
### Sensor proxy removal
|
||||
|
||||
The `pulse-sensor-proxy` from v4 is no longer needed — temperature monitoring is now handled by the unified agent. If you had the sensor proxy installed on your Proxmox hosts, remove it **on each host** after upgrading:
|
||||
@@ -89,25 +102,36 @@ Alternative option:
|
||||
|
||||
### Backups not showing (PVE)
|
||||
|
||||
If local PVE backups aren't appearing in Pulse, your API token may be missing the `PVEDatastoreAdmin` permission required for backup visibility.
|
||||
An empty backup table does not establish a permission failure. Pulse's server
|
||||
reads PVE backup inventory through the saved Proxmox API connection; a working
|
||||
host agent does not prove that this separate collection is current.
|
||||
|
||||
This can happen if:
|
||||
- You upgraded from v4 (older setup scripts didn't include this permission)
|
||||
- You set up nodes via the unified agent before v5.1.x (the agent wasn't granting this permission)
|
||||
- You created the API token manually without the storage permission
|
||||
1. Compare an **existing** archive in native PVE with **Proxmox → Backups →
|
||||
By date**, retaining its node, storage, guest type/ID and time. Check the
|
||||
selected connection and filters. Direct PBS and PVE passthrough are distinct
|
||||
sources, and Coverage posture is not the same as archive presence. A failed
|
||||
or partial read is not an empty inventory.
|
||||
2. Retain the existing collection status, original redacted error and time.
|
||||
Connection liveness and a successful connection test do not establish backup
|
||||
freshness. Do not run another backup, restore, guest-agent probe or restart
|
||||
just to obtain evidence. An OK backup task does not prove guest thaw; follow
|
||||
the [backup safety precaution](VM_DISK_MONITORING.md#backup-safety).
|
||||
3. If a request was rejected, have the Proxmox administrator check the **actual
|
||||
rejected endpoint**, installed PVE version and configured service user/token.
|
||||
With privilege separation, both user and token ACLs must permit that request
|
||||
at the relevant scope and inheritance. Authentication failure is not proof
|
||||
of a missing storage role, and audit-only access is not proof of access to
|
||||
every storage-content endpoint. Do not grant blanket storage-administrator
|
||||
access, disable privilege separation or substitute an administrator token
|
||||
merely because backups are missing.
|
||||
|
||||
**Quick fix** (run on each Proxmox host):
|
||||
```bash
|
||||
pveum aclmod /storage -user pulse-monitor@pve -role PVEDatastoreAdmin
|
||||
pveum aclmod /storage -token 'pulse-monitor@pve!<token-name>' -role PVEDatastoreAdmin
|
||||
```
|
||||
Replace `pulse-monitor@pve!<token-name>` with the full token ID shown in Pulse,
|
||||
for example `pulse-monitor@pve!pulse-example`. Privilege-separated PVE tokens
|
||||
need the storage ACL on the token as well as the service user.
|
||||
**Do not delete the monitored node, remove registration state or rerun setup as
|
||||
a diagnostic.** Setup can rotate an existing API token and change permissions.
|
||||
Preserve the connection, credentials, registration state and backup/history data.
|
||||
Make any evidenced repair through normal maintenance outside backups, then
|
||||
observe ordinary polling rather than repeating **Test Connection**.
|
||||
|
||||
**Alternative** (re-run setup):
|
||||
1. Delete the node from Pulse Settings
|
||||
2. Re-run the setup (either the UI-generated script or agent with `--enable-proxmox`)
|
||||
3. The new token will have correct permissions
|
||||
|
||||
Note: The "re-run setup" option only works on v5.1.x or later, which includes the fix for agent-based setups.
|
||||
Use the [complete missing-PVE-backup checks](UNIFIED_AGENT.md#pve-backups-not-showing-recovery)
|
||||
and [Proxmox permission guidance](TROUBLESHOOTING.md#check-permissions-proxmox).
|
||||
Keep token secrets, full ACL listings and private infrastructure details out of
|
||||
public reports; follow [Getting Help](TROUBLESHOOTING.md#-getting-help).
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Keep the historical upgrade entry point from recommending destructive recovery."""
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
GUIDE = "UPGRADE_v5.md"
|
||||
|
||||
|
||||
def upgrade_guide():
|
||||
return (ROOT / "docs" / GUIDE).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def section(heading):
|
||||
return upgrade_guide().split(heading, 1)[1].split("\n### ", 1)[0]
|
||||
|
||||
|
||||
class UpgradeV5DocsTest(unittest.TestCase):
|
||||
def test_shipped_help_matches_source(self):
|
||||
self.assertEqual((ROOT / "docs" / GUIDE).read_bytes(),
|
||||
(ROOT / "frontend-modern/public/docs" / GUIDE).read_bytes())
|
||||
|
||||
def test_historical_page_routes_current_upgrades_without_downgrading(self):
|
||||
intro = " ".join(upgrade_guide().split("## Before You Upgrade", 1)[0].split())
|
||||
for phrase in ("historical guide", "v4-to-v5 transition", "AUTO_UPDATE.md",
|
||||
"INSTALL.md", "do not downgrade to v5"):
|
||||
self.assertIn(phrase, intro)
|
||||
|
||||
def test_existing_login_recovery_does_not_reset_auth_or_expose_bootstrap_token(self):
|
||||
auth = " ".join(section("### Bootstrap token on fresh auth setup").split())
|
||||
for phrase in ("Do not delete `.env`", "repeat first-time setup",
|
||||
"TROUBLESHOOTING.md#i-forgot-my-password",
|
||||
"preserving the existing configuration and data",
|
||||
"genuinely needs initial setup", "not a replacement for an existing password",
|
||||
"enter it in the setup screen", "do not post it in a report",
|
||||
"put it in a URL"):
|
||||
self.assertIn(phrase, auth)
|
||||
self.assertNotIn("for example by deleting", auth)
|
||||
|
||||
def test_missing_backups_do_not_trigger_acl_mutation_or_reenrolment(self):
|
||||
backup = section("### Backups not showing (PVE)")
|
||||
self.assertNotRegex(backup, r"aclmod|Quick fix|Delete the node|--enable-proxmox")
|
||||
shell = "\n".join(re.findall(r"```(?:bash|sh)\n(.*?)```", backup, re.DOTALL))
|
||||
self.assertEqual(shell, "")
|
||||
backup = " ".join(backup.split())
|
||||
for phrase in ("empty backup table does not establish a permission failure",
|
||||
"actual rejected endpoint", "installed PVE version",
|
||||
"configured service user/token", "both user and token ACLs",
|
||||
"scope and inheritance", "Authentication failure is not proof",
|
||||
"audit-only access is not proof", "Do not grant blanket storage-administrator",
|
||||
"disable privilege separation", "substitute an administrator token",
|
||||
"Do not delete the monitored node, remove registration state or rerun setup",
|
||||
"Setup can rotate an existing API token", "connection, credentials",
|
||||
"registration state and backup/history data", "outside backups"):
|
||||
self.assertIn(phrase, backup)
|
||||
|
||||
def test_backup_source_freshness_and_safety_route_survive_upgrade(self):
|
||||
backup = " ".join(section("### Backups not showing (PVE)").split())
|
||||
for phrase in ("server reads PVE backup inventory", "saved Proxmox API connection",
|
||||
"host agent does not prove", "node, storage, guest type/ID and time",
|
||||
"Proxmox → Backups → By date", "connection and filters",
|
||||
"Direct PBS and PVE passthrough are distinct sources",
|
||||
"Coverage posture is not the same as archive presence",
|
||||
"failed or partial read is not an empty inventory",
|
||||
"do not establish backup freshness", "original redacted error and time",
|
||||
"Do not run another backup, restore, guest-agent probe or restart",
|
||||
"OK backup task does not prove guest thaw", "observe ordinary polling",
|
||||
"Keep token secrets, full ACL listings and private infrastructure details"):
|
||||
self.assertIn(phrase, backup)
|
||||
for target in ("VM_DISK_MONITORING.md#backup-safety",
|
||||
"UNIFIED_AGENT.md#pve-backups-not-showing-recovery",
|
||||
"TROUBLESHOOTING.md#check-permissions-proxmox",
|
||||
"TROUBLESHOOTING.md#-getting-help"):
|
||||
self.assertIn(target, backup)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user