Installing the Mixer Web UI
mixer_web is the LiveView control interface for shiloh-mixer. It talks to the mixer over a local control-plane socket (UDP 19997) and exposes a web UI on port 8889 with per-channel faders, mutes, bus assignment, and scene management.
The app is a Phoenix 1.8 application with LiveView. It is intended for LAN use — no authentication by default.
Prerequisites
- Elixir ≥ 1.15 and Erlang/OTP (managed by
miseon this server — see note below) - Node.js (for asset compilation; only needed at build time)
NOTE: On the Shiloh servers, Elixir/Erlang are managed by
miseand are not on$PATHby default. Prefix allmixandiexcommands withmise exec --. For example:mise exec -- mix deps.get.
Install Elixir with mise if not already present:
mise install elixir@1.18
mise use elixir@1.18
Or install system-wide on Debian/Ubuntu:
sudo apt install elixir erlang
1. Get dependencies
cd ~/shiloh-broadcaster/server/mixer_web
mise exec -- mix deps.get
2. Compile assets (development)
mise exec -- mix assets.setup # downloads esbuild + tailwind
mise exec -- mix assets.build # compiles JS + CSS
3. Generate a secret key base
Required for production. Generate and save it somewhere secure (e.g. a drop-in systemd config):
mise exec -- mix phx.gen.secret
# → prints a 64-byte hex string, e.g.:
# AbcDef1234...
4. Configuration
The app is configured via environment variables at runtime. The relevant variables are:
| Variable | Default | Description |
|---|---|---|
PORT |
8889 |
HTTP listen port |
PHX_HOST |
localhost |
Hostname used in URL generation |
PHX_SERVER |
(unset) | Set to true to start the HTTP server |
SECRET_KEY_BASE |
(required in prod) | 64-byte secret from mix phx.gen.secret |
The mixer endpoint defaults are set in config/config.exs. To override at runtime without touching the config file, set the environment variables before starting the server.
5. Development run
cd ~/shiloh-broadcaster/server/mixer_web
PORT=8889 mise exec -- mix phx.server
The UI is available at http://localhost:8889. LiveReload is active in dev mode — edits to .ex/.heex files reload automatically.
6. Production run (release)
For a long-lived production deployment, build a Mix release:
cd ~/shiloh-broadcaster/server/mixer_web
MIX_ENV=prod mise exec -- mix assets.deploy
MIX_ENV=prod mise exec -- mix release
The release is assembled at _build/prod/rel/mixer_web/. Copy it to the target location:
cp -r _build/prod/rel/mixer_web ~/mixer_web
Run it:
PHX_SERVER=true \
PHX_HOST=stg-srv001.bq.shilohbv.com \
PORT=8889 \
SECRET_KEY_BASE="<your-secret>" \
~/mixer_web/bin/mixer_web start
7. systemd user unit
The repo ships server/systemd/mixer_web.service. The unit expects the release at ~/mixer_web/bin/mixer_web.
The SECRET_KEY_BASE is kept out of the unit file in a drop-in to avoid committing secrets:
mkdir -p ~/.config/systemd/user/mixer_web.service.d
cat > ~/.config/systemd/user/mixer_web.service.d/secret.conf << 'EOF'
[Service]
Environment=SECRET_KEY_BASE=<paste-your-secret-here>
EOF
chmod 600 ~/.config/systemd/user/mixer_web.service.d/secret.conf
Install the main unit:
cp ~/shiloh-broadcaster/server/systemd/mixer_web.service \
~/.config/systemd/user/mixer_web.service
The unit file (for reference):
[Unit]
Description=mixer_web — Phoenix LiveView mixer UI (port 8889)
After=network-online.target shiloh-mixer.service
Wants=network-online.target
[Service]
Type=simple
Environment=PHX_SERVER=true
Environment=PHX_HOST=stg-srv001.bq.shilohbv.com
Environment=PORT=8889
ExecStart=/home/shiloh/mixer_web/bin/mixer_web start
ExecStop=/home/shiloh/mixer_web/bin/mixer_web stop
Restart=on-failure
RestartSec=3
SuccessExitStatus=143
TimeoutStopSec=15
[Install]
WantedBy=default.target
NOTE:
SuccessExitStatus=143maps SIGTERM (exit code 143) to a clean shutdown so theRestart=on-failurepolicy only fires on actual crashes, not onsystemctl stop.
Enable and start:
systemctl --user daemon-reload
systemctl --user enable mixer_web.service
systemctl --user start mixer_web.service
systemctl --user status mixer_web.service
The UI is intentionally not PartOf=shiloh-mixer.service — it stays running across mixer restarts and LiveView reconnects automatically once the mixer is back.
Troubleshooting
| Symptom | Likely cause |
|---|---|
SECRET_KEY_BASE is missing |
Production mode without the env var — add the drop-in unit |
cannot connect to mixer |
Check that the mixer is running on localhost (mixer address is compiled-in as 127.0.0.1:19997) |
| Assets return 404 | Run mix assets.deploy and mix phx.digest before building the release |
| LiveView socket disconnects | Origin mismatch; check_origin: false in runtime.exs disables this check on LAN |