SSL / HTTPS
Enable HTTPS for production deployments
Production should use HTTPS for APP_URL, EDGE_BASE_URL, and OAuth redirect URIs. Without it, browsers block secure cookies and OAuth providers reject redirect URIs.
Built-in HTTPS (Docker)
The fastest path for Docker installs:
# Point DNS A records for your-domain.com and edge.your-domain.com to this host first
cd nixstream
./install.sh --ssl your-domain.comThis:
- Generates a
docker/caddy/Caddyfilefor your domain - Starts Caddy on ports 80/443 with automatic Let's Encrypt
- Proxies
your-domain.comto nginx (Laravel) andedge.your-domain.comto nixstream-edge - Sets
APP_URL,FRONTEND_URL,EDGE_BASE_URL, andSESSION_SECURE_COOKIE=truein.env
Re-run ./install.sh after changing the domain, or edit .env and docker/caddy/Caddyfile manually.
Certificate issuance fails if DNS is not pointed at the server before Caddy starts. Wait for DNS propagation, then restart: docker compose -f docker-compose.yml -f docker-compose.ssl.yml --profile ssl restart caddy.
Why HTTPS matters
Admin panel sessions, OAuth (Vimeo, Drive, Dropbox), EDGE_BASE_URL, and share embeds on HTTPS sites all need HTTPS. RTMP ingest on 1935 does not; it is a separate TCP port.
Reverse proxy (recommended)
Place Caddy, Traefik, or Nginx in front of the Docker stack:
Internet to HTTPS on port 443, through your reverse proxy, to nixstream_nginx on port 80.Caddy example
your-domain.com {
reverse_proxy localhost:8080
}Caddy obtains Let's Encrypt certs for you. Point the DNS A record at the server, then start Caddy.
Traefik example
Label the nginx service with Traefik router rules and enable the Let's Encrypt resolver. Traefik picks up Docker containers on its own.
Host Nginx proxy
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}Certbot + Nginx
- Obtain certificates with Certbot on the host
- Mount certificates into the nginx container or terminate SSL on the host proxy
- Update
docker/nginx/default.conffor SSL listeners if terminating inside Docker - Set
APP_URL=https://your-domain.comin.env - Restart:
docker compose restart nginx app
sudo certbot certonly --nginx -d your-domain.comManual install
Configure SSL in your host Nginx virtual host pointing to core/public/:
root /var/www/nixstream/nixstream/public;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;See Manual Installation for the full Nginx vhost.
Environment updates
After enabling HTTPS, update:
APP_URL=https://your-domain.com
FRONTEND_URL=https://your-domain.com
EDGE_BASE_URL=https://edge.your-domain.com
SESSION_SECURE_COOKIE=trueOAuth redirect URIs inherit from APP_URL. Update provider consoles if the domain changed.
Clear config cache:
php artisan config:cacheCertificate renewal
Let's Encrypt certificates expire every 90 days. Certbot and Caddy renew them on a schedule. Verify renewal:
sudo certbot renew --dry-runHSTS (optional)
Add Strict-Transport-Security after confirming HTTPS works:
Strict-Transport-Security: max-age=31536000; includeSubDomainsMixed HTTP/HTTPS causes cookie and CORS issues with the admin panel. Use HTTPS end-to-end in production.
Troubleshooting
Redirect loop: check X-Forwarded-Proto on the proxy. OAuth redirect mismatch: APP_URL must match the provider console exactly. Mixed content: asset URLs need HTTPS. Untrusted cert: use Let's Encrypt or another public CA; self-signed certs fail in browsers.
Env vars after HTTPS: Environment Variables. OAuth callbacks: Integrations. Bare-metal vhost: Manual Installation.