Everything you need to set it up, open the right ports, run it and fix it when something doesn't work. Tap Copy next to any command to copy it.
Your phone (or OBS) sends video to this server. The server picks the input you want on air, shows a Be-right-back screen if the signal drops, turns it into one steady program, and sends that program to each platform you add (Twitch, YouTube, Kick…). Viewers never see your signal wobble, because the program carries on.
The program is encoded once and every destination just copies it, so extra destinations cost almost no CPU. The flip side: by default every destination gets the same picture. With a Pro licence you can pick one input for a single destination (in its row on the Live tab); that costs one extra encoder.
The dashboard is split into tabs: Live (inputs, destinations, recording), Stats, On-screen (Be-right-back and Starting-soon screens, clips, picture-in-picture, overlay), Automation (backup switching, auto-start/stop, chat commands, Discord, the cwtch.es remote) and Settings (picture quality, ports, licence, updates, backup).
IRL Relay runs in Docker, and the steps depend on what the computer behind it runs. Pick yours and this section shows everything for it: install, finding the control page, everyday commands, updating, firewall, Tailscale and WireGuard, the graphics card, and OBS inside the relay. Your choice is remembered on this device.
Names used below: image and container irl-relay, program files in /mnt/user/appdata/irl-relay, your settings and clips in /mnt/user/appdata/irl-relay-data. If you used other names (like irl-toolkit) swap them in. Commands are run in Unraid's terminal: the >_ icon at the top right of the Unraid page.
1. Get the files onto the server. Download the zip from the downloads page. Either copy the zip into your appdata share over the network (on Windows that is \\TOWER\appdata, using your server's name) and unzip it in the terminal, or unzip it on your computer and copy the irl-relay folder into appdata.
cd /mnt/user/appdata && unzip irl-relay-*.zip
app folder, then build the image (the dot at the end matters; takes a few minutes the first time):cd /mnt/user/appdata/irl-relay && docker build -t irl-relay .
docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -v /mnt/user/appdata/irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
choose-a-password to your own, and yourname.duckdns.org to the address your phone uses away from home (see Ports and your router). No name yet? Leave out the whole -e PUBLIC_HOST=… part and add it later. Paste it as ONE line: line breaks cause "invalid reference format". --restart unless-stopped makes it come back after a reboot.Then open the control page (next section) and log in with the password you chose. After that, follow the Quick start to add your phone and a destination.
Your Unraid server's address is shown on its Main page, or run hostname -I in the terminal. Open http://YOUR-SERVER-IP:8780. Give the server a fixed address in your router (see Ports and your router) so it never changes.
docker ps
-f to watch it live, Ctrl+C to leave). First thing to check when something's wrong:docker logs --tail 100 irl-relay
docker restart irl-relay docker stop irl-relay docker start irl-relay
{"ok": true, ...}):curl -s http://localhost:8780/api/ping
hostname -I
docker inspect irl-relay | grep CONTROL
CONTROL_PASSWORD. The password you give at start always replaces the saved one.docker rm -f irl-relay
docker logs irl-relay | grep -i password
exit to leave):docker exec -it irl-relay sh
docker stats irl-relay
cp -r /mnt/user/appdata/irl-relay-data /mnt/user/appdata/irl-relay-data-backup
-e LICENSE_KEY=IRL1.xxxxx.yyyyy
Download the new zip from the downloads page and replace the program files with the new ones (keep the Dockerfile and the app folder together; your settings are not in there). Then rebuild and start it again. Your inputs, destinations, licence and recordings stay, because they live in the data folder.
docker rm -f irl-relay cd /mnt/user/appdata/irl-relay && docker build -t irl-relay .
Then run the docker run line from the install step again.
Unraid has no firewall by default, so there is nothing to open on the server. Only the router needs port forwarding (see Ports and your router). Never forward port 8780.
To use WireGuard from inside IRL Relay (Settings → Private network → WireGuard) add --cap-add=NET_ADMIN --device=/dev/net/tun to the run line.
NVIDIA. 1) In Community Apps install Nvidia Driver and reboot. 2) Open Settings → Nvidia Driver and copy your card's GPU UUID (it starts with GPU-). 3) Remove the old container (docker rm -f irl-relay) and start it again with these extra options, using your own UUID. Still one line:
docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=GPU-your-uuid-here -e NVIDIA_DRIVER_CAPABILITIES=all -v /mnt/user/appdata/irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
Intel or AMD graphics. The driver is part of Linux, so there is nothing to install on the computer itself. This needs the graphics drivers inside the image, so build it once with the extra option below (it adds roughly 100 MB), then start it with --device /dev/dri.
renderD128 (or a similar name):ls /dev/dri
cd /mnt/user/appdata/irl-relay && docker build --build-arg WITH_GPU=1 -t irl-relay .
docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp --device /dev/dri -v /mnt/user/appdata/irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
If Test says the device can't be opened (permission denied), add the group that owns it, usually render: --group-add $(getent group render | cut -d: -f3) on the run line.
/dev/dri folder is sometimes empty until the Intel driver is switched on in Unraid; search "Unraid Intel iGPU" for the one-line step.Then, for any of these: open Settings → Quality, set Encoder to your card and press Test. It should say the test passed; if not, the message says what is missing (see what to expect).
Optional and for stronger computers; read what it is and who it's for first. These replace the normal build and start lines (your settings are kept in the data folder).
cd /mnt/user/appdata/irl-relay && docker build --build-arg WITH_OBS=1 -t irl-relay-obs .
-p 6080:6080 is only for the remote desktop:docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -p 6080:6080 -v /mnt/user/appdata/irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay-obs
For Ubuntu, Debian, Linux Mint and Raspberry Pi OS (64-bit), on a normal computer, a mini PC, a Raspberry Pi or a rented server. Names used below: image and container irl-relay, program files in ~/irl-relay, your settings and clips in ~/irl-relay-data. If a command says "permission denied" for Docker, put sudo in front.
Docker. If docker --version already answers, skip this. Otherwise Docker's own install script works on Ubuntu and Debian; then let your user run Docker and log out and in again:
curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER
Raspberry Pi: the image supports ARM, but a Pi has far less power than a PC. Start at 720p30, and don't use the OBS-inside image.
1. Get the files. The newest zip is on the downloads page. On the server (swap the version for the newest one):
sudo apt install -y unzip curl curl -LO https://cwtch.es/downloads/irl-relay-1.13.zip unzip irl-relay-*.zip -d "$HOME" mkdir -p "$HOME/irl-relay-data"
cd $HOME/irl-relay && docker build -t irl-relay .
docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -v $HOME/irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
choose-a-password to your own, and yourname.duckdns.org to the address your phone uses away from home (see Ports and your router). No name yet? Leave out the whole -e PUBLIC_HOST=… part and add it later. Paste it as ONE line: line breaks cause "invalid reference format". --restart unless-stopped makes it come back after a reboot.Then open the control page (next section) and log in with the password you chose. After that, follow the Quick start to add your phone and a destination.
Find the computer's home address, then open http://YOUR-SERVER-IP:8780 from any computer or phone on your home network. Give it a fixed address in your router (see Ports and your router).
hostname -I
docker ps
-f to watch it live, Ctrl+C to leave). First thing to check when something's wrong:docker logs --tail 100 irl-relay
docker restart irl-relay docker stop irl-relay docker start irl-relay
{"ok": true, ...}):curl -s http://localhost:8780/api/ping
hostname -I
docker inspect irl-relay | grep CONTROL
CONTROL_PASSWORD. The password you give at start always replaces the saved one.docker rm -f irl-relay
docker logs irl-relay | grep -i password
exit to leave):docker exec -it irl-relay sh
docker stats irl-relay
cp -r $HOME/irl-relay-data $HOME/irl-relay-data-backup
-e LICENSE_KEY=IRL1.xxxxx.yyyyy
Download the new zip from the downloads page and replace the program files with the new ones (keep the Dockerfile and the app folder together; your settings are not in there). Then rebuild and start it again. Your inputs, destinations, licence and recordings stay, because they live in the data folder.
docker rm -f irl-relay cd $HOME/irl-relay && docker build -t irl-relay .
Then run the docker run line from the install step again.
If you use ufw: ports that Docker publishes (the ones in the run line) are opened by Docker itself, and ufw rules don't block them, so you don't need to add anything for IRL Relay to work. The flip side is that ufw can't hide port 8780 either, so just never forward 8780 on your router. On a rented server, also open 1935 TCP and 8890 UDP in the provider's own firewall page, and use its public address as the server address (a rented server has no router and no CG-NAT).
Tailscale on the computer itself (the long way):
curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up
WireGuard on the computer itself (for the tunnel to a VPS, see WireGuard): put the relay config in /etc/wireguard/wg0.conf, then:
sudo apt install wireguard sudo wg-quick up wg0 sudo systemctl enable wg-quick@wg0
To use WireGuard from inside IRL Relay (Settings → Private network → WireGuard) add --cap-add=NET_ADMIN --device=/dev/net/tun to the run line.
NVIDIA. 1) Install the driver (skip if nvidia-smi already shows your card). Ubuntu: the command below, then reboot. Debian: enable the non-free section of your apt sources, then sudo apt install nvidia-driver and reboot. 2) Install NVIDIA's Container Toolkit, which lets Docker hand the card to a container. 3) Do the last steps.
sudo ubuntu-drivers install && sudo reboot
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list && sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
NVIDIA on Linux: the last steps (same for every distribution)
sudo nvidia-ctk runtime configure --runtime=docker && sudo systemctl restart docker
docker run --rm --gpus all debian:bookworm-slim nvidia-smi
--gpus all added:docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp --gpus all -v $HOME/irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
Intel or AMD graphics. The driver is part of Linux, so there is nothing to install on the computer itself. This needs the graphics drivers inside the image, so build it once with the extra option below (it adds roughly 100 MB), then start it with --device /dev/dri.
renderD128 (or a similar name):ls /dev/dri
cd $HOME/irl-relay && docker build --build-arg WITH_GPU=1 -t irl-relay .
docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp --device /dev/dri -v $HOME/irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
If Test says the device can't be opened (permission denied), add the group that owns it, usually render: --group-add $(getent group render | cut -d: -f3) on the run line.
Then, for any of these: open Settings → Quality, set Encoder to your card and press Test. It should say the test passed; if not, the message says what is missing (see what to expect).
Optional and for stronger computers; read what it is and who it's for first. These replace the normal build and start lines (your settings are kept in the data folder).
cd $HOME/irl-relay && docker build --build-arg WITH_OBS=1 -t irl-relay-obs .
-p 6080:6080 is only for the remote desktop:docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -p 6080:6080 -v $HOME/irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay-obs
For Fedora, RHEL, Rocky, AlmaLinux, CentOS Stream, Arch, Manjaro and openSUSE. Names used below: image and container irl-relay, program files in ~/irl-relay, your settings and clips in ~/irl-relay-data. If a command says "permission denied" for Docker, put sudo in front.
Docker. If docker --version already answers, skip this. Pick your family, then let your user run Docker and log out and in again. (If you use Podman, the commands are the same with podman instead of docker, but the Tailscale, WireGuard and graphics steps here assume Docker.)
curl -fsSL https://get.docker.com | sudo sh sudo systemctl enable --now docker sudo usermod -aG docker $USER
sudo pacman -S docker unzip curl sudo systemctl enable --now docker sudo usermod -aG docker $USER
sudo zypper install docker unzip curl sudo systemctl enable --now docker sudo usermod -aG docker $USER
1. Get the files. The newest zip is on the downloads page. On the server (swap the version for the newest one; install unzip and curl first if you don't have them):
curl -LO https://cwtch.es/downloads/irl-relay-1.13.zip unzip irl-relay-*.zip -d "$HOME" mkdir -p "$HOME/irl-relay-data"
cd $HOME/irl-relay && docker build -t irl-relay .
:Z after /data is for systems with SELinux (Fedora, RHEL and relatives); on Arch or openSUSE you can leave it off:docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -v $HOME/irl-relay-data:Z:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
choose-a-password to your own, and yourname.duckdns.org to the address your phone uses away from home (see Ports and your router). No name yet? Leave out the whole -e PUBLIC_HOST=… part and add it later. Paste it as ONE line: line breaks cause "invalid reference format". --restart unless-stopped makes it come back after a reboot.Then open the control page (next section) and log in with the password you chose. After that, follow the Quick start to add your phone and a destination.
Find the computer's home address, then open http://YOUR-SERVER-IP:8780 from any computer or phone on your home network. Give it a fixed address in your router (see Ports and your router).
hostname -I
docker ps
-f to watch it live, Ctrl+C to leave). First thing to check when something's wrong:docker logs --tail 100 irl-relay
docker restart irl-relay docker stop irl-relay docker start irl-relay
{"ok": true, ...}):curl -s http://localhost:8780/api/ping
hostname -I
docker inspect irl-relay | grep CONTROL
CONTROL_PASSWORD. The password you give at start always replaces the saved one.docker rm -f irl-relay
docker logs irl-relay | grep -i password
exit to leave):docker exec -it irl-relay sh
docker stats irl-relay
cp -r $HOME/irl-relay-data $HOME/irl-relay-data-backup
-e LICENSE_KEY=IRL1.xxxxx.yyyyy
Download the new zip from the downloads page and replace the program files with the new ones (keep the Dockerfile and the app folder together; your settings are not in there). Then rebuild and start it again. Your inputs, destinations, licence and recordings stay, because they live in the data folder.
docker rm -f irl-relay cd $HOME/irl-relay && docker build -t irl-relay .
Then run the docker run line from the install step again.
Docker opens the ports in the run line by itself, so IRL Relay normally works with the firewall on. If you can't reach the control page from another computer on firewalld (Fedora, RHEL and relatives), allow it for your home network, and the two video ports for streaming in:
sudo firewall-cmd --permanent --add-port=8780/tcp --add-port=1935/tcp --add-port=8890/udp && sudo firewall-cmd --reload
Never forward port 8780 on your router. If the graphics-card Test or the container complains about permissions on an SELinux system, the :Z in the run line is the first thing to check.
Tailscale on the computer itself (the long way):
curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up
WireGuard on the computer itself (for the tunnel to a VPS, see WireGuard): put the relay config in /etc/wireguard/wg0.conf, then:
sudo dnf install wireguard-tools sudo wg-quick up wg0 sudo systemctl enable wg-quick@wg0
sudo pacman -S wireguard-tools sudo wg-quick up wg0 sudo systemctl enable wg-quick@wg0
To use WireGuard from inside IRL Relay (Settings → Private network → WireGuard) add --cap-add=NET_ADMIN --device=/dev/net/tun to the run line.
NVIDIA. 1) Install the driver. Fedora: from RPM Fusion (akmod-nvidia, plus xorg-x11-drv-nvidia-cuda so nvidia-smi and the encoder libraries are there). RHEL and relatives: NVIDIA's own install guide. Arch: the nvidia and nvidia-utils packages. Reboot and check that nvidia-smi shows your card. 2) Install NVIDIA's Container Toolkit. 3) Do the last steps.
curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo && sudo dnf install -y nvidia-container-toolkit
sudo pacman -S nvidia nvidia-utils nvidia-container-toolkit
NVIDIA on Linux: the last steps (same for every distribution)
sudo nvidia-ctk runtime configure --runtime=docker && sudo systemctl restart docker
docker run --rm --gpus all debian:bookworm-slim nvidia-smi
--gpus all added:docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp --gpus all -v $HOME/irl-relay-data:Z:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
On Fedora and RHEL with SELinux, if Test mentions a permission problem, add --security-opt label=disable to the run line.
Intel or AMD graphics. The driver is part of Linux, so there is nothing to install on the computer itself. This needs the graphics drivers inside the image, so build it once with the extra option below (it adds roughly 100 MB), then start it with --device /dev/dri.
renderD128 (or a similar name):ls /dev/dri
cd $HOME/irl-relay && docker build --build-arg WITH_GPU=1 -t irl-relay .
docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp --device /dev/dri -v $HOME/irl-relay-data:Z:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
If Test says the device can't be opened (permission denied), add the group that owns it, usually render: --group-add $(getent group render | cut -d: -f3) on the run line.
Then, for any of these: open Settings → Quality, set Encoder to your card and press Test. It should say the test passed; if not, the message says what is missing (see what to expect).
Optional and for stronger computers; read what it is and who it's for first. These replace the normal build and start lines (your settings are kept in the data folder).
cd $HOME/irl-relay && docker build --build-arg WITH_OBS=1 -t irl-relay-obs .
-p 6080:6080 is only for the remote desktop:docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -p 6080:6080 -v $HOME/irl-relay-data:Z:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay-obs
For Windows 10 and 11 with Docker Desktop. IRL Relay runs while the PC is on and Docker Desktop is running. Commands are typed in PowerShell (search for it in the Start menu). Names used below: image and container irl-relay, program files in C:\irl-relay, your settings and clips in a Docker volume called irl-relay-data.
1. Get the files. Download the zip from the downloads page, right-click it and choose Extract All…, and extract it to C:\. You end up with a folder C:\irl-relay that contains Dockerfile and app.
cd C:\irl-relay docker build -t irl-relay .
docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -v irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
choose-a-password to your own, and yourname.duckdns.org to the address your phone uses away from home (see Ports and your router). No name yet? Leave out the whole -e PUBLIC_HOST=… part and add it later. Paste it as ONE line: line breaks cause "invalid reference format". --restart unless-stopped makes it come back after a reboot.irl-relay-data, which Docker looks after (it survives updates and removing the container). Recordings are in there too: download them from the control page.Then open the control page (next section) and log in with the password you chose. After that, follow the Quick start to add your phone and a destination.
On the same PC open http://localhost:8780. From your phone or another computer you need this PC's home address: run ipconfig and look for IPv4 Address under your network, then open http://YOUR-SERVER-IP:8780. Give the PC a fixed address in your router (see Ports and your router).
ipconfig
docker ps
-f to watch it live, Ctrl+C to leave). First thing to check when something's wrong:docker logs --tail 100 irl-relay
docker restart irl-relay docker stop irl-relay docker start irl-relay
{"ok": true, ...}):curl.exe -s http://localhost:8780/api/ping
ipconfig
docker inspect irl-relay | Select-String CONTROL
CONTROL_PASSWORD. The password you give at start always replaces the saved one.docker rm -f irl-relay
docker logs irl-relay | Select-String -Pattern password
exit to leave):docker exec -it irl-relay sh
docker stats irl-relay
C:\irl-relay-backup:mkdir C:\irl-relay-backup docker run --rm -v irl-relay-data:/data -v C:\irl-relay-backup:/backup debian:bookworm-slim tar czf /backup/irl-relay-data.tgz -C /data .
-e LICENSE_KEY=IRL1.xxxxx.yyyyy
Download the new zip from the downloads page and replace the program files with the new ones (keep the Dockerfile and the app folder together; your settings are not in there). Then rebuild and start it again. Your inputs, destinations, licence and recordings stay, because they live in the data folder.
docker rm -f irl-relay cd C:\irl-relay docker build -t irl-relay .
Then run the docker run line from the install step again.
The first time IRL Relay starts, Windows may ask whether Docker Desktop Backend may accept connections: choose Private networks (your home network). To add the rules yourself, run this in PowerShell as administrator (right-click PowerShell → Run as administrator). Port 8780 is only needed for other computers at home; never forward it on your router.
New-NetFirewallRule -DisplayName "IRL Relay video in" -Direction Inbound -Protocol TCP -LocalPort 1935 -Action Allow -Profile Private New-NetFirewallRule -DisplayName "IRL Relay SRT in" -Direction Inbound -Protocol UDP -LocalPort 8890 -Action Allow -Profile Private New-NetFirewallRule -DisplayName "IRL Relay control page" -Direction Inbound -Protocol TCP -LocalPort 8780 -Action Allow -Profile Private
The WireGuard panel inside IRL Relay needs --cap-add=NET_ADMIN --device=/dev/net/tun, which Docker Desktop may not allow. If it doesn't work, use the Windows WireGuard app above instead.
NVIDIA only. Install the current NVIDIA driver on Windows (from nvidia.com or GeForce Experience) and make sure Docker Desktop uses the WSL 2 backend (its default). There is nothing else to install: Docker passes the card through by itself. Check it, then start IRL Relay with --gpus all added:
docker run --rm --gpus all debian:bookworm-slim nvidia-smi
--gpus all added:docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp --gpus all -v irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
Intel and AMD graphics can't be used from Docker on Windows (they need /dev/dri, which only exists on Linux). Use the processor, or an NVIDIA card.
Then, for any of these: open Settings → Quality, set Encoder to your card and press Test. It should say the test passed; if not, the message says what is missing (see what to expect).
Docker Desktop gives containers only part of the PC. Before using OBS inside, open Docker Desktop → Settings → Resources (or the .wslconfig file for WSL 2) and allow at least 4 processors and 4 GB of memory.
Optional and for stronger computers; read what it is and who it's for first. These replace the normal build and start lines (your settings are kept in the data folder).
cd C:\irl-relay ; docker build --build-arg WITH_OBS=1 -t irl-relay-obs .
-p 6080:6080 is only for the remote desktop:docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -p 6080:6080 -v irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay-obs
For a Mac (Apple silicon or Intel) with Docker Desktop. IRL Relay runs while the Mac is on, awake and Docker Desktop is running. Commands are typed in Terminal (Applications → Utilities). Names used below: image and container irl-relay, program files in ~/irl-relay, your settings and clips in a Docker volume called irl-relay-data.
1. Get the files. Download the zip from the downloads page, double-click it to unzip, and drag the irl-relay folder into your home folder, so it ends up at ~/irl-relay with Dockerfile and app inside.
cd ~/irl-relay && docker build -t irl-relay .
docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -v irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay
choose-a-password to your own, and yourname.duckdns.org to the address your phone uses away from home (see Ports and your router). No name yet? Leave out the whole -e PUBLIC_HOST=… part and add it later. Paste it as ONE line: line breaks cause "invalid reference format". --restart unless-stopped makes it come back after a reboot.irl-relay-data, which Docker looks after (it survives updates and removing the container). Recordings are in there too: download them from the control page.Then open the control page (next section) and log in with the password you chose. After that, follow the Quick start to add your phone and a destination.
On the same Mac open http://localhost:8780. From your phone or another computer you need this Mac's home address (the command below gives the Wi-Fi one; use en1 if you're on a cable), then open http://YOUR-SERVER-IP:8780. Give the Mac a fixed address in your router (see Ports and your router).
ipconfig getifaddr en0
docker ps
-f to watch it live, Ctrl+C to leave). First thing to check when something's wrong:docker logs --tail 100 irl-relay
docker restart irl-relay docker stop irl-relay docker start irl-relay
{"ok": true, ...}):curl -s http://localhost:8780/api/ping
ipconfig getifaddr en0
docker inspect irl-relay | grep CONTROL
CONTROL_PASSWORD. The password you give at start always replaces the saved one.docker rm -f irl-relay
docker logs irl-relay | grep -i password
exit to leave):docker exec -it irl-relay sh
docker stats irl-relay
~/irl-relay-backup:mkdir -p "$HOME/irl-relay-backup" docker run --rm -v irl-relay-data:/data -v "$HOME/irl-relay-backup:/backup" debian:bookworm-slim tar czf /backup/irl-relay-data.tgz -C /data .
-e LICENSE_KEY=IRL1.xxxxx.yyyyy
Download the new zip from the downloads page and replace the program files with the new ones (keep the Dockerfile and the app folder together; your settings are not in there). Then rebuild and start it again. Your inputs, destinations, licence and recordings stay, because they live in the data folder.
docker rm -f irl-relay cd ~/irl-relay && docker build -t irl-relay .
Then run the docker run line from the install step again.
The first time IRL Relay starts, macOS may ask whether Docker may accept incoming network connections: choose Allow. Nothing else to open on the Mac. Only the router needs port forwarding (see Ports and your router); never forward 8780.
The WireGuard panel inside IRL Relay needs --cap-add=NET_ADMIN --device=/dev/net/tun, which Docker Desktop may not allow. If it doesn't work, use the Mac WireGuard app above instead.
Docker on a Mac can't pass a graphics card through to a container, so IRL Relay uses the processor here. Nothing to set up: leave Encoder on the processor.
Docker Desktop gives containers only part of the Mac. Before using OBS inside, open Docker Desktop → Settings → Resources and allow at least 4 CPUs and 4 GB of memory.
Optional and for stronger computers; read what it is and who it's for first. These replace the normal build and start lines (your settings are kept in the data folder).
cd ~/irl-relay && docker build --build-arg WITH_OBS=1 -t irl-relay-obs .
-p 6080:6080 is only for the remote desktop:docker rm -f irl-relay; docker run -d --name irl-relay --restart unless-stopped -p 8780:8780 -p 1935:1935 -p 8890:8890/udp -p 8889:8889 -p 8189:8189/udp -p 6080:6080 -v irl-relay-data:/data -e CONTROL_PASSWORD=choose-a-password -e PUBLIC_HOST=yourname.duckdns.org irl-relay-obs
For Synology (DSM 7.2 and newer, with Container Manager), QNAP (Container Station), TrueNAS SCALE and similar NAS boxes, for Docker inside a Proxmox virtual machine, and for rented servers. These systems mostly run Docker from a compose file, so that is what is shown. The folders below are Synology's (/volume1/docker); on QNAP use a folder like /share/Container, on TrueNAS a folder on one of your pools.
1935 TCP and 8890 UDP in the provider's firewall.1. Get the files. Download the zip from the downloads page, unzip it on your computer and copy the irl-relay folder to a shared folder on the NAS, for example docker (so it ends up at /volume1/docker/irl-relay, with Dockerfile and app inside). Also make an empty folder next to it called irl-relay-data.
2. Add this compose file to the program folder as compose.yaml (change the password, the address, and the data folder to match yours):
services:
irl-relay:
build: .
image: irl-relay
container_name: irl-relay
restart: unless-stopped
ports:
- "8780:8780"
- "1935:1935"
- "8890:8890/udp"
- "8889:8889"
- "8189:8189/udp"
volumes:
- /volume1/docker/irl-relay-data:/data
environment:
- CONTROL_PASSWORD=choose-a-password
- PUBLIC_HOST=yourname.duckdns.org3. Build and start it. Either over SSH, or in Synology's Container Manager choose Project → Create, point it at the program folder and let it build from the compose file (QNAP and TrueNAS have the same idea under their Container Station / Apps screens).
sudo):cd /volume1/docker/irl-relay && sudo docker compose up -d --build
restart: unless-stopped brings it back after a reboot. The image is built from the Dockerfile in the same folder, so keep Dockerfile, app and compose.yaml together.Then open the control page (next section) and log in with the password you chose. After that, follow the Quick start to add your phone and a destination.
Use the NAS's address on your home network (shown in its admin page, or hostname -I over SSH), open http://YOUR-SERVER-IP:8780. Give the NAS a fixed address in your router (see Ports and your router). If the page doesn't load, check that nothing else on the NAS already uses one of the ports (8780, 1935, 8889).
Over SSH (add sudo on Synology), or the same actions in the NAS's container screen:
docker ps
docker logs --tail 100 irl-relay
docker restart irl-relay docker stop irl-relay docker start irl-relay
CONTROL_PASSWORD in the compose file and run the compose command again):docker inspect irl-relay | grep CONTROL
docker logs irl-relay | grep -i password
docker stats irl-relay
cp -r /volume1/docker/irl-relay-data /volume1/docker/irl-relay-data-backup
Download the new zip from the downloads page and replace the program files with the new ones (keep the Dockerfile and the app folder together; your settings are not in there). Then rebuild and start it again. Your inputs, destinations, licence and recordings stay, because they live in the data folder.
cd /volume1/docker/irl-relay && sudo docker compose down && sudo docker compose up -d --build
If you've switched the NAS's own firewall on (Synology: Control Panel → Security → Firewall), allow 1935 TCP and 8890 UDP for streaming in, and 8780 TCP for your home network only. Only the router needs port forwarding (see Ports and your router); never forward 8780.
cap_add: [NET_ADMIN] and devices: ["/dev/net/tun:/dev/net/tun"] to the service.Most Synology and QNAP models can't use a graphics card for this, so keep the processor. For the few that can:
ls /dev/dri over SSH lists renderD128, build with --build-arg WITH_GPU=1 (or args: WITH_GPU: 1 under build: in the compose file) and add devices: ["/dev/dri:/dev/dri"] to the service. deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu, video, compute, utility]Then, for any of these: open Settings → Quality, set Encoder to your card and press Test. It should say the test passed; if not, the message says what is missing (see what to expect).
Needs a strong NAS (4 or more cores); read what it is and who it's for first. In the compose file add args: WITH_OBS: 1 under build:, change image: to irl-relay-obs, and add the port "6080:6080" for the remote desktop, then run the build and start command again.
http://YOUR-SERVER-IP:8780. Log in with the password you chose.These are the ports the container uses. You only need to open the ones for the way you send video to the server from outside your home.
| Port | Type | What for | Open to the internet? |
|---|---|---|---|
1935 | TCP | RTMP in: OBS, and most phone apps | Yes, if you stream from outside your home |
8890 | UDP | SRT in: best for bad mobile signal (needs an SRT-capable app) | Yes, if you use SRT |
8780 | TCP | This control page | No, keep it private (see Staying safe) |
8889 | TCP | Live preview in the control page (WebRTC) | Only if you want the preview away from home |
8189 | UDP | The preview's video stream (WebRTC) | Only with the preview above |
Everything else (the internal receiver on 8554 and 9997) stays inside the container and must never be opened.
192.168.1.131) so it never changes. Find the current one with hostname -I on the server.1935 TCP → the server's address, port 1935; and external 8890 UDP → the same address, port 8890. Make sure UDP is really selected for SRT.yourname.duckdns.org and it always points home.-e PUBLIC_HOST=yourname.duckdns.org (see Set up on your system). Without it the page shows whatever address you opened it from, which is usually the home one.192.168.1.131), which is faster and doesn't depend on the router.Some providers share one public address between many customers. This is called CG-NAT (carrier-grade NAT). It is common on mobile and 5G home internet, and on some cable and fibre plans. You can't forward ports on an address you share, so a phone away from home can't reach your relay directly. A home-address name can't fix that either: it would only point at the provider's shared address.
How to tell:
100.64 to 100.127, or one that differs from what a "what is my IP" website shows from a computer at home.What you can do:
What still works behind CG-NAT: everything that only needs the relay to reach out: sending to Twitch and other destinations, the cwtch.es remote, helpers, chat commands, Discord alerts, licence checks and updates. Streaming from inside your own home network works too. It's only video coming in from outside your home that needs an inbound connection.
Tailscale makes a private network between your devices. Your phone and your relay get private addresses (starting 100.) and can reach each other from anywhere, with no router changes and no port forwarding. It's free for personal use. Only your own devices, signed in to your Tailscale account, can use it.
Or install Tailscale on the server itself (the long way, outside IRL Relay):
curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up
100.101.102.103. (The Tailscale admin page at login.tailscale.com/admin/machines shows it too.)tailscale ip -4
rtmp://100.101.102.103:1935/live with your stream keysrt://100.101.102.103:8890?streamid=publish:live/YOURKEY-e PUBLIC_HOST=100.101.102.103 (see Set up on your system) so the control page shows these addresses ready to copy. Leave the home-address name off, it isn't needed.http://100.101.102.103:8780, while Tailscale is on. Nothing on the relay itself needs changing, and the ports stay closed to the rest of the internet.If the video is choppy: Tailscale prefers a direct connection between the two devices, and falls back to a slower relayed one if it can't make one. Check which you have with the commands below. If it says relay, give it a few seconds, then try again. A direct connection (direct) is what you want.
tailscale status tailscale ping YOUR-PHONE-NAME
If it won't connect: check the phone shows the Tailscale key icon (connected), that both devices appear as Connected on login.tailscale.com/admin/machines, and that you used the 100. address, not your home one. If the relay runs in Docker, the ports are already published on the server, so they're reachable on its Tailscale address too.
WireGuard does the same job as Tailscale, but you run it yourself. It's worth it if you'd rather not use an account with a third party, or you already use it. There are two cases.
--cap-add=NET_ADMIN and --device=/dev/net/tun (on Unraid, put them in Extra Parameters), then open Settings → Private network → WireGuard, paste the config made for this relay and press Check and connect. The config is checked first, then kept privately in the data folder (it is never shown again, and is not part of a backup). It refuses config lines that run commands, and settings that would send all your internet traffic through the VPN. The page then shows the relay's VPN address and the matching addresses under How to connect this input.1. You have a public address (no CG-NAT). Your router or server is the WireGuard server and your phone connects to your home.
51820) to the server in your router.192.168.1.50) as the server address in the streaming app, with the same ports.2. You are behind CG-NAT. Nothing can connect in to your home, so both your relay and your phone connect out to a small always-on server on the internet (a cheap VPS with a public address). That server just passes traffic between them, so use one you trust. It doesn't need to be fast. If this sounds like a lot, Tailscale above does all of it for you.
Steps below use 10.8.0.1 for the VPS, 10.8.0.2 for the relay and 10.8.0.3 for the phone. Do the first two on the VPS (Debian or Ubuntu).
sudo apt install wireguard qrencode umask 077 for n in hub relay phone; do wg genkey | tee $n.key | wg pubkey > $n.pub; done cat *.key *.pub
That prints six lines. Keep them handy: you'll paste each key into the right place below. A .key file is a private key. Never share those, and only put each one on its own device.
/etc/wireguard/wg0.conf (fill in the hub.key, relay.pub and phone.pub values):[Interface] Address = 10.8.0.1/24 ListenPort = 51820 PrivateKey = HUB.KEY-VALUE PostUp = sysctl -w net.ipv4.ip_forward=1 PostUp = iptables -A FORWARD -i wg0 -o wg0 -j ACCEPT PostDown = iptables -D FORWARD -i wg0 -o wg0 -j ACCEPT [Peer] # the relay PublicKey = RELAY.PUB-VALUE AllowedIPs = 10.8.0.2/32 [Peer] # the phone PublicKey = PHONE.PUB-VALUE AllowedIPs = 10.8.0.3/32
sudo wg-quick up wg0 sudo systemctl enable wg-quick@wg0 sudo ufw allow 51820/udp
/etc/wireguard/wg0.conf (the relay.key and hub.pub values; use your VPS's address or name):[Interface] Address = 10.8.0.2/24 PrivateKey = RELAY.KEY-VALUE [Peer] PublicKey = HUB.PUB-VALUE Endpoint = YOUR-VPS-ADDRESS:51820 AllowedIPs = 10.8.0.0/24 PersistentKeepalive = 25
sudo apt install wireguard sudo wg-quick up wg0 sudo systemctl enable wg-quick@wg0
phone.conf on the VPS (the phone.key and hub.pub values), then turn it into a QR code:[Interface] Address = 10.8.0.3/24 PrivateKey = PHONE.KEY-VALUE [Peer] PublicKey = HUB.PUB-VALUE Endpoint = YOUR-VPS-ADDRESS:51820 AllowedIPs = 10.8.0.0/24 PersistentKeepalive = 25
qrencode -t ansiutf8 < phone.conf
sudo wg show. Both peers should show a recent latest handshake. From the relay's server, ping 10.8.0.1 should answer.rtmp://10.8.0.2:1935/live (or srt://10.8.0.2:8890?streamid=publish:live/YOURKEY) and your stream key. Optionally start the relay with -e PUBLIC_HOST=10.8.0.2.phone.conf from the VPS with shred -u phone.conf *.key. The hub's key stays safe inside wg0.conf.Each input on the control page shows its own address. Use one input per camera (or phone), and never share a key between two devices.
| Way | Address | Notes |
|---|---|---|
| RTMP | Server rtmp://YOUR-SERVER-IP:1935/liveStream key: the key shown on the input | Works in OBS (Settings → Stream → Service: Custom) and nearly every phone streaming app. If an app has one box for a URL, use rtmp://…:1935/live/YOURKEY. |
| SRT | srt://YOUR-SERVER-IP:8890?streamid=publish:live/YOURKEY | Copes much better with weak mobile signal. Use an app that supports SRT (many IRL apps do). Needs the UDP port forwarded. |
Phone tips: use the public address (not the 192.168… one) when you're out; 720p at 2.5 to 4 Mbps is a sensible mobile start; keep the phone's own bitrate at or below what your connection can really do. Bonded or multi-SIM apps help a lot on the move.
Inputs are always ready. The server decodes the latest picture of every input all the time, so switching is instant. Inputs that aren't on air still use a little CPU.
Upload needed at the server = the program bitrate × the number of destinations that are on.
Example: 3000 kbps program to Twitch, YouTube and Kick = 3 × 3 Mbps = 9 Mbps upload. Add about 20% spare.
Download needed at the server = the bitrates of the inputs sending to it (a phone at 4 Mbps needs 4 Mbps down at home).
Vertical (portrait) streaming: in Picture quality choose one of the Vertical sizes (720×1280 or 1080×1920, Pro for 1080) if you mainly stream to vertical platforms such as TikTok or Instagram. The whole program, and so every destination, then goes out in portrait. A portrait phone fills the frame; a landscape input is shrunk to fit with black bars above and below. A destination never sees your input, only the program, so the size is always the one you picked here.
If your upload is limited, send to fewer destinations, or lower the quality under Picture quality. Many platforms also offer their own multi-streaming, which is lighter on your connection.
| Free | Pro | |
|---|---|---|
| Inputs | 2 | 8 |
| Destinations | 2 | 8 |
| Picture quality | up to 720p30, 4500 kbps | up to 1080p60, 12000 kbps |
| Automatic backup switching | – | ✓ |
| cwtch.es remote (no ports) | – | ✓ |
| Overlay on the video | – | ✓ |
| Picture-in-picture | – | ✓ |
| A different input to one destination | – | ✓ |
| Auto-start and auto-stop | – | ✓ |
| Discord alerts | – | ✓ |
| Chat commands | – | ✓ |
| Recording | – | ✓ |
| Your clips on the Be-right-back screen | – | ✓ |
The normal image runs on almost anything. If your server is a stronger computer, you can build a second image that has OBS Studio inside. OBS takes your phone's picture, adds your scenes, then sends its result back into the relay as an input called OBS. The relay is still in front of Twitch and Kick, so the Be-right-back protection, destinations and recording work as usual, even if OBS stops.
To install it: the exact commands for your system are under OBS inside the relay in Set up on your system. In short, you build a second image with --build-arg WITH_OBS=1 and start it with the extra -p 6080:6080 for the remote desktop.
Then:
Editing scenes. Switch on Remote desktop in Settings → OBS and press Open OBS desktop. You see the full OBS window in your browser and can add images, videos, text, filters, more scenes and so on, like normal OBS. The page asks for the password shown in the same panel. Use it at home or over your private network (Tailscale), don't forward port 6080 on your router, and switch it off when you're done. Your scenes are kept in the data folder, so they survive updates.
Good to know. OBS sends to the relay by itself, so don't press Stop Streaming inside OBS (it will start again by itself after a few seconds). A video, audio or image file can't be added from your own computer: put the files in the data folder (obs/ inside it) and add them from there. Reset scenes puts the two starting scenes back. Turn off OBS removes the OBS input and stops it, and keeps your scenes for next time. If OBS won't start, the panel says why; the details are in obs/obs.log in the data folder.
By default the relay does the video encoding on the computer's processor. That works everywhere and is the right choice for most people. If the server also has a graphics card, the card can do that work instead, which leaves the processor free for other things (or lets a small server cope with a higher quality). You choose it under Settings → Quality → Encoder.
Which kind do I have? An NVIDIA graphics card → NVIDIA. The graphics built into most Intel processors, or an AMD graphics card or processor → Intel or AMD. The container has to be given the card when it starts, and how depends on your system: the commands are under Graphics card in Set up on your system (Unraid, Ubuntu & Debian, Other Linux, Windows, NAS).
Good to know. A hardware encoder gives about the same picture as the processor at the same bitrate, sometimes a touch softer; if you notice, go up one quality step. Some NVIDIA GeForce cards only allow a few encodes at once, and each destination you send a different input to (Pro) uses one more, so if Test mentions the card being busy or at its limit, close other programs that use the card's video encoder (Plex, OBS, a second relay). This is a new feature: if it never works on your card, the relay keeps streaming on the processor and the message says what it found. Mac, and Intel or AMD graphics on Windows, can't pass a card through, so use the processor there.
A second still screen for before you go live. Add the destinations, start the program, leave it on Starting soon while people arrive, then switch to your input when you're ready. Change its words under Starting-soon screen. Chat command: !soon (!switch soon works too).
Instead of plain words, the Starting-soon and Be-right-back screens can show a page from your cwtch.es dashboard, such as the Next Stream Countdown, Big Countdown Timer or Stream Overlay Text Cards. Copy that tool's OBS link from your dashboard, paste it under the screen's text box and press Save. A small web browser inside the app draws it, only while that screen is on air (it takes a couple of seconds to appear; the plain screen shows meanwhile), and it fills the picture. Only cwtch.es links are accepted, and sound from the page isn't included. If a page is set, it is used instead of your clips on the Be-right-back screen. This needs the latest Dockerfile (it adds the browser), so rebuild the image after updating. It makes the image a few hundred MB bigger.
If the input on air loses signal, viewers see the Be-right-back screen instead of a frozen picture or a dead stream. Change the words under Be-right-back screen. PRO Turn on Clips on the Be-right-back screen to play your newest Twitch clips, with sound, instead of the still picture: press Connect Twitch to get a token, approve the single permission (Twitch requires "manage clips" before it shares clip downloads; nothing is ever created or deleted), paste the token and switch it on. Clips are saved on the server and refreshed every half hour.
Choose a main input and a backup. If the main one drops (or falls under the minimum bitrate you set) for a few seconds it switches to the backup, and switches back once the main has been good for a while. Turn on Be-right-back as the backup if you don't have a second camera. Two shortcuts: for Main input choose Whichever input I'm on air with and it protects whatever you last switched to by hand; for Backup choose Any other live input, then Be-right-back and it uses the first of your other inputs that has a signal (and moves on if that one drops too), falling back to the Be-right-back screen.
Control the relay from a page on cwtch.es without opening any port. In the cwtch.es remote panel press Link this relay: it shows a one-time code. Open cwtch.es/irl-remote.html on your phone or any computer and type the code. You then get the same big buttons as the phone remote (switch input, Be-right-back, Starting-soon, Go live/Stop, destinations on/off). Your relay checks in with cwtch.es by itself, every 15 seconds, or every 2 seconds while a page is open; nothing ever connects in to your home network. Only those few actions can be done this way: no settings, stream keys or files are reachable, and cwtch.es only holds your input and destination names and on/off state. A button can take a few seconds to take effect. Each paired phone or browser is listed by name in the same panel with a Remove button, and Unlink removes every paired device at once. A code works once and runs out after 15 minutes. Paired devices stay paired until you remove them; if you prefer, tick Let each pairing run out after 30 days and they have to pair again after that. It needs a Pro licence that has been activated.
In Settings, Home-address name gives this relay a name like k7p4q-9xmh3t-2wb6nd.cwtch.live that always points at your home connection, even when your internet provider changes your address. This relay tells cwtch.es now and then (cwtch.es sees the address from the request itself) and cwtch.es keeps the name up to date, so the server address in your phone app or OBS never needs changing. You still need the router forwards from Ports and your router; the name only replaces the number. It is off by default, because it puts your home address in public DNS under that long random name; turning it off removes the name. A name that hasn't been seen for 30 days is removed. It doesn't help behind carrier-grade NAT, where the provider shares one address between many customers (see CG-NAT).
Once the relay is linked, the Helpers list in the same panel lets chosen people (your moderators, say) open cwtch.es/irl-remote.html and press Log in with Twitch instead of using a code. Add their Twitch names and choose what each may do: Switch scenes only (they see the input buttons, nothing else) or Full control (they can also start and stop the stream and switch destinations). Only names on your list get in. Twitch tells cwtch.es just the person's name; no stream keys, settings or files are ever reachable. Add the names from my chat commands copies your chat-command list in as scenes-only helpers. To cut someone off, remove their name: it takes up to 15 seconds. (Remove on a paired device only logs that device out, so a helper could log in again until their name is gone.) Your own phones keep using pairing codes.
Draws a cwtch.es widget (a countdown, goal bar, alert box and so on) over whatever is on air, for every destination and for recordings. In your cwtch.es dashboard copy the widget's OBS link, paste it in the Overlay on the video panel, pick a position and size, and switch it on. Use a widget with a see-through background (they are by default) so the picture shows around it. Showing and hiding it is instant. The first time you set it, and whenever you change the page, the size or the position, the stream restarts for a moment (your destinations reconnect) because the video encoder has to be rebuilt to make room for it. It's drawn by the small web browser inside the app, only while the stream is running, and needs the latest Dockerfile (it adds Chromium). Destinations set to a single input don't get the overlay.
Show a second input as a small picture (a quarter of the width, with a thin white border) in a corner of whatever is on air. Pick the input and the corner in the Picture-in-picture panel and switch it on. It shows while the small input has a signal and isn't the one on air, disappears by itself if that input drops, and never appears over the Be-right-back or Starting-soon screens. Only its picture is used; its sound isn't mixed in. It's drawn on the main program, so destinations set to one input don't get it.
Normally every destination gets the same picture (the program). With two or more inputs, each destination has a menu next to Edit: Main program (the default) or Only <input>. For example, send your camera to YouTube while Twitch follows whatever you switch to. A destination set to one input always shows that input, and shows the Be-right-back card if that input has no signal, and it isn't affected by switching or by automatic backup switching. Each different input you route to adds one extra encoder, which uses more processor and has the same picture quality settings as the main one. The extra encoders only run while the program is running. Removing an input puts its destinations back on the main program.
Each input card has a Sound button (tap to mute) and a volume slider from 0 to 200%. 100% leaves the sound as it arrives. Use it to quieten a noisy camera mic or lift a quiet phone. It only changes the sound viewers hear; the input itself is untouched. Going above 100% can distort loud sound.
Start when an input connects: while the program is stopped, the moment a phone or camera starts sending (and keeps sending for a few seconds) the stream starts by itself, showing the input that connected. If you stop it by hand while the phone is still sending, it stays stopped until something connects again. Stop when nothing has been connected for: ends the stream once no input has been sending for the number of minutes you choose, so you aren't left streaming a Be-right-back screen to nobody. A countdown shows on the panel. The Starting-soon screen never triggers an auto-stop.
Posts a message in a Discord channel of your own when you go live or stop, when the input you're on air with drops or comes back, when you switch input, and when a destination loses its connection. In Discord open the channel's settings → Integrations → Webhooks → New webhook → Copy Webhook URL, paste it into the Discord alerts panel and use Send a test message. Pick which kinds of message you want. Messages never ping anyone. The webhook address stays on this server (and in a settings backup); anyone who has it can post in that channel, so keep it private.
Open http://your-server:8780/remote on your phone (or tap Phone remote at the top of the control page) for a page made for thumbs: big buttons to switch input, Be-right-back and Starting-soon, a Go live button (stopping asks for a second tap so you can't do it by accident), and a switch for each destination. It uses the same password as the control page. Add it to your home screen for one-tap access.
You and your mods steer the stream from Twitch chat: !brb (Be-right-back screen), !soon (Starting-soon screen), !back (main input), !switch 2 or !switch name, !inputs, !status. Everyone else is ignored. By default every moderator can use them, plus any Twitch names you add to the list. To let only certain moderators in, set Who can use commands to Only the names below and list their Twitch names; other moderators are then ignored (you, as the channel owner, always can). It listens without logging in; for it to reply in chat, add a bot account name and that account's chat token.
The What viewers get box under the inputs is live video of the program (shown while the program is running). To watch one input before you switch to it, click its picture: a window opens with that input live, as it arrives from the device. The small pictures on the cards are only snapshots that refresh every couple of seconds. Live video uses ports 8889 (TCP) and 8189 (UDP). At home that just works; away from home they need forwarding too, and the page must be opened over plain http:// (a secure https:// page can't embed it).
The Live stats section shows each input's bitrate for the last couple of minutes, how often it dropped and when, plus how long each destination has been live.
Saves what viewers see to an MP4 on the server (about 1.5 GB per hour at 3000 kbps). Download or delete recordings from the panel. They live in the data folder under recordings.
docker ps. If it isn't there, docker logs irl-relay tells you why.8780: http://192.168.x.x:8780. Find the address with hostname -I (Linux, Unraid, NAS), ipconfig (Windows) or ipconfig getifaddr en0 (Mac).curl -s http://localhost:8780/api/ping should answer. If it does, it's the address or a firewall.--runtime=nvidia on Unraid, --gpus all elsewhere). "No graphics device" or "driver couldn't start" (Intel/AMD) means --device /dev/dri is missing, or the image wasn't built with --build-arg WITH_GPU=1. After fixing it, press Test again. Full steps are under Use a graphics card. Streaming is never affected: the processor is used meanwhile.docker inspect irl-relay | grep CONTROL (Windows PowerShell: docker inspect irl-relay | Select-String CONTROL) to see what it was started with. To change it, remove the container and run it again with a new CONTROL_PASSWORD (see Set up on your system). Your settings are kept.docker run command was pasted with line breaks. Paste it as one line.-e PUBLIC_HOST=your.public.address.or.domain so it shows the one phones should use away from home.1935 TCP (RTMP) or 8890 UDP (SRT).docker logs -f irl-relay while you press start on the phone.cwtch.es.docker stats irl-relay; if it's high, lower the resolution or frame rate, or remove inputs you don't use.-p 8781:8780) and use that port instead.8889 TCP and 8189 UDP forwarded as well. Not needed at home, or for streaming.docker logs --tail 50 irl-relay for the platform's error.To see or change the password, use the commands under Everyday commands in your system's tab (Set up on your system): you remove the container and start it again with a new CONTROL_PASSWORD, and your settings are kept. The password you give at start always replaces the saved one.
Turn it on in Settings → Two-step login: scan the picture with an authenticator app, type the 6-digit code once, and save the recovery codes it shows. After that, logging in (here and on the phone remote page) needs the password and a code.
-e IRL_RESET_2FA=1 added. Log in with just the password, then remove the container and start it once more without that setting, and turn two-step login back on.New-version notice. About twice a day the control page asks one public file on cwtch.es which release is newest, and shows a banner if yours is older. It sends nothing about you (only the version number). To switch it off, add -e UPDATE_CHECK=0 to the docker run line.
You can also save your settings from the control page: Backup and restore → Download a backup. To put them back (on this computer or a new one), use Restore from a backup… and pick the file. It restores your inputs, destinations, picture settings, screens, automatic switching, chat and clips settings, and your licence. It does not include the control password or recordings. The file contains your stream keys, so keep it private.
Start with a Pro key. You can paste a key on the Licence panel, or add -e LICENSE_KEY=IRL1.xxxxx.yyyyy to the run line.
IRL Relay · help · control page