Security
Security profiles, domain rules, geo restrictions, and API keys
NixStream has several layers for protecting content, admin access, and API integrations. Configure them in the admin panel under Settings > Security.
Authentication methods
| Context | Method |
|---|---|
| Admin panel | Laravel Sanctum (session via POST /api/login) |
| Client API | Bearer token (API key from Settings) |
| Share links | Token-based URL, optional password |
| Media (HLS, DASH, images, live) | Signed Edge URLs (nixstream-edge) with Redis TTL |
Each method is independent. Compromising a share link token does not grant admin or API access.
API keys
Generate keys in Settings > General. Keys are hashed with SHA-256 at rest and can't be retrieved after creation.
Pass the plain key in requests:
Authorization: Bearer YOUR_API_KEYBest practices:
- Generate separate keys for each integration
- Rotate keys periodically
- Revoke unused keys immediately
- Never commit keys to source control
Security profiles
Apply profiles to videos and live streams to control who can watch and where playback is allowed.
Domain allowlist
Restrict playback to approved domains. Useful for embed scenarios where you only want your own site to host the player.
Example: allow yourdomain.com and app.yourdomain.com. Playback from any other origin is blocked.
Geo rules
Allow or block specific countries. Helpful for licensing restrictions or compliance requirements.
Configure allowed and blocked country lists in the security profile editor.
Referrer checks
Validate the embedding page origin before serving the player. Adds a layer of protection against unauthorized embeds even if someone copies your embed code.
Edge media delivery
All VOD (HLS + DASH/MPD), images, thumbnail VTT, and live HLS are served by nixstream-edge, not Laravel public storage.
Docker install auto-starts Edge, shares Redis and EDGE_SIGNING_SECRET, and marks the Edge integration connected (Settings > Integrations).
Local storage
Local output disks require Edge to be connected. Without Edge, local media playback does not work.
AES-128 and signed tokens
- VOD HLS segments are always AES-128 encrypted at package time.
- Keys stay in the database and Redis playback sessions; the player never fetches keys.
- Edge strips
#EXT-X-KEYand decrypts segments for authorized signed requests. - DASH (
stream.mpd) is delivered under the same signed session.
AES-128 and signed tokens require Edge (or a CDN that supports them). Cloud object storage alone isn't enough. Pointing a public bucket or cdn_endpoint at S3/R2 doesn't provide signed-token or AES-128 protection.
Back up the database. Encryption keys aren't recoverable from ciphertext alone.
Playback authorization (optional)
By default, Edge uses bearer signed URLs: anyone with a valid playback URL can watch until the session expires (same model as S3/CloudFront signed URLs). Fine for many CDN-style deployments.
For stricter control, enable Require user or share-link auth in Settings > Integrations > Edge:
| Setting | Default | Description |
|---|---|---|
| Require user or share-link auth | Off | Bind playback sessions to a viewer identity instead of anonymous bearer URLs |
| Max concurrent devices | 0 (unlimited) | When auth is enabled, cap how many simultaneous playback sessions one user may hold (0 = no limit) |
When auth is enabled:
- Logged-in panel users get sessions stamped with
user_idand a user epoch. Ban, password reset, or account deactivation bumps the epoch and invalidates all of that user's active sessions instantly (one RedisINCR, no key enumeration). - Share links and embeds (no login) get sessions stamped with
link_idand a link epoch, so share playback still works without forcing login. Revoking a link invalidates its sessions the same way. - Mint caches are scoped per user or link so one viewer can't reuse another viewer's session.
When auth is disabled (default), behavior is unchanged: signed URLs work for any holder until Redis TTL expires.
Instant revocation triggers (when auth is enabled):
- Password change (self-service or admin reset)
- User deactivated or deleted
- Link epoch bump via
revokeLink()(for programmatic link takedown)
Per-device kick is available via the user_sessions Redis set when a device limit is configured; the oldest session is evicted when the cap is reached at mint time.
See Integrations, Edge for where to configure these options.
Role-based access
Team permissions use Spatie Permission with default roles:
- Admin: Full access including user management and API keys
- Manager: Content and analytics without user administration
- Editor: Upload and manage videos
Customize roles in config/acl.php. After changes, run:
php artisan permission:cache-resetProduction hardening checklist
Before going live, confirm:
-
APP_DEBUG=falseandAPP_ENV=production - HTTPS enabled for
APP_URLandEDGE_BASE_URL - Default admin password changed
- API keys generated only for active integrations
- Security profiles applied to published content
- Edge playback auth reviewed (
edge_require_user_authin Settings > Integrations > Edge) - RTMP port 1935 restricted if possible (allow only trusted encoder IPs)
- Database credentials are strong and not the defaults
- Regular backups configured (see backup guide)
- Server OS and Docker images kept updated
Share link security
Share links use random 40-character tokens. Password-protected links hash passwords with bcrypt. You can set expiration between 1 and 365 days.
Even with a valid share link, security profiles still apply. A password-protected link on a domain-restricted video will require both the password and a matching embed origin.