We offer customization solutions and support ([email protected]) | Visit us on bitbyte3 for complete VOD solutions with apps.
NixStream
Guides

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

ContextMethod
Admin panelLaravel Sanctum (session via POST /api/login)
Client APIBearer token (API key from Settings)
Share linksToken-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_KEY

Best 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-KEY and 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:

SettingDefaultDescription
Require user or share-link authOffBind playback sessions to a viewer identity instead of anonymous bearer URLs
Max concurrent devices0 (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_id and a user epoch. Ban, password reset, or account deactivation bumps the epoch and invalidates all of that user's active sessions instantly (one Redis INCR, no key enumeration).
  • Share links and embeds (no login) get sessions stamped with link_id and 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-reset

Production hardening checklist

Before going live, confirm:

  • APP_DEBUG=false and APP_ENV=production
  • HTTPS enabled for APP_URL and EDGE_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_auth in 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 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.

On this page