Clarify agent upgrade and notification docs
Some checks are pending
Build and Test / Secret Scan (push) Waiting to run
Build and Test / Frontend & Backend (push) Waiting to run

This commit is contained in:
rcourtman 2026-06-12 19:26:26 +01:00
parent 39585aa65a
commit 11464b4df8
18 changed files with 182 additions and 33 deletions

View file

@ -96,7 +96,7 @@ bash install.sh --version "${PULSE_VERSION}"
rm -f install.sh install.sh.sshsig
```
Note: this installs the Pulse **server**. Agent installs use the command generated in **Settings → Unified Agents → Installation commands** (served from `/install.sh` on your Pulse server).
Note: this installs the Pulse **server**. Agent installs and v5-to-v6 agent upgrades use the command generated in **Settings → Infrastructure → Install on a host** (served from `/install.sh` on your Pulse server).
### Option 2: Docker
```bash

View file

@ -43,8 +43,8 @@ environment where `PULSE_DOCKER=true`/`/.dockerenv` is detected.
Preferred option (no SSH keys, no proxy wiring):
1. Install the unified agent (`pulse-agent`) on each Proxmox host with Proxmox integration enabled.
- Use the UI to generate an install command in **Settings → Agents → Installation commands**, or run:
1. Install or upgrade the unified agent (`pulse-agent`) on each Proxmox host with Proxmox integration enabled.
- Use the UI to generate an install or upgrade command in **Settings → Infrastructure → Install on a host**, or run:
```bash
curl -fsSL http://pulse.example.com:7655/install.sh | \
sudo bash -s -- --url http://pulse.example.com:7655 --token <api-token> --enable-proxmox
@ -105,7 +105,7 @@ ls /home/pulse/.ssh/id_ed25519* 2>/dev/null && echo "⚠️ SSH keys present"
Verify temperature collection is agent-based:
- UI: **Settings → Agents** shows each Proxmox host connected and reporting.
- UI: the Proxmox or Machines page shows the host as agent-backed after the agent reports.
- On each Proxmox host:
```bash
systemctl status pulse-agent

View file

@ -2,7 +2,7 @@
Pro, legacy Pro+, and Cloud support centralized management of `pulse-agent` configurations, allowing administrators to define "Configuration Profiles" and assign them to specific installed agents. This enables bulk updates and consistent configuration across your fleet without manually editing configuration files on each host.
Profiles are managed in the UI: **Settings → Unified Agents → Agent Profiles**.
Profiles are managed in the UI from **Settings → Infrastructure → Install on a host → Manage agent profiles**.
## Concepts
@ -34,7 +34,7 @@ The following settings can be controlled remotely via profiles:
Notes:
- `interval` accepts a duration string. If you send a JSON number, it is interpreted as seconds.
- Docker auto-detection can still enable Docker monitoring if the agent is not explicitly configured. To force-disable Docker, set `PULSE_ENABLE_DOCKER=false` or install with `--enable-docker=false` on the host. That local disable also blocks remote profiles from turning Docker/Podman monitoring back on.
- `commandsEnabled` (AI command execution) is controlled separately per agent in **Settings → Unified Agents** and is applied live on report. It is not part of profile settings.
- `commandsEnabled` (AI command execution) is controlled separately per agent from the Infrastructure agent controls and is applied live on report. It is not part of profile settings.
## API Usage

View file

@ -435,6 +435,18 @@ docker run --init -e HTTPS_ENABLED=true \
API tokens provide scoped, revocable access to Pulse. Manage tokens in **Settings → Security → API Tokens**.
The token shown during first-run setup is the primary automation API token for
that Pulse instance. It is separate from your web login password and is meant
for agents, scripts, integrations, kiosks, and temporary setup handoffs. Tokens
are shown once; later token rows show only identifying hints such as prefix,
suffix, label, scopes, and last-used metadata.
Revoking a token is safe for Pulse itself, but it immediately breaks any agent,
script, kiosk, or integration still using that token. When a consumer needs to
stay online, create and install a replacement token first, then revoke the old
one. An agent whose token has been revoked stops authenticating until it is
reinstalled or reconfigured with a valid token.
### Token Scopes
| Scope | Description |

View file

@ -214,7 +214,7 @@ services:
To disable registry checks entirely, set `PULSE_DISABLE_DOCKER_UPDATE_CHECKS=true` on the **agent**.
You can also toggle "Hide Docker Update Buttons" from the UI: **Settings → Unified Agents** (Docker Settings card).
You can also toggle "Hide Docker Update Buttons" from the UI in **Settings → System → General** under **Docker / Podman updates**.
---

View file

@ -56,12 +56,12 @@ The agent will:
Use this when you can run a command on the PBS host but do not want to install the agent.
From Pulse's Settings page:
1. Go to **Settings → Unified Agents**
2. Click **Add Node**
3. Open **Advanced** and select **API Only**
4. Enter your PBS server's URL
5. Click copy to get the setup command
6. Run the command on your PBS server
1. Go to **Settings → Infrastructure**.
2. Click **Add infrastructure**.
3. Choose **Proxmox Backup Server**.
4. Use the API-only setup path and enter your PBS server's URL.
5. Click copy to get the setup command.
6. Run the command on your PBS server.
Example (what the UI generates):
```bash

View file

@ -26,6 +26,17 @@ Generate an installation command in the UI:
Choose a target profile in that screen when you want explicit install flags for Docker, Kubernetes, Proxmox VE, or Proxmox Backup Server.
The same generated command is also the supported v5-to-v6 agent upgrade path.
Run it on the host that already has the v5 `pulse-agent` service to replace the
binary and service configuration in place; do not uninstall the old service
first unless you are intentionally removing that host from Pulse.
An installed agent is configured for one Pulse URL and one token. Do not point
one running service at both a v5 server and a v6 server. After the upgrade,
check the relevant platform page or **Machines** view once the agent has
reported, and confirm the host-local version with `pulse-agent --version` if
the UI has not received a fresh report yet.
### Linux (systemd)
```bash
curl -fsSL http://<pulse-ip>:7655/install.sh | \
@ -274,7 +285,7 @@ Behavior:
- The agent fetches remote config on startup from `/api/agents/agent/{agent_id}/config`.
- Profile settings override local flags/env for supported keys.
- Profile changes take effect on the next agent restart.
- Command execution (`commandsEnabled`) is controlled per agent in **Settings → Unified Agents** and can change live.
- Command execution (`commandsEnabled`) is controlled per agent from the Infrastructure agent controls and can change live.
- Remote config responses can be signed with `PULSE_AGENT_CONFIG_SIGNING_KEY` (base64 Ed25519 private key).
- To require signed payloads, set `PULSE_AGENT_CONFIG_SIGNATURE_REQUIRED=true` on Pulse and agents.
- If you use a custom signing key, set `PULSE_AGENT_CONFIG_PUBLIC_KEYS` on agents to trust the matching public key.

View file

@ -28,7 +28,7 @@ If you prefer CLI, use the installed update helper for the target version:
sudo /bin/update --version vX.Y.Z
```
`/bin/update` is installed by the supported systemd and Proxmox LXC server installer. If your host does not have it yet, follow the signed server-installer flow in [INSTALL.md](INSTALL.md). Agent updates still use the `/install.sh` command generated in **Settings → Infrastructure → Install on a host**.
`/bin/update` is installed by the supported systemd and Proxmox LXC server installer. If your host does not have it yet, follow the signed server-installer flow in [INSTALL.md](INSTALL.md). Agent updates and v5-to-v6 agent upgrades still use the `/install.sh` command generated in **Settings → Infrastructure → Install on a host**; that screen is for both first installs and in-place agent upgrades.
Operator note for builds after `v6.0.0-rc.2`: the historical Pulse update
signer was not recovered. Hosts pinned to the `rc.2` trust root should not
@ -66,14 +66,15 @@ No. Upgrade the existing Pulse server installation in place.
### Do I need to uninstall my existing Pulse Unified Agents first?
No. Use the unified installer to upgrade existing agent deployments in place.
No. Use the unified installer to upgrade existing agent deployments in place. Generate the current command from **Settings → Infrastructure → Install on a host**, then run it on the host that already has the v5 agent service. You do not need to remove the old service first.
### Does upgrading the Pulse server to v6 automatically upgrade my agents?
No. The server upgrade and the Unified Agent upgrade are separate operations.
After the server is on v6, use the generated install or upgrade command from
**Settings → Infrastructure → Install on a host** when you want to move agents
to v6.
to v6. A v5 agent can be missing from v6 Reporting until it has upgraded,
authenticated, and sent its first v6 report.
### Will an upgraded v5 agent keep the same identity in v6?
@ -85,6 +86,24 @@ identity rather than creating a duplicate record during the upgrade.
No. Existing installed agents are expected to continue through the v6
compatibility boundary for legacy persisted agent scopes.
If you create a replacement token during the upgrade, install or reconfigure the
agent with the replacement before revoking the old token. Revoking the token
currently used by an agent stops that agent from authenticating until it is
reinstalled or reconfigured with a valid token.
### Where do I check installed agent versions in v6?
After an agent reports to v6, check the relevant platform page or **Machines**
view for the agent-backed host and version/status details. Version and outdated
agent notices appear only after the agent has successfully reported; they are
not an offline inventory of every v5 service that existed before the server
upgrade. On the host itself, confirm the local binary with:
```bash
pulse-agent --version
systemctl status pulse-agent
```
### Can one installed Pulse Unified Agent report to both a Pulse v5 instance and a Pulse v6 instance at the same time?
Not as a supported in-place setup. A running Unified Agent installation is

View file

@ -6,7 +6,7 @@ Pulse includes built-in templates for popular services and a generic JSON templa
1. Go to **Alerts → Notification Destinations**.
2. Click **Add Webhook**.
3. Select service type and paste the URL.
3. Click the current service label (Generic by default) to open the service picker, choose the destination type, and paste the URL.
## 📝 Service URLs
@ -51,6 +51,7 @@ For generic webhooks, use Go templates to format the JSON payload.
- **Telegram templates**: `{{.ChatID}}` is populated from the URL query string.
- **PagerDuty**: set `routing_key` as a custom field (or header) in the webhook config.
- **Pushover**: add `token` and `user` custom fields (required). Legacy `app_token` and `user_token` inputs are migrated automatically.
- **ntfy**: choose **ntfy** in the service picker before entering the topic URL. Leave the service as Generic only when you want to send a custom JSON payload.
**Example Payload:**
```json

View file

@ -739,6 +739,12 @@ posture for install and support guidance: it describes activation, recovery,
and BYOK/local AI setup, while explicitly keeping general in-app trials,
trial-return callbacks, and hosted AI quickstart acquisition out of the
ordinary upgrade path.
That same upgrade guidance and the current shipped release notes must describe
v5-to-v6 agent upgrades through the current Infrastructure install surface:
`Settings → Infrastructure → Install on a host` is the supported path for both
first installs and in-place agent upgrades, and v6 may only show agent
version/status details after the upgraded agent authenticates and sends a fresh
report rather than from an offline inventory of pre-upgrade v5 services.
That same release-confidence lane now also owns the shipped Helm chart path,
so release automation, packaged chart metadata, and chart-runtime smoke no

View file

@ -461,6 +461,12 @@ not bounce the operator back to GitHub `main` for section references that the
running build already owns locally. Their Relay security section must also use
the current Relay-and-higher entitlement boundary instead of stale Pro-only
license wording.
Agent-based Proxmox hardening guidance in those same security docs must also
point operators to the current Infrastructure install or upgrade command
surface and to post-report verification on the relevant platform page or
Machines view. It must not revive the retired Settings Agents install-command
route or imply that v6 can prove upgraded-agent state before the agent has
authenticated and reported.
That same governed settings trust boundary now also includes
`frontend-modern/src/components/Settings/SecurityOverviewPanel.tsx`,
`frontend-modern/src/components/Settings/QuickSecuritySetup.tsx`,

View file

@ -41,7 +41,11 @@ After upgrading the server, update existing agents separately using the command
`Settings -> Infrastructure -> Install on a host`
That is the supported v5-to-v6 crossover path for agent testing.
That is the supported v5-to-v6 crossover path for agent testing. The same
screen is used for first installs and in-place upgrades of existing v5 agents.
Version/status details appear in v6 only after an upgraded agent authenticates
and sends a fresh report, so the UI is not an offline inventory of every v5
service that existed before the server upgrade.
### Do I need to uninstall existing v5 agents before updating them?

View file

@ -435,6 +435,18 @@ docker run --init -e HTTPS_ENABLED=true \
API tokens provide scoped, revocable access to Pulse. Manage tokens in **Settings → Security → API Tokens**.
The token shown during first-run setup is the primary automation API token for
that Pulse instance. It is separate from your web login password and is meant
for agents, scripts, integrations, kiosks, and temporary setup handoffs. Tokens
are shown once; later token rows show only identifying hints such as prefix,
suffix, label, scopes, and last-used metadata.
Revoking a token is safe for Pulse itself, but it immediately breaks any agent,
script, kiosk, or integration still using that token. When a consumer needs to
stay online, create and install a replacement token first, then revoke the old
one. An agent whose token has been revoked stops authenticating until it is
reinstalled or reconfigured with a valid token.
### Token Scopes
| Scope | Description |

View file

@ -43,8 +43,8 @@ environment where `PULSE_DOCKER=true`/`/.dockerenv` is detected.
Preferred option (no SSH keys, no proxy wiring):
1. Install the unified agent (`pulse-agent`) on each Proxmox host with Proxmox integration enabled.
- Use the UI to generate an install command in **Settings → Agents → Installation commands**, or run:
1. Install or upgrade the unified agent (`pulse-agent`) on each Proxmox host with Proxmox integration enabled.
- Use the UI to generate an install or upgrade command in **Settings → Infrastructure → Install on a host**, or run:
```bash
curl -fsSL http://pulse.example.com:7655/install.sh | \
sudo bash -s -- --url http://pulse.example.com:7655 --token <api-token> --enable-proxmox
@ -105,7 +105,7 @@ ls /home/pulse/.ssh/id_ed25519* 2>/dev/null && echo "⚠️ SSH keys present"
Verify temperature collection is agent-based:
- UI: **Settings → Agents** shows each Proxmox host connected and reporting.
- UI: the Proxmox or Machines page shows the host as agent-backed after the agent reports.
- On each Proxmox host:
```bash
systemctl status pulse-agent

View file

@ -35,15 +35,4 @@ export const alertsHelpContent: HelpContent[] = [
],
addedInVersion: 'v4.0.0',
},
{
id: 'alerts.thresholds.perGuest',
title: 'Per-Guest Threshold Overrides',
description:
'Each VM or container can have custom threshold settings that override the defaults.\n\n' +
'Use this to set different thresholds for:\n' +
'- Database servers (higher memory thresholds)\n' +
'- Build servers (higher CPU thresholds)\n' +
'- Development VMs (more relaxed thresholds)',
addedInVersion: 'v4.2.0',
},
];

View file

@ -183,6 +183,68 @@ class DocumentationCurrentnessTest(unittest.TestCase):
for phrase in forbidden_phrases:
self.assertNotIn(phrase, content, msg=f"{rel} contains stale paid-cap wording: {phrase}")
def test_current_agent_docs_point_to_infrastructure_install_flow(self) -> None:
current_docs = (
"README.md",
"SECURITY.md",
"docs/CENTRALIZED_MANAGEMENT.md",
"docs/DOCKER.md",
"docs/PBS.md",
"docs/UNIFIED_AGENT.md",
"docs/UPGRADE_v6.md",
"docs/releases/RELEASE_NOTES_v6_RC1.md",
"frontend-modern/public/docs/SECURITY.md",
)
retired_agent_settings_paths = (
"Settings → Unified Agents",
"Settings -> Unified Agents",
"Settings → Agents → Installation commands",
"Settings -> Agents -> Installation commands",
)
for rel in current_docs:
content = read(rel)
for retired_path in retired_agent_settings_paths:
self.assertNotIn(retired_path, content, msg=f"{rel} still points at {retired_path}")
root_readme = read("README.md")
upgrade_doc = read("docs/UPGRADE_v6.md")
unified_agent_doc = read("docs/UNIFIED_AGENT.md")
self.assertIn("Settings → Infrastructure → Install on a host", root_readme)
self.assertIn("v5-to-v6 agent upgrades", root_readme)
self.assertIn("first installs and in-place agent upgrades", upgrade_doc)
self.assertIn("supported v5-to-v6 agent upgrade path", unified_agent_doc)
self.assertIn("Version and outdated", upgrade_doc)
self.assertIn("only after the agent has successfully reported", upgrade_doc)
def test_api_token_docs_explain_primary_token_and_revocation_safety(self) -> None:
config_doc = read("docs/CONFIGURATION.md")
public_config_doc = read("frontend-modern/public/docs/CONFIGURATION.md")
expected_fragments = (
"primary automation API token",
"separate from your web login password",
"Revoking a token is safe for Pulse itself",
"immediately breaks any agent",
"script, kiosk, or integration still using that token",
"create and install a replacement token first",
)
for content in (config_doc, public_config_doc):
for fragment in expected_fragments:
self.assertIn(fragment, content)
def test_webhook_docs_make_ntfy_service_picker_discoverable(self) -> None:
webhook_doc = read("docs/WEBHOOKS.md")
self.assertIn("Click the current service label (Generic by default) to open the service picker", webhook_doc)
self.assertIn("choose **ntfy** in the service picker before entering the topic URL", webhook_doc)
def test_alert_help_no_longer_documents_custom_threshold_overrides(self) -> None:
alerts_help = read("frontend-modern/src/content/help/alerts.ts")
self.assertNotIn("alerts.thresholds.perGuest", alerts_help)
self.assertNotIn("Per-Guest Threshold Overrides", alerts_help)
self.assertNotIn("custom threshold settings that override the defaults", alerts_help)
if __name__ == "__main__":
unittest.main()

View file

@ -195,6 +195,18 @@ Old metadata section.
self.assertIn("operator-state", changelog)
self.assertIn("Pulse Mobile pairing for handoff", support_pack)
def test_shipped_rc1_notes_document_current_agent_upgrade_surface(self) -> None:
repo_root = Path(__file__).resolve().parents[2]
release_notes = (repo_root / "docs/releases/RELEASE_NOTES_v6_RC1.md").read_text(
encoding="utf-8"
)
self.assertIn("Settings -> Infrastructure -> Install on a host", release_notes)
self.assertIn("first installs and in-place upgrades", release_notes)
self.assertIn("after an upgraded agent authenticates", release_notes)
self.assertNotIn("Settings -> Agents -> Installation commands", release_notes)
self.assertNotIn("Settings → Agents → Installation commands", release_notes)
def test_agent_paradigm_release_notes_blurb_documents_distribution_path(self) -> None:
"""The agent-paradigm source draft must keep its honest scope:
an integrator reading the blurb sees a published distribution

View file

@ -10,6 +10,7 @@ import unittest
SCRIPT_DIR = Path(__file__).resolve().parents[1]
REPO_ROOT = SCRIPT_DIR.parent
sys.path.insert(0, str(SCRIPT_DIR))
import telemetry_adoption_report as report
@ -94,6 +95,20 @@ class TelemetryAdoptionReportTest(unittest.TestCase):
"6.0.0-rc.2",
)
def test_security_docs_use_current_agent_install_surface(self) -> None:
security_docs = (
REPO_ROOT / "SECURITY.md",
REPO_ROOT / "frontend-modern/public/docs/SECURITY.md",
)
for path in security_docs:
with self.subTest(path=path.relative_to(REPO_ROOT)):
content = path.read_text(encoding="utf-8")
self.assertIn("Settings → Infrastructure → Install on a host", content)
self.assertIn("Proxmox or Machines page", content)
self.assertNotIn("Settings → Agents → Installation commands", content)
self.assertNotIn("Settings -> Agents -> Installation commands", content)
def test_summarize_rows_uses_latest_install_state_and_splits_release_validation(self) -> None:
now = datetime.now(timezone.utc).replace(microsecond=0)
rows = [