Guardian is an access-control layer for Plex Media Server. It polls the Plex sessions API, matches each stream against per-user and per-device policy, and terminates the sessions that fail.
Warning
Looking for a maintainer. Reach out in Discussions.
Do not expose Guardian directly to the internet. Run it on a LAN, behind a VPN, or behind a reverse proxy with SSO.
| Area | Capabilities |
|---|---|
| Access control | Approve, reject or hold devices; global default plus per-user overrides; LAN/WAN and CIDR allowlists over IPv4 and IPv6; weekly time schedules; time-limited temporary grants |
| Limits | Global and per-user concurrent stream caps, with an option to exclude devices on a temporary grant |
| Monitoring | Live Plex and Plexamp sessions, device fingerprints, stream quality and progress, searchable session history |
| Notifications | SMTP email, Apprise (100+ services) and in-app alerts for new devices, blocks, location changes and user notes |
| Administration | Settings export/import, automatic cleanup of inactive devices, CLI recovery scripts |
| User portal | Plex users sign in to see their own devices, the policies that apply to them, and to leave notes on rejected devices |
- A reachable Plex Media Server and a Plex authentication token
- Docker with Compose, or Node.js to run from source
mkdir -p guardian && cd guardian
curl -o docker-compose.yml https://raw.githubusercontent.com/HydroshieldMKII/Guardian/main/docker-compose.example.yml
docker compose up -dThe web UI listens on port 3000 by default
git clone https://github.com/HydroshieldMKII/Guardian.git
cd Guardian
docker compose -f docker-compose.dev.yml up -d --buildUnder Docker → Compose, create a stack from docker-compose.example.yml, adjust the volume and port, and deploy.
| Variable | Default | Purpose |
|---|---|---|
TRUST_PROXY_HOPS |
1 |
Number of proxies in front of Guardian. Determines which address in X-Forwarded-For is treated as the client. |
APP_URL |
unset | Public address Guardian is reached on, for example https://guardian.example.com. Used to build password reset links. Required for password resets; ignored otherwise. |
DATABASE_PATH |
/app/data/plex-guard.db |
SQLite database file. |
Important
Export your settings first: Settings → Admin Tools → Export Settings.
docker compose pull && docker compose up -dLost admin access
docker compose exec guardian node backend/src/scripts/list-admins.js
docker compose exec guardian node backend/src/scripts/update-admin.js "USERNAME" "NEW_PASSWORD"Locked out by captcha
docker compose exec guardian node backend/src/scripts/disable-captcha.jsCannot connect to Plex — check that the server is reachable from the container, the token is valid, and that SSL settings match the server.
Notifications not arriving — use the test buttons in Settings, then check credentials and spam filtering.
Reset emails not arriving — confirm SMTP works with the test button, confirm APP_URL is set, and confirm the admin account has an email address.
Otherwise, open an issue.
cd backend && npm ci && npm run start:dev # port 3001
cd frontend && npm ci && npm run dev # port 3000Run before opening a pull request:
(cd backend && npm run lint:ci && npm run typecheck && npm run test:cov && npm run build)
(cd frontend && npm run typecheck && npm run test:cov && npm run build)Open an issue with the bug or feature template, or a pull request with the checklist filled in. Report security issues through a private advisory, not a public issue.
Released under the PolyForm Noncommercial License 1.0.0.








