mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-17 16:07:40 +01:00
docs: standardize markdown syntax and remove deprecated sensor-proxy docs
This commit is contained in:
@@ -51,9 +51,9 @@ pd # Alias for ./scripts/hot-dev.sh
|
||||
Or use VS Code task: `Cmd+Shift+P` → "Tasks: Run Task" → "Start Pulse Dev Server"
|
||||
|
||||
**Access the app:**
|
||||
- Frontend: http://localhost:7655
|
||||
- Backend API: http://localhost:7656
|
||||
- Metrics: http://localhost:9091
|
||||
- Frontend: <http://localhost:7655>
|
||||
- Backend API: <http://localhost:7656>
|
||||
- Metrics: <http://localhost:9091>
|
||||
|
||||
## Development Workflows
|
||||
|
||||
@@ -66,7 +66,7 @@ Or use VS Code task: `Cmd+Shift+P` → "Tasks: Run Task" → "Start Pulse Dev Se
|
||||
**Backend (3-5 seconds):**
|
||||
- Edit any `.go` file
|
||||
- Save → Terminal shows:
|
||||
```
|
||||
```text
|
||||
🔄 Change detected: yourfile.go
|
||||
Rebuilding backend...
|
||||
✓ Build successful, restarting backend...
|
||||
@@ -241,7 +241,7 @@ Custom overrides: Create `.env.devcontainer` (gitignored)
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
```text
|
||||
MacBook (VS Code)
|
||||
↓ Remote-SSH
|
||||
dev-containers VM (Proxmox)
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -20,10 +20,10 @@ Steps to reproduce the behavior:
|
||||
What you expected to happen.
|
||||
|
||||
**Environment:**
|
||||
- Pulse Version: [e.g. v4.15.0]
|
||||
- Installation Type: [e.g. ProxmoxVE LXC, Docker, Manual]
|
||||
- Pulse Version: [e.g. v4.15.0]
|
||||
- Installation Type: [e.g. ProxmoxVE LXC, Docker, Manual]
|
||||
|
||||
**Additional context**
|
||||
Add any other context, screenshots, or logs here.
|
||||
|
||||
💡 **Tip:** If you're experiencing connection issues, API errors, or missing data, you can attach diagnostics from Settings → Diagnostics tab → Export for GitHub (sanitized version)
|
||||
💡 **Tip:** If you're experiencing connection issues, API errors, or missing data, you can attach diagnostics from Settings → Diagnostics tab → Export for GitHub (sanitized version)
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -17,4 +17,4 @@ A clear and concise description of what you want to happen.
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
10
.markdownlint-cli2.jsonc
Normal file
10
.markdownlint-cli2.jsonc
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"config": ".markdownlint.json",
|
||||
"globs": [
|
||||
"**/*.md"
|
||||
],
|
||||
"ignores": [
|
||||
"**/node_modules/**",
|
||||
".agent/workflows/hot-dev.md"
|
||||
]
|
||||
}
|
||||
25
.markdownlint.json
Normal file
25
.markdownlint.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"MD013": false,
|
||||
"MD029": {
|
||||
"style": "ordered"
|
||||
},
|
||||
"MD022": false,
|
||||
"MD030": false,
|
||||
"MD031": false,
|
||||
"MD032": false,
|
||||
"MD060": false,
|
||||
"MD033": {
|
||||
"allowed_elements": [
|
||||
"br",
|
||||
"details",
|
||||
"div",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"img",
|
||||
"p",
|
||||
"summary",
|
||||
"strong"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -75,9 +75,7 @@ The frontend is a modern Single Page Application (SPA) built with **SolidJS** an
|
||||
* **Vite**: For fast development and optimized builds.
|
||||
|
||||
### State Management
|
||||
* **Stores (`frontend-modern/src/stores`)**:
|
||||
* `websocket.ts`: The central nervous system. It maintains the WS connection, handles reconnection logic, and updates reactive signals when new data arrives.
|
||||
* `metricsHistory.ts`: Buffers incoming metrics to drive historical charts (Sparklines) without needing a time-series database backend.
|
||||
* **Stores (`frontend-modern/src/stores`)**: `websocket.ts` manages the WS connection and reactive updates; `metricsHistory.ts` buffers metrics for sparklines.
|
||||
|
||||
### Component Design
|
||||
* **Atomic Design**: Small, reusable components (`MetricBar`, `StatusBadge`) compose into larger views (`NodeSummaryTable`).
|
||||
|
||||
@@ -43,6 +43,14 @@ cd ..
|
||||
npm run mock:on # Optional: enable mock data
|
||||
```
|
||||
|
||||
Backend-only hot reload (requires `air`):
|
||||
|
||||
```bash
|
||||
air -c .air.toml
|
||||
```
|
||||
|
||||
Set `HOT_DEV_USE_PRO=true` to build the Pro variant when available.
|
||||
|
||||
Mock mode is supported for development, but the internal developer notes are not shipped in this repository.
|
||||
|
||||
---
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Pulse
|
||||
|
||||
<div align="center">
|
||||
<img src="docs/images/pulse-logo.svg" alt="Pulse Logo" width="120" />
|
||||
<h1>Pulse</h1>
|
||||
<p><strong>Real-time monitoring for Proxmox, Docker, and Kubernetes infrastructure.</strong></p>
|
||||
|
||||
[](https://github.com/rcourtman/Pulse)
|
||||
|
||||
10
SECURITY.md
10
SECURITY.md
@@ -70,7 +70,7 @@ docker exec pulse rm -rf /home/pulse/.ssh/id_ed25519*
|
||||
|
||||
#### Security Boundary
|
||||
|
||||
```
|
||||
```text
|
||||
┌─────────────────────────────────────┐
|
||||
│ Proxmox Host │
|
||||
│ ┌───────────────────────────────┐ │
|
||||
@@ -112,9 +112,9 @@ Verify temperature collection is agent-based:
|
||||
journalctl -u pulse-agent -n 200 --no-pager
|
||||
```
|
||||
|
||||
**Documentation:** https://github.com/rcourtman/Pulse/blob/main/SECURITY.md#critical-security-notice-for-container-deployments
|
||||
**Issues:** https://github.com/rcourtman/pulse/issues
|
||||
**Private disclosures:** security@pulseapp.io
|
||||
**Documentation:** <https://github.com/rcourtman/Pulse/blob/main/SECURITY.md#critical-security-notice-for-container-deployments>
|
||||
**Issues:** <https://github.com/rcourtman/pulse/issues>
|
||||
**Private disclosures:** <security@pulseapp.io>
|
||||
|
||||
---
|
||||
|
||||
@@ -239,7 +239,7 @@ docker run -e ALLOW_UNPROTECTED_EXPORT=true rcourtman/pulse:latest
|
||||
**Note:** for production, prefer Docker secrets or systemd environment files
|
||||
for sensitive data.
|
||||
|
||||
## Security Features
|
||||
## Security Features Summary
|
||||
|
||||
### Core Protection
|
||||
- **Encryption**: credentials encrypted at rest (AES-256-GCM)
|
||||
|
||||
@@ -150,10 +150,10 @@ all HTTP access attempts to the audit log.
|
||||
- Format: JSON with hash chaining (`prev_hash`, `event_hash`, `seq`)
|
||||
- Access: Owned by `pulse-sensor-proxy`, `0640`, `chattr +a`
|
||||
|
||||
Follow `docs/operations/AUDIT_LOG_ROTATION.md` for rotation (remove `+a`,
|
||||
Follow standard log rotation practices (e.g., `logrotate`) for rotation (remove `+a`,
|
||||
truncate, restart service, reapply `+a`). Also consider forwarding with
|
||||
`scripts/setup-log-forwarding.sh`; see
|
||||
`docs/operations/SENSOR_PROXY_LOGS.md` for log forwarding and verification
|
||||
See standard rsyslog practices for log forwarding and verification.
|
||||
steps.
|
||||
|
||||
## Metrics & Monitoring
|
||||
@@ -234,5 +234,5 @@ If you suspect config corruption (service won't start, temperatures stopped):
|
||||
sudo systemctl start pulse-sensor-proxy
|
||||
```
|
||||
|
||||
For additional hardening steps, read `docs/security/SENSOR_PROXY_HARDENING.md` and
|
||||
For additional hardening steps, read the main `docs/security/TEMPERATURE_MONITORING.md` guide and
|
||||
`docs/security/TEMPERATURE_MONITORING.md`.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Pulse AI
|
||||
|
||||
Pulse Pro unlocks **AI Patrol** for continuous, automated health checks. Learn more at https://pulserelay.pro or see the technical overview in [PULSE_PRO.md](PULSE_PRO.md).
|
||||
Pulse Pro unlocks **AI Patrol** for continuous, automated health checks. Learn more at <https://pulserelay.pro> or see the technical overview in [PULSE_PRO.md](PULSE_PRO.md).
|
||||
|
||||
## What Patrol Actually Does (Technical)
|
||||
|
||||
|
||||
20
docs/API.md
20
docs/API.md
@@ -8,18 +8,18 @@ Pulse provides a comprehensive REST API for automation and integration.
|
||||
|
||||
Most API requests require authentication via one of the following methods:
|
||||
|
||||
**1. API Token (Recommended)**
|
||||
### API Token (Recommended)
|
||||
Pass the token in the `X-API-Token` header.
|
||||
```bash
|
||||
curl -H "X-API-Token: your-token" http://localhost:7655/api/health
|
||||
```
|
||||
|
||||
**2. Bearer Token**
|
||||
### Bearer Token
|
||||
```bash
|
||||
curl -H "Authorization: Bearer your-token" http://localhost:7655/api/health
|
||||
```
|
||||
|
||||
**3. Session Cookie**
|
||||
### Session Cookie
|
||||
Standard browser session cookie (used by the UI).
|
||||
|
||||
Public endpoints include:
|
||||
@@ -54,6 +54,18 @@ Returns the complete state of your infrastructure (Nodes, VMs, Containers, Stora
|
||||
### Version Info
|
||||
`GET /api/version`
|
||||
Returns version, build time, and update status.
|
||||
Example response:
|
||||
```json
|
||||
{
|
||||
"version": "5.0.16",
|
||||
"buildTime": "2026-01-19T22:20:18Z",
|
||||
"channel": "stable",
|
||||
"deploymentType": "systemd",
|
||||
"updateAvailable": true,
|
||||
"latestVersion": "5.0.17"
|
||||
}
|
||||
```
|
||||
Version fields are returned as plain semantic versions (no leading `v`).
|
||||
|
||||
---
|
||||
|
||||
@@ -312,7 +324,7 @@ Returns scheduler health, DLQ, and breaker status. Requires `monitoring:read`.
|
||||
- `POST /api/updates/apply`
|
||||
- `GET /api/updates/status`
|
||||
- `GET /api/updates/stream`
|
||||
- `GET /api/updates/plan?version=vX.Y.Z` (optional `channel`)
|
||||
- `GET /api/updates/plan?version=X.Y.Z` (optional `channel`, accepts `v` prefix)
|
||||
- `GET /api/updates/history`
|
||||
- `GET /api/updates/history/entry?id=<event_id>`
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Pulse uses a split-configuration model to ensure security and flexibility.
|
||||
|
||||
| File | Purpose | Security Level |
|
||||
|------|---------|----------------|
|
||||
| ------ | --------- | ---------------- |
|
||||
| `.env` | Authentication & Secrets | 🔒 **Critical** (Read-only by owner) |
|
||||
| `.encryption.key` | Encryption key for `.enc` files | 🔒 **Critical** |
|
||||
| `system.json` | General Settings | 📝 Standard |
|
||||
@@ -36,6 +36,8 @@ Pulse uses a split-configuration model to ensure security and flexibility.
|
||||
| `ai_remediations.json` | AI remediation suggestions | 📝 Standard |
|
||||
| `ai_incidents.json` | AI incident tracking | 📝 Standard |
|
||||
|
||||
Guest metadata entries are keyed by the canonical guest ID format `instance:node:vmid` (for example, `pve1:node1:100`). Legacy dash-separated keys are migrated automatically.
|
||||
|
||||
All files are located in `/etc/pulse/` (Systemd) or `/data/` (Docker/Kubernetes) by default.
|
||||
|
||||
Path overrides:
|
||||
@@ -85,7 +87,7 @@ See [OIDC Documentation](OIDC.md) and [Proxy Auth](PROXY_AUTH.md) for details.
|
||||
Environment overrides (lock the corresponding UI fields):
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| ---------- | ------------- |
|
||||
| `OIDC_ENABLED` | Enable OIDC (`true`/`false`) |
|
||||
| `OIDC_ISSUER_URL` | Issuer URL from your IdP |
|
||||
| `OIDC_CLIENT_ID` | Client ID |
|
||||
@@ -101,6 +103,7 @@ Environment overrides (lock the corresponding UI fields):
|
||||
| `OIDC_ALLOWED_EMAILS` | Allowed emails (space or comma-separated) |
|
||||
| `OIDC_GROUP_ROLE_MAPPINGS` | Group-to-role mappings (Pro). Format: `group1=role1,group2=role2` |
|
||||
| `OIDC_CA_BUNDLE` | Custom CA bundle path |
|
||||
|
||||
</details>
|
||||
|
||||
> **Note**: `API_TOKEN` / `API_TOKENS` are legacy and will be migrated into `api_tokens.json` on startup.
|
||||
@@ -138,7 +141,7 @@ Controls runtime behavior like ports, logging, and polling intervals. Most of th
|
||||
Environment variables take precedence over `system.json`.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| ---------- | ------------- | --------- |
|
||||
| `FRONTEND_PORT` | Public listening port | `7655` |
|
||||
| `PORT` | Legacy alias for `FRONTEND_PORT` | *(unset)* |
|
||||
| `BACKEND_HOST` | Bind host for the HTTP server and metrics listener (advanced) | *(unset)* |
|
||||
@@ -149,7 +152,7 @@ Environment variables take precedence over `system.json`.
|
||||
#### Log Levels
|
||||
|
||||
| Level | Description |
|
||||
|-------|-------------|
|
||||
| ------- | ------------- |
|
||||
| `error` | Only errors and critical issues |
|
||||
| `warn` | Errors + warnings (recommended for minimal logging) |
|
||||
| `info` | Standard operational messages (startup, connections, alerts) |
|
||||
@@ -158,7 +161,7 @@ Environment variables take precedence over `system.json`.
|
||||
> **Tip**: If your syslog is being flooded with Pulse messages, set `LOG_LEVEL=warn` to significantly reduce log volume while still capturing important events.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| ---------- | ------------- | --------- |
|
||||
| `PULSE_PUBLIC_URL` | URL for UI links, notifications, and OIDC. For reverse proxies, keep this as the public URL and use `PULSE_AGENT_CONNECT_URL` for agent installs if you need a direct/internal address. | Auto-detected |
|
||||
| `PULSE_AGENT_CONNECT_URL` | Dedicated direct URL for agents (overrides `PULSE_PUBLIC_URL` for agent install commands). Alias: `PULSE_AGENT_URL`. | *(unset)* |
|
||||
| `PULSE_AGENT_CONFIG_SIGNING_KEY` | Base64 Ed25519 private key used to sign remote agent config payloads. | *(unset)* |
|
||||
@@ -195,7 +198,7 @@ When `allowEmbedding` is `false`, Pulse sends `X-Frame-Options: DENY` and `frame
|
||||
### Monitoring Overrides
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| ---------- | ------------- | --------- |
|
||||
| `PVE_POLLING_INTERVAL` | PVE metrics polling frequency | `10s` |
|
||||
| `PBS_POLLING_INTERVAL` | PBS metrics polling frequency | `60s` |
|
||||
| `PMG_POLLING_INTERVAL` | PMG metrics polling frequency | `60s` |
|
||||
@@ -222,7 +225,7 @@ When `allowEmbedding` is `false`, Pulse sends `X-Frame-Options: DENY` and `frame
|
||||
### Logging Overrides
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| ---------- | ------------- | --------- |
|
||||
| `LOG_FILE` | Log file path (empty = stdout) | *(unset)* |
|
||||
| `LOG_MAX_SIZE` | Log file max size (MB) | `100` |
|
||||
| `LOG_MAX_AGE` | Log file retention (days) | `30` |
|
||||
@@ -233,7 +236,7 @@ When `allowEmbedding` is `false`, Pulse sends `X-Frame-Options: DENY` and `frame
|
||||
These are stored in `system.json` and managed via the UI.
|
||||
|
||||
| Key | Description | Default |
|
||||
|-----|-------------|---------|
|
||||
| ----- | ------------- | --------- |
|
||||
| `updateChannel` | Update channel (`stable` or `rc`) | `stable` |
|
||||
| `autoUpdateEnabled` | Allow one-click updates | `false` |
|
||||
| `autoUpdateCheckInterval` | Stored UI preference (server currently checks hourly) | `24` |
|
||||
@@ -244,7 +247,7 @@ These are stored in `system.json` and managed via the UI.
|
||||
You can auto-import an encrypted backup on first startup. This is useful for automated provisioning and test environments.
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| ---------- | ------------- |
|
||||
| `PULSE_INIT_CONFIG_DATA` | Base64 or raw contents of an export bundle (auto-imports on first start) |
|
||||
| `PULSE_INIT_CONFIG_FILE` | Path to an export bundle on disk (auto-imports on first start) |
|
||||
| `PULSE_INIT_CONFIG_PASSPHRASE` | Passphrase for the export bundle (required) |
|
||||
@@ -256,7 +259,7 @@ You can auto-import an encrypted backup on first startup. This is useful for aut
|
||||
These are primarily for development or test harnesses and should not be used in production.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| ---------- | ------------- | --------- |
|
||||
| `PULSE_UPDATE_SERVER` | Override update server base URL (testing only) | *(unset)* |
|
||||
| `PULSE_UPDATE_STAGE_DELAY_MS` | Adds artificial delays between update stages (testing only) | *(unset)* |
|
||||
| `PULSE_ALLOW_DOCKER_UPDATES` | Expose update UI/actions in Docker (debug only) | `false` |
|
||||
@@ -339,7 +342,7 @@ API tokens provide scoped, revocable access to Pulse. Manage tokens in **Setting
|
||||
### Token Scopes
|
||||
|
||||
| Scope | Description |
|
||||
|-------|-------------|
|
||||
| ------- | ------------- |
|
||||
| `*` (Full access) | All permissions (legacy, not recommended) |
|
||||
| `monitoring:read` | View dashboards, metrics, alerts |
|
||||
| `monitoring:write` | Acknowledge/silence alerts |
|
||||
@@ -356,7 +359,7 @@ API tokens provide scoped, revocable access to Pulse. Manage tokens in **Setting
|
||||
The UI offers quick presets for common use cases:
|
||||
|
||||
| Preset | Scopes | Use Case |
|
||||
|--------|--------|----------|
|
||||
| -------- | -------- | ---------- |
|
||||
| **Kiosk / Dashboard** | `monitoring:read` | Read-only dashboard displays |
|
||||
| **Host agent** | `host-agent:report` | Host agent authentication |
|
||||
| **Container report** | `docker:report` | Container agent (read-only) |
|
||||
@@ -372,7 +375,7 @@ For unattended displays (wall monitors, dashboards), use a kiosk token to avoid
|
||||
2. Click **New token** and select the **Kiosk / Dashboard** preset
|
||||
3. Copy the generated token
|
||||
4. Access Pulse via URL with token:
|
||||
```
|
||||
```text
|
||||
https://your-pulse-url/?token=YOUR_TOKEN_HERE
|
||||
```
|
||||
|
||||
|
||||
@@ -65,7 +65,6 @@ Pull a new image and restart:
|
||||
docker pull rcourtman/pulse:latest
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Kubernetes (Helm)
|
||||
|
||||
Upgrade the chart:
|
||||
@@ -74,4 +73,3 @@ Upgrade the chart:
|
||||
helm repo update
|
||||
helm upgrade pulse pulse/pulse -n pulse
|
||||
```
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ If a setting is disabled with an amber warning, it's being overridden by an envi
|
||||
Pulse Pro unlocks **AI Patrol** — scheduled, cross-system analysis that correlates real-time state, recent metrics history, and diagnostics to surface actionable findings.
|
||||
|
||||
Example output includes trend-based capacity warnings, backup regressions, Kubernetes AI cluster analysis, and correlated container failures that simple threshold alerts miss.
|
||||
See [AI Patrol](AI.md), [Pulse Pro technical overview](PULSE_PRO.md), and https://pulserelay.pro.
|
||||
See [AI Patrol](AI.md), [Pulse Pro technical overview](PULSE_PRO.md), and <https://pulserelay.pro>.
|
||||
|
||||
### Why do VMs show "-" for disk usage?
|
||||
Proxmox API returns `0` for VM disk usage by default. You must install the **QEMU Guest Agent** inside the VM and enable it in Proxmox (VM → Options → QEMU Guest Agent).
|
||||
|
||||
@@ -143,6 +143,7 @@ Pulse can self-update to the latest stable version.
|
||||
**Enable via UI**: Settings → System → Updates
|
||||
|
||||
### Manual Update
|
||||
|
||||
| Platform | Command |
|
||||
|----------|---------|
|
||||
| **Docker** | `docker pull rcourtman/pulse:latest && docker restart pulse` |
|
||||
|
||||
@@ -4,9 +4,9 @@ This guide explains how to deploy the Pulse Server (Hub) and Pulse Agents on Kub
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* A Kubernetes cluster (v1.19+)
|
||||
* `helm` (v3+) installed locally
|
||||
* `kubectl` configured to talk to your cluster
|
||||
- A Kubernetes cluster (v1.19+)
|
||||
- `helm` (v3+) installed locally
|
||||
- `kubectl` configured to talk to your cluster
|
||||
|
||||
## 1. Deploying the Pulse Server
|
||||
|
||||
@@ -42,7 +42,7 @@ helm template pulse pulse/pulse \
|
||||
--namespace pulse \
|
||||
--set persistence.enabled=true \
|
||||
> pulse-server.yaml
|
||||
```
|
||||
```text
|
||||
|
||||
You can then apply this file:
|
||||
|
||||
@@ -126,11 +126,11 @@ Use a token scoped for the agent:
|
||||
|
||||
#### Important DaemonSet Configuration
|
||||
|
||||
**PULSE_AGENT_ID (Required for DaemonSets)**
|
||||
##### PULSE_AGENT_ID (Required for DaemonSets)
|
||||
|
||||
When running as a DaemonSet, all pods share the same API token but need a unified identity. Without `PULSE_AGENT_ID`, each pod auto-generates a unique ID (e.g., `mac-xxxxx`), causing token conflicts:
|
||||
|
||||
```
|
||||
```text
|
||||
API token is already in use by agent "mac-aa5496fed726". Each Kubernetes agent must use a unique API token.
|
||||
```
|
||||
|
||||
@@ -141,7 +141,7 @@ Set `PULSE_AGENT_ID` to a shared cluster name so all pods report as one logical
|
||||
value: "my-k8s-cluster"
|
||||
```
|
||||
|
||||
**Resource Visibility Flags**
|
||||
##### Resource Visibility Flags
|
||||
|
||||
By default, Pulse only shows resources with problems (unhealthy pods, failing deployments). To see all resources:
|
||||
|
||||
@@ -241,8 +241,8 @@ roleRef:
|
||||
Talos Linux is immutable, so you cannot install the agent via the shell script. Use the DaemonSet approach above.
|
||||
|
||||
### Agent Configuration for Talos
|
||||
* **Storage**: Talos mounts the ephemeral OS on `/`. Persistent data is usually in `/var`. The Pulse agent generally doesn't store state, but if it did, ensure it maps to a persistent path.
|
||||
* **Network**: The agent will report the Pod IP by default. To report the Node IP, set `PULSE_REPORT_IP` using the Downward API:
|
||||
- **Storage**: Talos mounts the ephemeral OS on `/`. Persistent data is usually in `/var`. The Pulse agent generally doesn't store state, but if it did, ensure it maps to a persistent path.
|
||||
- **Network**: The agent will report the Pod IP by default. To report the Node IP, set `PULSE_REPORT_IP` using the Downward API:
|
||||
|
||||
Add this to the DaemonSet `env` section:
|
||||
```yaml
|
||||
@@ -254,6 +254,6 @@ Talos Linux is immutable, so you cannot install the agent via the shell script.
|
||||
|
||||
## 4. Troubleshooting
|
||||
|
||||
* **Agent not showing in UI**: Check logs for the DaemonSet pods, for example: `kubectl logs -l app=pulse-agent -n pulse`.
|
||||
* **"Permission Denied" on metrics**: Ensure `securityContext.privileged: true` is set or proper capabilities are added.
|
||||
* **Connection Refused**: Ensure `PULSE_URL` is correct and reachable from the agent pods.
|
||||
- **Agent not showing in UI**: Check logs for the DaemonSet pods, for example: `kubectl logs -l app=pulse-agent -n pulse`.
|
||||
- **"Permission Denied" on metrics**: Ensure `securityContext.privileged: true` is set or proper capabilities are added.
|
||||
- **Connection Refused**: Ensure `PULSE_URL` is correct and reachable from the agent pods.
|
||||
|
||||
@@ -58,8 +58,8 @@ These endpoints require authentication with the `monitoring:read` scope.
|
||||
|
||||
`GET /api/metrics-store/history` supports:
|
||||
|
||||
- `resourceType` (required): `node`, `guest`, `storage`, `docker`, `dockerHost`
|
||||
- `resourceId` (required): resource identifier
|
||||
- `resourceType` (required): `node`, `vm`, `container`, `storage`, `dockerHost`, `dockerContainer`
|
||||
- `resourceId` (required): resource identifier (for VMs/containers use `instance:node:vmid`)
|
||||
- `metric` (optional): `cpu`, `memory`, `disk`, etc. Omit to return all metrics for the resource.
|
||||
- `range` (optional): `1h`, `6h`, `12h`, `24h`, `7d`, `30d`, `90d` (default `24h`)
|
||||
|
||||
@@ -67,7 +67,7 @@ Example:
|
||||
|
||||
```bash
|
||||
curl -H "X-API-Token: $TOKEN" \
|
||||
"http://localhost:7655/api/metrics-store/history?resourceType=guest&resourceId=vm-100&range=7d&metric=cpu"
|
||||
"http://localhost:7655/api/metrics-store/history?resourceType=vm&resourceId=pve1:node1:100&range=7d&metric=cpu"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
36
docs/OIDC.md
36
docs/OIDC.md
@@ -5,12 +5,12 @@ Enable Single Sign-On (SSO) with providers like Authentik, Keycloak, Okta, and A
|
||||
## 🚀 Quick Start
|
||||
|
||||
1. **Configure Provider**: Create an OIDC application in your IdP.
|
||||
* **Redirect URI**: `https://<your-pulse-domain>/api/oidc/callback`
|
||||
* **Scopes**: `openid`, `profile`, `email`
|
||||
- **Redirect URI**: `https://<your-pulse-domain>/api/oidc/callback`
|
||||
- **Scopes**: `openid`, `profile`, `email`
|
||||
2. **Enable in Pulse**: Go to **Settings → Security → Single Sign-On**.
|
||||
3. **Enter Details**:
|
||||
* **Issuer URL**: The base URL of your IdP (e.g., `https://auth.example.com/application/o/pulse/`).
|
||||
* **Client ID & Secret**: From your IdP.
|
||||
- **Issuer URL**: The base URL of your IdP (e.g., `https://auth.example.com/application/o/pulse/`).
|
||||
- **Client ID & Secret**: From your IdP.
|
||||
4. **Save**: The login page will now show a "Continue with Single Sign-On" button.
|
||||
|
||||
> **Tip**: To hide the username/password form and only show the SSO button, set `PULSE_AUTH_HIDE_LOCAL_LOGIN=true` in your environment. You can still access the local login by appending `?show_local=true` to the URL (e.g., `https://your-pulse-instance/?show_local=true`).
|
||||
@@ -30,9 +30,9 @@ Enable Single Sign-On (SSO) with providers like Authentik, Keycloak, Okta, and A
|
||||
|
||||
### Access Control
|
||||
Restrict access to specific users or groups:
|
||||
* **Allowed Groups**: Only users in these groups can login. Requires the `groups` scope/claim.
|
||||
* **Allowed Domains**: Restrict to specific email domains (e.g., `example.com`).
|
||||
* **Allowed Emails**: Allow specific email addresses.
|
||||
- **Allowed Groups**: Only users in these groups can login. Requires the `groups` scope/claim.
|
||||
- **Allowed Domains**: Restrict to specific email domains (e.g., `example.com`).
|
||||
- **Allowed Emails**: Allow specific email addresses.
|
||||
|
||||
### Group-to-Role Mapping (Pro)
|
||||
|
||||
@@ -86,21 +86,21 @@ For persistent sessions that don't require frequent re-authentication:
|
||||
## 📚 Provider Examples
|
||||
|
||||
### Authentik
|
||||
* **Type**: OAuth2/OpenID (Confidential)
|
||||
* **Redirect URI**: `https://pulse.example.com/api/oidc/callback`
|
||||
* **Signing Key**: Must use **RS256** (create a certificate/key pair if needed).
|
||||
* **Issuer URL**: `https://auth.example.com/application/o/pulse/`
|
||||
- **Type**: OAuth2/OpenID (Confidential)
|
||||
- **Redirect URI**: `https://pulse.example.com/api/oidc/callback`
|
||||
- **Signing Key**: Must use **RS256** (create a certificate/key pair if needed).
|
||||
- **Issuer URL**: `https://auth.example.com/application/o/pulse/`
|
||||
|
||||
### Keycloak
|
||||
* **Client ID**: `pulse`
|
||||
* **Access Type**: Confidential
|
||||
* **Valid Redirect URIs**: `https://pulse.example.com/api/oidc/callback`
|
||||
* **Issuer URL**: `https://keycloak.example.com/realms/myrealm`
|
||||
- **Client ID**: `pulse`
|
||||
- **Access Type**: Confidential
|
||||
- **Valid Redirect URIs**: `https://pulse.example.com/api/oidc/callback`
|
||||
- **Issuer URL**: `https://keycloak.example.com/realms/myrealm`
|
||||
|
||||
### Azure AD
|
||||
* **Redirect URI**: `https://pulse.example.com/api/oidc/callback` (Web)
|
||||
* **Issuer URL**: `https://login.microsoftonline.com/<tenant-id>/v2.0`
|
||||
* **Note**: Enable "ID tokens" in Authentication settings.
|
||||
- **Redirect URI**: `https://pulse.example.com/api/oidc/callback` (Web)
|
||||
- **Issuer URL**: `https://login.microsoftonline.com/<tenant-id>/v2.0`
|
||||
- **Note**: Enable "ID tokens" in Authentication settings.
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ Authenticate users via your existing reverse proxy (Authentik, Authelia, Cloudfl
|
||||
| `PROXY_AUTH_SECRET` | **Required**. Shared secret to verify requests. | - |
|
||||
| `PROXY_AUTH_USER_HEADER` | **Required**. Header containing the username. | - |
|
||||
| `PROXY_AUTH_ROLE_HEADER` | Header containing user groups/roles. | - |
|
||||
| `PROXY_AUTH_ROLE_SEPARATOR` | Separator for multiple roles in the header. | `|` |
|
||||
| `PROXY_AUTH_ROLE_SEPARATOR` | Separator for multiple roles in the header. | `\|` |
|
||||
| `PROXY_AUTH_ADMIN_ROLE` | Role name that grants admin access. | `admin` |
|
||||
| `PROXY_AUTH_LOGOUT_URL` | URL to redirect to after logout. | - |
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
# 📡 Proxy Control Plane
|
||||
|
||||
The Control Plane synchronizes `pulse-sensor-proxy` instances with the Pulse server, ensuring they trust the correct nodes without manual configuration.
|
||||
|
||||
> **Deprecated in v5:** `pulse-sensor-proxy` (and its control-plane sync) is deprecated and not recommended for new deployments. New installs should use `pulse-agent --enable-proxmox` for temperature monitoring.
|
||||
|
||||
> **Important**: The control-plane endpoints are disabled by default. Set `PULSE_ENABLE_SENSOR_PROXY=true` on the Pulse server to enable legacy proxy support.
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Pulse[Pulse Server] -- HTTPS /api/temperature-proxy --> Proxy[Sensor Proxy]
|
||||
Proxy -- SSH --> Nodes[Cluster Nodes]
|
||||
```
|
||||
|
||||
1. **Registration**: The proxy registers with Pulse on startup/install.
|
||||
2. **Sync**: The proxy periodically fetches the "Authorized Nodes" list from Pulse.
|
||||
3. **Validation**: The proxy only executes commands on nodes authorized by Pulse.
|
||||
|
||||
## 🔄 Workflow
|
||||
|
||||
1. **Install**: `install-sensor-proxy.sh` calls `/api/temperature-proxy/register`.
|
||||
2. **Token Exchange**: Pulse returns a control-plane token which the proxy saves to `/etc/pulse-sensor-proxy/.pulse-control-token`.
|
||||
3. **Polling**: The proxy polls `/api/temperature-proxy/authorized-nodes` every 60s (configurable).
|
||||
4. **Update**: If the node list changes (e.g., a new node is added to Pulse), the proxy updates its internal allowlist automatically.
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
The proxy configuration in `/etc/pulse-sensor-proxy/config.yaml` handles the sync:
|
||||
|
||||
```yaml
|
||||
pulse_control_plane:
|
||||
url: https://pulse.example.com:7655
|
||||
token_file: /etc/pulse-sensor-proxy/.pulse-control-token
|
||||
refresh_interval: 60
|
||||
```
|
||||
|
||||
## 🛡️ Security
|
||||
|
||||
* **Tokens**: The control-plane token is unique per proxy instance.
|
||||
* **Least Privilege**: The proxy only knows about nodes explicitly added to Pulse.
|
||||
* **Fallback**: If the control plane is unreachable, the proxy uses its last known good configuration.
|
||||
@@ -68,9 +68,6 @@ Pulse Pro unlocks **LLM-backed AI Patrol** — automated background monitoring t
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
<p>Found a bug or have a suggestion?</p>
|
||||
<a href="https://github.com/rcourtman/Pulse/issues">
|
||||
<img src="https://img.shields.io/badge/GitHub-Issues-green" alt="GitHub Issues" />
|
||||
</a>
|
||||
</div>
|
||||
Found a bug or have a suggestion?
|
||||
|
||||
[](https://github.com/rcourtman/Pulse/issues)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# Release Notes
|
||||
|
||||
Pulse release notes live on GitHub:
|
||||
https://github.com/rcourtman/Pulse/releases
|
||||
<https://github.com/rcourtman/Pulse/releases>
|
||||
|
||||
For historical v4 notes that previously lived in this repo, see:
|
||||
`docs/releases/RELEASE_NOTES_v4.md`
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ allowed_nodes:
|
||||
|
||||
# Require cluster membership validation
|
||||
strict_node_validation: true
|
||||
```
|
||||
```text
|
||||
|
||||
**Default Behavior:** If `allowed_nodes` is empty and proxy runs on Proxmox host, automatically validates against cluster membership (secure by default).
|
||||
|
||||
@@ -241,7 +241,7 @@ allowed_peers:
|
||||
#### Enhanced Metrics
|
||||
|
||||
New Prometheus metrics for security monitoring:
|
||||
```
|
||||
```text
|
||||
pulse_proxy_node_validation_failures_total{reason}
|
||||
pulse_proxy_read_timeouts_total
|
||||
pulse_proxy_write_timeouts_total
|
||||
@@ -378,7 +378,7 @@ go build ./cmd/pulse-sensor-proxy
|
||||
### References
|
||||
|
||||
- **Temperature Monitoring Overview:** `docs/security/TEMPERATURE_MONITORING.md`
|
||||
- **Sensor Proxy Hardening:** `docs/security/SENSOR_PROXY_HARDENING.md`
|
||||
- **Sensor Proxy Hardening:** Standardized security controls for legacy deployments.
|
||||
|
||||
---
|
||||
|
||||
@@ -396,4 +396,4 @@ All fixes implemented and tested 2025-11-07.
|
||||
|
||||
---
|
||||
|
||||
**For questions or security concerns, file issues at:** https://github.com/rcourtman/Pulse/issues
|
||||
**For questions or security concerns, file issues at:** <https://github.com/rcourtman/Pulse/issues>
|
||||
|
||||
@@ -13,7 +13,7 @@ curl -fsSL http://<pulse-ip>:7655/install.sh | \
|
||||
bash -s -- --url http://<pulse-ip>:7655 --token <api-token> --enable-proxmox
|
||||
```
|
||||
|
||||
If you use the agent method, the rest of this document (sensor proxy) is optional. See `docs/security/TEMPERATURE_MONITORING.md` for the security model overview.
|
||||
If you use the agent method, the rest of this document (sensor proxy) is optional.
|
||||
|
||||
## Migration: pulse-sensor-proxy → pulse-agent
|
||||
|
||||
@@ -79,14 +79,14 @@ If running Pulse in Docker, you must install the proxy on the host and share the
|
||||
```bash
|
||||
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \
|
||||
sudo bash -s -- --standalone --pulse-server http://<pulse-ip>:7655
|
||||
```
|
||||
```text
|
||||
|
||||
2. **Update `docker-compose.yml`**:
|
||||
Add the socket volume to your Pulse service:
|
||||
```yaml
|
||||
volumes:
|
||||
- /mnt/pulse-proxy:/run/pulse-sensor-proxy:ro
|
||||
```
|
||||
```text
|
||||
> **Note**: The standalone installer creates the socket at `/mnt/pulse-proxy` on the host. Map it to `/run/pulse-sensor-proxy` inside the container.
|
||||
|
||||
3. **Restart Pulse**: `docker compose up -d`
|
||||
@@ -103,7 +103,7 @@ If you have Pulse running on **Server A** and want to monitor temperatures on **
|
||||
Replace `<PULSE_CONTAINER_ID>` with the LXC container ID where Pulse runs on Server A (e.g., `100`).
|
||||
|
||||
2. The installer will detect that the container doesn't exist locally and install in **host monitoring only** mode:
|
||||
```
|
||||
```text
|
||||
[WARN] Container 100 does not exist on this node
|
||||
[WARN] Will install sensor-proxy for host temperature monitoring only
|
||||
```
|
||||
@@ -137,15 +137,15 @@ journalctl -u pulse-sensor-proxy -f
|
||||
1. **Pulse Sensor Proxy**: A lightweight service runs on the Proxmox host.
|
||||
2. **Secure Access**: It reads sensors (via `lm-sensors`) and exposes them securely.
|
||||
3. **Transport**:
|
||||
* **Local**: Uses a Unix socket (`/run/pulse-sensor-proxy`) for zero-latency, secure access.
|
||||
* **Remote**: Uses mutual TLS over HTTPS (port 8443).
|
||||
- **Local**: Uses a Unix socket (`/run/pulse-sensor-proxy`) for zero-latency, secure access.
|
||||
- **Remote**: Uses mutual TLS over HTTPS (port 8443).
|
||||
4. **No SSH Keys**: Pulse containers no longer need SSH keys to read temperatures.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Advanced Configuration
|
||||
|
||||
#### Manual Configuration (No Script)
|
||||
### Manual Configuration (No Script)
|
||||
|
||||
If you can't run the installer script, create the configuration manually:
|
||||
|
||||
@@ -375,8 +375,7 @@ ls -l /run/pulse-sensor-proxy/pulse-sensor-proxy.sock
|
||||
journalctl -u pulse-sensor-proxy -f
|
||||
```
|
||||
|
||||
Forward these logs off-host for retention by following
|
||||
[operations/SENSOR_PROXY_LOGS.md](operations/SENSOR_PROXY_LOGS.md).
|
||||
Forward these logs off-host for retention by following standard rsyslog/syslog practices.
|
||||
|
||||
In the Pulse container, check the logs at startup:
|
||||
```bash
|
||||
@@ -730,7 +729,6 @@ pulse-sensor-proxy config set-allowed-nodes --replace --merge 192.168.0.1
|
||||
- Installer uses CLI (no more shell/Python divergence)
|
||||
|
||||
**See also:**
|
||||
- [Sensor Proxy Config Management Guide](operations/SENSOR_PROXY_CONFIG.md) - Complete runbook
|
||||
- [Sensor Proxy CLI Reference](../cmd/pulse-sensor-proxy/README.md) - Full command documentation
|
||||
|
||||
## Control-Plane Sync & Migration
|
||||
@@ -786,7 +784,7 @@ If temperature monitoring isn't working:
|
||||
ssh root@cluster-node "sensors -j"
|
||||
```
|
||||
|
||||
3. **Check GitHub Issues:** https://github.com/rcourtman/Pulse/issues
|
||||
3. **Check GitHub Issues:** <https://github.com/rcourtman/Pulse/issues>
|
||||
4. **Include in bug report:**
|
||||
- Pulse version
|
||||
- Deployment type (LXC/Docker/native)
|
||||
|
||||
@@ -34,56 +34,56 @@ sudo pulse bootstrap-token
|
||||
|
||||
### Authentication
|
||||
|
||||
**"Invalid username or password" after setup**
|
||||
#### "Invalid username or password" after setup
|
||||
- **Docker Compose**: Did you escape the `$` signs in your hash? Use `$$2a$$...`.
|
||||
- **Truncated Hash**: Ensure your bcrypt hash is exactly 60 characters.
|
||||
|
||||
**Cannot login / 401 Unauthorized**
|
||||
#### Cannot login / 401 Unauthorized
|
||||
- Clear browser cookies.
|
||||
- Check if your IP is locked out (wait 15 mins).
|
||||
- If another admin can log in, use `POST /api/security/reset-lockout` to clear the lockout for your username or IP.
|
||||
|
||||
**Audit Log verification shows unsigned events**
|
||||
#### Audit Log verification shows unsigned events
|
||||
- **Symptom**: Audit Log entries show “Unsigned” or verification fails in the UI.
|
||||
- **Root cause**: `PULSE_AUDIT_SIGNING_KEY` is not set, so events are stored without signatures.
|
||||
- **Fix**: Set `PULSE_AUDIT_SIGNING_KEY` and restart Pulse Pro. Newly created events will be signed; existing unsigned events remain unsigned.
|
||||
|
||||
**Audit Log is empty**
|
||||
#### Audit Log is empty
|
||||
- **Symptom**: Audit Log shows zero events or "Console Logging Only."
|
||||
- **Root cause**: OSS build uses console logging only, or Pulse Pro audit logging is not enabled.
|
||||
- **Fix**: Use Pulse Pro with audit logging enabled, then generate new audit events (logins, token creation, password changes).
|
||||
|
||||
**Audit Log verification fails for older events**
|
||||
#### Audit Log verification fails for older events
|
||||
- **Symptom**: Older events fail verification while newer events pass.
|
||||
- **Root cause**: The signing key changed or was rotated, so signatures no longer match.
|
||||
- **Fix**: Keep `PULSE_AUDIT_SIGNING_KEY` stable. If rotated intentionally, expect older events to fail verification.
|
||||
|
||||
### Monitoring Data
|
||||
|
||||
**VMs show "-" for disk usage**
|
||||
#### VMs show "-" for disk usage
|
||||
- Install **QEMU Guest Agent** in the VM.
|
||||
- Enable "QEMU Guest Agent" in Proxmox VM Options.
|
||||
- Restart the VM.
|
||||
- See [VM Disk Monitoring](VM_DISK_MONITORING.md).
|
||||
|
||||
**Temperature data missing**
|
||||
#### Temperature data missing
|
||||
- Install `lm-sensors` on the host.
|
||||
- Run `sensors-detect`.
|
||||
- Install the unified agent on the Proxmox host with `--enable-proxmox`.
|
||||
- See [Temperature Monitoring](TEMPERATURE_MONITORING.md).
|
||||
|
||||
**Docker hosts appearing/disappearing**
|
||||
#### Docker hosts appearing/disappearing
|
||||
- **Duplicate IDs**: Cloned VMs often share `/etc/machine-id`.
|
||||
- **Fix**: Run `rm /etc/machine-id && systemd-machine-id-setup` on the clone.
|
||||
|
||||
### Notifications
|
||||
|
||||
**Emails not sending**
|
||||
#### Emails not sending
|
||||
- Check SMTP settings in **Alerts → Notification Destinations**.
|
||||
- Check logs: `docker logs pulse | grep email`.
|
||||
- Ensure your SMTP provider allows the connection (e.g., Gmail App Passwords).
|
||||
|
||||
**Webhooks failing**
|
||||
#### Webhooks failing
|
||||
- Verify the URL is reachable from the Pulse server.
|
||||
- If targeting private IPs, allow them in **Settings → System → Network → Webhook Security**.
|
||||
- Check Pulse logs for HTTP status codes and response bodies.
|
||||
|
||||
@@ -85,7 +85,6 @@ curl -fsSL http://<pulse-ip>:7655/install.sh | \
|
||||
|
||||
Legacy env var: `PULSE_KUBE_INCLUDE_ALL_POD_FILES` is still accepted for backward compatibility.
|
||||
|
||||
|
||||
## Auto-Detection
|
||||
|
||||
Auto-detection behavior:
|
||||
@@ -178,7 +177,6 @@ The agent can report S.M.A.R.T. disk temperatures when running in Agent mode. Th
|
||||
- **Disk exclusions** (`--disk-exclude` / `PULSE_DISK_EXCLUDE`) also apply to S.M.A.R.T. monitoring.
|
||||
Use patterns like `sda`, `/dev/sdb`, `nvme*`, or `*cache*` to exclude specific block devices.
|
||||
|
||||
|
||||
## Auto-Update
|
||||
|
||||
The unified agent automatically checks for updates every hour. When a new version is available:
|
||||
|
||||
@@ -17,9 +17,7 @@ Monitor actual disk usage inside your VMs using the QEMU Guest Agent.
|
||||
## ⚙️ Requirements
|
||||
|
||||
* **QEMU Guest Agent**: Must be installed and running inside the VM.
|
||||
* **Proxmox Permissions**:
|
||||
* **Proxmox 8**: `VM.Monitor`
|
||||
* **Proxmox 9+**: `VM.GuestAgent.Audit`
|
||||
* **Proxmox Permissions**: `VM.Monitor` (Proxmox 8) or `VM.GuestAgent.Audit` (Proxmox 9+).
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
|
||||
@@ -85,20 +85,9 @@ Returns a real-time snapshot of the adaptive scheduler, including queue state, c
|
||||
### Instances (`instances`)
|
||||
The authoritative source for per-instance health.
|
||||
|
||||
* **`pollStatus`**:
|
||||
* `lastSuccess`: Timestamp of last successful poll.
|
||||
* `lastError`: Details of the last error (message, category).
|
||||
* `consecutiveFailures`: Current failure streak.
|
||||
* **`breaker`**:
|
||||
* `state`: `closed` (healthy), `open` (failing), `half_open` (recovering).
|
||||
* `retryAt`: Next retry time if open/half-open.
|
||||
* `since`: When the current breaker state started.
|
||||
* `lastTransition`: Timestamp of the last state transition.
|
||||
* **`deadLetter`**:
|
||||
* `present`: `true` if the instance is in the DLQ (stopped polling).
|
||||
* `reason`: Why it was moved to DLQ (e.g., `permanent_failure`).
|
||||
* `retryCount`: DLQ retry attempts.
|
||||
* `nextRetry`: Next scheduled retry (if any).
|
||||
* **`pollStatus`**: `lastSuccess` timestamp, `lastError` details, `consecutiveFailures` count.
|
||||
* **`breaker`**: `state` (`closed`/`open`/`half_open`), `retryAt` next retry, `since` state start, `lastTransition` timestamp.
|
||||
* **`deadLetter`**: `present` flag, `reason` (e.g., `permanent_failure`), `retryCount`, `nextRetry` if scheduled.
|
||||
|
||||
### Top-Level Queue and DLQ
|
||||
* **`queue`**: Snapshot of the active task queue (depth + per-type counts).
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
Pulse uses an adaptive scheduler to optimize polling based on instance health and activity.
|
||||
|
||||
## 🧠 Architecture
|
||||
* **Scheduler**: Calculates intervals based on health/staleness.
|
||||
* **Priority Queue**: Min-heap keyed by `NextRun`.
|
||||
* **Circuit Breaker**: Prevents hot loops on failing instances using success/failure counters.
|
||||
* **Backoff**: Exponential retry delays (5s min to 5m max).
|
||||
* **Worker Pool**: One worker per configured instance (PVE/PBS/PMG), capped at 10.
|
||||
* **Global Concurrency Cap**: At most 2 polling cycles run at once to avoid resource spikes.
|
||||
- **Scheduler**: Calculates intervals based on health/staleness.
|
||||
- **Priority Queue**: Min-heap keyed by `NextRun`.
|
||||
- **Circuit Breaker**: Prevents hot loops on failing instances using success/failure counters.
|
||||
- **Backoff**: Exponential retry delays (5s min to 5m max).
|
||||
- **Worker Pool**: One worker per configured instance (PVE/PBS/PMG), capped at 10.
|
||||
- **Global Concurrency Cap**: At most 2 polling cycles run at once to avoid resource spikes.
|
||||
|
||||
## 🔬 Implementation Details (Developer Info)
|
||||
|
||||
@@ -43,6 +43,7 @@ Adaptive polling is **disabled by default**.
|
||||
There is currently no dedicated UI for adaptive polling in v5.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `ADAPTIVE_POLLING_ENABLED` | `false` | Enable/disable. |
|
||||
@@ -66,6 +67,7 @@ Exposed at `:9091/metrics`.
|
||||
| `pulse_scheduler_queue_due_soon` | Gauge | Tasks due in the next 12 seconds. |
|
||||
|
||||
## ⚡ Circuit Breaker
|
||||
|
||||
| State | Trigger | Recovery |
|
||||
| :--- | :--- | :--- |
|
||||
| **Closed** | Normal operation. | — |
|
||||
@@ -78,7 +80,7 @@ Exposed at `:9091/metrics`.
|
||||
`GET /api/monitoring/scheduler/health` (Auth required)
|
||||
|
||||
Returns:
|
||||
* Queue depth & breakdown.
|
||||
* Dead-letter tasks.
|
||||
* Circuit breaker states.
|
||||
* Per-instance staleness.
|
||||
- Queue depth & breakdown.
|
||||
- Dead-letter tasks.
|
||||
- Circuit breaker states.
|
||||
- Per-instance staleness.
|
||||
|
||||
@@ -11,6 +11,7 @@ This listener is separate from the main UI/API port (`7655`). In Docker and Kube
|
||||
**Helm note:** the current chart exposes only port `7655`, so Prometheus scraping requires an additional Service that targets `9091` (and a matching ServiceMonitor).
|
||||
|
||||
## 🌐 HTTP Ingress
|
||||
|
||||
| Metric | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `pulse_http_request_duration_seconds` | Histogram | Latency buckets by `method`, `route`, `status`. |
|
||||
@@ -18,6 +19,7 @@ This listener is separate from the main UI/API port (`7655`). In Docker and Kube
|
||||
| `pulse_http_request_errors_total` | Counter | Error totals by `method`, `route`, `status_class` (`client_error`, `server_error`, `none`). |
|
||||
|
||||
## 🔄 Polling & Nodes
|
||||
|
||||
| Metric | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `pulse_monitor_poll_duration_seconds` | Histogram | Per-instance poll latency. |
|
||||
@@ -34,6 +36,7 @@ This listener is separate from the main UI/API port (`7655`). In Docker and Kube
|
||||
| `pulse_monitor_node_poll_staleness_seconds` | Gauge | Seconds since last node success (`-1` if never succeeded). |
|
||||
|
||||
## 🧠 Scheduler Health
|
||||
|
||||
| Metric | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `pulse_scheduler_queue_due_soon` | Gauge | Tasks due within the next 12 seconds. |
|
||||
@@ -45,6 +48,7 @@ This listener is separate from the main UI/API port (`7655`). In Docker and Kube
|
||||
| `pulse_scheduler_breaker_retry_seconds` | Gauge | Seconds until next retry allowed. |
|
||||
|
||||
## ⚡ Diagnostics Cache
|
||||
|
||||
| Metric | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `pulse_diagnostics_cache_hits_total` | Counter | Cache hits. |
|
||||
@@ -52,6 +56,7 @@ This listener is separate from the main UI/API port (`7655`). In Docker and Kube
|
||||
| `pulse_diagnostics_refresh_duration_seconds` | Histogram | Refresh latency. |
|
||||
|
||||
## 🚨 Alert Lifecycle
|
||||
|
||||
| Metric | Type | Description |
|
||||
| :--- | :--- | :--- |
|
||||
| `pulse_alerts_active` | Gauge | Active alerts by `level` and `type`. |
|
||||
@@ -63,6 +68,6 @@ This listener is separate from the main UI/API port (`7655`). In Docker and Kube
|
||||
| `pulse_alert_duration_seconds` | Histogram | Time from alert fire to resolve (by `type`). |
|
||||
|
||||
## 🚨 Alerting Examples
|
||||
* **High Error Rate**: `rate(pulse_http_request_errors_total[5m]) > 0.05`
|
||||
* **Stale Node**: `pulse_monitor_node_poll_staleness_seconds > 300`
|
||||
* **Breaker Open**: `pulse_scheduler_breaker_state == 2`
|
||||
- **High Error Rate**: `rate(pulse_http_request_errors_total[5m]) > 0.05`
|
||||
- **Stale Node**: `pulse_monitor_node_poll_staleness_seconds > 300`
|
||||
- **Breaker Open**: `pulse_scheduler_breaker_state == 2`
|
||||
|
||||
@@ -11,19 +11,19 @@ Safely enable dynamic scheduling (v5+).
|
||||
|
||||
## 🟢 Enable
|
||||
Choose one method:
|
||||
* **UI**: Not currently exposed in the v5 UI (use CLI or env vars).
|
||||
* **CLI**:
|
||||
- systemd/LXC: `jq '.adaptivePollingEnabled=true' /etc/pulse/system.json > /tmp/system.json && sudo mv /tmp/system.json /etc/pulse/system.json`
|
||||
- Docker/Kubernetes: edit `/data/system.json` in the volume and restart the container/pod
|
||||
* **Env**: `ADAPTIVE_POLLING_ENABLED=true` (Docker/K8s).
|
||||
- **UI**: Not currently exposed in the v5 UI (use CLI or env vars).
|
||||
- **CLI**:
|
||||
- systemd/LXC: `jq '.adaptivePollingEnabled=true' /etc/pulse/system.json > /tmp/system.json && sudo mv /tmp/system.json /etc/pulse/system.json`
|
||||
- Docker/Kubernetes: edit `/data/system.json` in the volume and restart the container/pod
|
||||
- **Env**: `ADAPTIVE_POLLING_ENABLED=true` (Docker/K8s).
|
||||
|
||||
## 🔍 Monitor (First 15m)
|
||||
Watch for stability:
|
||||
```bash
|
||||
watch -n 5 'curl -s http://localhost:9091/metrics | grep pulse_monitor_poll_queue_depth'
|
||||
```
|
||||
* **Success**: Queue depth < 50, no permanent errors.
|
||||
* **Failure**: High queue depth, open breakers.
|
||||
- **Success**: Queue depth < 50, no permanent errors.
|
||||
- **Failure**: High queue depth, open breakers.
|
||||
|
||||
## ↩️ Rollback
|
||||
If instability occurs > 10m:
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# 🔄 Sensor Proxy Audit Log Rotation
|
||||
|
||||
> **Deprecated in v5:** `pulse-sensor-proxy` is deprecated and not recommended for new deployments.
|
||||
> This document is retained for existing installations during the migration window.
|
||||
|
||||
The proxy writes append-only, hash-chained logs to `/var/log/pulse/sensor-proxy/audit.log`.
|
||||
|
||||
## ⚠️ Important
|
||||
* **Do not delete**: The file is protected with `chattr +a`.
|
||||
* **Rotate when**: >200MB or >30 days.
|
||||
|
||||
## 🛠️ Manual Rotation
|
||||
|
||||
Run as root:
|
||||
|
||||
```bash
|
||||
# 1. Unlock file
|
||||
chattr -a /var/log/pulse/sensor-proxy/audit.log
|
||||
|
||||
# 2. Rotate (copy & truncate)
|
||||
cp -a /var/log/pulse/sensor-proxy/audit.log /var/log/pulse/sensor-proxy/audit.log.$(date +%Y%m%d)
|
||||
: > /var/log/pulse/sensor-proxy/audit.log
|
||||
|
||||
# 3. Relock & Restart
|
||||
chown pulse-sensor-proxy:pulse-sensor-proxy /var/log/pulse/sensor-proxy/audit.log
|
||||
chmod 0640 /var/log/pulse/sensor-proxy/audit.log
|
||||
chattr +a /var/log/pulse/sensor-proxy/audit.log
|
||||
systemctl restart pulse-sensor-proxy
|
||||
```
|
||||
|
||||
## 🤖 Logrotate Config
|
||||
|
||||
Create `/etc/logrotate.d/pulse-sensor-proxy`:
|
||||
|
||||
```conf
|
||||
/var/log/pulse/sensor-proxy/audit.log {
|
||||
weekly
|
||||
rotate 8
|
||||
compress
|
||||
missingok
|
||||
notifempty
|
||||
create 0640 pulse-sensor-proxy pulse-sensor-proxy
|
||||
sharedscripts
|
||||
prerotate
|
||||
/usr/bin/chattr -a /var/log/pulse/sensor-proxy/audit.log || true
|
||||
endscript
|
||||
postrotate
|
||||
/bin/systemctl restart pulse-sensor-proxy.service || true
|
||||
/usr/bin/chattr +a /var/log/pulse/sensor-proxy/audit.log || true
|
||||
endscript
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: Do NOT use `copytruncate`. The restart is required to reset the hash chain.
|
||||
@@ -4,6 +4,7 @@ Manage Pulse auto-updates on host-mode installations.
|
||||
> **Note**: Docker/Kubernetes users should manage updates via their orchestrator.
|
||||
|
||||
## ⚙️ Components
|
||||
|
||||
| File | Purpose |
|
||||
| :--- | :--- |
|
||||
| `pulse-update.timer` | Daily check (02:00 + jitter). |
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
# ⚙️ Sensor Proxy Configuration
|
||||
|
||||
> **Deprecated in v5:** `pulse-sensor-proxy` is deprecated and not recommended for new deployments.
|
||||
> Use `pulse-agent --enable-proxmox` for temperature monitoring.
|
||||
> This document is retained for existing installations during the migration window.
|
||||
|
||||
Safe configuration management using the built-in CLI.
|
||||
|
||||
## 📂 Files
|
||||
* **`config.yaml`**: General settings (logging, metrics).
|
||||
* **`allowed_nodes.yaml`**: Authorized node list (managed via CLI).
|
||||
|
||||
## 🛠️ CLI Reference
|
||||
|
||||
### Validation
|
||||
Check for errors before restart.
|
||||
```bash
|
||||
pulse-sensor-proxy config validate
|
||||
```
|
||||
|
||||
### Managing Nodes
|
||||
**Add Nodes (Merge):**
|
||||
```bash
|
||||
pulse-sensor-proxy config set-allowed-nodes --merge 192.168.0.10
|
||||
```
|
||||
|
||||
**Replace List:**
|
||||
```bash
|
||||
pulse-sensor-proxy config set-allowed-nodes --replace \
|
||||
--merge 192.168.0.1 --merge 192.168.0.2
|
||||
```
|
||||
|
||||
## ⚠️ Troubleshooting
|
||||
|
||||
**Validation Fails:**
|
||||
* Check for duplicate `allowed_nodes` blocks in `config.yaml`.
|
||||
* Run `pulse-sensor-proxy config validate 2>&1` for details.
|
||||
|
||||
**Lock Errors:**
|
||||
* Remove stale locks if process is dead: `rm /etc/pulse-sensor-proxy/*.lock`.
|
||||
|
||||
**Empty List:**
|
||||
* Valid for IPC-only clusters.
|
||||
* Populate manually if needed using `--replace`.
|
||||
@@ -1,35 +0,0 @@
|
||||
# 📝 Sensor Proxy Log Forwarding
|
||||
|
||||
> **Deprecated in v5:** `pulse-sensor-proxy` is deprecated and not recommended for new deployments.
|
||||
> Use `pulse-agent --enable-proxmox` for temperature monitoring.
|
||||
> This document is retained for existing installations during the migration window.
|
||||
|
||||
Forward `audit.log` and `proxy.log` to a central SIEM via RELP + TLS.
|
||||
|
||||
## 🚀 Quick Start
|
||||
Run the helper script with your collector details:
|
||||
|
||||
```bash
|
||||
sudo REMOTE_HOST=logs.example.com \
|
||||
REMOTE_PORT=6514 \
|
||||
CERT_DIR=/etc/pulse/log-forwarding \
|
||||
CA_CERT=/path/to/ca.crt \
|
||||
CLIENT_CERT=/path/to/client.crt \
|
||||
CLIENT_KEY=/path/to/client.key \
|
||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/setup-log-forwarding.sh)"
|
||||
```
|
||||
|
||||
## 📋 What It Does
|
||||
1. **Inputs**: Watches `/var/log/pulse/sensor-proxy/{audit,proxy}.log`.
|
||||
2. **Queue**: Disk-backed queue (50k messages) for reliability.
|
||||
3. **Output**: RELP over TLS to `REMOTE_HOST`.
|
||||
4. **Mirror**: Local debug file at `/var/log/pulse/sensor-proxy/forwarding.log`.
|
||||
|
||||
## ✅ Verification
|
||||
1. **Check Status**: `sudo systemctl status rsyslog`
|
||||
2. **View Mirror**: `tail -f /var/log/pulse/sensor-proxy/forwarding.log`
|
||||
3. **Test**: Restart proxy and check remote collector for `pulse.audit` tag.
|
||||
|
||||
## 🧹 Maintenance
|
||||
* **Disable**: Remove `/etc/rsyslog.d/pulse-sensor-proxy.conf` and restart rsyslog.
|
||||
* **Rotate Certs**: Replace files in `CERT_DIR` and restart rsyslog.
|
||||
@@ -3,29 +3,29 @@
|
||||
This file archives the v4-era release notes that previously lived at `docs/RELEASE_NOTES.md`.
|
||||
|
||||
For current releases, refer to GitHub Releases:
|
||||
https://github.com/rcourtman/Pulse/releases
|
||||
<https://github.com/rcourtman/Pulse/releases>
|
||||
|
||||
---
|
||||
|
||||
# Pulse v4.31.0
|
||||
## Pulse v4.31.0
|
||||
|
||||
## What's Changed
|
||||
### What's Changed (v4.31.0)
|
||||
|
||||
### Temperature monitoring over HTTPS
|
||||
#### Temperature monitoring over HTTPS
|
||||
- `pulse-sensor-proxy` now exposes an authenticated HTTPS endpoint per Proxmox host. Pulse stores each proxy’s URL + bearer token and always polls `https://node:8443/temps` before falling back to local sockets or SSH, eliminating the fragile “single proxy for every node” chain.
|
||||
- Installations auto-register via the new `/api/temperature-proxy/register` endpoint, generate 4096-bit certificates, enforce CIDR allowlists, and log every HTTP request through the proxy’s audit pipeline.
|
||||
- The backend temperature collector understands proxy URLs/tokens, respects strict timeouts, and publishes richer diagnostics so operators can see which node failed and why.
|
||||
|
||||
### Installer, diagnostics, and UI updates
|
||||
#### Installer, diagnostics, and UI updates
|
||||
- `scripts/install-sensor-proxy.sh` gained `--http-mode` / `--http-addr`, automatic TLS generation, rollback-on-failure, allowed subnet auto-population, and a comprehensive uninstall path that purges sockets, TLS secrets, and LXC bind mounts.
|
||||
- A new `Settings → Diagnostics → Temperature Proxy` table surfaces proxy health, registration status, and the errors returned by the HTTPS endpoint.
|
||||
- `scripts/tests/test-sensor-proxy-http.sh` exercises the HTTP installer path end-to-end inside Docker to prevent regressions.
|
||||
|
||||
### Host agent refinements
|
||||
#### Host agent refinements
|
||||
- Windows PowerShell installers/uninstallers now log verbosely, harden permissions, and clean up services more reliably.
|
||||
- Linux host-agent scripts aligned with the new diagnostics UX and scoped token workflow so onboarding is less error-prone.
|
||||
|
||||
## Upgrade Notes
|
||||
### Upgrade Notes (v4.31.0)
|
||||
|
||||
Temperature monitoring will not work for remote nodes until every Proxmox host is reinstalled with the new HTTPS workflow. Follow these steps per host:
|
||||
|
||||
@@ -46,7 +46,7 @@ curl -vk https://node.example:8443/health \
|
||||
-H "Authorization: Bearer $(sudo cat /etc/pulse-sensor-proxy/.http-auth-token)"
|
||||
```
|
||||
|
||||
## Installation
|
||||
### Installation (v4.31.0)
|
||||
- **Install or upgrade with the helper script**
|
||||
```bash
|
||||
curl -sL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
|
||||
@@ -72,7 +72,7 @@ curl -vk https://node.example:8443/health \
|
||||
--namespace pulse --create-namespace
|
||||
```
|
||||
|
||||
## Downloads
|
||||
### Downloads (v4.31.0)
|
||||
- Multi-arch Linux tarballs (amd64/arm64/armv7)
|
||||
- Standalone sensor proxy binaries (now include HTTP mode)
|
||||
- Helm chart archive (pulse-4.31.0-helm.tgz)
|
||||
@@ -81,29 +81,29 @@ curl -vk https://node.example:8443/health \
|
||||
|
||||
---
|
||||
|
||||
# Pulse v4.26.1
|
||||
## Pulse v4.26.1
|
||||
|
||||
## What's Changed
|
||||
### New
|
||||
### What's Changed (v4.26.1)
|
||||
#### New
|
||||
- Standalone host agents now ship with guided Linux, macOS, and Windows installers that stream registration status back to Pulse, generate scoped commands from **Settings → Agents**, and feed host metrics into alerts alongside Proxmox and Docker.
|
||||
- Alert thresholds gained host-level overrides, connectivity toggles, and snapshot size guardrails so you can tune offline behaviour per host while keeping a global policy for other resources.
|
||||
- API tokens now support fine-grained scopes with a redesigned manager that previews command templates, highlights unused credentials, and makes revocation a single click.
|
||||
- Proxmox replication jobs surface in a dedicated **Proxmox → Replication** view with API plumbing to track task health and bubble failures into the monitoring pipeline.
|
||||
- Docker Swarm environments now receive service/task-aware reporting with configurable scope, plus a Docker settings view that highlights manager/worker roles, stack health, rollout status, and service alert thresholds.
|
||||
|
||||
### Improvements
|
||||
#### Improvements
|
||||
- Dashboard loads and drawer links respond faster thanks to cached guest metadata, reduced polling allocations, and inline URL editing that no longer flashes on WebSocket updates.
|
||||
- Settings navigation is reorganized with dedicated platform and agent sections, richer filters, and platform icons that make onboarding and discovery workflows clearer.
|
||||
- LXC guests now report dynamic interface IPs, configuration metadata, and queue metrics so alerting, discovery, and drawers stay accurate even during rapid container churn.
|
||||
- Notifications consolidate into a consistent toast system, with clearer feedback during agent setup, token generation, and background job state changes.
|
||||
|
||||
### Bug Fixes
|
||||
#### Bug Fixes
|
||||
- Enforced explicit node naming and respected custom Proxmox ports so cluster discovery, overrides, and disk monitoring defaults remain intact after edits.
|
||||
- Hardened setup-token flows and checksum handling in the installers to prevent stale credentials and guarantee the correct binaries are fetched.
|
||||
- Treated 501 responses from the Proxmox API as non-fatal during failover, restored FreeBSD disk counter parsing, and stopped guest link icons from re-triggering animations on updates.
|
||||
- Preserved inline editor state across WebSocket refreshes and ensured Docker host identifiers stay collision-safe in mixed environments.
|
||||
|
||||
## Installation
|
||||
### Installation (v4.26.1)
|
||||
- **Install or upgrade with the helper script**
|
||||
```bash
|
||||
curl -sL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
|
||||
@@ -129,7 +129,7 @@ curl -vk https://node.example:8443/health \
|
||||
--namespace pulse --create-namespace
|
||||
```
|
||||
|
||||
## Downloads
|
||||
### Downloads (v4.26.1)
|
||||
- Multi-arch Linux tarballs (amd64/arm64/armv7)
|
||||
- Standalone sensor proxy binaries
|
||||
- Helm chart archive (pulse-4.26.1-helm.tgz)
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# 🛡️ Sensor Proxy AppArmor (Optional)
|
||||
|
||||
> **Deprecated in v5:** `pulse-sensor-proxy` is deprecated and not recommended for new deployments.
|
||||
> Use `pulse-agent --enable-proxmox` for temperature monitoring.
|
||||
> This document is retained for existing installations during the migration window.
|
||||
|
||||
Secure `pulse-sensor-proxy` with AppArmor and Seccomp.
|
||||
|
||||
## 🛡️ AppArmor
|
||||
|
||||
Profile: `security/apparmor/pulse-sensor-proxy.apparmor`
|
||||
* **Allows**: Configs, logs, SSH keys, outbound TCP/SSH.
|
||||
* **Blocks**: Raw sockets, module loading, ptrace, exec outside allowlist.
|
||||
|
||||
### Install & Enforce
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/security/apparmor/pulse-sensor-proxy.apparmor | \
|
||||
sudo tee /etc/apparmor.d/pulse-sensor-proxy >/dev/null
|
||||
sudo apparmor_parser -r /etc/apparmor.d/pulse-sensor-proxy
|
||||
sudo aa-enforce pulse-sensor-proxy
|
||||
```
|
||||
|
||||
## 🔒 Seccomp
|
||||
|
||||
Profile: `security/seccomp/pulse-sensor-proxy.json`
|
||||
* **Allows**: Go runtime syscalls, network, file IO.
|
||||
* **Blocks**: Everything else (returns `EPERM`).
|
||||
|
||||
### Systemd (Classic)
|
||||
Add to service override:
|
||||
```ini
|
||||
[Service]
|
||||
AppArmorProfile=pulse-sensor-proxy
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallAllow=accept;connect;recvfrom;sendto;recvmsg;sendmsg;sendmmsg;getsockname;getpeername;getsockopt;setsockopt;shutdown
|
||||
```
|
||||
|
||||
### Containers (Docker/Podman)
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/security/seccomp/pulse-sensor-proxy.json | \
|
||||
sudo tee /etc/pulse-sensor-proxy.seccomp.json >/dev/null
|
||||
|
||||
podman run --seccomp-profile /etc/pulse-sensor-proxy.seccomp.json ...
|
||||
```
|
||||
|
||||
## 🔍 Verification
|
||||
Check status with `aa-status` or `journalctl -t auditbeat`.
|
||||
@@ -1,64 +0,0 @@
|
||||
# 🛡️ Sensor Proxy Hardening
|
||||
|
||||
> **Deprecated in v5:** `pulse-sensor-proxy` is deprecated and not recommended for new deployments.
|
||||
> Use `pulse-agent --enable-proxmox` for temperature monitoring.
|
||||
> This document is retained for existing installations during the migration window.
|
||||
|
||||
The `pulse-sensor-proxy` runs on the host to securely collect temperatures, keeping SSH keys out of containers.
|
||||
|
||||
## 🏗️ Architecture
|
||||
* **Host**: Runs `pulse-sensor-proxy` (unprivileged user).
|
||||
* **Container**: Connects via Unix socket (`/run/pulse-sensor-proxy/pulse-sensor-proxy.sock`).
|
||||
* **Auth**: Uses `SO_PEERCRED` to verify container UID/PID.
|
||||
|
||||
## 🔒 Host Hardening
|
||||
|
||||
### Service Account
|
||||
Runs as `pulse-sensor-proxy` (no shell, no home).
|
||||
```bash
|
||||
id pulse-sensor-proxy # uid=XXX(pulse-sensor-proxy)
|
||||
```
|
||||
|
||||
### Systemd Security
|
||||
The service unit uses:
|
||||
* `User=pulse-sensor-proxy`
|
||||
* `NoNewPrivileges=true`
|
||||
* `ProtectSystem=strict`
|
||||
* `PrivateTmp=true`
|
||||
|
||||
### File Permissions
|
||||
| Path | Owner | Mode |
|
||||
| :--- | :--- | :--- |
|
||||
| `/var/lib/pulse-sensor-proxy/` | `pulse-sensor-proxy` | `0750` |
|
||||
| `/var/lib/pulse-sensor-proxy/ssh/` | `pulse-sensor-proxy` | `0700` |
|
||||
| `/run/pulse-sensor-proxy/` | `pulse-sensor-proxy` | `0775` |
|
||||
|
||||
## 📦 LXC Configuration
|
||||
Required for the container to access the proxy socket.
|
||||
|
||||
**`/etc/pve/lxc/<VMID>.conf`**:
|
||||
```ini
|
||||
unprivileged: 1
|
||||
lxc.apparmor.profile: generated
|
||||
lxc.mount.entry: /run/pulse-sensor-proxy mnt/pulse-proxy none bind,create=dir 0 0
|
||||
```
|
||||
|
||||
## 🔑 Key Management
|
||||
SSH keys are restricted to `sensors -j` only.
|
||||
|
||||
**Rotation**:
|
||||
```bash
|
||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/pulse-proxy-rotate-keys.sh)"
|
||||
```
|
||||
* **Dry Run**: Add `--dry-run`.
|
||||
* **Rollback**: Add `--rollback`.
|
||||
|
||||
## 🚨 Incident Response
|
||||
If compromised:
|
||||
1. **Stop Proxy**: `systemctl stop pulse-sensor-proxy`.
|
||||
2. **Rotate Keys**: Remove old keys from nodes manually or use the rotation helper above.
|
||||
3. **Audit Logs**: Check `journalctl -u pulse-sensor-proxy`.
|
||||
4. **Reinstall**:
|
||||
```bash
|
||||
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | sudo bash
|
||||
```
|
||||
@@ -1,39 +0,0 @@
|
||||
# 🌐 Sensor Proxy Network Segmentation
|
||||
|
||||
> **Deprecated in v5:** `pulse-sensor-proxy` is deprecated and not recommended for new deployments.
|
||||
> Use `pulse-agent --enable-proxmox` for temperature monitoring.
|
||||
> This document is retained for existing installations during the migration window.
|
||||
|
||||
Isolate the proxy to prevent lateral movement.
|
||||
|
||||
## 🚧 Zones
|
||||
* **Pulse App**: Connects to Proxy via Unix socket (local).
|
||||
* **Sensor Proxy**: Outbound SSH to Proxmox nodes only.
|
||||
* **Proxmox Nodes**: Accept SSH from Proxy.
|
||||
* **Logging**: Accepts RELP/TLS from Proxy.
|
||||
|
||||
## 🛡️ Firewall Rules
|
||||
|
||||
| Source | Dest | Port | Purpose | Action |
|
||||
| :--- | :--- | :--- | :--- | :--- |
|
||||
| **Pulse App** | Proxy | `unix` | RPC Requests | **Allow** (Local) |
|
||||
| **Proxy** | Nodes | `22` | SSH (sensors) | **Allow** |
|
||||
| **Proxy** | Logs | `6514` | Audit Logs | **Allow** |
|
||||
| **Any** | Proxy | `22` | SSH Access | **Deny** (Use Bastion) |
|
||||
| **Proxy** | Internet | `any` | Outbound | **Deny** |
|
||||
|
||||
## 🔧 Implementation (iptables)
|
||||
```bash
|
||||
# Allow SSH to Proxmox
|
||||
iptables -A OUTPUT -p tcp -d <PROXMOX_SUBNET> --dport 22 -j ACCEPT
|
||||
|
||||
# Allow Log Forwarding
|
||||
iptables -A OUTPUT -p tcp -d <LOG_HOST> --dport 6514 -j ACCEPT
|
||||
|
||||
# Drop all other outbound
|
||||
iptables -P OUTPUT DROP
|
||||
```
|
||||
|
||||
## 🚨 Monitoring
|
||||
* Alert on outbound connections to non-whitelisted IPs.
|
||||
* Monitor `pulse_proxy_limiter_rejects_total` for abuse.
|
||||
@@ -32,9 +32,9 @@ The agent runs `sensors -j` locally and reports temperatures directly to Pulse.
|
||||
`pulse-sensor-proxy` is deprecated in v5 and is not recommended for new deployments. This section is retained for existing installations during the migration window.
|
||||
|
||||
### 🛡️ Security Model
|
||||
* **Isolation**: SSH keys live on the host, not in the container.
|
||||
* **Least Privilege**: Proxy runs as `pulse-sensor-proxy` (no shell).
|
||||
* **Verification**: Container identity verified via `SO_PEERCRED`.
|
||||
- **Isolation**: SSH keys live on the host, not in the container.
|
||||
- **Least Privilege**: Proxy runs as `pulse-sensor-proxy` (no shell).
|
||||
- **Verification**: Container identity verified via `SO_PEERCRED`.
|
||||
|
||||
### 🏗️ Components
|
||||
1. **Pulse Backend**: Connects to Unix socket `/mnt/pulse-proxy/pulse-sensor-proxy.sock`.
|
||||
@@ -43,14 +43,14 @@ The agent runs `sensors -j` locally and reports temperatures directly to Pulse.
|
||||
|
||||
### 🔒 Key Restrictions
|
||||
SSH keys deployed to nodes are locked down:
|
||||
```
|
||||
```text
|
||||
command="sensors -j",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
|
||||
```
|
||||
|
||||
### 🚦 Rate Limiting
|
||||
* **Per Peer**: ~12 req/min.
|
||||
* **Concurrency**: Max 2 parallel requests per peer.
|
||||
* **Global**: Max 8 concurrent requests.
|
||||
- **Per Peer**: ~12 req/min.
|
||||
- **Concurrency**: Max 2 parallel requests per peer.
|
||||
- **Global**: Max 8 concurrent requests.
|
||||
|
||||
### 📝 Auditing
|
||||
All requests logged to system journal:
|
||||
@@ -61,6 +61,5 @@ Logs include: `uid`, `pid`, `method`, `node`, `correlation_id`.
|
||||
|
||||
### Related Docs
|
||||
|
||||
- Sensor proxy hardening: `docs/security/SENSOR_PROXY_HARDENING.md`
|
||||
- Network segmentation: `docs/security/SENSOR_PROXY_NETWORK.md`
|
||||
- AppArmor/Seccomp: `docs/security/SENSOR_PROXY_APPARMOR.md`
|
||||
- Unified Agent Security: [`docs/AGENT_SECURITY.md`](../AGENT_SECURITY.md)
|
||||
- Repository Security Policy: [`/SECURITY.md`](../../SECURITY.md)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This `frontend-modern` directory is **AUTO-GENERATED** during builds.
|
||||
|
||||
## The REAL frontend location is:
|
||||
## The REAL frontend location is
|
||||
### `/opt/pulse/frontend-modern`
|
||||
|
||||
## Why does this exist?
|
||||
@@ -14,10 +14,10 @@ This `frontend-modern` directory is **AUTO-GENERATED** during builds.
|
||||
- **YOUR CHANGES WILL BE LOST** on the next build
|
||||
- The Makefile deletes and recreates this directory
|
||||
|
||||
## How to edit frontend code:
|
||||
## How to edit frontend code
|
||||
1. Edit files in `/opt/pulse/frontend-modern/src/`
|
||||
2. The dev server (port 7655) will hot-reload
|
||||
3. When building for production, the Makefile copies it here
|
||||
|
||||
---
|
||||
This file exists to prevent confusion. The directory structure is intentional and required by Go's limitations.
|
||||
This file exists to prevent confusion. The directory structure is intentional and required by Go's limitations.
|
||||
|
||||
@@ -19,4 +19,4 @@ Go's `//go:embed` directive has limitations:
|
||||
2. Cannot follow symbolic links
|
||||
3. Must embed files within the Go module
|
||||
|
||||
This is a known Go limitation and our structure works around it.
|
||||
This is a known Go limitation and our structure works around it.
|
||||
|
||||
@@ -13,7 +13,7 @@ This guide will help you get the update integration tests running quickly.
|
||||
```bash
|
||||
cd tests/integration
|
||||
./scripts/setup.sh
|
||||
```
|
||||
```text
|
||||
|
||||
This will:
|
||||
- Install npm dependencies
|
||||
@@ -85,11 +85,11 @@ npm run docker:rebuild
|
||||
|
||||
While the test environment is running:
|
||||
|
||||
- **Pulse UI**: http://localhost:7655
|
||||
- **Mock GitHub API**: http://localhost:8080
|
||||
- **Pulse UI**: <http://localhost:7655>
|
||||
- **Mock GitHub API**: <http://localhost:8080>
|
||||
- **Health checks**:
|
||||
- http://localhost:7655/api/health
|
||||
- http://localhost:8080/health
|
||||
- <http://localhost:7655/api/health>
|
||||
- <http://localhost:8080/health>
|
||||
|
||||
## Viewing Test Results
|
||||
|
||||
@@ -175,7 +175,7 @@ See `.github/workflows/test-updates.yml` for CI configuration.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
```text
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────┐
|
||||
│ Playwright │────▶│ Pulse Server │────▶│ Mock GitHub API │
|
||||
│ (Browser UI) │ │ (Test Instance) │ │ (Controlled │
|
||||
@@ -216,4 +216,4 @@ test('my new test', async ({ page }) => {
|
||||
- Check the [main README](./README.md) for detailed information
|
||||
- Review existing test files for examples
|
||||
- Check Docker logs for service issues
|
||||
- Review Playwright documentation: https://playwright.dev
|
||||
- Review Playwright documentation: <https://playwright.dev>
|
||||
|
||||
@@ -4,7 +4,7 @@ End-to-end Playwright tests that validate critical user flows against a running
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
```text
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────┐
|
||||
│ Playwright │────▶│ Pulse Server │────▶│ Mock GitHub API │
|
||||
│ (Browser UI) │ │ (Test Instance) │ │ (Controlled │
|
||||
|
||||
Reference in New Issue
Block a user