Self-hosted Plex dashboard with real-time monitoring, stats, library browsing, and notifications.
208
A self-hosted Plex media server dashboard with real-time stream monitoring, per-user watch statistics, library browsing, trend analysis, server health monitoring, and push notifications. Cinema-themed dark UI with PWA support.
1. Create a project directory:
mkdir StreamPulse && cd StreamPulse
2. Create a docker-compose.yml:
services:
streampulse:
image: playeronegameover/streampulse:latest
container_name: streampulse
restart: unless-stopped
ports:
- "3333:3333"
volumes:
- streampulse-data:/app/database
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 3333
LOG_LEVEL: info
TZ: UTC # change to your timezone
SESSION_DRIVER: cookie
APP_KEY: ${APP_KEY}
volumes:
streampulse-data:
3. Create a .env file alongside your docker-compose.yml:
APP_KEY=your-secret-key-here
Generate a secure key with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
4. Start:
docker compose up -d
Migrations run automatically on startup.
5. Open: http://your-server-ip:3333
Sign in with your Plex account. The first user to log in becomes the admin. After login, connect your Plex server in the setup wizard.
docker compose pull
docker compose up -d
| Variable | Required | Default | Description |
|---|---|---|---|
APP_KEY | ✅ | - | Encryption secret. Generate with openssl rand -hex 32 |
NODE_ENV | ✅ | - | Set to production |
HOST | ✅ | - | Set to 0.0.0.0 |
PORT | ✅ | 3333 | HTTP port |
LOG_LEVEL | ✅ | info | fatal error warn info debug trace |
SESSION_DRIVER | ✅ | cookie | Set to cookie |
TZ | - | system | Timezone, e.g. UTC, Europe/London, America/New_York |
PLEX_CLIENT_ID | - | auto-generated | Fixed Plex client identifier. Auto-generated if omitted |
Plex server configuration is done via the Setup page after first login (stored in the database, not environment variables).
| Setting | Description |
|---|---|
| Plex Server | Select which Plex server to monitor from your linked Plex account. Connection details are stored automatically |
Screening mode settings are configurable via the settings panel on the Screening page:
| Setting | Description |
|---|---|
| Selected Users | Filter the recently-added carousel to specific Plex users |
| Selected Libraries | Filter the recently-added carousel to specific library sections |
| Display Duration | How long each item is shown in the carousel (30-300 seconds, default 30) |
| PIN Code | Optional 6-digit PIN required to exit screening mode |
The SQLite database is stored at /app/database/streampulse.sqlite3 inside the container. The compose file maps this to a named volume (streampulse-data) so data survives container restarts and rebuilds.
Backup:
docker cp streampulse:/app/database/streampulse.sqlite3 ./backup.sqlite3
Restore:
docker compose down
docker run --rm -v streampulse-data:/data -v $(pwd):/backup alpine cp /backup/backup.sqlite3 /data/streampulse.sqlite3
docker compose up -d
The container needs network access to your Plex Media Server. If Plex runs on the same machine as Docker:
host.docker.internal (Docker 20.10+) or --network hosthost.docker.internalWhen configuring your Plex server in the setup wizard, enter the IP or hostname reachable from inside the container (not localhost unless using host networking).
Configure push notifications from the Notifications page (admin only). Supports multiple channels, each subscribing to specific events with optional filtering.
Channels: Discord, Slack, Pushover, Telegram, Gotify, ntfy, Webhook (with custom headers and full event payload)
Events:
Filters per channel: users, media types, location (LAN/WAN), libraries, concurrent stream threshold
StreamPulse uses Server-Sent Events (SSE) for real-time features. Your reverse proxy must not buffer SSE responses.
Nginx:
server {
listen 80;
server_name StreamPulse.example.com;
location / {
proxy_pass http://127.0.0.1:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
IIS (requires URL Rewrite + ARR modules):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Proxy to StreamPulse" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:3333/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
For IIS, also increase the ARR timeout to 300s and disable response buffering in Application Request Routing Cache - Server Proxy Settings.
| Area | Detail |
|---|---|
| Auth | Plex OAuth - users authenticate with their Plex account. Session-based with 30-day expiry |
| CSRF / XSS | Handled by @adonisjs/shield (CSRF tokens on all state-changing requests, CSP headers, X-Frame-Options: DENY, X-Content-Type-Options). All user-generated content HTML-escaped |
| SSRF | Image proxy validates paths against an allowlist, blocks traversal, enforces content-type and size limits |
| Cookies | HTTP-only, secure in production, SameSite lax |
| HSTS | Strict Transport Security enabled (180 days) |
| Secrets | Plex tokens and server access tokens excluded from JSON serialization |
| Admin routes | Setup, health, user management, and server management restricted to admin users only |
| Auth guard | All routes except /login and OAuth callback require an authenticated session |
StreamPulse is an independent project and is not affiliated with, endorsed by, or associated with Plex, Inc.
This software relies on third-party services and APIs, including the Plex Media Server API. Certain features may become temporarily or permanently unavailable if those dependencies change, become incompatible, or are discontinued for any technical or legal reason.
Media artwork, thumbnails, and metadata displayed within StreamPulse are retrieved from Plex and their upstream providers. These assets may be subject to copyright and remain the property of their respective rights holders.
This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the authors be liable for any claim, damages, or other liability arising from the use of this software.
Content type
Image
Digest
sha256:1e33985e9…
Size
123.3 MB
Last updated
5 months ago
docker pull playeronegameover/streampulse