Installation Guide

Detailed instructions for installing TheiaCast on various platforms

Table of Contents

System Requirements

Server Requirements

ComponentMinimumRecommended
CPU2 cores4 cores
RAM2 GB4 GB
Storage10 GB50+ GB (depending on content)
OSLinux, Windows, macOSLinux (Ubuntu 22.04 LTS)
Network100 Mbps1 Gbps
SoftwareDocker & Docker ComposeDocker & Docker Compose

Display Device Requirements

Windows Client

ComponentMinimumRecommended
CPUIntel Core i3 or equivalentIntel Core i5 or better
RAM2 GB4 GB
Storage5 GB10 GB
OSWindows 10Windows 11
NetworkStable connection to serverWired Ethernet

Raspberry Pi Client

ComponentMinimumRecommended
ModelRaspberry Pi 3B+Raspberry Pi 4 (4GB RAM)
Storage16 GB microSD32 GB microSD (Class 10)
OSRaspberry Pi OS LiteRaspberry Pi OS (64-bit)
NetworkWi-FiWired Ethernet

Android / Fire TV Client

Android TV or Fire TV device running Android 7.0 / Fire OS 6 or later(tested on a Fire TV Stick 4K Max). See Android / Fire TV Client under Client Installation for setup and current limitations.

LG webOS Client (Beta)

LG commercial/Smart Signage webOS displays with Developer Mode available. See LG webOS Client under Client Installation for setup.

Samsung Tizen (SSSP) Client (Beta)

Samsung Smart Signage Platform displays (QB/QM/QP series and similar) - not consumer Tizen TVs. Requires a Samsung Partner certificate to sign the app before install. See Samsung Tizen (SSSP) Client under Client Installation for setup.


Server Installation

Automated Installer (Recommended)

install-theiacast-server.sh does everything below in one run on Ubuntu or Debian: checks for Docker (installing it and its dependencies if missing), then a guided setup that writes docker-compose.yml, .env, and docker/mediamtx/mediamtx.yml for you, optionally opens the needed firewall ports, and starts the stack. Run it as a normal sudo-capable user — not root, and not with sudo in front of the command below; the script escalates internally only for the steps that need it:

curl -sSL https://gist.githubusercontent.com/jimmyeao/215ab17d99d5eb7f998176c25ee1fc73/raw/install-theiacast-server.sh | bash

It’s safe to re-run — it detects an existing install, backs up your current.env anddocker-compose.yml first, and reuses your existing PostgreSQL password and JWT secret rather than generating new ones (which would otherwise leave the backend unable to authenticate against your existing database — Postgres only honors a password change on a brand-new, empty data volume). The manual steps below are exactly what this script automates, and are the reference if you need to install on an unsupported OS or want to see precisely what each step does.

Docker Installation (Manual)

Docker provides the easiest and most reliable installation method.

Step 1: Install Docker

On Ubuntu/Debian:

# Update package index
sudo apt update

# Install prerequisites
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common

# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# Add your user to docker group
sudo usermod -aG docker $USER

# Log out and back in for group changes to take effect

On Windows:

  1. Download Docker Desktop from https://www.docker.com/products/docker-desktop
  2. Run the installer
  3. Restart your computer
  4. Launch Docker Desktop

On macOS:

  1. Download Docker Desktop from https://www.docker.com/products/docker-desktop
  2. Drag Docker.app to Applications
  3. Launch Docker from Applications

Step 2: Verify Docker Installation

docker --version
docker compose version

You should see version numbers for both commands.

Step 3: Create TheiaCast Directory Structure

mkdir -p ~/theiacast
cd ~/theiacast
mkdir -p ssl-certs  # For optional SSL certificates

Step 4: Create docker-compose.yml

Create a file named docker-compose.yml with the following content:

services:
  postgres:
    image: postgres:15-alpine
    container_name: theiacast-postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
      POSTGRES_DB: theiacast
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d theiacast"]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 10s
    restart: unless-stopped

  backend:
    image: ghcr.io/jimmyeao/theiacast-backend:latest
    container_name: theiacast-backend
    environment:
      - ConnectionStrings__Default=Host=postgres;Port=5432;Database=theiacast;Username=postgres;Password=${POSTGRES_PASSWORD:-postgres}
      - ASPNETCORE_ENVIRONMENT=Production
      - Jwt__Secret=${JWT_SECRET:-dev-secret-key}
      - BASE_URL=http://backend:8080
      # Optional: set your own initial admin password instead of the logged one-time one - see Step 9
      - Setup__InitialAdminPassword=${INITIAL_ADMIN_PASSWORD:-}
      # Teams Relay: the public RTMP endpoint shown to admins for handing to meeting organizers
      - TeamsRelay__PublicRtmpHost=${TEAMS_RELAY_PUBLIC_HOST:-localhost}
      - TeamsRelay__PublicRtmpPort=1935
      - TeamsRelay__MediaMtxApiBaseUrl=http://mediamtx:9997
    ports:
      - "5001:8080"
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - theiacast_media:/app/wwwroot
      - theiacast_dataprotection_keys:/app/dataprotection-keys
      - ${SSL_CERT_PATH:-./ssl-certs}:/app/ssl-certs
    restart: unless-stopped

  frontend:
    image: ghcr.io/jimmyeao/theiacast-frontend:latest
    container_name: theiacast-frontend
    ports:
      - "${HTTP_PORT:-80}:80"
      - "${HTTPS_PORT:-443}:443"
    volumes:
      - ${SSL_CERT_PATH:-./ssl-certs}:/etc/nginx/ssl:ro
    depends_on:
      - backend
    restart: unless-stopped

  # Teams Relay (Microsoft Teams RTMP -> screens). Publishes only RTMP ingest on 1935;
  # devices reach the HLS output through the frontend's /hls/ proxy, so no other port is
  # needed on the host. Requires the mediamtx.yml config file below (Step 5) at this
  # relative path.
  mediamtx:
    image: bluenviron/mediamtx:1.9.3
    container_name: theiacast-mediamtx
    volumes:
      - ./docker/mediamtx/mediamtx.yml:/mediamtx.yml:ro
    ports:
      - "1935:1935"
    depends_on:
      - backend
    restart: unless-stopped

volumes:
  postgres_data:
  theiacast_media:
  theiacast_dataprotection_keys:

The theiacast_dataprotection_keys volume must persist — it holds the keys that encrypt stored content passwords and auto-login sessions, and losing it makes them unreadable after a redeploy. The backend ssl-certs mount is the same directory the frontend serves TLS from, so the admin UI’s Settings → SSLupload lands where nginx can read it.

Step 5: Create the Teams Relay config file (mediamtx.yml)

The mediamtx service above mounts this file read-only at a path relative to your docker-compose.yml. Create it:

mkdir -p docker/mediamtx

Then create docker/mediamtx/mediamtx.yml with the following content:

logLevel: info

###############################################
# RTMP - Teams' Custom Streaming app publishes here as rtmp://<host>:1935/live/<streamKey>

rtmp: yes
rtmpAddress: :1935
rtmpEncryption: "no" # Teams RTMP-Out does not use RTMPS

###############################################
# HLS output for device playback

hls: yes
hlsAddress: :8888
# mpegts (classic TS-segmented HLS), not the default lowLatency/fmp4 - the fmp4/CMAF path
# needs broader MSE support than webOS/Android WebView's firmware-dependent Chromium builds
# can be assumed to have. A few extra seconds of glass-to-glass latency is an acceptable
# trade for playback actually working on every device client.
hlsVariant: mpegts
# Don't remux until a device actually requests the stream - no point generating HLS segments
# while a session is only WaitingForPublish or nobody has tuned in yet.
hlsAlwaysRemux: false

###############################################
# Control API - polled by the backend for live/idle state and used to force-disconnect an
# orphaned publish. Never published to the host - see the compose file above.

api: yes
apiAddress: :9997

###############################################
# Publish authentication - the actual security boundary for Teams Relay. Every publish
# attempt (i.e. every RTMP connection reaching the port forwarded from the internet) is
# checked against an active session's stream key by the backend before MediaMTX accepts it.
# Reads (device HLS pulls) are excluded - they stay on the LAN/internal network.

authMethod: http
authHTTPAddress: http://backend:8080/teams-relay/mediamtx-auth
authHTTPExclude:
  - action: read
  - action: playback
  - action: api
  - action: metrics

###############################################
# Paths - Teams Relay stream keys are opaque per-session tokens, so paths are created
# dynamically per publish rather than pre-registered; this single "all_others" block applies
# to every one of them.

paths:
  all_others:

Only ever mount this file read-only (:ro, already set in the compose file above) into the stock bluenviron/mediamtx image — don’t build a custom image around it. The official image has no shell, so it can’t run script-based hooks; the backend instead polls MediaMTX’s Control API directly, which needs no image customization at all.

Step 6: Create Environment File (.env)

Create a .env file in the same directory:

# PostgreSQL password
POSTGRES_PASSWORD=YourSecurePassword123!

# JWT secret (minimum 32 characters)
JWT_SECRET=your-very-long-and-secure-secret-key-here-32-chars-minimum

# Optional: set the 'admin' account's password on first boot (min 8 chars). If you leave this
# unset, a one-time random password is generated and logged once instead - see Step 9.
INITIAL_ADMIN_PASSWORD=

# Optional: Custom ports
# HTTP_PORT=80
# HTTPS_PORT=443

# Teams Relay: the public hostname/IP meeting organizers publish RTMP to (your public IP or
# DDNS hostname - the admin UI shows it to them as the streaming server)
TEAMS_RELAY_PUBLIC_HOST=change_me_to_your_public_ip_or_ddns_hostname

# Optional: Custom SSL certificate path
# SSL_CERT_PATH=./ssl-certs

Important Security Notes:

  • Replace YourSecurePassword123! with a strong, unique password
  • Replace the JWT_SECRET with a long, random string (32+ characters)
  • Keep this file secure and never commit it to version control

Step 7: Start TheiaCast

sudo docker compose up -d

This command will:

  • Download the required Docker images (first time only)
  • Create and start all containers
  • Set up the database
  • Configure networking

Step 8: Verify Installation

Check that all containers are running:

sudo docker compose ps

You should see three containers (postgres, backend, frontend) with status "Up".

Check the logs:

# View all logs
sudo docker compose logs

# Follow backend logs
sudo docker compose logs -f backend

# Follow frontend logs
sudo docker compose logs -f frontend

Step 9: Access the Dashboard

Open your web browser and navigate to:

  • HTTP: http://localhost or http://your-server-ip
  • HTTPS: https://localhost or https://your-server-ip (if SSL configured)

First Login:

There is no shipped default password. Log in as admin with whichever password the seed used:

  • If you set INITIAL_ADMIN_PASSWORD in your .env before first boot (see Step 6), use that password.
  • Otherwise a one-time random password was generated and logged once at startup - find it with docker compose logs backend | grep "one-time generated password", then change it after logging in.

There is no self-registration for the first account - Register requires being already signed in as an Admin. The seeded admin user is the bootstrap account every other user gets created from.


Client Installation

Windows Client

The Windows installer provides an interactive setup that configures everything automatically.

Step 1: Register Device in Dashboard

  1. Open the TheiaCast web dashboard
  2. Navigate to "Devices"
  3. Click "+ Add Device"
  4. Enter a device name (e.g., "Reception Display")
  5. Enter a unique device ID (e.g., "reception-01")
  6. Click "Create"
  7. Copy the device token from the popup - you'll need this during installation

Step 2: Download and Run Installer

  1. Download the installer from our CDN
  2. Run the installer as Administrator
  3. When prompted, enter:
    • Server URL: http://your-server-ip:5001
    • Device ID: The device ID you created (e.g., "reception-01")
    • Device Token: The token you copied from the dashboard
  4. The installer will automatically install and start the client as a Windows service

Note: The installer handles all configuration automatically. You do not need to manually edit any files or install the service using PowerShell.

Step 3: Verify Connection

  1. Return to the TheiaCast web dashboard
  2. Go to "Devices"
  3. Your device should show "Online" with a green indicator
  4. If not online, check the service status in Windows Services or view logs in Event Viewer

Raspberry Pi Client

The automated installer script handles all dependencies, configuration, and service setup.

Step 1: Prepare Raspberry Pi

1. Install Raspberry Pi OS:

2. Update system:

sudo apt update
sudo apt upgrade -y

Step 2: Register Device in Dashboard

  1. Open the TheiaCast web dashboard on another computer
  2. Navigate to "Devices"
  3. Click "+ Add Device"
  4. Enter a device name (e.g., "Lobby Display")
  5. Enter a unique device ID (e.g., "lobby-pi-01")
  6. Click "Create"
  7. Copy the device token from the popup - you'll need this during installation

Step 3: Run Automated Installer

Run the following command on your Raspberry Pi. The installer will automatically detect your system, install all required dependencies (Node.js, Chromium, etc.), and configure the client.

sudo curl -sSL https://gist.githubusercontent.com/jimmyeao/9a6922cdf1c69da92f1be9c7e3463052/raw/install-theiacast-client.sh | sudo bash

During installation, you will be prompted to enter:

  • Server URL: http://your-server-ip:5001
  • Device ID: The device ID you created in the dashboard
  • Device Token: The token you copied from the dashboard

Note: The installer script handles everything automatically including:

  • Installing Node.js and other dependencies
  • Downloading and installing the TheiaCast client
  • Creating the configuration file
  • Setting up the systemd service
  • Starting the client automatically

Step 4: Verify Connection

  1. Check the service status:
    sudo systemctl status theiacast-client
  2. Return to the TheiaCast web dashboard
  3. Go to "Devices"
  4. Your device should show "Online" with a green indicator

Device status

The device card also shows:

  • IP address - the device's IP address
  • Seen from - the connection IP as observed by the server
  • OS / version - the operating system running on the device
  • Client version - the version of the TheiaCast client
  • Screen resolution - the resolution of the attached display
  • Last seen - when the device last checked in

Note: These populate automatically once a device running the latest client connects. If they're blank, re-run the installer to update the client.

Service Management

On Raspberry Pi the client runs as a system service, so these commands require sudo.

# Check status
sudo systemctl status theiacast-client

# View recent logs
sudo journalctl -u theiacast-client -n 50

# Follow live logs
sudo journalctl -u theiacast-client -f

# Restart the client app
sudo systemctl restart theiacast-client

# Stop the client
sudo systemctl stop theiacast-client

Note: The service is enabled at boot, so the client starts automatically after a reboot. It waits for the desktop session to come up before launching.

Updating the Client

To update, re-run the same install one-liner. It preserves your existing configuration - press Enter at each prompt to keep the current Server URL, Device ID, and Device Token. Upgrades from older versions are migrated automatically.

sudo curl -sSL https://gist.githubusercontent.com/jimmyeao/9a6922cdf1c69da92f1be9c7e3463052/raw/install-theiacast-client.sh | sudo bash

Device Controls

The device card in the dashboard has two power actions:

  • Restart client software (↻) - relaunches the TheiaCast client app only. It takes a few seconds and does not reboot the operating system. Use this for a stuck client, or to clear a browser memory leak.
  • Reboot device (OS) (⏻) - reboots the whole Raspberry Pi. The device will be offline for roughly 1-2 minutes.

Note: The permission required to reboot the device is configured automatically by the installer - there is no manual setup. If the button does nothing, the device is running an older client; re-run the installer to update it.

Android / Fire TV Client

Download the signed APK from the Downloads page (or the Customer Portal for a build with your server address pre-configured), or grab the latest directly: https://thfhaappstore.blob.core.windows.net/theiacast/theiacast-client-android.apk. Not yet on the Amazon Appstore or Google Play — sideload it, or push it with a mobile-device-management tool.

It targets Android TV and Fire TV devices (tested on a Fire TV Stick 4K Max) and runs as a native app with a full-screen WebView — the device itself is the browser, not a headless one it drives.

Setup

  1. Install the APK on the device: adb connect <device-ip>:5555 then adb install -r theiacast-client-android.apk (sideload), or push it via a mobile-device-management tool.
  2. On first launch, an on-screen form asks for the server address. The TV’s system keyboard is D-pad navigable — no separate remote-typing needed.
  3. The app then shows a pairing QR code. Scan it, or enter the code, from Devices → Add Device → Pair in the dashboard to claim the device.
  4. The device registers and appears on the Devices page like any other client.

Fire TV: the “Are you still watching?” prompt

Fire OS shows a “still watching” prompt after roughly four hours when an app is on screen and awake with no remote input — exactly what a signage player does. Apps cannot suppress it in code (Amazon reserves that for the platform). To turn it off, any of: set Settings → Display & Sounds → Screensaver to Never; or grant the app WRITE_SECURE_SETTINGS once over adb (adb shell pm grant com.theiacast.client android.permission.WRITE_SECURE_SETTINGS) and it disables the screensaver and sleep timeouts itself on every launch; or for a permanent fix that survives resets, Amazon exempts signage apps by package name — contact [email protected] and we can raise the exemption request with Amazon Developer Support. Even without either step the app self-recovers: if the prompt goes unacknowledged and Fire OS sends the app to the home screen, it relaunches itself within a couple of seconds.

Current limitations

  • Live remote view works, but needs a one-time on-screen consent dialog after each app restart (Android grants no way to skip it).
  • Remote input is limited — click and scroll work; typing is text-replacement only, not character-by-character.
  • Remote control is unavailable on Fire TV specifically — Fire OS blocks third-party accessibility services. Android TV / Google TV is expected to be fine.
  • There is no in-app self-update yet — a new version means installing a new APK.

LG webOS Client (Beta)

Beta. This build has not yet been verified against a physical LG signage display. The steps below match how the client is built and how LG documents the webOS TV CLI, but expect rough edges - email [email protected] if you hit an issue.

Download the .ipk from the Downloads page, or the latest directly: https://thfhaappstore.blob.core.windows.net/theiacast/theiacast-client-webos.ipk. Installing it needs the webOS TV CLI — the webOS OSE ares-cli some Linux distros package does not work against a real consumer TV and fails with permission/connection errors.

On the TV

  1. Open the Developer Mode app and enable Developer Mode.
  2. In the same app, turn on the Key Server.
  3. Note the TV’s IP address and the 6-character Passphrase it shows.

On your computer

# Download the TV's SSH private key (Key Server must be ON)
curl -sS http://<TV_IP>:9991/webos_rsa -o ~/.ssh/webos_rsa
chmod 600 ~/.ssh/webos_rsa

# Pair with the TV (installs the CLI on demand via npx)
npx -p @webos-tools/cli ares-setup-device -a theiacast-webos \
  -i "host=<TV_IP>" -i "port=9922" -i "username=prisoner" \
  -i "privatekey=webos_rsa" -i "passphrase=<PASSPHRASE>"

# Install
npx -p @webos-tools/cli ares-install -d theiacast-webos theiacast-client-webos.ipk

username is prisoner for a consumer LG TV; commercial signage sets may use root if rooted. On first launch the app asks for the TheiaCast server address, then shows a pairing code/QR to claim from Devices → Add Device → Pair.

In-app self-update does not work on a stock consumer TV — webOS denies the privileged Luna calls it needs to a third-party app. Update by repeating the ares-install step with a newer .ipk, or ask your TheiaCast admin to push it via Settings → Devices → (device) → webOS Deploy (a server-side push over the same dev-mode SSH channel, works on consumer TVs where the in-app path is denied). Live remote screenshots/screencast are also not available on a stock consumer TV for the same reason.

Samsung Tizen (SSSP) Client (Beta)

Beta. This build has not yet been verified against a physical Samsung SSSP display. The steps below match how the client is built and how Samsung documents SSSP widget signing/installation, but expect rough edges - email [email protected] if you hit an issue.

Targets Samsung Smart Signage Platform displays (QB/QM/QP series and similar) — the commercial-signage line, not consumer Tizen TVs.

The signing requirement (read this first). SSSP hardware refuses widgets that are not signed with a Samsung Partner certificate — the free public/personal Tizen developer certificates are explicitly rejected. Applying to the Samsung Partner Program is a business step external to TheiaCast and is the usual bottleneck — start it before you need the screens live. The release artifact (theiacast-client-tizen.wgt, on the Downloads page) is unsigned on purpose — it must be re-signed before a display will accept it.

# Sign with your partner profile from Tizen Studio's CLI
tizen package -t wgt -s <your-partner-profile> -- theiacast-client-tizen.wgt

Install paths, easiest first

  • MagicINFO / SI Server (recommended for fleets): Samsung’s own provisioning tooling can host and push signed widgets to displays; the SI Server URL Launcher on the display polls an endpoint serving the .wgt.
  • Tizen Studio CLI (development/emulator): tizen install -n theiacast-client-tizen.wgt against an emulator or a developer-mode panel.
  • USB: copy the signed .wgt onto a USB stick and install from the display’s on-screen menu.

Setup after install is identical to the webOS client: on first launch the app asks for the TheiaCast server address, then shows a pairing code/QR to claim from Devices → Add Device → Pair.

Feature caveats on Tizen (platform limits, not missing work)

  • Screenshots / remote view / screencast: no screen-capture API exists for a web app on Tizen. Requests return “unsupported”.
  • In-app updates: no equivalent of the webOS install service. Update via MagicINFO/SI Server or a new signed .wgt; the Updates page reports this honestly if you try.
  • Screen power / volume / reboot: behind Samsung’s B2B partner APIs — not reachable from a normal web app. A device reboot reloads the app instead.

Playlist rotation, broadcasts/tickers, Teams Relay, remote click/type/scroll, auto-login and cookie-consent injection all work as on the other clients.


Post-Installation

SSL Certificate Setup (Optional)

For HTTPS access, you need SSL certificates.

Option 1: Self-Signed Certificate (Testing)

# Use the exact IP or DNS name admins will type into the browser.
HOST=192.168.1.50            # or e.g. signage.example.com

cd ~/theiacast/ssl-certs
openssl req -x509 -nodes -days 825 -newkey rsa:2048 -set_serial 1 \
  -keyout key.pem -out cert.pem \
  -subj "/CN=$HOST" \
  -addext "subjectAltName=IP:$HOST"     # use DNS:$HOST instead if HOST is a hostname
chmod 600 key.pem
Files must be named cert.pem and key.pem in ssl-certs/. subjectAltName and -set_serial are not optional: current Chrome/Edge/Safari reject a certificate with no SAN, and OpenSSL 1.x otherwise picks a serial number browsers can refuse outright (ERR_SSL_SERVER_CERT_BAD_FORMAT, with no “continue anyway”). A self-signed certificate still warns; where Edge/Chrome policy (SSLErrorOverrideAllowed=false) removes the bypass, import cert.peminto the machine’s Trusted Root store (GPO/Intune) or use a CA-issued certificate. After changing the files: docker compose restart frontend, then check docker compose logs frontend for certificate found, serving HTTPS on 443.

Option 2: Let's Encrypt (Production)

# Install certbot
sudo apt install certbot python3-certbot-nginx

# Obtain certificate
sudo certbot --nginx -d yourdomain.com

# Certificates will be in /etc/letsencrypt/live/yourdomain.com/
# Copy to TheiaCast directory
sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem ~/theiacast/ssl-certs/cert.pem
sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem ~/theiacast/ssl-certs/key.pem
sudo chown $USER:$USER ~/theiacast/ssl-certs/*.pem

Restart frontend:

cd ~/theiacast
docker compose restart frontend

Firewall Configuration

If you're using a firewall, open the required ports:

# Ubuntu/Debian with ufw
sudo ufw allow 80/tcp    # HTTP
sudo ufw allow 443/tcp   # HTTPS
sudo ufw allow 5001/tcp  # Backend API

# Or with firewalld (CentOS/RHEL)
sudo firewall-cmd --permanent --add-port=80/tcp
sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-port=5001/tcp
sudo firewall-cmd --reload

For Teams Relay (streaming a Teams meeting to screens), the RTMP ingest port must also be reachable from the internet — forward 1935/tcp on your router/firewall to the host, and set TEAMS_RELAY_PUBLIC_HOST in .env to the public hostname organizers publish to.

Backup Configuration

Set up regular backups of your data:

#!/bin/bash
# backup-theiacast.sh

BACKUP_DIR="/backup/theiacast"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# Backup database
docker exec theiacast-postgres pg_dump -U postgres theiacast > $BACKUP_DIR/db_$DATE.sql

# Backup media files
docker run --rm -v theiacast_media:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/media_$DATE.tar.gz -C /data .

# Keep only last 7 days
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete

Make it executable and add to cron:

chmod +x backup-theiacast.sh
crontab -e
# Add: 0 2 * * * /path/to/backup-theiacast.sh

Troubleshooting

Server Issues

Containers won't start:

# Check logs
docker compose logs

# Check specific service
docker compose logs backend

# Restart all services
docker compose restart

Database connection errors:

# Check PostgreSQL is running
docker compose ps postgres

# Check database logs
docker compose logs postgres

# Reset database (WARNING: Deletes all data)
docker compose down -v
docker compose up -d

Port conflicts:

# Check what's using port 80
sudo lsof -i :80

# Change port in .env file
echo "HTTP_PORT=8080" >> .env
docker compose up -d

Client Issues

Windows client won't start:

  1. Check Windows Event Viewer for errors
  2. Verify service is running in Windows Services
  3. Check firewall allows outbound connections
  4. Verify server URL is accessible: curl http://your-server:5001/health

Raspberry Pi client crashes:

# Check logs
sudo journalctl -u theiacast-client -n 100

# Check system resources
htop

# Increase memory (edit /boot/config.txt)
gpu_mem=256

# Restart
sudo reboot

Device shows offline:

  1. Check network connectivity: ping your-server-ip
  2. Verify device token is correct
  3. Check client logs for connection errors
  4. Verify firewall allows WebSocket connections (port 5001)

Common Issues

See the FAQ for more troubleshooting tips.


Next Steps

Need Help?

Need technical support? Visit our Contact page or email [email protected]