LibrePortal
Sponsor
Install

Stoat

Discord-style Chat

Stoat is the closest open-source match to Discord, with servers, channels, roles, and voice and video chat. Run it for your friends or your community, on your own server.

On this page
  1. At a glance
  2. What it's good for
  3. Signing in
  4. Adding people
  5. Voice and video
  6. Good to know
  7. Addresses and ports
  8. Settings
  9. In its config file
  10. Tools
  11. Works with
  12. Privacy and security
  13. What leaves this server
  14. What LibrePortal turns off
  15. Sources
  16. Under the hood

Good to know before you install

Separate accounts; no single sign-on: Stoat cannot sign in with LibrePortal, so everyone uses a Stoat account of their own. Voice calls ask Google's STUN servers for the server's address unless you turn that off in Privacy settings; LiveKit hands Google's STUN to callers' apps unless LibreSTUN is installed.

At a glance#

What it is
Discord-style Chat Communication
Where it opens
Web Interface On its own port at http://your-server:port, or stoat.your-domain once you have a domain
Updates
Automatic A backup is taken first, and it rolls back if the update fails
Backups
Included Part of the daily backup when that's switched on
Copies
One per server

What it's good for#

If your friends or your gaming group live on Discord, Stoat will feel familiar straight away. You make servers, each with text channels and voice channels, give people roles with different permissions, and chat, share pictures and jump into a voice call. The difference is that it's yours: no adverts, no one else reading along, and nobody can close your server but you. You may know it by its earlier name, Revolt.

For a work-style team chat, Rocket.Chat or Mattermost suit better. Stoat is for hanging out.

Signing in#

Upstream, the first person to register on a new Stoat becomes its owner, with no email check and nothing to slow anyone down. LibrePortal closes that gap: as soon as Stoat's API answers during the install, it registers the owner account itself.

  • Email: admin@stoat.local. It's only a login name; nothing is ever sent to it.
  • Handle: administrator (Stoat refuses admin).
  • Password: in the Login Details shown when the install finished; press Welcome on the app's page to see it again.

Open Stoat with the Web Interface button and sign in. The first start takes a few minutes: Stoat is sixteen containers, which start in order, and its API keeps restarting until its database and message queue are both ready.

Keep invite-only on when you install

LibrePortal only wins the race for the owner account because nobody else can register. If you switch invite-only off before installing, anyone who reaches Stoat during those first minutes could register first and become its owner. Install with invite-only on. The Create User Account tool works either way, so there's rarely a reason to turn it off.

Adding people#

Registration is invite-only on LibrePortal (CFG_STOAT_INVITE_ONLY=true), so strangers who find your Stoat can't make accounts. You add people from the Tools tab instead:

  1. Run Create User Account with the person's email address. Leave the password empty to have one made, and the handle empty to use the part of the email before the @.
  2. Send them the address, their email and password. The account is ready to use straight away, with Stoat's first-time questions already answered.

The email doesn't have to be real, because Stoat sends no mail here, but a real one makes it easier for people to remember what they signed in with.

Reset User Password, List Users, Disable User Account (which stops someone signing in but keeps their account and messages) and Enable User Account cover the rest.

Voice and video#

Voice and video need two things.

HTTPS. Browsers only allow a page to use your microphone and camera when it's served over HTTPS. Text chat, channels, roles and uploads all work on a plain http://192.168.1.50:port address; calls don't, and the VPN doesn't change that, because the browser checks the address. Either of LibrePortal's HTTPS choices fixes it.

The call ports. Calls travel directly between Stoat's call server and each person, not through the web page. They try UDP ports 50000 to 50100 first, and fall back to TCP port 7881, which is public and open. LibrePortal publishes the UDP range but doesn't open it in the firewall, so from outside your network calls use the slower TCP fallback until you add one rule:

sudo ufw allow 50000:50100/udp

LibrePortal's firewall rebuild only adds the rules for the ports it knows about and doesn't clear the others, so a rule you add yourself stays.

To check: on a rooted install LibrePortal manages the firewall with ufw-docker; check whether a plain ufw allow actually opens a Docker-published UDP range there, or whether it needs a ufw-docker/route rule instead

Good to know#

  • Its address is built in at install. Stoat's web app is made with its own address inside it: https://stoat.example.com with a domain and Traefik, http://192.168.1.50:port without. If you add a domain later, press Update Configuration on its Config tab so it's rebuilt with the new one.
  • It can't share the server with Screego. Screego's relay ports are UDP 50000 to 50019, inside Stoat's call range, so only one of the two can run on a server.
  • Phone and desktop apps. Stoat's web page works in a phone's browser. To check: check whether Stoat's phone and desktop apps can be pointed at a self-hosted server, and how
  • It isn't behind Authelia, and shouldn't be: Stoat's own apps talk to its API, and an extra sign-in page in front would stop them.
  • Backups include everything: the database, uploaded files and its secret keys. The key that encrypts uploaded files is made once at the first install and never replaced, because without it every file ever uploaded would be unreadable. Keep your backups safe for the same reason.
  • Updates are paused for now. Stoat relies on two small helper images (MinIO) that its makers have stopped publishing. Until those are replaced, LibrePortal can't update Stoat: it's set to Manual, and both Update and Upgrade would fail at the download. Nothing is lost in the meantime; Stoat keeps running on the version you installed. To check: Stoat is manual because minio/minio and minio/mc are gone from Docker Hub (update-backup-audit F18); once its compose moves to published images, document its normal update path (lockstep parts, Upgrade for a new release)
  • One per server. Its call server needs fixed port numbers.

Addresses and ports#

Stoat has 3 ports. LibrePortal picks a free port number for each when you install, so yours will differ from anyone else's. The Config tab's Network section shows them, and the app's Open button uses the right one. "Anyone" means it's reachable from wherever your server is reachable; you can make it private later.

What it isWho can reach itWith a domain
Web Interface Anyone stoat.your-domain
LiveKit voice/video (TCP fallback) TCP Anyone Port only
LiveKit voice/video (UDP media) UDP Anyone Port only

Settings#

In its config file#

Stoat's own settings aren't on the Config tab yet. They live in the app's config file, described here so you know they exist. How to change them.

SettingWhat it doesStarts as
Name
CFG_STOAT_DISPLAY_NAME
What this app is called on your dashboards. Leave empty to use its usual name Empty
Show on the LibrePortal Dashboard
CFG_STOAT_SHOW_ON_DASHBOARD
Whether this app gets a shortcut on the front page of the LibrePortal WebUI, separate from any Dashy dashboard
Choices: true, false
true
Public STUN Servers
CFG_STOAT_PUBLIC_STUN
Whether the voice server (LiveKit) may ask Google's STUN servers for its public address; off, it announces this server's public address from LibrePortal instead
Choices: true, false
true
LibreSTUN
CFG_STOAT_LIBRESTUN
Whether calls use this server's own STUN and TURN server (LibreSTUN) when it is installed; off keeps how this app made calls before
Choices: auto, off
auto

Tools#

Stoat's Tools tab has 5 buttons for jobs you'd otherwise need a terminal for. Each one runs as a task, so you can watch it on the Tasks page and read what it did. More about Tools.

Create User Account

Register an account and finish its onboarding, so it can sign in straight away.

Asks for: Email, Password (optional), Username (handle) (optional)
Reset User Password

Set a new password for an existing account. Stoat hashes it, so the account stays usable.

Asks for: Username or email, New password (optional)
List Users

Every Stoat account, with its email and whether it is disabled.

Disable User AccountCan't be undone

Block sign-in without deleting the account or its messages. Reversible.

Asks for: Username or email
Enable User Account

Undo a disable and let the account sign in again.

Asks for: Username or email

Works with#

These are the other apps Stoat knows how to work with. Once it's installed, its page shows the same list with whether each one is connected. How this works.

  • LibreSTUN: Calls connect from anywhere through your own STUN and TURN server, with nothing going to Google. LibrePortal sets this up by itself when both are installed.
  • Grafana: Shows dashboards for the apps that have one. works with every app
  • Prometheus: Collects metrics from the apps that can export them. works with every app
  • Uptime Kuma: Watches your apps and shows when one goes down. works with every app

Privacy and security#

Worth knowing Stoat is your own chat server. Messages stay on your server; voice calls may ask Google's free STUN service for your address, and push alerts go through your browser's push service.

What leaves this server#

  • Voice calls may ask a public STUN server for the server's address (switchable in Config); LibreSTUN gives callers your own
  • Web push goes through the browser maker's push service
  • Link previews fetch the pages people paste

What LibrePortal turns off#

Nothing needed switching off.

Licence: AGPL-3.0 (Stoat/Revolt backend; verify per repo). Audited: 21 October 2026. See the privacy of every app and the Promise.

Sources#

Under the hood#

  • It runs these images: mongo:8.0.34@sha256:b9924c330a8bbc5800fe9c69f04a84e221eca7b28fd049a0354147d9908fa142, valkey/valkey:9.1.2-alpine@sha256:48332870af354a799964c0012ae1194a0bf2bf894eb508f945810596dc2d8d11, rabbitmq:4.4.0-alpine@sha256:21577d148f4f7563a87d761862fa353f59348a094833ca8b1b1a46a8102dffce, chrislusf/seaweedfs:4.48@sha256:4e61d15fd35994cb1e43e1e553dff106794841fd9a99ade2fc8c8bfce4d7872d, caddy:2.11.7-alpine@sha256:eb4d35b7452d1ab6171fbdbe8d9275b2301dad6dad92115d91e19fb9b24d510f, ghcr.io/stoatchat/api:v0.15.1@sha256:21d5c842b6182c58df0330e16dff7c234b879e48b3888c12b9836037c91b5314, ghcr.io/stoatchat/events:v0.15.1@sha256:7bca2ff5f7c5ab8a2aa1dcdc89c7ee18c6dac9fbe9cac70cbb1d1a16df912e0c, ghcr.io/stoatchat/file-server:v0.15.1@sha256:becd5d4bc81b3541cf79b385f6c7c6de7dcbdb2be898a6eb45aea2a5c14df2c4, ghcr.io/stoatchat/proxy:v0.15.1@sha256:7b4ab6e698490c315e418cfc4d419d5874a662e9246276994305750187b1f2e2, ghcr.io/stoatchat/gifbox:v0.15.1@sha256:9dbe75ab2d7986f49ad33d8aafba81bbc15cb123bd820f3faea0033c144561ef, ghcr.io/stoatchat/crond:v0.15.1@sha256:6c419872ed364cd7fb61d2148bc24a93d0427221050db3b4c76957f8bd0e6474, ghcr.io/stoatchat/pushd:v0.15.1@sha256:e8a4d518df332a79bf958a858555dd12c4d607b53abe80a566e08db98c09f673, ghcr.io/stoatchat/voice-ingress:v0.15.1@sha256:04b0a44a697f3defebbd2de5fd27314b23b0cc5763ed3171adcbed8364e64461, ghcr.io/stoatchat/livekit-server:v1.9.13@sha256:affc38db52172aa994b4457804f1568c0fa7a5ac59096e1041408f69689c8d90, ghcr.io/stoatchat/for-web:0c31cf0@sha256:18423e92d574fd5d056928aecc88968c3b2dc1a04b36e941bf67ddc5f1442262.
  • It can sit behind Authelia's sign-in once Authelia is installed.
  • Its own project and documentation: github.com/stoatchat/self-hosted

Ports, settings, tools and connections on this page are read from LibrePortal v0.10.97's app catalogue each time the guide is built.

Next steps