Ports

Port Default Listener What it carries
8443 build-time (omx_webui_tls_port) nginx The https + HTTP/2 origin — the surface, the REST entity API (with ?watch=1 SSE streams multiplexed on the one h2 connection), the manual, health, telemetry, patchbay REST. This is the LAN door (deployment/h2 rulings, amendment 2026-09-03). Opened in firewalld by the package.
8880 build-time (omx_webui_port) nginx The plain listener. Carries no API: only the redirect to the https origin and the trust page serving the root certificate (/trust/root.crt) for a browser that does not yet trust it. Opened in firewalld by the package.
8080 runtime (web.port), product default openmixer-server The console's own listener, which nginx proxies to (127.0.0.1:<web.port>, /etc/openmixer/nginx/upstream.conf). Binds localhost — both loopbacks and nothing else — so a device on the LAN reaches it only through nginx at 8443. The number itself is runtime config, not a package parameter; see below.
8890 runtime (OPENMIXER_PATCHBAY_PORT) openmixer-patchbay The standalone patchbay tool, when you run it. Not started by any unit. Binds 127.0.0.1 only (OPENMIXER_PATCHBAY_HOST), and nginx does not proxy it.
5555 runtime mod-host The LV2 insert host's command socket, on 127.0.0.1. The server spawns it (ensureModHost in packages/server/src/software-mixer-loader.ts) after probing for an existing one, so it is a listener you did not start by hand. Worth knowing about when a port conflicts or an unrelated mod-host is already running.

8443 — the surface, and the LAN door

The nginx drop-in at /etc/nginx/conf.d/openmixer-web-ui.conf plus the https server block it includes (/etc/openmixer/nginx/tls.conf, present once a certificate has been issued) serve /usr/share/openmixer/web-ui on 8443 and proxy these paths to the server:

/api/*         the REST entity API (and its ?watch=1 SSE streams) — includes
               /api/net/binding, the console's own discoverable port
/manual        the bundled manual
/health        liveness
/telemetry     the latency and xrun report
/patchbay/*    the routing endpoints

TLS terminates here, with the console's own bundled local CA, and installing the anchor is covered in Backup and TLS. 8880 carries no API at all: it is a plain redirect to https://<host>:8443 plus the trust page a browser without the anchor can still read, so opening 8880 alone reaches only that page, never the mixer.

The listen ports and the upstreams are plain configuration in those two files. Both are also build-time parameters of the RPM (omx_webui_port, omx_webui_tls_port, omx_web_port), which is how the packaged files and the firewalld rules stay consistent with each other.

You do not edit the upstream. /etc/openmixer/nginx/upstream.conf is generated from web.port of /etc/openmixer/config.json — by %post at install — and the drop-in includes it. After that, one step:

sudo openmixer-apply-port

It regenerates the upstream, moves the SELinux port label from whatever it was to the port the config now names, and reloads nginx — all three, in order. There is no other way to get an edit into nginx: the packaged server unit is a --user unit and cannot write /etc/openmixer or call semanage, so it runs no nginx step of any kind. A restart alone, or a bare systemctl reload nginx, leaves nginx proxying to the OLD port.

8080 — the server

The server's own port is runtime configuration, not a package parameter, and 8080 is only its product default — the number an install carries until something says otherwise. It can be set five ways, in this order of precedence:

  1. The persisted value from the surface's Setup → Network screen, in <state-dir>/network-settings.json.
  2. The CLI flag --web-port.
  3. The environment variable OPENMIXER_WEB_PORT.
  4. web.port in the config file (/etc/openmixer/config.json, or whatever --config / OPENMIXER_CONFIG names). See configuration files.
  5. The built-in default, 8080.

Layers 1, 3 and 4 are the ones a shell script can see (there is no --web-port flag for a script to read), and /usr/lib/openmixer/openmixer-config-port.sh is what sees them: the nginx upstream, the SELinux port label and the gig-safe restart hooks all ask it rather than carrying the number. It walks the layers in the same order — the persisted file, then the env var, then the config file — reading <state-dir>/network-settings.json in the same session a hook or openmixer-apply-port runs in, so a port set from Setup → Network reaches nginx the same way an edit to config.json does.

The same chain applies to --web-host / OPENMIXER_WEB_HOST / web.host (default localhost: both loopbacks, nothing else).

Precedence is resolved per field, not per layer: a persisted host does not stop the config file's web.port from applying. The Setup → Network screen shows which layer won each field, so file there means the value came from the config file.

The config file sits at the bottom because it is the deployment's baseline — a --web-port typed at the console, or an OPENMIXER_WEB_PORT in a systemd drop-in, is meant for this run and still wins.

To find the port an installed console actually answers on, ask nginx's own upstream (cat /etc/openmixer/nginx/upstream.conf) or the entity that carries it live — curl -sk https://127.0.0.1:8443/api/net/binding. There is no separate discovery endpoint: a GET /config outside the entity contract used to duplicate this and was retired (deployment/h2 rulings, amendment 2026-09-03) once nothing in the surface was found reading it.

Exposing the mixer to other devices

The surface is designed to be opened on several devices at once — a tablet at front of house, a laptop backstage. Open 8443 and 8880 (nginx) on the firewall and nothing else: 8443 carries the surface, the entity API and its SSE streams over https/h2; 8880 only redirects to it and serves the trust page. The console's own port is bound on loopback only, so there is nothing on it for a LAN device to reach. An operator who wants the plain port on a LAN address sets web.host explicitly — it is never the default.

The trap is opening 8880 alone: it never carries the API, with or without a server-port change — a device that only reaches 8880 gets the trust page, never the mixer.

sudo firewall-cmd --add-port=8443/tcp --add-port=8880/tcp --permanent && sudo firewall-cmd --reload

Checking what is actually listening

ss -ltnp | grep -E ':8443|:8880|:8080|:8890|:5555'
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/health   # engine, loopback only
curl -sk -o /dev/null -w '%{http_code}\n' https://127.0.0.1:8443/health # nginx, the LAN door
curl -sI http://127.0.0.1:8880/                                         # redirects to :8443