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:
- The persisted value from the surface's Setup → Network screen, in
<state-dir>/network-settings.json. - The CLI flag
--web-port. - The environment variable
OPENMIXER_WEB_PORT. web.portin the config file (/etc/openmixer/config.json, or whatever--config/OPENMIXER_CONFIGnames). See configuration files.- 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