Install C21 Live Control and C21 Live Encoder on one host
When to use this layout
A single host runs both C21 Live Control (a Docker compose stack) and C21 Live Encoder (the encoding engine and its Apache front end, installed on the host). Live Control manages the Encoder on its own host through the Devices section, and can manage other Encoders on other hosts as well.
This layout suits deployments with few hosts available, such as a cloud VM that has to provide both the control plane and the first encoding capacity. When you have more than one host, the standard layout — Control and each Encoder on their own hosts — is simpler to operate: follow Install C21 Live Control and Install C21 Live Encoder instead.
How the two products share the host
Both products serve HTTPS on port 443 by default, so one of them has to move. Everything else coexists without changes.
| Port | Live Control | Live Encoder | On a shared host |
|---|---|---|---|
443/tcp | HTTPS — operator UI and REST API | HTTPS — Encoder API and outputs | Conflict. Live Control moves to 9443. |
80/tcp | — | HTTP | Unchanged. |
9080/tcp | HTTP (redirects to HTTPS) | — | Unchanged. |
3100/tcp | MCP server | — | Unchanged. |
8484/tcp | — | Delivery of outputs | Unchanged. |
Live Control is the product that moves, not the Encoder, because:
- Live Control reaches every registered Encoder at
https://<encoder-ip>/— the Device form takes an IP, not a port. - Players, CDNs and origins that pull the Encoder's local output fetch it from port
443.
Both products also share the host fingerprint: the license for both is bound to the same value.
Before you start
- A host that meets the prerequisites of both products — see Prepare the host, Install C21 Live Control and Install C21 Live Encoder. Size CPU and RAM for the Encoder workload plus the Control stack, which is capped at 4 cores and 3 GiB of RAM.
- Ubuntu 24.04 LTS (required by the Encoder) with a fixed IP address.
- The platform certificate and its private key for the host, issued by Cires21 for the host's IP (full chain: leaf and intermediate). The self-signed certificate the installers generate is not enough: Live Control must be able to validate the Encoder's certificate to register it.
- The same target version for both products, and 6.12.0 or later on every Encoder this Control manages — local and remote.
From 6.12.0 on, Live Control delivers logos and blackout files to the Encoder before each order. Earlier Encoders download them from Live Control
on port
443, which on this host answers as the Encoder, so logo overlays and blackouts fail on them. - A maintenance window — the Encoder installer updates the SSH server and drops SSH sessions for one to two minutes.
nohup) so that the SSH restart does not abort the install,
and read the log to follow progress.Steps
1. Prepare the host
Apply Prepare the host — DNS, NTP, swap and the OS update policy. For the firewall, follow step 8 below instead of the
ufw section of that page: on a shared host the Control ports are published by Docker and need a different rule set.
2. Install Live Control first
Live Control goes first because its installer requires port 443 to be free. Once it is moved to 9443 in the next step, port 443 is free for the Encoder.
sudo nohup bash -c "curl -fsSL https://get.cires21.com/livecontrol \
| bash -s -- --version <X.Y.Z> --yes; echo INSTALL_EXIT=\$?" > /tmp/lc-install.log 2>&1 &
tail -f /tmp/lc-install.log # Wait for INSTALL_EXIT=0
Keep the access details and the initial credentials that the installer prints at the end of the log.
admin still has its initial password.
On a host exposed to the Internet, apply the Control part of the firewall (step 8) right after step 3, before you go on.3. Move Live Control HTTPS to port 9443
Create a compose override in the Live Control installation directory (/opt/livecontrol by default). The installer only regenerates
docker-compose.yml, so this file survives updates.
sudo tee /opt/livecontrol/docker-compose.override.yml >/dev/null <<'EOF'
# Shared Control + Encoder host: the Encoder serves HTTPS on 443.
services:
livecontrol:
ports: !override
- "9080:80"
- "9443:443"
EOF
sudo systemctl restart livecontrol # Recreates the containers with the new ports
livecontrol restart is not enough here: it restarts the containers without applying the new port mapping.
The !override tag requires Docker Compose 2.24.4 or later — check it with docker compose version. Verify that Live Control answers on 9443 and that 443 is free:
curl -sk -o /dev/null -w "%{http_code}\n" https://127.0.0.1:9443/ # 200
sudo ss -ltnp | grep ':443 ' # No output
From now on the operator UI is at https://<host>:9443/.
4. Install Live Encoder
sudo nohup bash -c "curl -fsSL https://get.cires21.com/liveencoder \
| bash -s -- --version <X.Y.Z> --yes; echo INSTALL_EXIT=\$?" > /tmp/le-install.log 2>&1 &
tail -f /tmp/le-install.log # Wait for INSTALL_EXIT=0; SSH drops for 1–2 minutes during the run
On a cloud VM without capture cards or GPU, add --skip-drivers to the installer flags. Live Control keeps running during the Encoder install.
5. Install the licenses
Both products report the same fingerprint:
sudo livecontrol license info
sudo liveencoder license info
Send that single value to your Cires21 representative with the product slots your contract covers. Cires21 returns one license file per product; install each with its own CLI:
sudo livecontrol license install /path/to/control-license.txt
sudo livecontrol restart
sudo livecontrol license verify
sudo liveencoder license install /path/to/encoder-license.txt
sudo liveencoder restart
sudo liveencoder license verify
See Licenses for the slots of each product.
6. Install the certificate in both products
Both products present the same certificate: the Encoder through its Apache front end on 443, Live Control on 9443.
# Live Encoder
sudo install -m 644 <host>.crt /etc/ssl/certs/cert.pem
sudo install -m 600 <host>.key /etc/ssl/private/private-key.pem
sudo apache2ctl configtest && sudo systemctl reload apache2
# Live Control
sudo livecontrol ssl import <host>.crt <host>.key
Check that Live Control validates the Encoder's certificate. Live Control reaches the Encoder through the host's IP, as it would reach a remote Encoder:
sudo docker exec livecontrol curl -s -o /dev/null -w "%{ssl_verify_result}\n" https://<host-ip>/ # 0
Any value other than 0 means the certificate chain or the IP in the certificate does not match, and registering the Encoder in step 9 will fail.
7. First login and admin password rotation
Open https://<host>:9443/ and sign in as admin with the initial password printed by the installer. The UI asks you to rotate the password before
anything else. Until the password is rotated, the REST API and the MCP server reject every request made with the admin account.
livecontrol security password reset does not replace this step: it sets a new password but leaves the account pending rotation.
admin account, using the password stored in the installation
directory (/opt/livecontrol by default). After the rotation, replace the admin password in that directory's .env and .credentials files with the new
one, then recreate the MCP service with cd /opt/livecontrol && sudo docker compose up -d livecontrol-mcp.8. Configure the firewall
The two products need two different rule sets, because their ports reach the host through different paths:
| Product | How its ports are exposed | Where to filter |
|---|---|---|
| Live Encoder | Directly on the host: 80, 443, 8484 and the ingest ports of your Channels (SRT, RTMP, UDP…). | The host firewall (ufw or the INPUT chain), as usual. |
| Live Control | Published by Docker: 9443, 9080, 3100. | The DOCKER-USER chain. Docker-published ports skip the INPUT chain, so ufw rules do not apply to them. |
Without a DOCKER-USER rule set, the Control ports — the MCP server included — are open to any address that can reach the host.
Encoder. Keep the policy of your deployment: allow the ingest ports your sources use, and restrict 80 / 443 / 8484 to the clients that pull the
Encoder output and to any other Live Control that manages this Encoder. If you restrict 443, re-run the certificate check of step 6 afterwards to confirm
that the local Live Control still reaches the Encoder.
With a default-deny policy, also allow the Encoder's own multicast traffic. The Encoder sends it to itself, and it arrives on the WAN interface with the host IP as source; if the firewall drops it, running Live streams stop:
sudo ufw allow in on <wan-interface> from <host-ip> to 224.0.0.0/4 proto udp comment 'Encoder internal multicast'
The local Live Control runs in a container, so its requests reach the Encoder from the Docker network of Live Control, not from the host IP.
Allow that subnet on 443 — Live Control does not use the Encoder's 80 or 8484:
sudo docker network inspect livecontrol_network -f '{{(index .IPAM.Config 0).Subnet}}' # For example 172.18.0.0/16
sudo ufw allow from <control-docker-subnet> to any port 443 proto tcp comment 'Encoder HTTPS from local Control'
Control. The script below allows the listed sources and drops everything else that enters on the WAN interface. Replies to connections started from the host, and traffic between containers, are not affected.
#!/usr/bin/env bash
# /usr/local/sbin/c21-docker-user-fw.sh
set -euo pipefail
WAN_IF="<wan-interface>" # For example eth0
ALLOW_SRC="<office-ip>/32 <vpn-subnet>" # Sources allowed to reach 9443, 9080 and 3100
for ipt in iptables ip6tables; do # Docker also publishes on IPv6
$ipt -N DOCKER-USER 2>/dev/null || true
$ipt -F DOCKER-USER
$ipt -A DOCKER-USER -i "$WAN_IF" -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
done
for src in $ALLOW_SRC; do
case "$src" in *:*) ipt=ip6tables ;; *) ipt=iptables ;; esac
$ipt -A DOCKER-USER -i "$WAN_IF" -s "$src" -j RETURN
done
for ipt in iptables ip6tables; do
$ipt -A DOCKER-USER -i "$WAN_IF" -j DROP
$ipt -A DOCKER-USER -j RETURN
done
iptables rules live only in memory and are lost when the host reboots, so apply the script from a systemd unit bound to Docker: it runs every time
Docker starts, including after a reboot and after a Live Control update.
# /etc/systemd/system/c21-docker-user-fw.service
[Unit]
Description=DOCKER-USER rules for C21 Live Control
After=docker.service
PartOf=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/c21-docker-user-fw.sh
[Install]
WantedBy=docker.service
sudo chmod 755 /usr/local/sbin/c21-docker-user-fw.sh
sudo systemctl daemon-reload
sudo systemctl enable --now c21-docker-user-fw.service
sudo iptables -S DOCKER-USER
From an address outside the allowlist, ports 9443, 9080 and 3100 must now be closed.
9. Register the Encoder in Live Control
In the Live Control UI open Devices → Add device and register the Encoder of this host as you would register any other one — see Install C21 Live Encoder, step 4:
- Server IP — the IP of the host, the same one the certificate is issued for. No port: Live Control reaches the Encoder on
443. - Register username / Register password — the Encoder's
admincredentials (sudo liveencoder credentials show/credentials reset).
The Device row must show registration_status: registered. Other Encoders, on other hosts, are registered in the same way.
10. Verify
curl -sk -o /dev/null -w "%{http_code}\n" https://127.0.0.1:9443/ # Live Control UI: 200
sudo livecontrol status # Live Control services healthy
sudo liveencoder status # Encoder service running
sudo iptables -S DOCKER-USER # Control firewall in place
Then run a test Live stream on the local Encoder and check that its output is served from https://<host>/.
Updates on a shared host
Update both products in the same maintenance window, with the operation stopped:
| Update | Effect on the shared host |
|---|---|
| Live Control | The update reconfigures and restarts the Docker service. The Encoder service depends on Docker, so it is stopped and started with it: local Live streams drop for one to two minutes and recover on their own. The port override and the DOCKER-USER rules are kept. |
| Live Encoder | Live Control is not affected. SSH sessions can drop while the SSH server is updated. |
Follow the order recommended in Updates — Encoder first, then Live Control — and after the Live Control update check:
curl -sk -o /dev/null -w "%{http_code}\n" https://127.0.0.1:9443/ # Live Control still on 9443
sudo liveencoder status # Encoder back up
sudo iptables -S DOCKER-USER # Firewall rules still in place
Cross-links
- Prepare the host — DNS, NTP, swap and OS update policy.
- Install C21 Live Control — installer flags, CLI, backups, SSL.
- Install C21 Live Encoder — installer flags, hardware drivers, CLI.
- Updates — update flow, rollback and version compatibility.
- Licenses — license catalog and file format.
- Devices — the section where the registered Encoders appear.