docs: align sensor proxy config with current defaults

This commit is contained in:
rcourtman 2025-11-20 12:40:01 +00:00
parent 6ca543beb6
commit 3f10c97c4e
4 changed files with 105 additions and 80 deletions

View file

@ -1,60 +1,55 @@
# Pulse Sensor Proxy Configuration
# This file is optional. If not provided, the proxy will use sensible defaults.
# This file is optional. Defaults are safe for most installs; use it when you
# need to override CIDR allow lists, HTTP settings, or rate limits.
# Network Configuration
# Specify which networks are allowed to connect to the proxy
# If not specified, the proxy will auto-detect host IP addresses
# Network configuration
# The installer auto-detects host CIDRs if this is empty.
allowed_source_subnets:
- "127.0.0.1/32" # Localhost
- "192.168.0.0/24" # Local network
- "127.0.0.1/32"
- "192.168.0.0/24"
# Peer Authorization
# Specify which UIDs/GIDs are allowed to connect
# A peer is authorized when its UID OR GID matches one of these entries
# Required when running Pulse in a container (use mapped UID/GID from container)
allowed_peer_uids: [100999] # Legacy format; grants all capabilities unless overridden below
allowed_peer_gids: [100996]
# Preferred format with explicit capabilities (read, write, admin)
# Peer authorization
# Preferred capability-based format (legacy UID/GID lists still work)
allowed_peers:
- uid: 0
capabilities: [read, write, admin] # Host root retains full control
- uid: 100999
capabilities: [read] # Container peer limited to read-only RPCs
capabilities: [read] # Container peer limited to read-only RPCs
allowed_peer_uids: []
allowed_peer_gids: []
require_proxmox_hostkeys: false # Enforce Proxmox-known host keys before falling back to ssh-keyscan
# ID-Mapped Root Authentication
# Allow connections from ID-mapped root users (for LXC containers)
# ID-mapped root + namespaced users (LXC)
allow_idmapped_root: true
allowed_idmap_users:
- root
# Metrics Server
# Address for Prometheus metrics endpoint
metrics_address: "127.0.0.1:9127"
# Logging and limits
log_level: info
metrics_address: "default" # 127.0.0.1:9127 unless set otherwise
read_timeout: 5s
write_timeout: 10s
max_ssh_output_bytes: 1048576 # 1 MiB
require_proxmox_hostkeys: false # Only trust hosts in PVE known_hosts when true
# Limit SSH output size (bytes) when fetching temperatures
max_ssh_output_bytes: 1048576 # 1 MiB
# Allow list persistence (managed by installer/control-plane/CLI)
allowed_nodes_file: "/etc/pulse-sensor-proxy/allowed_nodes.yaml"
strict_node_validation: false # Set true to require allow list entries
# Rate Limiting (Optional)
# Control how frequently peers can make requests to prevent abuse
# Adjust these values based on your deployment size:
# - Small (1-3 nodes): Use defaults (1000ms, burst 5)
# - Medium (4-10 nodes): 500ms, burst 10
# - Large (10-20 nodes): 250ms, burst 20
# - Very Large (30+ nodes): 100ms, burst 30-50
#
# Formula: To poll all nodes in one cycle, set burst >= node_count
# For optimal performance: per_peer_interval_ms = (polling_interval_ms / node_count)
# Example: 10 second polling with 30 nodes = 10000ms / 30 ≈ 300ms interval
# Rate limiting (per calling UID)
rate_limit:
per_peer_interval_ms: 1000 # Minimum milliseconds between requests per peer (1000ms = 1 qps = 60 requests/min)
per_peer_burst: 5 # Number of requests allowed in a burst (supports up to 5 simultaneous requests)
per_peer_interval_ms: 1000 # 1 request per second
per_peer_burst: 5 # Allow burst of 5
# Default values if not specified:
# per_peer_interval_ms: 1000 (1 second = 1 qps = 60 requests/min)
# per_peer_burst: 5
#
# Security note: Lower intervals increase throughput but also increase exposure
# to potential abuse. For production, keep interval >= 100ms unless necessary.
# HTTPS mode (for remote nodes)
http_enabled: false
http_listen_addr: ":8443"
http_tls_cert: "/etc/pulse-sensor-proxy/tls/server.crt"
http_tls_key: "/etc/pulse-sensor-proxy/tls/server.key"
http_auth_token: "" # Populated by installer; keep secret
# Control-plane sync (keeps allowed_nodes.yaml updated automatically)
pulse_control_plane:
url: "https://pulse.example.com:7655"
token_file: "/etc/pulse-sensor-proxy/.pulse-control-token"
refresh_interval: 60
insecure_skip_verify: false

View file

@ -726,8 +726,9 @@ python3 -c "import yaml; yaml.safe_load(open('/tmp/test-config.yaml'))"
/tmp/pulse-sensor-proxy version
# Install
sudo install -m 0755 -o root -g root /tmp/pulse-sensor-proxy /usr/local/bin/pulse-sensor-proxy
sudo install -D -m 0755 -o root -g root /tmp/pulse-sensor-proxy /opt/pulse/sensor-proxy/bin/pulse-sensor-proxy
```
The installer and cleanup routines now expect the binary under `/opt/pulse/sensor-proxy/bin` to support read-only `/usr` mounts while keeping self-heal paths consistent.
2. **Install hardened systemd unit:**
```bash

View file

@ -224,8 +224,8 @@ When you need to provision the proxy yourself (for example via your own automati
1. **Install the binary**
```bash
curl -L https://github.com/rcourtman/Pulse/releases/download/<TAG>/pulse-sensor-proxy-linux-amd64 \
-o /usr/local/bin/pulse-sensor-proxy
chmod 0755 /usr/local/bin/pulse-sensor-proxy
-o /tmp/pulse-sensor-proxy
install -D -m 0755 /tmp/pulse-sensor-proxy /opt/pulse/sensor-proxy/bin/pulse-sensor-proxy
```
Use the arm64/armv7 artefact if required.
@ -242,18 +242,23 @@ When you need to provision the proxy yourself (for example via your own automati
```
4. **(Optional) Add `/etc/pulse-sensor-proxy/config.yaml`**
Only needed if you want explicit subnet/metrics settings; otherwise the proxy auto-detects host CIDRs.
Only needed if you want explicit subnet/metrics settings; otherwise the proxy auto-detects host CIDRs and registers with Pulse automatically.
```yaml
allowed_source_subnets:
- 192.168.1.0/24
metrics_address: 0.0.0.0:9127 # use "disabled" to switch metrics off
http_enabled: true
allowed_nodes_file: /etc/pulse-sensor-proxy/allowed_nodes.yaml
http_enabled: true # only when polling remote hosts over HTTPS
http_listen_addr: ":8443"
http_tls_cert: /etc/pulse-sensor-proxy/tls/server.crt
http_tls_key: /etc/pulse-sensor-proxy/tls/server.key
pulse_control_plane:
url: https://pulse.example.com:7655
token_file: /etc/pulse-sensor-proxy/.pulse-control-token
refresh_interval: 60
```
Provide `http_auth_token` (32+ bytes of random data) and ensure the TLS files exist. Tokens configured here must match the value saved in Pulse for each node.
Provide `http_auth_token` (32+ bytes of random data) only when you cannot register through Pulse, and ensure the TLS files exist. Allowed nodes live in `/etc/pulse-sensor-proxy/allowed_nodes.yaml`—use `pulse-sensor-proxy config set-allowed-nodes` instead of editing it by hand.
5. **Install the hardened systemd unit**
Copy the unit from `scripts/install-sensor-proxy.sh` or create `/etc/systemd/system/pulse-sensor-proxy.service` with:
@ -267,16 +272,21 @@ When you need to provision the proxy yourself (for example via your own automati
User=pulse-sensor-proxy
Group=pulse-sensor-proxy
WorkingDirectory=/var/lib/pulse-sensor-proxy
ExecStart=/usr/local/bin/pulse-sensor-proxy
ExecStartPre=/opt/pulse/sensor-proxy/bin/pulse-sensor-proxy config validate --config /etc/pulse-sensor-proxy/config.yaml
ExecStart=/opt/pulse/sensor-proxy/bin/pulse-sensor-proxy --config /etc/pulse-sensor-proxy/config.yaml
Restart=on-failure
RestartSec=5s
RuntimeDirectory=pulse-sensor-proxy
RuntimeDirectoryMode=0775
RuntimeDirectoryPreserve=yes
LogsDirectory=pulse/sensor-proxy
LogsDirectoryMode=0750
UMask=0007
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/var/lib/pulse-sensor-proxy
ReadWritePaths=-/run/corosync
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
@ -288,7 +298,7 @@ When you need to provision the proxy yourself (for example via your own automati
LockPersonality=true
RemoveIPC=true
RestrictSUIDSGID=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=true
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
@ -814,8 +824,8 @@ If you can't run the installer script, create the configuration manually:
**1. Download binary:**
```bash
curl -L https://github.com/rcourtman/Pulse/releases/latest/download/pulse-sensor-proxy-linux-amd64 \
-o /usr/local/bin/pulse-sensor-proxy
chmod 0755 /usr/local/bin/pulse-sensor-proxy
-o /tmp/pulse-sensor-proxy
install -D -m 0755 /tmp/pulse-sensor-proxy /opt/pulse/sensor-proxy/bin/pulse-sensor-proxy
```
**2. Create service user:**
@ -834,16 +844,18 @@ install -d -o pulse-sensor-proxy -g pulse-sensor-proxy -m 0755 /etc/pulse-sensor
**4. Create config (optional, for Docker):**
```yaml
# /etc/pulse-sensor-proxy/config.yaml
allowed_nodes_file: /etc/pulse-sensor-proxy/allowed_nodes.yaml
allowed_peer_uids: [1000] # Docker container UID
allow_idmapped_root: true
allowed_idmap_users:
- root
```
Allowed nodes live in `/etc/pulse-sensor-proxy/allowed_nodes.yaml`; change them via `pulse-sensor-proxy config set-allowed-nodes` so the proxy can lock and validate the file safely. Control-plane settings are added automatically when you register via Pulse, but you can supply them manually if you cannot reach the API (`pulse_control_plane.url`, `.token_file`, `.refresh_interval`).
**5. Install systemd service:**
```bash
# Download from: https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh
# Extract the systemd unit from lines 630-730, or see systemd unit in installer script
# Extract the systemd unit from the installer (ExecStartPre/ExecStart use /opt/pulse/sensor-proxy/bin)
systemctl daemon-reload
systemctl enable --now pulse-sensor-proxy
```
@ -856,48 +868,57 @@ ls -l /run/pulse-sensor-proxy/pulse-sensor-proxy.sock
#### Configuration File Format
The proxy reads `/etc/pulse-sensor-proxy/config.yaml` (optional):
The proxy reads `/etc/pulse-sensor-proxy/config.yaml` plus an allow-list in `/etc/pulse-sensor-proxy/allowed_nodes.yaml`:
```yaml
# Allowed UIDs that can connect to the socket (default: [0] = root only)
allowed_peer_uids: [0, 1000] # Allow root and UID 1000 (typical Docker)
allowed_source_subnets:
- 192.168.1.0/24
- 10.0.0.0/8
# Allowed GIDs that can connect to the socket (peer is accepted when UID OR GID matches)
allowed_peer_gids: [0]
# Preferred capability-based allow-list (uids inherit read/write/admin as specified)
# Capability-based access control (legacy UID/GID lists still work)
allowed_peers:
- uid: 0
capabilities: [read, write, admin]
- uid: 1000
capabilities: [read]
# Require host keys sourced from the Proxmox cluster known_hosts file (no ssh-keyscan fallback)
require_proxmox_hostkeys: false
# Allow ID-mapped root from LXC containers
allowed_peer_uids: []
allowed_peer_gids: []
allow_idmapped_root: true
allowed_idmap_users:
- root
# Source subnets for SSH key restrictions (auto-detected if not specified)
allowed_source_subnets:
- 192.168.1.0/24
- 10.0.0.0/8
log_level: info
metrics_address: default
read_timeout: 5s
write_timeout: 10s
max_ssh_output_bytes: 1048576
require_proxmox_hostkeys: false
# Allow list persistence (managed by installer/control-plane/CLI)
allowed_nodes_file: /etc/pulse-sensor-proxy/allowed_nodes.yaml
strict_node_validation: false
# Rate limiting (per calling UID)
rate_limit:
per_peer_interval_ms: 1000 # 1 request per second
per_peer_burst: 5 # Allow burst of 5
per_peer_interval_ms: 1000
per_peer_burst: 5
# Metrics endpoint (default: 127.0.0.1:9127)
metrics_address: 127.0.0.1:9127 # or "disabled"
# HTTPS mode (for remote nodes)
http_enabled: false
http_listen_addr: ":8443"
http_tls_cert: /etc/pulse-sensor-proxy/tls/server.crt
http_tls_key: /etc/pulse-sensor-proxy/tls/server.key
http_auth_token: "" # Populated during registration
# Maximum bytes accepted from SSH sensor output (default 1 MiB)
max_ssh_output_bytes: 1048576
# Control-plane sync (keeps allowed_nodes.yaml updated)
pulse_control_plane:
url: https://pulse.example.com:7655
token_file: /etc/pulse-sensor-proxy/.pulse-control-token
refresh_interval: 60
insecure_skip_verify: false
```
`allowed_peers` lets you scope access: grant the container UID only `read` to limit it to temperature fetching, while host-side automation can receive `[read, write, admin]`. Legacy `allowed_peer_uids`/`gids` remain for backward compatibility and imply full capabilities.
`allowed_nodes.yaml` is the source of truth for valid nodes. Avoid editing it directly—use `pulse-sensor-proxy config set-allowed-nodes` so the proxy can lock, dedupe, and write atomically. `allowed_peers` scopes socket access; legacy UID/GID lists remain for backward compatibility and imply full capabilities.
**Environment Variable Overrides:**
@ -909,7 +930,15 @@ PULSE_SENSOR_PROXY_ALLOWED_SUBNETS=192.168.1.0/24,10.0.0.0/8
# Allow/disallow ID-mapped root (overrides config file)
PULSE_SENSOR_PROXY_ALLOW_IDMAPPED_ROOT=true
# HTTP listener controls
PULSE_SENSOR_PROXY_HTTP_ENABLED=true
PULSE_SENSOR_PROXY_HTTP_ADDR=":8443"
PULSE_SENSOR_PROXY_HTTP_TLS_CERT=/etc/pulse-sensor-proxy/tls/server.crt
PULSE_SENSOR_PROXY_HTTP_TLS_KEY=/etc/pulse-sensor-proxy/tls/server.key
PULSE_SENSOR_PROXY_HTTP_AUTH_TOKEN="$(cat /etc/pulse-sensor-proxy/.http-auth-token)"
```
Additional overrides include `PULSE_SENSOR_PROXY_ALLOWED_PEER_UIDS`, `PULSE_SENSOR_PROXY_ALLOWED_PEER_GIDS`, `PULSE_SENSOR_PROXY_ALLOWED_NODES`, `PULSE_SENSOR_PROXY_READ_TIMEOUT`, `PULSE_SENSOR_PROXY_WRITE_TIMEOUT`, `PULSE_SENSOR_PROXY_METRICS_ADDR`, and `PULSE_SENSOR_PROXY_STRICT_NODE_VALIDATION`.
Example systemd override:
```ini
@ -1344,8 +1373,8 @@ test -S /run/pulse-sensor-proxy/pulse-sensor-proxy.sock && echo "Socket OK" || e
**Proxy Service Won't Start:**
1. Check logs: `journalctl -u pulse-sensor-proxy -n 50`
2. Verify binary exists: `ls -l /usr/local/bin/pulse-sensor-proxy`
3. Test manually: `/usr/local/bin/pulse-sensor-proxy --version`
2. Verify binary exists: `ls -l /opt/pulse/sensor-proxy/bin/pulse-sensor-proxy`
3. Test manually: `/opt/pulse/sensor-proxy/bin/pulse-sensor-proxy --version`
4. Check socket directory: `ls -ld /var/run`
### Future Improvements

View file

@ -232,7 +232,7 @@ journalctl -u pulse-sensor-proxy -n 100
journalctl -u pulse-sensor-proxy | grep -i "validation\|corrupt\|duplicate"
# Try starting in foreground for better errors
sudo -u pulse-sensor-proxy /usr/local/bin/pulse-sensor-proxy
sudo -u pulse-sensor-proxy /opt/pulse/sensor-proxy/bin/pulse-sensor-proxy # legacy installs: /usr/local/bin/pulse-sensor-proxy
```
**Fix:**