Documentation Updates: - Fix CORS documentation to reflect new secure defaults (no CORS by default) - Add API token management endpoints to API.md - Document CORS configuration in SECURITY.md - Update environment variable documentation with defaults - Add authentication variables (PULSE_PASSWORD, API_TOKEN, etc.) - Add troubleshooting for CORS and authentication issues - Remove outdated references to ALLOWED_ORIGINS=* - Clarify that CORS defaults to same-origin only All documentation now accurately reflects: - Security improvements from recent audit - New API token management features - Correct CORS behavior and configuration - Complete environment variable reference
6.7 KiB
Pulse Security
Smart Security Context (v4.3.2+)
Public Access Detection
Pulse automatically detects when it's being accessed from public networks:
- Private Networks: Local/RFC1918 addresses (192.168.x.x, 10.x.x.x, etc.)
- Public Networks: Any non-private IP address
- Stronger Warnings: Red alerts when accessed from public IPs without authentication
Trusted Networks Configuration
Define networks that don't require authentication:
# Environment variable (comma-separated CIDR blocks)
PULSE_TRUSTED_NETWORKS=192.168.1.0/24,10.0.0.0/24
# Or in systemd
sudo systemctl edit pulse-backend
[Service]
Environment="PULSE_TRUSTED_NETWORKS=192.168.1.0/24,10.0.0.0/24"
When configured:
- Access from trusted networks: No auth required
- Access from outside: Authentication enforced
- Useful for: Mixed home/remote access scenarios
Security Warning System
Pulse now includes a non-intrusive security warning system that helps you understand your security posture:
Security Score
Your instance receives a score from 0-5 based on:
- ✅ Credentials encrypted at rest (always enabled)
- ✅ Export/import protection
- ⚠️ Authentication enabled
- ⚠️ HTTPS connection
- ⚠️ Audit logging
Dismissing Warnings
If you're comfortable with your security setup, you can dismiss warnings:
- For 1 day - Reminder tomorrow
- For 1 week - Reminder next week
- Forever - Won't show again
To permanently disable all security warnings:
# Environment variable
PULSE_DISABLE_SECURITY_WARNINGS=true
Credential Security
- Storage: Encrypted at rest using AES-256-GCM (
/etc/pulse/nodes.enc) - Logs: Token values masked with
***in all outputs - API: Frontend receives only
hasToken: true, never actual values - Export: Requires API_TOKEN authentication to extract credentials
- Migration: Use passphrase-protected export/import (see Migration Guide)
Export/Import Protection
By default, configuration export/import is blocked for security. You have two options:
Option 1: Set API Token (Recommended)
# Using systemd (secure)
sudo systemctl edit pulse-backend
# Add:
[Service]
Environment="API_TOKEN=your-secure-token-here"
# Then restart:
sudo systemctl restart pulse-backend
# Docker
docker run -e API_TOKEN=your-token rcourtman/pulse:latest
Option 2: Allow Unprotected Export (Homelab)
# Using systemd
sudo systemctl edit pulse-backend
# Add:
[Service]
Environment="ALLOW_UNPROTECTED_EXPORT=true"
# Docker
docker run -e ALLOW_UNPROTECTED_EXPORT=true rcourtman/pulse:latest
Note: Never put API tokens or passwords in .env files! Use systemd environment variables or Docker secrets for sensitive data.
Security Features
Core Protection
- Encryption: All credentials encrypted at rest (AES-256-GCM)
- Export Protection: Exports always encrypted with passphrase
- Minimum Passphrase: 12 characters required for exports
- Security Tab: Check status in Settings → Security
Enterprise Security (When Authentication Enabled)
- CSRF Protection: All state-changing operations require CSRF tokens
- Rate Limiting:
- General API: 500 requests/minute
- Authentication: 10 attempts/minute
- Export/Import: 5 attempts/minute
- Account Lockout: Locks after 5 failed login attempts (15 minute cooldown)
- Session Management:
- Secure HttpOnly cookies
- 24-hour session expiry
- Session invalidation on password change
- Password Security: bcrypt hashing with cost 12
- Security Headers:
- Content-Security-Policy
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- X-XSS-Protection
- Audit Logging: All authentication events logged
What's Encrypted in Exports
- Node credentials (passwords, API tokens)
- PBS credentials
- Email settings passwords
What's NOT Encrypted
- Node hostnames and IPs
- Threshold settings
- General configuration
Authentication
Pulse supports multiple authentication methods that can be used independently or together:
Password Authentication
Protect your Pulse instance with a password. Passwords are automatically hashed with bcrypt for security.
# Using systemd
sudo systemctl edit pulse-backend
# Add:
[Service]
Environment="PULSE_PASSWORD=your-secure-password"
# Docker
docker run -e PULSE_PASSWORD=your-password rcourtman/pulse:latest
Features
- Web UI login required when password is set
- Change password from Settings → Security
- Passwords hashed with bcrypt (cost 12)
- Session-based authentication with secure HttpOnly cookies
- 24-hour session expiry
- CSRF protection for all state-changing operations
- Session invalidation on password change
API Token Authentication
For programmatic access and automation. Tokens can be generated and managed via the web UI.
# Using systemd
sudo systemctl edit pulse-backend
# Add:
[Service]
Environment="API_TOKEN=your-secure-token"
# Docker
docker run -e API_TOKEN=your-token rcourtman/pulse:latest
Token Management (Settings → Security → API Token)
- Generate new tokens via web UI when authenticated
- View existing token anytime (authenticated users only)
- Regenerate tokens without disrupting service
- Delete tokens to disable API access
Usage
# Include token in X-API-Token header
curl -H "X-API-Token: your-token" http://localhost:7655/api/health
Auto-Registration Security
Default Mode (Homelab Friendly)
- Nodes can auto-register without authentication
- Suitable for trusted networks
- Setup scripts work without additional configuration
Secure Mode
- Require API token for all operations
- Protects auto-registration endpoint
- Enable by setting API_TOKEN environment variable
CORS (Cross-Origin Resource Sharing)
By default, Pulse only allows same-origin requests (no CORS headers). This is the most secure configuration.
Configuring CORS for External Access
If you need to access Pulse API from a different domain:
# Docker
docker run -e ALLOWED_ORIGINS="https://app.example.com" rcourtman/pulse:latest
# systemd
sudo systemctl edit pulse-backend
[Service]
Environment="ALLOWED_ORIGINS=https://app.example.com"
# Multiple origins (comma-separated)
ALLOWED_ORIGINS="https://app.example.com,https://dashboard.example.com"
# Development mode (allows localhost)
PULSE_DEV=true
Security Note: Never use ALLOWED_ORIGINS=* in production as it allows any website to access your API.
Troubleshooting
Export blocked? Set API_TOKEN or ALLOW_UNPROTECTED_EXPORT=true Rate limited? Wait 1 minute and try again Can't login? Check PULSE_PASSWORD environment variable API access denied? Verify API_TOKEN is correct CORS errors? Configure ALLOWED_ORIGINS for your domain