This guide covers installing the Bedrud server (API, web UI, WebRTC media server) on a Linux server. For desktop and mobile client apps, see Client Installation.
Prerequisites
| Requirement | Details |
|---|---|
| Operating system | Debian 12+, Ubuntu 22.04+, Arch Linux (rolling), Fedora 39+ |
| Architecture | amd64 (x86_64) or arm64 (aarch64) |
| Access | Root or sudo |
| Init system | systemd |
| Hardware | 1 vCPU, 512 MB RAM minimum. 2 vCPU, 2 GB RAM recommended for 10+ concurrent rooms |
| Ports | 8090 (API + web UI), 7880 (LiveKit WebSocket), 50000–60000/udp (WebRTC media) |
| Auto-TLS | Additionally open 80 and 443. Requires a domain with DNS A record pointing to this server |
| Tools | curl, tar (pre-installed on most distros) |
No domain? Bedrud works with an IP address using self-signed TLS. Browsers will show a certificate warning but video and audio work. For trusted certificates on internal networks, see the Internal TLS Guide.
1. One-Command Install (Recommended)
Downloads and installs the Bedrud CLI binary to your PATH. Works on Linux, macOS, and Windows.
curl -fsSL https://get.bedrud.org | bashReload your shell after install:
source ~/.bashrc # or ~/.zshrcirm https://get.bedrud.org/install.ps1 | iexVerify:
bedrud --versionWant to customize the install? Use flags like --version 0.12.0, --install-dir /opt/bedrud, or --skip-shell. Full reference: CLI Installer.
2. Package Manager Install
Install via your distribution’s package manager.
curl -fsSL https://bedrud-ir.github.io/bedrud/bedrud.gpg.key \
| sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/bedrud.gpg
echo "deb https://bedrud-ir.github.io/bedrud stable main" \
| sudo tee /etc/apt/sources.list.d/bedrud.list
sudo apt update && sudo apt install bedrudThen run the interactive installer:
sudo bedrud installyay -S bedrud-bin
sudo bedrud installsudo curl -fsSL https://bedrud-ir.github.io/bedrud/dnf/bedrud.gpg.key \
-o /etc/pki/rpm-gpg/RPM-GPG-KEY-bedrud
sudo curl -fsSL https://bedrud-ir.github.io/bedrud/dnf/bedrud.repo \
-o /etc/yum.repos.d/bedrud.repo
sudo dnf install bedrud
sudo bedrud installFor desktop client installation (Linux, macOS, Windows) see Client Installation.
3. Docker
Run Bedrud in a container - no Linux server setup, no systemd, no binary download.
Pre-built Image (fastest)
docker pull ghcr.io/bedrud-ir/bedrud:latest
docker run -d --name bedrud \
-p 8090:8090 \
-p 7880:7880 \
-p 50000-60000:50000-60000/udp \
-v bedrud-data:/var/lib/bedrud \
ghcr.io/bedrud-ir/bedrud:latestDocker Compose
services:
bedrud:
image: ghcr.io/bedrud-ir/bedrud:latest
ports:
- "8090:8090"
- "7880:7880"
- "50000-60000:50000-60000/udp"
volumes:
- bedrud-data:/var/lib/bedrud
restart: unless-stopped
volumes:
bedrud-data:Ports
| Port | Service | Protocol |
|---|---|---|
| 8090 | API + Web UI | HTTP |
| 7880 | LiveKit | WebSocket + HTTP |
| 50000–60000 | WebRTC media | UDP |
Configuration
Pass a config file or use environment variables:
docker run -d --name bedrud \
-p 8090:8090 \
-p 7880:7880 \
-e JWT_SECRET=change-this-to-a-random-string \
-e LIVEKIT_API_KEY=prodkey \
-e LIVEKIT_API_SECRET=prodsecret \
-v bedrud-data:/var/lib/bedrud \
ghcr.io/bedrud-ir/bedrud:latestThe default JWT and LiveKit secrets are for quick testing only. Change them before exposing the container to the internet.
Full Docker documentation including volumes, reverse proxy, and TLS setup: Docker Guide.
4. Interactive Install
If you already have the bedrud binary on the server:
sudo ./bedrud installThe installer auto-detects your server’s IP and prompts for:
| Prompt | Default | Notes |
|---|---|---|
| IP address | Auto-detected (first non-loopback IPv4) | Press Enter to accept, or type a different IP |
| Domain | Empty (IP-only) | If provided with an email, enables Let’s Encrypt TLS |
| Empty | Used for Let’s Encrypt registration (only if domain is set) | |
| Self-signed TLS | Yes | Offered when no domain is provided. Default is Y |
All prompts are skipped when stdin is piped (non-interactive mode) - flags and defaults are used instead.
5. Non-Interactive (Flag-Based)
Skip all prompts by passing flags.
Let’s Encrypt (domain required)
Requires: DNS A record for your domain already pointing to this server’s IP.
sudo ./bedrud install --tls --domain meet.example.com --email webmaster@example.comSelf-Signed TLS (IP-based)
Requires: Nothing extra. Works immediately.
sudo ./bedrud install --tls --ip 1.2.3.4Plain HTTP (dev / internal only)
Requires: localhost or 127.0.0.1. Browsers block camera/mic on non-HTTPS except localhost.
sudo ./bedrud install --ip 1.2.3.4Self-Signed for a Domain (pre-DNS testing)
Requires: Domain name (DNS does not need to resolve yet).
sudo ./bedrud install --tls --domain meet.example.comCustom Port
Requires: Port not already in use.
sudo ./bedrud install --tls --port 8443 --domain meet.example.comExternal Certificates
Requires: PEM-formatted fullchain and private key files.
sudo ./bedrud install --tls --cert /path/to/fullchain.pem --key /path/to/privkey.pemCustom LiveKit Ports
Requires: All three ports open on your firewall.
sudo ./bedrud install --lk-port 9000 --lk-tcp-port 9001 --lk-udp-port 9002Behind a Reverse Proxy
Requires: A reverse proxy (Nginx, Caddy, Traefik, Cloudflare) terminating TLS in front of Bedrud.
sudo ./bedrud install --behind-proxy --domain meet.example.comSets behindProxy: true in the config and configures trusted proxy headers.
External LiveKit Server
Requires: A separate LiveKit server already running, accessible from this machine.
sudo ./bedrud install --external-livekit https://livekit.example.comSkips embedded LiveKit installation. API key and secret must match in both configs.
Separate LiveKit Domain
Requires: A domain that resolves directly to this server, bypassing any CDN.
sudo ./bedrud install --livekit-domain lk.example.com --domain meet.example.comUseful when the main domain is behind Cloudflare but WebRTC media needs a direct connection.
All Flags Reference
| Flag | Default | Description |
|---|---|---|
--tls | false | Enable HTTPS (self-signed or Let’s Encrypt) |
--self-signed | false | Generate a self-signed TLS certificate |
--no-tls | false | Disable TLS entirely (overrides --tls) |
--ip | auto-detected | Override the server IP address |
--domain | "" | Domain name for Let’s Encrypt or self-signed cert |
--email | "" | Email for Let’s Encrypt registration |
--port | 443 (TLS) / 8090 (HTTP) | Override the listening port |
--cert | "" | Path to existing certificate file (PEM) |
--key | "" | Path to existing private key file (PEM) |
--lk-port | 7880 | LiveKit API port |
--lk-tcp-port | 7881 | LiveKit RTC TCP port |
--lk-udp-port | 7882 | LiveKit RTC UDP port |
--fresh | false | Remove existing installation before installing |
--behind-proxy | false | Server is behind a reverse proxy / CDN |
--external-livekit | "" | URL of an external LiveKit server |
--livekit-domain | "" | Separate domain for LiveKit (bypass CDN) |
6. Fully Automated (Python CLI)
Build, upload, and configure your server from your local machine.
Requires: Python 3.12+, uv (Python package runner), SSH key access to the target server, Go 1.24+ and Bun installed locally.
cd tools/cli
uv run python bedrud.py --auto-config \
--ip <your-server-ip> \
--user root \
--auth-key ~/.ssh/id_rsa \
--domain meet.example.com \
--acme-email admin@example.comWhat it does:
- Builds the backend binary (
dist/bedrud) - Compresses it into
bedrud.tar.xz - Uploads it to the server via rsync
- Clears conflicting services (Nginx, Apache, Caddy)
- Configures the firewall (UFW)
- Runs the internal
installlogic on the server
| Flag | Description |
|---|---|
--ip | Server IP address |
--user | SSH user (default: root) |
--auth-key | Path to SSH private key |
--domain | Domain name for Let’s Encrypt |
--acme-email | Email for Let’s Encrypt |
--uninstall | Remove Bedrud from server |
What the Installer Does
When you run bedrud install, the following happens:
| Step | Action |
|---|---|
| 1 | Creates directories: /etc/bedrud, /var/lib/bedrud, /var/log/bedrud |
| 2 | Copies binary to /usr/local/bin/bedrud |
| 3 | Generates config.yaml with your settings /etc/bedrud/config.yaml |
| 4 | Generates livekit.yaml for media server /etc/bedrud/livekit.yaml |
| 5 | Creates two systemd services: bedrud.service & livekit.service |
| 6 | Enables and starts both services |
| 7 | Initializes SQLite database and certificate cache |
Service Entrypoints
bedrud --run --config /etc/bedrud/config.yaml # API + web server
bedrud --livekit --config /etc/bedrud/livekit.yaml # Media server
Post-Installation
Promote User to Admin
Register via the web UI at your server URL, then promote the user to admin:
sudo ./bedrud user promote --email admin@example.com
Verify Services
systemctl status bedrud livekitVerify the API
curl -s -o /dev/null -w "%{http_code}" http://localhost:8090Expect: 200
Check the Firewall
sudo ufw statusEnsure ports 8090/tcp, 7880/tcp, and 50000:60000/udp are allowed:
sudo ufw allow 8090/tcp
sudo ufw allow 7880/tcp
sudo ufw allow 50000:60000/udpView Logs
tail -f /var/log/bedrud/bedrud.logOr via journalctl:
journalctl -u bedrud -u livekit -fUpgrading
Package Manager
# Ubuntu / Debian
sudo apt update && sudo apt upgrade bedrud
# Arch Linux
yay -Syu bedrud-bin
# Fedora / RHEL
sudo dnf upgrade bedrudServices restart automatically after package upgrade.
Binary Download
Download the latest release and re-run install. The installer is safe to re-run - it overwrites the binary and config while preserving the database:
curl -fsSL -o bedrud.tar.xz https://github.com/bedrud-ir/bedrud/releases/latest/download/bedrud_linux_amd64.tar.xz
tar -xJf bedrud.tar.xz && chmod +x bedrud
sudo ./bedrud install --fresh--fresh removes the old installation first. Omit it to keep your existing config and database.
Docker
docker pull ghcr.io/bedrud-ir/bedrud:latest
docker stop bedrud && docker rm bedrud
docker run -d --name bedrud \
-p 8090:8090 \
-p 7880:7880 \
-p 50000-60000:50000-60000/udp \
-v bedrud-data:/var/lib/bedrud \
ghcr.io/bedrud-ir/bedrud:latestWith Docker Compose:
docker compose pull
docker compose up -dUninstallation
To completely remove Bedrud:
sudo bedrud uninstallThis stops services, removes systemd units, deletes the binary from /usr/local/bin, and cleans up /etc/bedrud, /var/lib/bedrud, and /var/log/bedrud.
Troubleshooting
| Problem | Solution |
|---|---|
| Port 80/443 in use | Stop conflicting web servers: systemctl stop nginx apache2 caddy |
| Services won’t start | Check logs: journalctl -u bedrud -u livekit --no-pager -n 50 |
| TLS certificate issues | Verify DNS: dig +short meet.example.com - must return this server’s IP |
| LiveKit port conflicts | Use --lk-port, --lk-tcp-port, --lk-udp-port flags to change ports |
| Install succeeded but 404 on web UI | Frontend not embedded. Build with make build before bedrud install. Binary-only builds skip the frontend |
| Install succeeded but services crashed | Check for silent failures: journalctl -u bedrud --no-pager -n 100. Verify config at /etc/bedrud/config.yaml |
| Port already in use (unknown process) | Find it: ss -tlnp | grep 8090 or ss -ulnp | grep 7880 |
| Firewall blocking media | Open ports: sudo ufw allow 8090/tcp && sudo ufw allow 7880/tcp && sudo ufw allow 50000:60000/udp |
| Self-signed cert warnings | Expected. See Internal TLS Guide for private CA setup |
| No video / WebRTC failed | HTTPS required for camera access. Use --tls. Ensure UDP 50000–60000 is open |
| Reverse proxy: wrong client IP | Use --behind-proxy flag. Configures trusted proxy headers |