← All guidesSelf-Hosting

Run a Private Stoat Chat Server on Your Own Domain

Use scripts to secure a fresh DigitalOcean Droplet, install Stoat's official Docker Compose stack, then prove the web client works before inviting anyone.

Companion GitHub repositoryCompanion Stoat Droplet runbookTylorMayfield/stoat-droplet-runbookView on GitHub

Create the Droplet and firewall

Create a fresh Ubuntu Droplet with at least 2 vCPUs and 2 GB RAM. Add an SSH key during creation. Then create a Cloud Firewall, attach it to this Droplet, and point a hostname such as chat.example.com at its public IPv4 address. This is a Docker Compose deployment, not an App Platform app or one-container demo.

  • TCP 22 from your own public IP or VPN only.
  • TCP 80 and 443 from everywhere for the web client and HTTPS certificates.
  • TCP 7881 and UDP 50000 through 50100 from everywhere only if you want LiveKit calls.
  • Leave MongoDB, Valkey, RabbitMQ, MinIO, and Docker without public host ports.

Attach the firewall before you connect

In the Cloud Firewall form, create the inbound rules below and choose this server under Apply to Droplets. Keep DigitalOcean's default outbound allow-all rules. The two call rules are optional. Do not add them if your community will not use calls.

Cloud Firewall rule checklist: restricted SSH, public HTTP and HTTPS, optional LiveKit call ports, and the Stoat Droplet selected for attachment.
A compact rule checklist for the DigitalOcean form. The firewall has to be attached to the Droplet.

Check the first response

Expected result
The public hostname returns HTTPS, Compose reports the expected services, and a separate browser can complete a harmless web-client test without exposing a backing service.
Stop if
Stop if SSH is open to the internet, a data service has a host port, DNS does not point to the Droplet, a certificate fails, a secret appears in output, or a LiveKit port is open without a deliberate call-testing plan.
Next step
Back up configuration and persistent data, test a restore away from production, then record the repository commit and image versions before inviting users.

Connect, harden, then install

Use the Droplet's public IPv4 address from the DigitalOcean dashboard. The hardening script updates Ubuntu and turns off SSH password login only when it finds a root SSH key. Keep this terminal open, then confirm a second SSH login works. The preflight script changes nothing. The install script requires --apply, refuses to overwrite /opt/stoat, and opens Stoat's configuration generator.

Connected Droplet4 steps

Before continuing: This updates Ubuntu and disables SSH password login after confirming a root SSH key exists. Keep the first SSH session open and test a second login.

  1. Connect to the Droplet
    Edit firstReplace every highlighted value before running this command.
    ssh root@YOUR_DROPLET_IP

    Replace before running: YOUR_DROPLET_IP

  2. Clone the runbook
    git clone https://github.com/TylorMayfield/stoat-droplet-runbook.git
  3. Open the runbook
    cd stoat-droplet-runbook
  4. Update Ubuntu and disable SSH passwords
    sudo ./scripts/harden-host.sh --apply
Connected Droplet3 steps

Before continuing: This installs Docker and writes Stoat secrets on a new server. Confirm the Cloud Firewall and DNS before you run the final install step.

  1. Open the runbook
    cd ~/stoat-droplet-runbook
  2. Check Ubuntu and DNS
    Edit firstReplace every highlighted value before running this command.
    sudo ./scripts/preflight.sh chat.example.com

    Replace before running: chat.example.com

  3. Install the official Stoat stack
    Edit firstReplace every highlighted value before running this command.
    sudo ./scripts/install-official-stoat.sh --apply chat.example.com

    Replace before running: chat.example.com

Start once, then check HTTPS

The configuration generator creates secrets.env. Back it up before you start the service. Start in the foreground, read errors if any appear, then stop with Ctrl+C and run the detached command. The verification script checks the Compose configuration, running services, and public HTTPS without printing secrets. It does not prove the web app works yet.

Connected Droplet4 steps

Before continuing: The foreground command starts the full Stoat service stack. Read its output before you stop it and start the detached service.

  1. Open the installed stack
    cd /opt/stoat
  2. Start once in the foreground
    sudo docker compose up
  3. Start in the background
    sudo docker compose up -d
  4. Check public HTTPS
    Edit firstReplace every highlighted value before running this command.
    sudo ~/stoat-droplet-runbook/scripts/verify-stoat.sh chat.example.com

    Replace before running: chat.example.com

Do one small real test

Open https://chat.example.com in a separate browser profile. Create a test account, send one harmless message, and upload a disposable file if you enabled file storage. If you enabled calls, test from a second network. A green HTTPS page does not prove the call ports work.

Use the browser client or install it as a PWA. Most official Stoat clients do not support self-hosted instances. Stop if a backing service is public, the certificate fails, secrets appear in output, or you cannot explain why a port is open. Read Stoat's official notices before every update.