Before You Start
- Network setup should happen before hardware arrives or before a deployment script runs. Whichever path you’re on, get the Network Requirements section done first so the transcoder can reach cameras and the Worlds platform the moment it’s powered on or deployed.
- Worlds does not store your video. Video is processed for AI/ML inference, but the video itself stays in storage you control (your own Azure Blob Storage or AWS S3, depending on your setup).
Choosing a Deployment Option
Option 1: Worlds-Managed Edge Transcoder Hardware
Plug-and-play: Worlds pre-configures the hardware, you handle local networking and power, and secure remote support is available over VPN. Hardware options:- Standard, climate-controlled environment - two Intel NUC small form factor computers in a high-availability, redundant configuration. Scalable up to 10 cameras.
- Ruggedized (outdoor/extreme environments) - a Protectli ruggedized computer rated for -10°C to 50°C (14°F to 122°F). Scalable up to 2 cameras.
- OS: Ubuntu 24.04 LTS, minimal install with only what the transcoder service needs
- Containerization: the transcoder runs in Docker, using the
worlds-transcoderimage, pulled from a private registry - Service management: a systemd service (
edge-transcoder.service) starts the container on boot, restarts it automatically on failure or power loss, and handles logs through Docker’s logging - Networking: UFW blocks all inbound traffic by default except SSH and HTTPS; Tailscale is optional for Worlds’ remote access; a static IP can be configured via netplan
- Monitoring: vnStat tracks network usage over time; container logs are available through Docker
- Configuration: values like
COMPANY_ID,SITE_ID, andTRANSCODER_NAMElive in/etc/default/transcoder, sourced by systemd at startup - Security: OpenSSH for remote management; the registry login credentials live in the environment file so only authorized images get pulled
Option 2: Customer-Managed Transcoder Options
Full control over resources, scaling, and hardware or cloud VM choice. Video never leaves your control. Compute options:- Edge hardware (see Deploying with Docker + systemd, below)
- Cloud-based transcoder VM (see Deploying with K3s, below, or a systemd install on a cloud VM)
- If using a cloud VM, you’ll want a private link between your edge/site (where the cameras are) and the cloud VM, so the transcoder can reach cameras on private IPs. Examples: AWS Direct Connect, PrivateLink, or Site-to-Site VPN; Azure ExpressRoute, Private Link, or Site-to-Site VPN.
- You’ll also need a cloud-based secure storage solution (AWS S3 or Azure Blob Storage). Worlds needs secure access to this storage for AI processing, but does not store your video in a Worlds-hosted environment, you retain full control over access, backup, and retention.
Application security baseline:
Network configuration summary (see Network Requirements below for full detail):
Installation:
- Worlds-provided hardware: ships pre-configured with minimal Ubuntu 24.04 LTS and the transcoder running in Docker. Needs standard 120VAC power and a non-PoE network connection; a mounting shelf and cables are included. Complete the Network Requirements section before the hardware arrives.
- Customer-managed: review hardware, network, storage, and security options with your Worlds Account Team first. Worlds provides a secure download link and installation instructions (see Deploying with Docker + systemd or Deploying with K3s below). Complete networking access before installing the transcoder server so you can fully verify functionality once it’s deployed.
Network Requirements
To allow proper communication between your on-site or cloud transcoder and the Worlds-hosted cloud environment, allow the local and outbound connections below. Work with your IT/Security team to apply these. All connections are outbound-initiated from the transcoder. No inbound firewall rules are required, including for remote support via Tailscale. Summary, at a glance:- Everything is outbound. Scope rules with
<Transcoder_IP>as the source where possible. - Allow outbound TCP 443 to the cloud FQDNs below.
- Allow the transcoder to reach your cameras locally (RTSP 554).
- Two endpoints use gRPC (HTTP/2):
coordinatorandtracks-service. If you run TLS inspection or a forward proxy, follow HTTP/2 & Proxy Requirements below, or these two will fail silently while everything else keeps working. - When you’re done, run the validation script in Post-Configuration Validation.
Outbound Internet (Transcoder → Cloud). All endpoints below are required; all are outbound TCP:
† Uses HTTP/2. If you run TLS inspection or a proxy, see HTTP/2 & Proxy Requirements below, or these will fail.
Note: image layer downloads may also use the ACR data endpoint (
*.blob.core.windows.net); make sure it isn’t blocked by URL filtering.
Local Network (Transcoder → LAN devices):
Note: for the IO adapter, also add a Nessus scan exclusion for
<io-adapter_IP>.
⚠️ HTTP/2 & Proxy Requirements (read this if you inspect or proxy traffic)
coordinator.<DOMAIN> and tracks-service.<DOMAIN> use gRPC, which requires HTTP/2 end to end. gRPC does not fall back to HTTP/1.1. If HTTP/2 is stripped or downgraded anywhere in the path, these two endpoints fail while plain HTTPS endpoints (blob storage, ACR, coordinator REST) keep working, which makes the failure easy to miss.
1. TLS inspection / SSL interception. If your proxy decrypts and re-encrypts TLS, do one of the following for both endpoints (and ideally all Worlds endpoints):
- Exempt them from TLS inspection (SSL bypass / allowlist) so the connection tunnels straight through. Simplest and most reliable.
- Configure the inspection engine to preserve HTTP/2 (pass the ALPN token
h2through unchanged), only if you’ve confirmed the product fully supports HTTP/2; many silently downgrade to HTTP/1.1.
- Set
HTTPS_PROXYon the transcoder (not justHTTP_PROXY), since all cloud endpoints are on port 443. - Do not put the Worlds hosts in
NO_PROXY, that forces a direct connection the egress firewall usually blocks. - The proxy must allow HTTP CONNECT to port 443 for these hosts.
coordinator REST: OK but tracks-service gRPC: UNREACHABLE, the channel stuck in CONNECTING (or a 15s timeout), and every camera fails to start. A successful port (nc) test does not rule this out, use the HTTP/2 check below.
Other common blockers:
- DNS filtering: the transcoder must resolve
*.<DOMAIN>,*.blob.core.windows.net,*.azurecr.io, and (if applicable)*.tailscale.com. - Bandwidth: video upload to blob storage is the dominant flow. Plan for sustained upstream capacity per camera; contact Worlds for sizing figures.
Post-Configuration Validation
After all rules are applied, run this once from the transcoder host (or pod). Every line should printPASS. Needs nc, and curl built with HTTP/2 support for the h2 check.
FAIL h2 alongside a PASS tcp for the same host means the port is open but HTTP/2 is being broken (TLS inspection or proxy). See HTTP/2 & Proxy Requirements above.
Alternative ALPN check if curl lacks HTTP/2 support (direct path only):
- Apply IP filtering per-device where possible, using
<Transcoder_IP>as the source. - If the transcoder runs on a cloud VM rather than the local network, routing must still grant it full access to the cameras’ network.
- All cloud service endpoints are hosted in Azure.
- For additional verification scripts or support, contact Worlds Support: support@worlds.io
Appendix: Optional Remote Support Access (Tailscale VPN)
Required only where management access is granted to the Worlds Support team via Tailscale VPN. All connections are outbound.
Verify Tailscale with
tailscale status and tailscale netcheck from the Tailnet.
Deploying with Docker + systemd
This path deploys the Worlds Edge Transcoder on a host using Docker (or Podman) and systemd. The deployment scripts will:- Detect and install NVIDIA drivers when a GPU is present
- Install the appropriate container runtime (Docker or Podman) for your OS
- Configure the NVIDIA Container Toolkit for GPU container access
- Create a systemd service that runs the transcoder container
- Enable GPU passthrough when available, and fall back to CPU otherwise
Prerequisites
Hardware:- CPU: 8+ cores, Memory: 8 GB+, Disk: 30 GB+ free
- GPU (optional): NVIDIA Tesla T4, RTX, or any NVIDIA card with encoder support
- Recommended instance: Azure Standard NC16as T4 v3 (16 vCPUs, 110 GiB memory) for up to 10 cameras at 1080p/30fps when running Face Blurring
- Ubuntu Server 24.04 LTS+ (fresh install recommended); RHEL 10+
- Internet access for package downloads; sudo privileges for the install user
- The scripts detect the OS and install or update the correct runtime: Ubuntu uses Docker, RHEL 10+ uses Podman
- Registry URL:
worldsedgecr.azurecr.io(default) - Registry username and password
- Image tag:
worlds-io/worlds-transcoder:<tag> - Worlds API Key, Company ID, Site ID, Transcoder Name, and Domain (e.g.,
company.worlds.io), your domain must resolveapi.$DOMAIN,coordinator.$DOMAIN, andtracks-service.$DOMAINto the cluster ingress
Architecture
The deployment creates the following on the host:Deployment Steps
1. Download the deployment scripts:deploy.sh is the main wrapper script and runs the full setup in two steps: runtime installation (docker-install.sh, container runtime, NVIDIA drivers, container toolkit), then transcoder deployment (deploy-transcoder.sh, configuration, systemd service, container start).
sudo.
During Step 1 (Runtime Installation), the script:
- Detects an NVIDIA GPU and installs drivers, if present
- Installs Docker Engine or Podman, based on OS
- Installs and configures the NVIDIA Container Toolkit, if a GPU is present
- Sets up the current user for container access
- Prompts for registry URL and credentials
- Verifies registry access
./deploy.sh, it detects the reboot and resumes automatically.
During Step 2 (Transcoder Deployment), you’re prompted for the needed values (defaults are generally fine to keep), then the script:
- Writes configuration to
/etc/default/transcoder - Creates the container start wrapper at
/usr/local/bin/edge-transcoder-start.sh - Creates and enables the systemd service
- Starts the transcoder container
- Verifies the deployment
- When a GPU is detected, you’re prompted to enable GPU passthrough for the container
- Face blur requires a GPU; the option only appears when GPU passthrough is enabled
- With no GPU available, both are automatically disabled (CPU-only mode)
- Video transcoding itself always runs on CPU, regardless of the GPU setting
Verification
Configuration Details
Environment file, location/etc/default/transcoder, owned by root:docker, mode 640:
/etc/systemd/system/edge-transcoder.service:
- Runs the container start wrapper script
- Applies GPU flags (
--gpus allor--device nvidia.com/gpu=all) whenUSE_GPU=true - Mounts
/dev/driand$HOME/logs/into the container - Passes all environment variables from
/etc/default/transcoder - Restarts on failure and starts on boot
Managing the Deployment
Update configuration interactively:GPU Notes
- GPU passthrough is enabled when available and the user opts in
- With no GPU present, the container runs CPU-only and face blur is disabled
- Video transcoding always runs on CPU; only face blur uses the GPU
Troubleshooting
Permission denied (Docker). Cause: the user isn’t in the docker group, or the shell session needs a refresh.Quick Reference
Support (Docker + systemd path)
Before contacting support, collect:systemctl status edge-transcoderoutput- Last 200 lines:
journalctl -u edge-transcoder -n 200 --no-pager docker infoanddocker --version(orpodman info)nvidia-smioutput, if GPU/etc/default/transcoder(redactWORLDS_API_KEY)- OS version:
cat /etc/os-release
Deploying with K3s
This path deploys the Worlds Transcoder on a K3s cluster at the edge (cloud or on-prem), with or without GPU. The included scripts auto-detect hardware, install NVIDIA drivers when a GPU is present, set up K3s, CoreDNS, and ACR, and deploy the transcoder workload.Prerequisites
Hardware:- CPU: 8+ cores, Memory: 8 GB+, Disk: 30 GB+ free
- GPU (optional): NVIDIA Tesla T4, RTX, or any NVIDIA card with encoder support
- Recommended instance: Azure Standard NC16as T4 v3 (16 vCPUs, 110 GiB memory) for up to 10 cameras at 1080p/30fps when running Face Blurring (face blur requires a supported NVIDIA GPU)
- Ubuntu Server 22.04 LTS+ (fresh install recommended); RHEL 10+
- Internet access for package downloads; sudo privileges for the install user
- Registry URL:
worldsedgecr.azurecr.io(default) - Registry username and password
- Image:
worlds-io/worlds-transcoder:<tag> - Worlds API Key, Company ID, Site ID, Transcoder Name, and Domain (e.g.,
company.worlds.io), your domain must resolveapi.$DOMAIN,coordinator.$DOMAIN, andtracks-service.$DOMAINto the cluster ingress
Deployment Steps
1. Download and extract:install-k3s.sh, deploy-transcoder.sh, and lib/common.sh.
2. Install K3s:
./install-k3s.sh, saved credentials resume automatically.
This step handles: OS detection, NVIDIA driver install (if a GPU is present), K3s install (pinned version, no Traefik), CoreDNS configuration to forward external queries to host DNS, GPU Operator setup, ACR integration, and labeling the current node.
Offline install (no github.com access):
worlds-ns namespace: the worlds-config ConfigMap, the worlds-secret Secret, and the worlds-transcoder Deployment.
4. Verify:
dial tcp: lookup ...: Try again errors and long ImagePullBackOff cycles. Pre-pull via k3s ctr (one persistent connection, single DNS lookup) before running deploy-transcoder.sh:
deploy-transcoder.sh finds the image in the local content store and starts the pod almost immediately. Skip this step on cloud hosts (Azure, AWS), their DNS resolvers handle the parallel-pull pattern fine.
Operations
Update configuration: re-run./deploy-transcoder.sh, it detects existing resources and applies the new values in place after confirmation.
Update a single ConfigMap value (no full re-prompt needed):
Troubleshooting
Test DNS from inside the cluster:
Cleanup
Reference
Support (K3s path)
Before contacting support, gather:- OS version:
cat /etc/os-release - K3s version:
k3s --version - Installation logs:
~/k3s-install.log,~/transcoder-deploy.log - Cluster state:
kubectl get pods -A - Pod logs:
kubectl logs -n worlds-ns -l app.kubernetes.io/name=worlds-transcoder --tail=100 - Full error messages

