refactor(prometheus,stoat): prefix service names so instances are possible

Both apps were barred from multiple instances by the same rule: a
service or container name with no <app> prefix cannot be made unique per
instance, so a second copy would fight the first for it.

Prometheus is now fully unblocked. node-exporter and cadvisor became
prometheus-node-exporter and prometheus-cadvisor — service key,
container_name and SERVICE_TAG default together — and prometheus.yml's
scrape targets follow them. The image references (prom/node-exporter,
gcr.io/cadvisor/cadvisor) and the job_name labels are deliberately
untouched: the first are upstream coordinates, the second are labels
dashboards and alert rules key off, and renaming either would break
something to fix nothing.

Stoat's sixteen services are now all stoat-prefixed. Its container_names
already were, so only the service keys and their depends_on references
moved. The subtlety is DNS: compose registers the service name as a
network alias, so renaming a key silently retires the name anything
else resolves it by — Revolt.toml reaches the broker as "rabbit", the
Caddyfile proxies to api, events, autumn, january and gifbox, and the
bucket job talks to http://minio:9000. Ten services already carried an
explicit alias that survives the rename; the six that did not
(database, redis, rabbit, createbuckets, crond, pushd) have been given
one holding their old short name. Every name that resolved before still
resolves. Verified by parsing the result: 16 services, every one keeping
its short alias, and no dangling depends_on in either app.

Stoat stays non-instanceable, but for one narrower reason now, recorded
in its config: LiveKit advertises its own tcp_port 7881 and UDP range
50000-50100 to clients from livekit.yml, so those cannot be randomised
per instance without generating that file per instance and allocating a
range for each.

Stoat's port descriptors name their parent service, so they follow the
rename too: caddy -> stoat-caddy, livekit -> stoat-livekit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
librelad 2026-08-19 23:57:05 +01:00
parent 3ebd4ee5bb
commit acc91777c4
5 changed files with 59 additions and 43 deletions

View File

@ -44,8 +44,8 @@ services:
# network_mode: "container:gluetun-service" # network_mode: "container:gluetun-service"
# GLUETUN_ON_END # GLUETUN_ON_END
node-exporter: #LIBREPORTAL|SERVICE_TAG_2|node-exporter prometheus-node-exporter: #LIBREPORTAL|SERVICE_TAG_2|prometheus-node-exporter
container_name: node-exporter container_name: prometheus-node-exporter
image: prom/node-exporter image: prom/node-exporter
restart: unless-stopped restart: unless-stopped
command: command:
@ -57,8 +57,8 @@ services:
DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
ipv4_address: IP_DATA_2 #LIBREPORTAL|IP_TAG_2|IP_DATA_2 ipv4_address: IP_DATA_2 #LIBREPORTAL|IP_TAG_2|IP_DATA_2
cadvisor: #LIBREPORTAL|SERVICE_TAG_3|cadvisor prometheus-cadvisor: #LIBREPORTAL|SERVICE_TAG_3|prometheus-cadvisor
container_name: cadvisor container_name: prometheus-cadvisor
image: gcr.io/cadvisor/cadvisor image: gcr.io/cadvisor/cadvisor
restart: unless-stopped restart: unless-stopped
privileged: true privileged: true

View File

@ -15,8 +15,7 @@ CFG_PROMETHEUS_APP_NAME=prometheus
# (own data/DB/subdomain/backups) via `libreportal instance create`. Only set on # (own data/DB/subdomain/backups) via `libreportal instance create`. Only set on
# apps whose compose identity (container_name, Traefik routers, backup labels) # apps whose compose identity (container_name, Traefik routers, backup labels)
# is instance-safe — see scripts/instance/instance_create.sh. # is instance-safe — see scripts/instance/instance_create.sh.
# Not instance-safe. Declares node-exporter and cadvisor, names with no "prometheus" prefix, which cannot be made unique per instance. CFG_PROMETHEUS_MULTI_INSTANCE=true
CFG_PROMETHEUS_MULTI_INSTANCE=false
CFG_PROMETHEUS_BACKUP=true CFG_PROMETHEUS_BACKUP=true
CFG_PROMETHEUS_BACKUP_STRATEGY=auto CFG_PROMETHEUS_BACKUP_STRATEGY=auto
CFG_PROMETHEUS_UPDATE_TYPE=auto CFG_PROMETHEUS_UPDATE_TYPE=auto

View File

@ -16,8 +16,8 @@ scrape_configs:
- job_name: 'node-exporter' - job_name: 'node-exporter'
static_configs: static_configs:
- targets: ['node-exporter:9100'] - targets: ['prometheus-node-exporter:9100']
- job_name: 'cadvisor' - job_name: 'cadvisor'
static_configs: static_configs:
- targets: ['cadvisor:8080'] - targets: ['prometheus-cadvisor:8080']

View File

@ -35,7 +35,7 @@ services:
# Upstream's healthcheck is kept rather than the LibrePortal HEALTHCHECK_TAG: # Upstream's healthcheck is kept rather than the LibrePortal HEALTHCHECK_TAG:
# half the stack uses `depends_on: condition: service_healthy` against it, so # half the stack uses `depends_on: condition: service_healthy` against it, so
# disabling the healthcheck would deadlock the boot order. Same for rabbit. # disabling the healthcheck would deadlock the boot order. Same for rabbit.
database: #LIBREPORTAL|SERVICE_TAG_1|database stoat-database: #LIBREPORTAL|SERVICE_TAG_1|stoat-database
container_name: stoat-database container_name: stoat-database
image: mongo:8.0 #LIBREPORTAL|STOAT_MONGO_VERSION_TAG|8.0 image: mongo:8.0 #LIBREPORTAL|STOAT_MONGO_VERSION_TAG|8.0
restart: unless-stopped restart: unless-stopped
@ -58,9 +58,11 @@ services:
networks: networks:
DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
ipv4_address: IP_DATA_1 #LIBREPORTAL|IP_TAG_1|IP_DATA_1 ipv4_address: IP_DATA_1 #LIBREPORTAL|IP_TAG_1|IP_DATA_1
aliases:
- database
# Valkey — event message broker and KV store. # Valkey — event message broker and KV store.
redis: #LIBREPORTAL|SERVICE_TAG_2|redis stoat-redis: #LIBREPORTAL|SERVICE_TAG_2|stoat-redis
container_name: stoat-redis container_name: stoat-redis
image: valkey/valkey:9-alpine #LIBREPORTAL|STOAT_VALKEY_VERSION_TAG|9-alpine image: valkey/valkey:9-alpine #LIBREPORTAL|STOAT_VALKEY_VERSION_TAG|9-alpine
restart: unless-stopped restart: unless-stopped
@ -69,9 +71,11 @@ services:
networks: networks:
DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
ipv4_address: IP_DATA_2 #LIBREPORTAL|IP_TAG_2|IP_DATA_2 ipv4_address: IP_DATA_2 #LIBREPORTAL|IP_TAG_2|IP_DATA_2
aliases:
- redis
# RabbitMQ — internal message broker (push notifications, voice events). # RabbitMQ — internal message broker (push notifications, voice events).
rabbit: #LIBREPORTAL|SERVICE_TAG_3|rabbit stoat-rabbit: #LIBREPORTAL|SERVICE_TAG_3|stoat-rabbit
container_name: stoat-rabbit container_name: stoat-rabbit
image: rabbitmq:4-alpine #LIBREPORTAL|STOAT_RABBITMQ_VERSION_TAG|4-alpine image: rabbitmq:4-alpine #LIBREPORTAL|STOAT_RABBITMQ_VERSION_TAG|4-alpine
restart: unless-stopped restart: unless-stopped
@ -90,13 +94,15 @@ services:
networks: networks:
DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
ipv4_address: IP_DATA_3 #LIBREPORTAL|IP_TAG_3|IP_DATA_3 ipv4_address: IP_DATA_3 #LIBREPORTAL|IP_TAG_3|IP_DATA_3
aliases:
- rabbit
# MinIO — S3-compatible object storage for uploads and avatars. # MinIO — S3-compatible object storage for uploads and avatars.
# #
# The bucket-name aliases are load-bearing: the file server addresses # The bucket-name aliases are load-bearing: the file server addresses
# buckets virtual-host style (<bucket>.minio), so without these the DNS # buckets virtual-host style (<bucket>.minio), so without these the DNS
# lookup fails and every upload errors. # lookup fails and every upload errors.
minio: #LIBREPORTAL|SERVICE_TAG_4|minio stoat-minio: #LIBREPORTAL|SERVICE_TAG_4|stoat-minio
container_name: stoat-minio container_name: stoat-minio
image: minio/minio:latest #LIBREPORTAL|STOAT_MINIO_VERSION_TAG|latest image: minio/minio:latest #LIBREPORTAL|STOAT_MINIO_VERSION_TAG|latest
restart: unless-stopped restart: unless-stopped
@ -125,11 +131,11 @@ services:
# One-shot: creates the uploads bucket, then exits. Not a failure when you # One-shot: creates the uploads bucket, then exits. Not a failure when you
# see it stopped. # see it stopped.
createbuckets: #LIBREPORTAL|SERVICE_TAG_5|createbuckets stoat-createbuckets: #LIBREPORTAL|SERVICE_TAG_5|stoat-createbuckets
container_name: stoat-createbuckets container_name: stoat-createbuckets
image: minio/mc:latest #LIBREPORTAL|STOAT_MINIO_MC_VERSION_TAG|latest image: minio/mc:latest #LIBREPORTAL|STOAT_MINIO_MC_VERSION_TAG|latest
depends_on: depends_on:
- minio - stoat-minio
# Credentials come in through the environment rather than being written # Credentials come in through the environment rather than being written
# into the entrypoint: a #LIBREPORTAL annotation only substitutes on the # into the entrypoint: a #LIBREPORTAL annotation only substitutes on the
# line it sits on, and inside a folded block scalar it would end up as # line it sits on, and inside a folded block scalar it would end up as
@ -150,10 +156,12 @@ services:
networks: networks:
DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
ipv4_address: IP_DATA_5 #LIBREPORTAL|IP_TAG_5|IP_DATA_5 ipv4_address: IP_DATA_5 #LIBREPORTAL|IP_TAG_5|IP_DATA_5
aliases:
- createbuckets
# Caddy — internal path router for the whole stack. This is the only service # Caddy — internal path router for the whole stack. This is the only service
# Traefik talks to, and the only one carrying a Traefik router. # Traefik talks to, and the only one carrying a Traefik router.
caddy: #LIBREPORTAL|SERVICE_TAG_6|caddy stoat-caddy: #LIBREPORTAL|SERVICE_TAG_6|stoat-caddy
container_name: stoat-caddy container_name: stoat-caddy
image: caddy:2-alpine #LIBREPORTAL|STOAT_CADDY_VERSION_TAG|2-alpine image: caddy:2-alpine #LIBREPORTAL|STOAT_CADDY_VERSION_TAG|2-alpine
restart: unless-stopped restart: unless-stopped
@ -198,17 +206,17 @@ services:
# GLUETUN_ON_END # GLUETUN_ON_END
# API server. # API server.
api: #LIBREPORTAL|SERVICE_TAG_7|api stoat-api: #LIBREPORTAL|SERVICE_TAG_7|stoat-api
container_name: stoat-api container_name: stoat-api
image: ghcr.io/stoatchat/api:v0.15.1 #LIBREPORTAL|STOAT_VERSION_TAG|v0.15.1 image: ghcr.io/stoatchat/api:v0.15.1 #LIBREPORTAL|STOAT_VERSION_TAG|v0.15.1
restart: unless-stopped restart: unless-stopped
env_file: secrets.env env_file: secrets.env
depends_on: depends_on:
database: stoat-database:
condition: service_healthy condition: service_healthy
redis: stoat-redis:
condition: service_started condition: service_started
rabbit: stoat-rabbit:
condition: service_healthy condition: service_healthy
volumes: volumes:
- ./Revolt.toml:/Revolt.toml:ro - ./Revolt.toml:/Revolt.toml:ro
@ -219,15 +227,15 @@ services:
- api - api
# Websocket / events service. # Websocket / events service.
events: #LIBREPORTAL|SERVICE_TAG_8|events stoat-events: #LIBREPORTAL|SERVICE_TAG_8|stoat-events
container_name: stoat-events container_name: stoat-events
image: ghcr.io/stoatchat/events:v0.15.1 #LIBREPORTAL|STOAT_EVENTS_VERSION_TAG|v0.15.1 image: ghcr.io/stoatchat/events:v0.15.1 #LIBREPORTAL|STOAT_EVENTS_VERSION_TAG|v0.15.1
restart: unless-stopped restart: unless-stopped
env_file: secrets.env env_file: secrets.env
depends_on: depends_on:
database: stoat-database:
condition: service_healthy condition: service_healthy
redis: stoat-redis:
condition: service_started condition: service_started
volumes: volumes:
- ./Revolt.toml:/Revolt.toml:ro - ./Revolt.toml:/Revolt.toml:ro
@ -238,15 +246,15 @@ services:
- events - events
# Autumn — file server. # Autumn — file server.
autumn: #LIBREPORTAL|SERVICE_TAG_9|autumn stoat-autumn: #LIBREPORTAL|SERVICE_TAG_9|stoat-autumn
container_name: stoat-autumn container_name: stoat-autumn
image: ghcr.io/stoatchat/file-server:v0.15.1 #LIBREPORTAL|STOAT_AUTUMN_VERSION_TAG|v0.15.1 image: ghcr.io/stoatchat/file-server:v0.15.1 #LIBREPORTAL|STOAT_AUTUMN_VERSION_TAG|v0.15.1
restart: unless-stopped restart: unless-stopped
env_file: secrets.env env_file: secrets.env
depends_on: depends_on:
database: stoat-database:
condition: service_healthy condition: service_healthy
createbuckets: stoat-createbuckets:
condition: service_started condition: service_started
volumes: volumes:
- ./Revolt.toml:/Revolt.toml:ro - ./Revolt.toml:/Revolt.toml:ro
@ -257,7 +265,7 @@ services:
- autumn - autumn
# January — link metadata and image proxy. # January — link metadata and image proxy.
january: #LIBREPORTAL|SERVICE_TAG_10|january stoat-january: #LIBREPORTAL|SERVICE_TAG_10|stoat-january
container_name: stoat-january container_name: stoat-january
image: ghcr.io/stoatchat/proxy:v0.15.1 #LIBREPORTAL|STOAT_JANUARY_VERSION_TAG|v0.15.1 image: ghcr.io/stoatchat/proxy:v0.15.1 #LIBREPORTAL|STOAT_JANUARY_VERSION_TAG|v0.15.1
restart: unless-stopped restart: unless-stopped
@ -272,7 +280,7 @@ services:
# Gifbox — Tenor proxy for the GIF picker. Inert until a Tenor API key is # Gifbox — Tenor proxy for the GIF picker. Inert until a Tenor API key is
# added to secrets.env; see the upstream Guides.md. # added to secrets.env; see the upstream Guides.md.
gifbox: #LIBREPORTAL|SERVICE_TAG_11|gifbox stoat-gifbox: #LIBREPORTAL|SERVICE_TAG_11|stoat-gifbox
container_name: stoat-gifbox container_name: stoat-gifbox
image: ghcr.io/stoatchat/gifbox:v0.15.1 #LIBREPORTAL|STOAT_GIFBOX_VERSION_TAG|v0.15.1 image: ghcr.io/stoatchat/gifbox:v0.15.1 #LIBREPORTAL|STOAT_GIFBOX_VERSION_TAG|v0.15.1
restart: unless-stopped restart: unless-stopped
@ -286,51 +294,55 @@ services:
- gifbox - gifbox
# Scheduled task daemon. # Scheduled task daemon.
crond: #LIBREPORTAL|SERVICE_TAG_12|crond stoat-crond: #LIBREPORTAL|SERVICE_TAG_12|stoat-crond
container_name: stoat-crond container_name: stoat-crond
image: ghcr.io/stoatchat/crond:v0.15.1 #LIBREPORTAL|STOAT_CROND_VERSION_TAG|v0.15.1 image: ghcr.io/stoatchat/crond:v0.15.1 #LIBREPORTAL|STOAT_CROND_VERSION_TAG|v0.15.1
restart: unless-stopped restart: unless-stopped
env_file: secrets.env env_file: secrets.env
depends_on: depends_on:
database: stoat-database:
condition: service_healthy condition: service_healthy
minio: stoat-minio:
condition: service_started condition: service_started
volumes: volumes:
- ./Revolt.toml:/Revolt.toml:ro - ./Revolt.toml:/Revolt.toml:ro
networks: networks:
DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
ipv4_address: IP_DATA_12 #LIBREPORTAL|IP_TAG_12|IP_DATA_12 ipv4_address: IP_DATA_12 #LIBREPORTAL|IP_TAG_12|IP_DATA_12
aliases:
- crond
# Push notification daemon. # Push notification daemon.
pushd: #LIBREPORTAL|SERVICE_TAG_13|pushd stoat-pushd: #LIBREPORTAL|SERVICE_TAG_13|stoat-pushd
container_name: stoat-pushd container_name: stoat-pushd
image: ghcr.io/stoatchat/pushd:v0.15.1 #LIBREPORTAL|STOAT_PUSHD_VERSION_TAG|v0.15.1 image: ghcr.io/stoatchat/pushd:v0.15.1 #LIBREPORTAL|STOAT_PUSHD_VERSION_TAG|v0.15.1
restart: unless-stopped restart: unless-stopped
env_file: secrets.env env_file: secrets.env
depends_on: depends_on:
database: stoat-database:
condition: service_healthy condition: service_healthy
redis: stoat-redis:
condition: service_started condition: service_started
rabbit: stoat-rabbit:
condition: service_healthy condition: service_healthy
volumes: volumes:
- ./Revolt.toml:/Revolt.toml:ro - ./Revolt.toml:/Revolt.toml:ro
networks: networks:
DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA DOCKER_NETWORK_DATA: #LIBREPORTAL|DOCKER_NETWORK_TAG|DOCKER_NETWORK_DATA
ipv4_address: IP_DATA_13 #LIBREPORTAL|IP_TAG_13|IP_DATA_13 ipv4_address: IP_DATA_13 #LIBREPORTAL|IP_TAG_13|IP_DATA_13
aliases:
- pushd
# Voice ingress daemon — receives LiveKit's webhooks. # Voice ingress daemon — receives LiveKit's webhooks.
voice-ingress: #LIBREPORTAL|SERVICE_TAG_14|voice-ingress stoat-voice-ingress: #LIBREPORTAL|SERVICE_TAG_14|stoat-voice-ingress
container_name: stoat-voice-ingress container_name: stoat-voice-ingress
image: ghcr.io/stoatchat/voice-ingress:v0.15.1 #LIBREPORTAL|STOAT_VOICE_INGRESS_VERSION_TAG|v0.15.1 image: ghcr.io/stoatchat/voice-ingress:v0.15.1 #LIBREPORTAL|STOAT_VOICE_INGRESS_VERSION_TAG|v0.15.1
restart: unless-stopped restart: unless-stopped
env_file: secrets.env env_file: secrets.env
depends_on: depends_on:
database: stoat-database:
condition: service_healthy condition: service_healthy
rabbit: stoat-rabbit:
condition: service_healthy condition: service_healthy
volumes: volumes:
- ./Revolt.toml:/Revolt.toml:ro - ./Revolt.toml:/Revolt.toml:ro
@ -351,13 +363,13 @@ services:
# to work from outside the LAN: # to work from outside the LAN:
# sudo ufw allow 50000:50100/udp # sudo ufw allow 50000:50100/udp
# Voice still falls back to TCP 7881 without it, at the cost of latency. # Voice still falls back to TCP 7881 without it, at the cost of latency.
livekit: #LIBREPORTAL|SERVICE_TAG_15|livekit stoat-livekit: #LIBREPORTAL|SERVICE_TAG_15|stoat-livekit
container_name: stoat-livekit container_name: stoat-livekit
image: ghcr.io/stoatchat/livekit-server:v1.9.13 #LIBREPORTAL|STOAT_LIVEKIT_VERSION_TAG|v1.9.13 image: ghcr.io/stoatchat/livekit-server:v1.9.13 #LIBREPORTAL|STOAT_LIVEKIT_VERSION_TAG|v1.9.13
restart: unless-stopped restart: unless-stopped
command: --config /etc/livekit.yml command: --config /etc/livekit.yml
depends_on: depends_on:
redis: stoat-redis:
condition: service_started condition: service_started
ports: ports:
- "PORTS_DATA_2" #LIBREPORTAL|PORTS_TAG_2|PORTS_DATA_2 - "PORTS_DATA_2" #LIBREPORTAL|PORTS_TAG_2|PORTS_DATA_2
@ -371,7 +383,7 @@ services:
- livekit - livekit
# The web client itself. Served by Caddy at /. # The web client itself. Served by Caddy at /.
web: #LIBREPORTAL|SERVICE_TAG_16|web stoat-web: #LIBREPORTAL|SERVICE_TAG_16|stoat-web
container_name: stoat-web container_name: stoat-web
image: ghcr.io/stoatchat/for-web:0c31cf0 #LIBREPORTAL|STOAT_WEB_VERSION_TAG|0c31cf0 image: ghcr.io/stoatchat/for-web:0c31cf0 #LIBREPORTAL|STOAT_WEB_VERSION_TAG|0c31cf0
restart: unless-stopped restart: unless-stopped

View File

@ -18,7 +18,12 @@ CFG_STOAT_APP_NAME=stoat
# (own data/DB/subdomain/backups) via `libreportal instance create`. Only set on # (own data/DB/subdomain/backups) via `libreportal instance create`. Only set on
# apps whose compose identity (container_name, Traefik routers, backup labels) # apps whose compose identity (container_name, Traefik routers, backup labels)
# is instance-safe — see scripts/instance/instance_create.sh. # is instance-safe — see scripts/instance/instance_create.sh.
# Not instance-safe. Pins LiveKit to host port 7881, and declares database/redis/rabbit/minio and friends — names with no "stoat" prefix that cannot be made unique per instance. # Not instance-safe, for ONE remaining reason. The service names are now all
# stoat-prefixed, so compose identity is no longer the blocker. What is: LiveKit
# advertises its own tcp_port (7881) and UDP range (50000-50100) to clients from
# livekit.yml, so those cannot be randomised per instance without generating that
# file per instance and allocating a UDP range for each. Until then a second copy
# could not bind 7881.
CFG_STOAT_MULTI_INSTANCE=false CFG_STOAT_MULTI_INSTANCE=false
# No prerequisites. Stoat bakes its public URL into the client bundle, but that # No prerequisites. Stoat bakes its public URL into the client bundle, but that
# URL can just as well be http://<lan-ip>:<port> — text chat, channels, roles # URL can just as well be http://<lan-ip>:<port> — text chat, channels, roles
@ -97,12 +102,12 @@ CFG_STOAT_NETWORK=default
# #
# Only one HTTP port: Caddy fronts the entire stack internally, so /api, /ws, # Only one HTTP port: Caddy fronts the entire stack internally, so /api, /ws,
# /autumn and the rest all arrive on this single host. # /autumn and the rest all arrive on this single host.
CFG_STOAT_PORT_1="caddy|webui|random:80|public|tcp|false|true|true|Web Interface||stoat" CFG_STOAT_PORT_1="stoat-caddy|webui|random:80|public|tcp|false|true|true|Web Interface||stoat"
# LiveKit's TCP fallback. Pinned rather than random on purpose: LiveKit # LiveKit's TCP fallback. Pinned rather than random on purpose: LiveKit
# advertises this exact port number to clients from livekit.yml, so a randomised # advertises this exact port number to clients from livekit.yml, so a randomised
# external port would be advertised wrongly and voice would fail to connect. # external port would be advertised wrongly and voice would fail to connect.
# Not Traefik-managed — WebRTC is not HTTP. # Not Traefik-managed — WebRTC is not HTTP.
CFG_STOAT_PORT_2="livekit|voice-tcp|7881:7881|public|tcp|false|false|false|LiveKit voice/video (TCP fallback)|" CFG_STOAT_PORT_2="stoat-livekit|voice-tcp|7881:7881|public|tcp|false|false|false|LiveKit voice/video (TCP fallback)|"
# Stoat exposes no safe way to set a password or grant a role from outside the # Stoat exposes no safe way to set a password or grant a role from outside the
# app, so these tools list and enable/disable only — see scripts/stoat_auth.sh. # app, so these tools list and enable/disable only — see scripts/stoat_auth.sh.