Skip to content

Deployment Guide

How to deploy OpenAVC to production hardware for your AV spaces.

For initial setup and testing, see Getting Started. This guide covers deploying to production.

Where OpenAVC Runs

OpenAVC runs on any hardware with Python 3.11+. Choose the deployment mode that fits your environment:

ModeDescriptionBest For
Windows PCInstall on a rack PC or mini PC using the Windows installer (.exe). Runs as a Windows service with a system tray app.AV racks with a Windows PC, smaller installations
Linux ServerInstall via script on any Linux machine. Runs as a system service.IT-managed infrastructure, dedicated AV servers
DockerOne container per space, orchestrated with docker-compose.Enterprise IT, multi-space servers
VMInstall in a virtual machine. One or many instances per VM.Organizations with virtualization infrastructure
Mini PC / SBCDedicated hardware (NUC, mini PC, single-board computer). One instance per space.Permanent installations, spaces needing serial/GPIO

All modes are functionally identical. Serial port control (RS-232/485) requires physical hardware access or USB adapters. IP-only control works in all modes including Docker and VM.

Installation

See Getting Started for detailed installation steps covering all four methods:

MethodInstall Command / Action
Windows InstallerDownload from GitHub Releases and run the .exe
Dockercurl -fsSL https://raw.githubusercontent.com/open-avc/openavc/main/installer/docker-compose.yml -o docker-compose.yml && docker compose up -d
Linuxcurl -sSL https://get.openavc.com | sudo bash
From Sourcegit clone, pip install, npm run build, python -m server.main

Network Configuration

PortProtocolPurposeRequired?
8080HTTP/WSWeb UI, REST API, WebSocketYes
19500HTTP/WSSimulator UI (development/testing only)No
19872UDPISC auto-discovery (multi-instance setups only)No

Ensure port 8080 is accessible from:

  • Touchscreens and tablets (Panel UI)
  • Programmer workstations (Programmer IDE)
  • Any external integrations using the REST API

For multi-instance setups using ISC auto-discovery, allow UDP broadcast on port 19872 within the same subnet. For cross-subnet ISC, configure peer addresses manually and allow TCP on each instance’s HTTP port.

Data Directory

OpenAVC separates application code from user data. The application directory contains server code and built frontends. The data directory contains your projects, drivers, configuration, and backups. Updates replace application files but never touch the data directory.

Data directory locations by platform:

PlatformData Directory
Linux/var/lib/openavc
WindowsC:\ProgramData\OpenAVC
Docker/data (volume mount)
Development./data (relative to repo root)

Override with the OPENAVC_DATA_DIR environment variable.

What lives in the data directory:

{data_dir}/
├── projects/ # .avc project files + scripts
├── drivers/ # Community and custom drivers
├── backups/ # Automatic pre-update backups
├── logs/ # Log files (rotated)
├── system.json # System configuration
└── update-cache/ # Downloaded update packages (temp)

System Configuration

System-level configuration controls the server itself: networking, authentication, logging, updates, and cloud connectivity. It is separate from project configuration and stored in the data directory so it persists across updates.

Location: {data_dir}/system.json (created with defaults on first startup if missing).

{
"network": {
"http_port": 8080,
"bind_address": "127.0.0.1",
"control_interface": ""
},
"auth": {
"programmer_password": "",
"api_key": "",
"panel_lock_code": ""
},
"isc": {
"enabled": true,
"discovery_enabled": true,
"auth_key": ""
},
"logging": {
"level": "info",
"file_enabled": true,
"max_size_mb": 50,
"max_files": 5
},
"updates": {
"check_enabled": true,
"channel": "stable",
"auto_check_interval_hours": 1,
"auto_backup_before_update": true,
"notify_only": false
},
"cloud": {
"enabled": false,
"endpoint": "wss://cloud.openavc.com/agent/v1",
"system_key": "",
"system_id": ""
},
"kiosk": {
"enabled": false,
"target_url": "http://localhost:8080/panel",
"cursor_visible": false
},
"tls": {
"enabled": false,
"port": 8443,
"auto_generate": true,
"cert_file": "",
"key_file": "",
"redirect_http": true
}
}

Configuration priority: Environment variables override system.json values. This lets Docker and CI environments inject config without modifying the file.

system.json pathEnvironment VariableDefault
network.http_portOPENAVC_PORT8080
network.bind_addressOPENAVC_BIND127.0.0.1
network.control_interfaceOPENAVC_CONTROL_INTERFACE""
auth.programmer_passwordOPENAVC_PROGRAMMER_PASSWORD""
auth.api_keyOPENAVC_API_KEY""
auth.panel_lock_codeOPENAVC_PANEL_LOCK_CODE""
logging.levelOPENAVC_LOG_LEVELinfo
updates.check_enabledOPENAVC_UPDATE_CHECKtrue
updates.channelOPENAVC_UPDATE_CHANNELstable
cloud.enabledOPENAVC_CLOUD_ENABLEDfalse
cloud.endpointOPENAVC_CLOUD_ENDPOINTwss://cloud.openavc.com/agent/v1
cloud.system_keyOPENAVC_CLOUD_SYSTEM_KEY""
cloud.system_idOPENAVC_CLOUD_SYSTEM_ID""
tls.enabledOPENAVC_TLS_ENABLEDfalse
tls.portOPENAVC_TLS_PORT8443
tls.auto_generateOPENAVC_TLS_AUTO_GENERATEtrue
tls.cert_fileOPENAVC_TLS_CERT_FILE""
tls.key_fileOPENAVC_TLS_KEY_FILE""
tls.redirect_httpOPENAVC_TLS_REDIRECT_HTTPtrue

You can also read and modify system configuration through the REST API:

  • GET /api/system/config returns the current configuration (sensitive fields redacted)
  • PATCH /api/system/config updates individual sections and saves to disk

Bind address security: The default bind address is 127.0.0.1 (localhost only) for Linux and from-source installations. The Windows installer and Docker pre-configure 0.0.0.0 (network-accessible) since these deployments typically serve touch panels on other devices. To allow network access, set bind_address to 0.0.0.0 in system.json or via the OPENAVC_BIND environment variable. When bound to 0.0.0.0 without authentication configured, the server logs a prominent warning at startup.

Updates

OpenAVC checks for updates automatically (every hour by default) via the GitHub Releases API. No data is sent to GitHub.

Check for updates: GET /api/system/updates/check

When an update is available, the response includes the version, changelog, and whether the installation supports self-update.

Deployment types and update behavior:

DeploymentSelf-UpdateWhat Happens
Windows installerYesDownloads and runs new installer silently
Linux packageYesDownloads archive, writes instruction file, restarts. A helper script applies the update before the service starts.
DockerNoShows notification with docker compose pull command
Git/devNoShows notification with git pull instructions

Pre-update backups: Before applying any update, OpenAVC automatically backs up your projects, drivers, and system.json to the backups/ directory.

Rollback: If the server fails to start after an update, it automatically rolls back to the previous version. You can also manually rollback via POST /api/system/updates/rollback.

Linux Service

On Linux, OpenAVC runs as a systemd service that starts automatically on boot:

/etc/systemd/system/openavc.service
[Unit]
Description=OpenAVC Room Control Server
After=network-online.target
Wants=network-online.target
[Service]
Type=exec
User=openavc
Group=openavc
WorkingDirectory=/opt/openavc
ExecStart=/opt/openavc/venv/bin/python -m server.main
Restart=always
RestartSec=5
Environment=OPENAVC_DATA_DIR=/var/lib/openavc
Environment=OPENAVC_LOG_DIR=/var/log/openavc
Environment=OPENAVC_PROJECT=/var/lib/openavc/projects/default/project.avc
Environment=OPENAVC_BIND=0.0.0.0
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/var/lib/openavc /var/log/openavc /opt/openavc/driver_repo /opt/openavc/plugin_repo
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target

Enable and start the service:

Terminal window
sudo systemctl enable openavc
sudo systemctl start openavc

Docker

Download the maintained compose file and start the container. This is the supported install path — the compose file pins the network and capability settings discovery needs, so don’t try to translate it back into docker run flags or strip pieces out:

Terminal window
curl -fsSL https://raw.githubusercontent.com/open-avc/openavc/main/installer/docker-compose.yml -o docker-compose.yml
docker compose up -d # Start
docker compose pull # Update to latest
docker compose up -d # Restart with new image

For serial/USB device passthrough, uncomment the devices: block in the compose file.

Why the compose file uses host networking and NET_RAW

Device discovery, mDNS, and SSDP all need the container to be reachable on, and able to send packets to, the same physical network as your AV equipment. With Docker’s default bridge network the container sits behind NAT on a private 172.x subnet and cannot see your LAN, so scans return zero devices. network_mode: host puts the container directly on the host’s network stack so discovery works. cap_add: NET_RAW lets OpenAVC’s unprivileged user run the ICMP ping sweep that finds live hosts.

Docker Desktop on Windows or Mac

Docker Desktop runs the Linux container inside a WSL2 (Windows) or HyperKit (Mac) virtual machine that does not share the host’s LAN, so device discovery cannot work even with network_mode: host. If you need discovery on Windows or Mac, use the native installer instead. Docker Desktop is fine for evaluating the software or for IP-only deployments where you’ll add devices manually.

Multi-space deployments

For multiple rooms on a single host, use separate containers with different ports and data volumes. Multi-room layouts must use bridge networking (host mode would conflict on port 8080), which means device discovery is not available in multi-room mode and devices must be added manually by IP. If discovery matters, run one OpenAVC container per physical host using the single-room compose above, or set up macvlan networking so each container gets its own LAN IP.

services:
room-101:
image: ghcr.io/open-avc/openavc:latest
ports: ["8081:8080"]
volumes: ["room-101-data:/data"]
room-102:
image: ghcr.io/open-avc/openavc:latest
ports: ["8082:8080"]
volumes: ["room-102-data:/data"]

Touchscreen Kiosk Setup

For dedicated touchscreen displays, enable kiosk mode in system.json:

{
"kiosk": {
"enabled": true,
"target_url": "http://localhost:8080/panel",
"cursor_visible": false
}
}

On Linux with a desktop environment, the openavc-panel.service auto-launches Chromium in kiosk mode. The Raspberry Pi image includes this pre-configured. On other Linux installs, create the service manually:

/etc/systemd/system/openavc-panel.service
[Unit]
Description=OpenAVC Panel Kiosk Display
After=openavc.service graphical.target
Wants=openavc.service
[Service]
Type=simple
User=openavc
Environment=DISPLAY=:0
ExecStart=/opt/openavc/scripts/panel-kiosk.sh
Restart=on-failure
RestartSec=10
[Install]
WantedBy=graphical.target

The panel-kiosk.sh script reads the kiosk settings from system.json, waits for the server to be ready, hides the cursor (for touch-only panels), and launches Chromium in fullscreen kiosk mode. Touch input via USB HID (including HDMI monitors with a USB touch cable) is handled by the Linux kernel automatically.

On the Raspberry Pi image, an openavc-info.service also displays the IP address and access URLs on the HDMI console at boot, so you can find the device on the network even without mDNS.

Authentication

Authentication is optional. When the server is only accessible locally (bind address 127.0.0.1), no credentials are needed. When the server is accessible on the network (0.0.0.0), you should set at least a programmer password to prevent unauthorized changes to your project.

The Panel UI is never password-protected. End users can always open the touch panel without logging in.

When to set each credential

SettingEnvironment VariableWhen to use it
auth.programmer_passwordOPENAVC_PROGRAMMER_PASSWORDSet this when the server is network-accessible and you want to prevent other people on the network from opening the Programmer IDE and modifying your project. The browser will prompt for a password. This is for humans logging in via a browser.
auth.api_keyOPENAVC_API_KEYSet this if you have third-party integrations (control scripts, middleware, or external software) that connect to the OpenAVC REST API or WebSocket. Provide the key to those systems via the X-API-Key header. Not needed unless you are building custom integrations.
auth.panel_lock_codeOPENAVC_PANEL_LOCK_CODESet this if the panel runs on a public-facing display and you want to prevent users from navigating away from the touch panel UI.

You do not need to set both programmer password and API key. Either one protects the Programmer IDE and API. The password is for humans (browser login), the API key is for machines (HTTP headers). If both are set, either credential is accepted.

What gets protected

When at least one credential is configured:

  • /api/status, /api/health, and /api/library remain open (no auth)
  • All other REST endpoints require HTTP Basic or X-API-Key
  • The /programmer static files require HTTP Basic credentials
  • Panel WebSocket connections remain open; programmer WebSocket connections require a ?token= query param or X-API-Key header
  • The Panel UI at /panel is always accessible (it’s a touch screen, not a config tool)

HTTPS

HTTPS is off by default. OpenAVC typically runs on an isolated AV VLAN where plain HTTP is the convention (Crestron and Extron web UIs also default to HTTP). Turn HTTPS on when you need it: corporate or higher-ed networks that block HTTP, public Wi-Fi between the panel and the server, or browser features that require a secure context (clipboard, notifications).

Enabling from the Programmer IDE

The supported path:

  1. Open the Programmer IDE and go to Settings > Security.
  2. Toggle Enable HTTPS on.
  3. Leave Auto-generate (recommended) selected unless your organization has its own CA.
  4. Click Save.
  5. Restart the server (the banner tells you a restart is required).
  6. Reopen the IDE at https://<host>:8443/programmer. The browser shows a one-time warning the first time it sees the self-signed cert; click through, or install the CA cert on each device that needs warning-free access (see “Installing the CA” below).

The Security card shows live cert details (subject, issuer, fingerprint, SAN list, expiry, warnings) once the TLS listener is running.

Enabling without the IDE

For headless deployments, set the environment variables before starting the server:

Terminal window
export OPENAVC_TLS_ENABLED=true
export OPENAVC_TLS_PORT=8443 # optional, defaults to 8443

Or edit {data_dir}/system.json:

"tls": {
"enabled": true,
"port": 8443
}

Then restart the server. On first start with TLS on, OpenAVC generates a self-signed CA and server cert under {data_dir}/tls/. The cert is valid for 10 years and covers localhost, 127.0.0.1, the OS hostname, and every LAN IPv4 the host has at generation time. It is regenerated automatically if the primary local IP changes later.

Providing your own certificate

If your organization has an internal CA and you’d rather use a cert signed by it, switch to Use my own certificate in the IDE (or set tls.auto_generate to false in system.json) and point tls.cert_file / tls.key_file at the PEM files. Both must be absolute paths on the server’s filesystem. Wildcard certs work as long as the SAN matches the hostname clients use.

If the cert is missing, unreadable, malformed, or expired, OpenAVC refuses to start the TLS listener and writes a precise error to the startup log. It does not silently fall back to HTTP. Fix the cert configuration and restart.

HTTP-to-HTTPS redirect

When HTTPS is enabled, OpenAVC also runs a tiny HTTP listener on the original port (8080 by default) that 301/308-redirects every request to the HTTPS URL. This keeps old bookmarks, printed QR codes, and panel apps pointed at http:// working without any user action. Disable it in Settings > Security if you want to take port 8080 down entirely.

Installing the CA on panel devices

Auto-generated certs are signed by an internal CA that no client trusts out of the box. Until you install the CA, browsers and the panel apps show a warning. To install it warning-free:

  1. From any browser on the same network, visit https://<server>:8443/api/certificate (no auth required) — or click Download CA certificate in Settings > Security.
  2. Transfer the downloaded openavc-ca.crt to the panel device (email, AirDrop, USB).
  3. iOS: open the file, then Settings > General > VPN & Device Management > Install Profile. After install, also enable trust under Settings > General > About > Certificate Trust Settings.
  4. Android: open the file via Settings > Security > Encryption & credentials > Install a certificate > CA certificate (path varies by manufacturer).
  5. Windows / macOS / Linux: add the cert to the system trust store (or browser trust store, depending on the browser).

Once the CA is trusted, future cert regenerations (e.g., the server gets a new LAN IP) keep working without re-installing trust.

Reverse-proxy deployments

If you front OpenAVC with nginx, Caddy, or another reverse proxy that terminates TLS for you, leave OpenAVC’s tls.enabled at false and let the proxy do the work. Set tls.redirect_http to false if you want OpenAVC to skip its own redirect listener (the proxy will handle that too).

Health Check

GET /api/health returns server health with no authentication required. Use this for monitoring tools, load balancers, and container orchestration health checks.

{
"status": "healthy",
"version": "0.5.2",
"uptime_seconds": 3600.5,
"devices": { "total": 5, "connected": 4, "error": 1 },
"cloud": { "connected": true }
}

Security Notes

  • Communication is HTTP by default, suitable for isolated AV VLANs.
  • HTTPS is available as a built-in opt-in (see the HTTPS section above). Auto-generated self-signed cert by default, or supply your own cert/key for environments with an internal CA. Reverse-proxy TLS is still supported for deployments that prefer it.
  • ISC (inter-system communication) uses a shared auth key for system-to-system traffic, and switches to wss:// automatically when peers advertise HTTPS.
  • The default bind address is localhost only. Change to 0.0.0.0 in system.json when you need network access.

See Also