Run the loopback stack with Compose
By hand, on loopback. The Compose bundle (
deploy/compose/compose.yaml) runs the whole station on one machine with every listener on loopback: LiveKit, the desk, playout and the listener process (Liquidsoap 2.5 withicecast.server), the control plane, the chat and PostgreSQL. On its own it has no reverse proxy and no TURN, so nobody off the machine can join or listen.weavesignal.shinstalls this bundle in one command, making the secrets and choosing free ports; this page is the same by hand. To put it on the internet, with a reverse proxy, a certificate and TURN over TLS, see Publish a station from the Compose bundle (public.yaml).
Before you start
Section titled “Before you start”- Podman 5 with
docker-composeas its compose provider, or Docker withdocker compose. Notpodman-compose: it ignores the settings file each service is given (the top-levelconfigs), so the services start without them. On Podman,docker-composereaches Podman through your user’s API socket:systemctl --user enable --now podman.socketif it cannot connect. - The repository, checked out where it will stay: the bundle mounts playout’s scripts (
playout/) and the default loop (assets/default-loop/) from it. - A server that is not overloaded (Memory and CPU).
The images
Section titled “The images”The bundle runs the published server image, forgejo.weavesignal.top/weavesignal/weavesignal-server:1.0.0, which holds the desk, the control plane, the chat and the public pages.
Liquidsoap 2.5.0-rc1, LiveKit 1.13.10 and PostgreSQL 18 come from their upstream images.
Compose pulls them all on the first up.
To run an image built from the repository instead, from its root:
podman build -t localhost/weavesignal-desk-spike:dev spike/desk-imagejust desk-imagejust server-imageThe first two build the desk’s base and build images; the third builds localhost/weavesignal-server:m1.
Set SERVER_IMAGE=localhost/weavesignal-server:m1 in .env to use it.
Fill in the settings
Section titled “Fill in the settings”-
Copy the example:
Terminal window cd deploy/composecp .env.example .env.envholds secrets and is ignored by git. -
Set the station’s identifier,
STATION_ID:weavesignal-control sample-configprints a fresh one. -
Set the secrets:
Setting What LIVEKIT_API_SECRETLiveKit’s API secret, at least 32 characters LISTENERS_SOURCE_PASSWORD,POSTGRES_PASSWORDany strong passwords CONTROL_ADMIN_TOKENthe station key: the studio app signs in with it first and makes the first staff account (Add staff and sign in); the chat also reads the studio’s view with it CHAT_EMAIL_KEYat least 32 characters, such as openssl rand -hex 32; the chat does not start without it (The email key)CONTROL_EMAIL_KEYthe same for staff email addresses; needed when MAIL_MODEis onCONTROL_TOKEN_KEYat least 32 characters; keys API tokens and webhook secrets (Integrations). Optional: unset, it is derived from the station key, and changing the station key then revokes every token Keep the three keys with the database’s backups: a different key finds none of the accounts, and revokes every token, made under the old one.
-
Set
CONSENT_CONTACTto an email address or a link where callers ask for their call to be taken down. Call-in stays closed until it is set (ADR-0124).
Every port is a setting (ADR-0075): change CONTROL_PORT, CHAT_PORT, LISTENERS_PORT, SRT_INGEST_PORT, PLAYOUT_FEED_PORT, DESK_FEED_PORT, LIVEKIT_HTTP_PORT or LIVEKIT_MEDIA_PORT if a default is taken.
.env.example names the other settings: mail, listing, the MP3 stream, playout’s processing, video, and FEED_BUFFER_S, the listener process’s cushion of playout’s feed (0.5 s; raise it to 1–2 s only on a busy host, as each second is a second more delay).
Start it
Section titled “Start it”podman compose up -dOr docker compose up -d.
The services use the host’s network so the loopback addresses stay exact.
PostgreSQL listens on a Unix socket only and takes no port (ADR-0092).
The desk is restarted if it stops, and playout connects to it again within about a second.
Check it
Section titled “Check it”curl http://127.0.0.1:7310/healthIt answers with "database":"ok" once the control plane has its database.
A listener on the same machine can play http://127.0.0.1:7312/programme.opus.
To check that only LiveKit’s media port listens off loopback, run the bundle’s own test from the repository’s root:
just test-bundleIt builds the server image, brings the bundle up on test ports with throwaway secrets, checks the control plane, a room token, the desk and playout, the listener process’s feed cushion behind the real desk, the MP3 stream and the default loop, scans the ports, and takes the bundle down with its volumes.
The studio app
Section titled “The studio app”The control plane in the bundle is given the desk’s control socket, so the studio app, signed in to the station, drives the desk. The bundle has no synthetic people; to try the studio app with a room already full of them, use the test stack in Run a first show.
just compose-check, which validates the bundle, with its edges and its public route, against .env.example, and just test-bundle are both part of just ci.
Text and images CC BY-SA 4.0; code samples AGPL-3.0-only, as the code is. Licences.