Skip to content

Install

  • A Linux box with Docker (Compose v2) and Node.js installed.
  • To go live: a DNS A record for your hostname pointing at the box, and ports 80 and 443 reachable from the internet. Let’s Encrypt issues the certificate against port 80. To evaluate on the box itself, skip both.
  1. Unpack the bundle:

    Terminal window
    tar xzf teamhud-selfhost.tar.gz && cd teamhud
  2. Run first boot:

    Terminal window
    ./firstboot.sh

    It asks only what it cannot work out:

    Question Answer
    Public hostname teamhud.example.com. Blank on a cloud VM uses <ip>.sslip.io (a real certificate, no DNS record needed); blank elsewhere evaluates on localhost
    Address clients reach this host on The box’s public (or LAN) IP. It suggests one
    Addresses allowed to open /admin Your office or VPN IP. It offers the one your SSH session comes from; blank leaves /admin protected by the System admin login alone
    Invite-only sign-up: people join with an invitation sent to their email? true (default): people join by invitation; false lets anyone with the address sign up. Not asked when your sign-in provider is the only way in. The setup page asks again, and you can change it later in Server settings > Sign-up
    Sign in with Slack? Sign in with Microsoft (Teams)? false (default). true asks for the app’s credentials from your own Slack or Entra app, then whether that is the only way to create an account
    Install the game server? Team mini-games. Defaults to true; answer false and the image is never pulled

    Then it writes .env, generates every secret, starts the stack, and runs verify-stack.sh.

  3. Open the setup link it prints at the end, https://<your-host>/setup?token=…, and sign up. Until the first team exists the server lets nobody else in: no sign-up, no sign-in and no calls without that token, and every account made with it becomes a System admin. The setup page also asks who may create accounts afterwards: invite only (recommended, the default), your sign-in provider only, or anyone. The token is also in .env as SETUP_TOKEN. A self-hosted server with no team and no SETUP_TOKEN stays shut and says so in its log: run ./firstboot.sh, or set SETUP_TOKEN and restart.

  4. A server that has never been activated shows only the activation screen. Sign in to TeamHUD Cloud and approve the code, or paste a licence key. See Licensing.

The Set up your TeamHUD server page, Step 1 of 4, with Your name, email and Password fields and a Create administrator button.
The setup link opens the sign-up form. The first account becomes the System admin.

firstboot.sh is safe to re-run. It never overwrites a secret and never re-asks a question you have answered, so a first boot that failed halfway is fixed by running it again. Export the answers (PUBLIC_HOST=… ./firstboot.sh) and it asks nothing, which is how it runs unattended.

verify-stack.sh signs up a real user and walks the whole path:

schemas → migrations → login-token hook → API auth → server reaching its own media server
→ a real call routed there, at an address clients can actually dial

Trust it over docker compose ps. The two failures that matter most, System admins who are silently not System admins and calls that connect with no audio, both show every container as healthy.

  1. Install TeamHUD from teamhud.app.
  2. On the sign-in screen, open Use a different TeamHUD server and enter https://teamhud.example.com. Evaluating on the box itself? http://127.0.0.1:3001 works without a certificate: loopback is treated as secure.
  3. Sign in with the System admin account, then invite your team.