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
MacInstall with the macOS installer (.pkg). Runs as a background service with a menu-bar app.Mac-based spaces (churches, schools, studios)
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
macOS InstallerDownload the .pkg from GitHub Releases (Apple Silicon or Intel) and double-click it
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.

Host firewall: handled for you

The standard installs keep the OS firewall in step with the features you enable — turning on HTTPS or Short URLs in Settings never needs a manual firewall edit:

  • Windows installer: adds one program-scoped rule for openavc-server.exe with no fixed port list. Inbound traffic is accepted only on ports the server is actually listening on, so HTTPS (8443 or custom), Short URLs (80), custom HTTP ports, and plugin media ports work the moment they’re enabled — and nothing is left open that the server isn’t serving. Installs made before this rule shipped are upgraded automatically the next time the installer runs.
  • Linux (service installs) and Raspberry Pi: a root helper (firewall-sync.sh) runs each time the service starts and syncs ufw or firewalld (whichever is active) with the configured listeners: the HTTP port, the HTTPS port when TLS is on, and port 80 when Short URLs are on. Feature toggles take a restart to apply, so the firewall follows automatically. Ports the helper opened are closed again when the feature is turned off; rules you added yourself are never touched. Hosts with no active firewall are left alone. Existing installs pick this up with their next in-app update.
  • Docker: the container cannot (and should not) manage the host firewall. With the single-room compose file (host networking), open the ports on the host exactly as you would for a native install. With bridge networking (multi-room), Docker’s published ports handle reachability itself.
  • macOS: the macOS application firewall is app-based and off by default; when enabled, its default settings automatically allow signed software — which the OpenAVC server is — to receive incoming connections. If your organization disables that auto-allow, approve OpenAVC once in System Settings > Network > Firewall.

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
macOS/Library/Application Support/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
├── driver_repo/ # Community and custom drivers (installed from the IDE)
├── plugin_repo/ # Community and custom plugins (installed from the IDE)
├── backups/ # Automatic pre-update backups
├── logs/ # Log files (rotated)
├── system.json # System configuration
└── update-cache/ # Downloaded update packages (temp)

driver_repo/ and plugin_repo/ live under the data directory so the content you install from the Programmer IDE survives application upgrades. On Docker this is essential — /app is rewritten by every image pull, but /data is on a mounted volume.

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": "",
"trust_forwarded_for": false,
"backend_module": ""
},
"auth": {
"programmer_username": "",
"programmer_password": "",
"api_key": "",
"panel_lock_code": "",
"allow_anonymous": "auto"
},
"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": 24,
"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
},
"discovery": {
"advertise": true
},
"tls": {
"enabled": false,
"port": 8443,
"auto_generate": true,
"cert_file": "",
"key_file": "",
"redirect_http": true
}
}

A few keys deserve a note:

  • auth.allow_anonymous controls whether an instance with no credentials serves the Programmer IDE openly. The default "auto" means a from-source development checkout runs open, while every packaged install (Windows, macOS, Linux, Docker, Pi) requires the first-run setup screen to set an admin password before the IDE is reachable. Set true or false to force either behavior. Setting true opens the full admin surface to everyone who can reach the instance, not just the Programmer IDE but the configuration API, including the ability to set or overwrite the admin credential, change the bind address, and disable TLS. Open an instance only where reachability is already restricted (bind to localhost, or front it with an authenticating reverse proxy) rather than trusting the network to be friendly.
  • auth.programmer_username is optional. When empty, any username is accepted with the correct password. Set it to require a specific username at the login prompt.
  • discovery.advertise controls the mDNS advertisement that lets panel apps find this server on the network. Set to false to hide the server from discovery (devices then connect by IP address).
  • network.trust_forwarded_for should be true only when OpenAVC runs behind a reverse proxy that sets X-Forwarded-For, so per-client rate limiting sees the real client address.
  • network.backend_module is reserved for specialized deployments that supply their own host-network configuration backend. Leave it empty.

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""
network.trust_forwarded_forOPENAVC_TRUST_FORWARDED_FORfalse
auth.programmer_usernameOPENAVC_PROGRAMMER_USERNAME""
auth.programmer_passwordOPENAVC_PROGRAMMER_PASSWORD""
auth.api_keyOPENAVC_API_KEY""
auth.panel_lock_codeOPENAVC_PANEL_LOCK_CODE""
auth.allow_anonymousOPENAVC_ALLOW_ANONYMOUSauto
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""
discovery.advertiseOPENAVC_MDNS_ADVERTISEtrue
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 packaged installs — Windows installer, macOS installer, Docker, and the Linux install script — pre-configure 0.0.0.0 (network-accessible) since these deployments typically serve touch panels on other devices. A from-source installation defaults to 127.0.0.1 (localhost only); to allow network access, set bind_address to 0.0.0.0 in system.json or via the OPENAVC_BIND environment variable. To force localhost-only on a packaged install, set OPENAVC_BIND=127.0.0.1 instead. 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
macOS installerYesDownloads an archive, writes an instruction file, restarts. The launchd wrapper swaps the app bundle before the server starts.
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. The backup covers the data directory only. On Linux, logs live at /var/log/openavc (outside the data directory) and are rotated separately, so they are not part of the pre-update backup — by design, since logs aren’t needed to restore a working system.

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
AmbientCapabilities=CAP_NET_RAW
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

Why the unit grants CAP_NET_RAW: device discovery’s ICMP ping sweep needs to open an ICMP/raw socket to find live hosts. The service runs as the unprivileged openavc user, and NoNewPrivileges=true strips the file capability from /bin/ping when it execs — so the sweep can only send echo requests if the process holds CAP_NET_RAW directly. The installer’s unit grants it (scoped to OpenAVC alone). If you hand-write your own unit, keep this line: without it the kernel’s default ping_group_range excludes the service’s group and scans silently return zero devices. (LXC containers and minimal hosts hit the same wall — this one line fixes them all, with no host-wide sysctl change.)

macOS Service

On macOS, the .pkg installer sets everything up for you. The server runs as a system LaunchDaemon (com.openavc.server) that starts at boot, and a menu-bar app runs as a per-user LaunchAgent (com.openavc.menubar) that starts at login. The installer also creates the data directory at /Library/Application Support/OpenAVC and seeds the default project.

The menu-bar app shows server status and device count and provides quick links to the Programmer IDE and Panel, an update check, start/stop/restart controls, and an Uninstall OpenAVC item (all of which prompt for your password, since the server runs as root).

To control the service manually from Terminal:

Terminal window
# Status
sudo launchctl print system/com.openavc.server
# Restart
sudo launchctl kickstart -k system/com.openavc.server
# Stop / start
sudo launchctl bootout system/com.openavc.server
sudo launchctl bootstrap system /Library/LaunchDaemons/com.openavc.server.plist

Updates and rollback work the same as on Windows and Linux: the server downloads the new build, and on restart the daemon’s wrapper swaps the app bundle in place (keeping the previous version for one-step rollback).

Uninstalling on macOS

Because OpenAVC runs as a background service, dragging the app to the Trash is not enough on its own. Use one of these:

  • Menu bar: click the OpenAVC menu-bar icon and choose Uninstall OpenAVC, then enter your password. This stops the service and the menu-bar app, removes the application, and keeps your projects and settings.
  • Terminal: run the bundled uninstaller.
Terminal window
# Keep your projects and settings
sudo bash /Applications/OpenAVC.app/Contents/Resources/macos-uninstall.sh
# Remove everything, including projects, settings, and logs
sudo bash /Applications/OpenAVC.app/Contents/Resources/macos-uninstall.sh --purge

Your projects and settings live in /Library/Application Support/OpenAVC. They are kept unless you pass --purge, so reinstalling picks up where you left off.

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"]

First Boot (Raspberry Pi Image)

The Raspberry Pi image is ready to run the moment it boots. There is nothing to install and no terminal to open. The flow from a freshly flashed card to a working device is:

  1. Flash and boot. Write the openavc-<version>-pi.img.xz image to an SD card, insert it, connect an HDMI display and a network cable, and power on. The first boot runs a one-time setup (creating the data directory and starting the service), so allow an extra minute before the device is ready.

  2. Read the device’s address off the screen. With no project loaded yet, the HDMI display shows the setup screen: the device’s IP address, the Programmer and Panel URLs, and what to do next. The IP also prints on the HDMI text console during boot, so you can find the device even without a display manager. On networks with mDNS, the device is also reachable at http://openavc.local:8080.

  3. Open the Programmer and create a password. Browse to http://openavc.local:8080/programmer (or the IP from the screen) from a computer on the same network. Because shipped devices are closed by default, the first visit shows a Create admin password screen. Set a password here. This claims the device, and the same password becomes the operating-system login for the openavc user (see Raspberry Pi: OS login and SSH).

  4. Build your project. Add devices, design the panel, and save. As soon as the project has panel content, the on-device display switches from the setup screen to the Panel UI on its own. You never have to touch the device to finish setup.

What ships locked down on a fresh image:

  • No usable OS password, and SSH off. The openavc account is locked until you set the admin password in step 3, and sshd does not start. Enable SSH later from Settings > Security if you need remote console access.
  • The admin surface is closed. Until you complete step 3, the Programmer and REST API require the credential you are about to set. The Panel UI is always open, so end users never see a login.

To set the IP, hostname, or WiFi without attaching a keyboard, see Changing the device’s network settings. To force the display back to the setup screen while a project is running, open /setup?stay=1.

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.

While kiosk mode is off (the default on a fresh device), the display shows the setup screen (/setup) instead of the panel: the device’s IP address, the Programmer and Panel URLs, and first-run instructions. The screen updates live — connecting a network cable or claiming the device refreshes it automatically, no reboot needed. Once your project has panel content, the display switches to the Panel UI on its own; you never have to touch the device to complete setup. (To read the setup screen while a project is running, open /setup?stay=1.)

Changing the device’s network settings

On the Pi appliance (and any Linux install running NetworkManager), OpenAVC can configure the machine’s own network — no SSH or terminal needed:

  • From the device’s screen: the setup screen has a Network Settings section with a DHCP/static form and WiFi scan-and-join. This works before the device has any network connection at all, which is how you bring a device onto a static-only network or a WiFi-only site. Text entry needs a keyboard (USB, or the on-screen keyboard on tablet hardware).
  • From a laptop: Programmer > Settings > Network > This Device’s Network offers the same controls plus a hostname field. When you change the address you’re connected through, the Programmer becomes unreachable at the old address — the confirmation dialog shows the new URL to reconnect to.

How a change takes effect depends on the hardware. On the Pi appliance and Linux installs, changes apply immediately, and a static IP that fails to activate is rolled back to the previous configuration automatically, so a typo can’t strand the device off the network. On appliance hardware where the network is managed by the device firmware, the form notes that applying a change restarts the device — settings are saved to the boot configuration and the device comes back up on the new address; if the new settings are wrong, fix them from the device’s own setup screen. On deployments where OpenAVC doesn’t manage the host (Windows, Docker, Linux without NetworkManager), these controls don’t appear — configure the host’s network as you normally would.

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.

Raspberry Pi: OS login and SSH

The Pi appliance image ships with the operating-system login locked down:

  • There is no default OS password. The openavc Linux account is locked in the image, so there is no openavc/openavc shared login to exploit. The kiosk display still auto-starts (auto-login does not use a password).
  • The admin password you set on the first-run Create admin password screen becomes the OS console/SSH login for the openavc user as well — one credential for both. Changing it in Settings > Security re-syncs the OS login.
  • SSH is off by default. Enable it with the Enable SSH toggle in Settings > Security when you need remote console access; log in as openavc with the admin password. Turn it off from the same toggle.

This applies only to the Pi appliance image. A generic Linux install.sh host runs OpenAVC as an unprivileged service account and does not manage the OS login or sshd — set those up yourself as usual.

Authentication

Packaged installs (Windows, macOS, Linux, Docker, Pi) start unclaimed: the first person to open the Programmer IDE sees a setup screen that sets the admin password, so a shipped controller is never left open on the network. A from-source development checkout runs open by default; set a programmer password before making it network-accessible (0.0.0.0). To run an instance intentionally open (for example behind your own SSO reverse proxy), set auth.allow_anonymous to true and restrict reachability at the proxy.

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. Optionally set auth.programmer_username (OPENAVC_PROGRAMMER_USERNAME) to require a specific username; when it is unset, any username is accepted with the correct password.
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 and /api/health remain open (no auth), along with the bootstrap endpoints the login and setup screens need (/api/auth/required, /api/startup-status, /api/setup/status, /api/cloud/status) and the CA certificate download at /api/certificate
  • All other REST endpoints, including /api/library, require HTTP Basic or X-API-Key
  • The /programmer static files are served without credentials; the IDE shows a login screen, and every API call it makes requires credentials
  • Panel WebSocket connections remain open but are restricted to touch-panel interactions; programmer WebSocket connections authenticate via the X-API-Key header, the browser’s cached HTTP Basic credentials, or an auth.-prefixed WebSocket subprotocol token
  • 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 redirects every request to the HTTPS URL with a temporary redirect (302/307), so nothing caches a permanent redirect that would outlive a later decision to turn HTTPS back off. 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.

Trusted certificates without any client setup

If the system is paired with OpenAVC Cloud, you can skip CA installs entirely: Settings > Security offers a one-click trusted certificate. The cloud obtains a publicly trusted certificate for the system (the private key never leaves the server), and the HTTP listener sends clients to a certified URL that any browser accepts with a normal padlock. Browsers first get a quick in-page reachability check, so a device that cannot resolve the certified name (blocked resolver, no internet at the venue) automatically lands on the bare-IP HTTPS URL with the standard warning instead of a dead page. Nothing needs to be installed on client devices, which makes it the right choice for guest and BYOD scenarios. Network details, including the DNS rebind exception some routers need, are in the network and security cut sheet.

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).

Short URLs (port 80 redirect)

By default, people have to include the port when typing an address: http://192.168.1.20:8080/panel. Turning on Short URLs in Settings > Network adds a small listener on port 80 that forwards every request to the real port, so http://192.168.1.20/panel just works. It composes with HTTPS and trusted certificates: with those on, typing the bare IP lands directly on the padlocked page. The listener serves no content, only redirects, and it is best-effort: if something else on the machine owns port 80, OpenAVC logs a warning and starts normally without it. Changing the toggle takes effect after a restart. Also set the environment variable OPENAVC_PORT80_REDIRECT=true for headless setups.

While the listener is up, the addresses OpenAVC shows people — the Panel Access card, its QR code and printed poster, the device setup screen, and the startup log — drop the port automatically. If the listener could not bind, those surfaces keep showing the full address with the port, so a displayed URL always works as shown.

Platform notes:

  • Windows: works as-is when port 80 is free (IIS or other web servers may own it).
  • Linux (service installs): binding port 80 as a non-root service needs CAP_NET_BIND_SERVICE. Fresh installs and new Raspberry Pi images grant it in the service unit. Existing installs need one line added under [Service] in /etc/systemd/system/openavc.service: extend AmbientCapabilities to CAP_NET_RAW CAP_NET_BIND_SERVICE, then systemctl daemon-reload && systemctl restart openavc.
  • Docker: the container runs as an unprivileged user, so port 80 stays unavailable inside it; if you want short URLs on a Docker deployment, front it with a reverse proxy instead.

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.22.0",
"uptime_seconds": 3600.5,
"update_available": "",
"devices": {
"total": 5,
"connected": 4,
"disconnected": 1,
"orphaned": 0,
"disabled": 0
},
"cloud": { "connected": true }
}

update_available is the version of a newer release if the periodic update check has found one, or an empty string when the server is up to date. It reflects the last cached check result and never triggers a network check itself. The device counts add up to total: connected and disconnected cover enabled devices, orphaned counts devices whose driver is not installed, and disabled counts devices turned off in the project.

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.
  • Packaged installs bind to all interfaces (0.0.0.0) so panels on other devices can connect; set a Programmer password (the first-run prompt) or an API key on any networked deployment. A from-source install binds to localhost only until you change it.

See Also