# # ============================================================================= # GENERAL CONFIGURATION # ============================================================================= # APP_NAME = name of application for use in scripts # REQUIRES = comma-separated install prerequisites (see scripts/checks/requirements/check_app_install.sh) # COMPOSE_FILE = default for no app_name in docker-compose file name, app if there is # BACKUP = if true, include this application in backup operations # UPDATE_TYPE = auto: new image builds are applied automatically (a recovery snapshot is taken first), manual: only when you press Update # HEALTHCHECK = if true, default docker health checks for that container will be enabled # AUTHELIA = if true, use Authelia authentication, if false turned off. # HEADSCALE = options : false, local, remote (see general config). e.g false or local,remote # ENABLE_VIDEO = if true, allow camera and screen sharing (needs an HTTPS origin to work in a browser) # MONITORING = if true, export this app's metrics to Prometheus + Grafana (needs both apps installed) # CFG_STOAT_APP_NAME=stoat # MULTI_INSTANCE = if true, this app can run as multiple isolated instances # (own data/DB/subdomain/backups) via `libreportal instance create`. Only set on # apps whose compose identity (container_name, Traefik routers, backup labels) # is instance-safe — see scripts/instance/instance_create.sh. # 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 # No prerequisites. Stoat bakes its public URL into the client bundle, but that # URL can just as well be http://: — text chat, channels, roles # and uploads all work that way over a LAN or WireGuard tunnel. Only camera and # microphone need an HTTPS origin, because browsers refuse getUserMedia outside # a secure context; a VPN does not change that, since the check is on the URL # scheme. Any HTTPS satisfies it, including a self-signed Traefik certificate. CFG_STOAT_REQUIRES="" CFG_STOAT_BACKUP=true # STORAGE = which storage location holds this app's data. Change it with # `libreportal app move stoat ` — editing here records intent only. CFG_STOAT_STORAGE=default # Storage Location - Which disk holds this app's data [default:Primary] CFG_STOAT_BACKUP_STRATEGY=auto # Auto. The components of this stack are released together and do expect # matching versions — which is exactly why they are all pinned to the same tag # (api, events, file-server, proxy, gifbox, crond, pushd, voice-ingress all on # one STOAT_*_VERSION_TAG). An automatic update pulls rebuilds of those pinned # tags, so the services move together or not at all; they cannot drift apart on # their own. Moving the stack to a new release line is the stepped Upgrade and # remains a deliberate act. CFG_STOAT_UPDATE_TYPE=auto CFG_STOAT_COMPOSE_FILE=default CFG_STOAT_HEALTHCHECK=true # Stoat's own accounts back its clients, and /api must stay reachable without a # forward-auth redirect in the way. CFG_STOAT_AUTHELIA=false CFG_STOAT_HEADSCALE=false CFG_STOAT_ENABLE_VIDEO=true CFG_STOAT_MONITORING=false # Service credentials fed to the compose via #LIBREPORTAL|STOAT__TAG|. # Generated on first install and preserved across reinstalls: RabbitMQ writes # its user into ./data/rabbit on first boot and ignores the env afterwards, so a # regenerated password would leave the broker unreachable. MinIO's root password # is shared by the object store and the bucket-creation job, which have to agree. CFG_STOAT_RABBITMQ_PASSWORD_1=RANDOMIZEDPASSWORD1 CFG_STOAT_MINIO_PASSWORD_1=RANDOMIZEDPASSWORD2 # Owner account, registered by the installer as soon as the API answers. # # Stoat is first-come-first-served: whoever registers first on a fresh instance # becomes the instance owner, and it ships with invite_only=false, no captcha and # no email verification. Left to the printed "go and sign up" advice, the window # between the app answering and you getting round to it is a window in which # anyone who can reach the port owns your instance. Claiming it during install # closes that window. # # ADMIN_USERNAME is Stoat's handle (letters, digits, _ and .), separate from the # login email. Blank ADMIN_EMAIL skips provisioning and leaves the instance with # no account at all. # # Both defaults are chosen because Stoat REJECTS the obvious ones, which is only # visible as a failed install otherwise: # - example.com is a reserved domain and comes back DisallowedContactSupport, # so the email uses .local. Nothing is sent to it — this build runs with # email verification off, so the address is only ever a login identifier. # - "admin" is a reserved username and comes back InvalidUsername, hence # "administrator". CFG_STOAT_ADMIN_EMAIL=admin@stoat.local CFG_STOAT_ADMIN_USERNAME=administrator CFG_STOAT_ADMIN_PASSWORD_1=RANDOMIZEDPASSWORD3 # INVITE_ONLY = if true, nobody can sign up from the web UI; accounts are added # with the Create User Account tool. # # Defaults CLOSED, unlike Vaultwarden's SIGNUPS_ALLOWED=true, because the reason # that one is open does not apply here: Vaultwarden has to let you register to # get in at all, whereas the owner account above is created for you. Matrix takes # the same closed default for the same shape of app — an open chat server with no # captcha and no email verification is a standing invitation once it is reachable. # Closed is not a dead end: the Create User Account tool mints its own single-use # invite, so it keeps working either way. # # Written into Revolt.toml at install, so changing it needs an Install/Reinstall # to take effect — a Reload only restarts containers and leaves the generated # config as it was. CFG_STOAT_INVITE_ONLY=true # # ============================================================================= # METADATA # ============================================================================= # CATEGORY = application category for grouping # TITLE = display name for the application # DESCRIPTION = short description of the application # LONG_DESCRIPTION = detailed description of the application # URL = source repository or documentation URL # ACTIONS = available actions for this application # REQUIRES_SERVICE = name of another LibrePortal app that must be installed before this one can be configured # CFG_STOAT_CATEGORY="communication" CFG_STOAT_TITLE="Stoat" CFG_STOAT_DESCRIPTION="Discord-style Chat" CFG_STOAT_LONG_DESCRIPTION="The closest open-source match to Discord — servers, channels, roles, and voice and video chat" CFG_STOAT_URL="https://github.com/stoatchat/self-hosted" CFG_STOAT_ACTIONS="configure|install|restart|shutdown|uninstall" # # ============================================================================= # NETWORK CONFIGURATION # ============================================================================= # DOMAIN = number of domain from the general config, useful when using multiple domains # WHITELIST = if true only allow whitelisted ips (see general config), if false allow all # CFG_STOAT_DOMAIN=1 CFG_STOAT_WHITELIST=false CFG_STOAT_NETWORK=default # # ============================================================================= # PORT CONFIGURATION # ============================================================================= # PORT_ = port configuration: app|name|external:internal|access|protocol|login|traefik|webui|description # - app: application name # - name: service identifier (webui, dns, ssh, etc.) # - external:internal: port mapping (external can be 'random' for auto-allocation) # - access: 'public' (internet accessible), 'private' (local network only), 'disabled' (not running) # - protocol: 'tcp' or 'udp' # - login: if true, this port requires basic-auth via Traefik (only meaningful when traefik=true) # - traefik: if true, Traefik handles this port (reverse proxy) # - webui: if true, this port serves the main web interface # - description: human-readable description of the service # # Only one HTTP port: Caddy fronts the entire stack internally, so /api, /ws, # /autumn and the rest all arrive on this single host. 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 # 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. # Not Traefik-managed — WebRTC is not HTTP. 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 # app, so these tools list and enable/disable only — see scripts/stoat_auth.sh.