For isolated networks - no public domain, no outbound internet, restricted connectivity.

Browsers require trusted HTTPS for camera/mic via WebRTC. Self-signed certs work but show warnings. For a clean setup, generate a private CA and distribute it to clients.

Generate Private CA and Server Certificate

Modern browsers require Subject Alternative Names (SANs) on certificates. The installer handles this automatically.

The bedrud install command generates self-signed certificates with proper SANs for the given IPs and domains:

sudo bedrud install --tls --ip YOUR_SERVER_IP

To also include a domain name:

sudo bedrud install --tls --ip YOUR_SERVER_IP --domain your.domain.com

Option 2: Manual Certificate Generation

If the installer’s built-in generation doesn’t fit your workflow, add -addext flags to the openssl commands.

Bedrud generates Ed25519 keys by default (PKCS8 format, ~128-bit security, deterministic signatures, 32-byte public keys), configurable to ECDSA P256 or RSA via the certAlgorithm config field or --cert-algorithm CLI flag. Choose the key type that matches your environment:

openssl genpkey -algorithm ed25519 -out ca.key
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/CN=Bedrud Internal CA"
 
openssl genpkey -algorithm ed25519 -out server.key
openssl req -new -key server.key -out server.csr \
  -subj "/CN=<your-server-ip-or-hostname>" \
  -addext "subjectAltName=IP:YOUR_SERVER_IP"
openssl x509 -req -days 1825 -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt \
  -addext "subjectAltName=IP:YOUR_SERVER_IP"
 
sudo ./bedrud install --tls --cert server.crt --key server.key --ip YOUR_SERVER_IP

ECDSA P256 (alternative)

openssl ecparam -genkey -name prime256v1 -out ca.key
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/CN=Bedrud Internal CA"
 
openssl ecparam -genkey -name prime256v1 -out server.key
openssl req -new -key server.key -out server.csr \
  -subj "/CN=<your-server-ip-or-hostname>" \
  -addext "subjectAltName=IP:YOUR_SERVER_IP"
openssl x509 -req -days 1825 -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt \
  -addext "subjectAltName=IP:YOUR_SERVER_IP"
 
sudo ./bedrud install --tls --cert server.crt --key server.key --ip YOUR_SERVER_IP

RSA (legacy compatibility, larger keys)

openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -subj "/CN=Bedrud Internal CA"
 
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
  -subj "/CN=<your-server-ip-or-hostname>" \
  -addext "subjectAltName=IP:YOUR_SERVER_IP"
openssl x509 -req -days 365 -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt \
  -addext "subjectAltName=IP:YOUR_SERVER_IP"
 
sudo ./bedrud install --tls --cert server.crt --key server.key --ip YOUR_SERVER_IP

HTTP Listener Port

When TLS is enabled, Bedrud also starts an HTTP listener (default port 80) for bots and local access. Ports below 1024 require root on Linux.

TURN/TLS Auto-Configuration

When server TLS is enabled (via the installer or server.enableTLS: true), the embedded LiveKit process automatically generates a temporary config with TURN/TLS settings. The server’s TLS certificate is reused for TURN/TLS on port 5349. The TURN domain is auto-set from server.host, UDP port 3478 is configured for TURN/STUN, and relative certFile/keyFile paths are resolved to absolute paths before being passed to LiveKit. No additional configuration is needed.

For custom TURN settings (separate domain, different cert, port overrides), provide a LiveKit YAML config file via livekit.configPath in config.yaml or the LIVEKIT_CONFIG_PATH environment variable.

Non-root setups — set an unprivileged port in /etc/bedrud/config.yaml:

server:
  httpPort: "8080"

Or via environment variable:

export SERVER_HTTP_PORT=8080

Alternatively, grant the binary permission to bind low ports:

sudo setcap 'cap_net_bind_service=+ep' $(which bedrud)

setcap must be re-run after each binary update (reinstall, upgrade, new build).

Add CA to Client Trust Stores

Distribute ca.crt to all client machines:

Windows

certmgr.msc  # Right-click ca.crt → Install Certificate → Trusted Root CAs

macOS

sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain ca.crt

Linux (Debian/Ubuntu)

sudo cp ca.crt /usr/local/share/ca-certificates/bedrud-ca.crt
sudo update-ca-certificates

Linux (Arch/Fedora)

sudo cp ca.crt /etc/pki/ca-trust/source/anchors/bedrud-ca.crt
sudo update-ca-trust

Distributing the Certificate

After enabling TLS, clients can fetch the server’s PEM certificate directly via the API:

curl -o bedrud-cert.pem https://YOUR_SERVER_IP/api/cert

This endpoint returns the server certificate currently in use. Combine with the CA distribution steps above for a complete trusted setup.

Restart browsers, then open https://YOUR_SERVER_IP (replace with the server’s actual IP address, e.g. 192.168.1.100). After restarting, the certificate will be trusted and camera/microphone access will work without warnings.

Troubleshooting

ProblemFix
Browser still warns certificate untrustedClear browser cache, restart browser after CA install
Camera/mic blockedVerify CA is in Trusted Root CAs, not intermediate
Certificate expiredRun sudo bedrud cert renew to regenerate (auto-renewal every 24h at 09:00)
CN mismatchModern browsers ignore the CN field — SAN is authoritative. Use the installer’s built-in cert generation (recommended) or add -addext 'subjectAltName=...' to the openssl command
Missing SANsModern browsers ignore the CN field. Use the installer’s built-in cert generation (recommended) or add -addext 'subjectAltName=...' to the openssl command

See also