Integrations on a self-hosted TeamHUD server
Your server runs without any of these. Calls, chat, presence and teams need nothing from Slack, Google or Microsoft. Each integration below is opt-in, and an empty variable means “off” — the server boots and behaves as if the feature did not exist.
What you register, and where, is the same shape every time: an app in the provider’s
console → its credentials in .env → a redirect URL on your hostname → a restart. The
guides:
| Integration | What your users get | Guide | Status |
|---|---|---|---|
| Slack | Slack DMs and channels in TeamHUD, live “doorbell” updates, optional Sign in with Slack | SLACK.md | ✅ works |
| Google (Gmail, Calendar, Drive) | Mail, calendar and Drive search, Gmail push updates | GOOGLE.md | ✅ works |
| Microsoft Teams | Teams chats and channels, Sign in with Microsoft | MICROSOFT.md | ✅ sign-in; ✅ doorbell (server side, simulated Graph); ⬜ Teams chats in-app |
| Outlook / any IMAP mail | Mail over IMAP, credentials never leave the user’s machine | MICROSOFT.md | desktop-only, no server setup |
Before you start: three things every integration needs
Section titled “Before you start: three things every integration needs”-
A real hostname with TLS. Slack, Google and Microsoft all refuse
http://redirect URLs on anything butlocalhost, and none of them will call a webhook at a raw IP. SetPUBLIC_HOST,PUBLIC_BASE_URLandAPP_URLfirst — see Before you put this on a domain in Going live on a domain. Every URL in these guides ishttps://teamhud.example.com; substitute yours. -
PUBLIC_BASE_URLmust never change afterwards without re-registering. Every redirect URL and webhook audience is derived from it. A hostname change silently breaks every integration at once, because the provider still has the old one on file. Where a variable exists to pin a URL (SLACK_REDIRECT_URI,GOOGLE_REDIRECT_URI), pin it. -
Each variable goes in
.envonly.docker-compose.ymlalready forwards every variable these guides name. After editing.env:Terminal window docker compose up -d # recreates whatever changed — including GoTruedocker compose logs server | head -50 # the boot log says what it foundUse
docker compose up -d, not./deploy.sh, for anything touching sign-in:deploy.shrecreates only the server, and theGOTRUE_*variables belong to GoTrue.
Point your users’ desktops at your server
Section titled “Point your users’ desktops at your server”This is the step everyone misses. The desktop app does not route Slack and Google
sign-in through the server a user signed into. Out of the box it uses TeamHUD’s own hosted
apps at dashboard.teamhud.app. It does this on purpose (your server may not have these
configured), but it means that until you tell the desktop otherwise, your Slack and Google
apps are never used. What your users see instead:
- Slack connects, but through TeamHUD’s Slack app rather than yours. Live updates never arrive, because the entitlement was signed by our server and yours cannot verify it. Chat falls back to polling.
- Gmail connects, but Gmail push fails to register (
token_exchange_failedin the server log). Token refresh against a self-hosted session can also fail, and then mail, calendar and Drive go quiet with no reconnect prompt.
Set two environment variables on every desktop that signs into your server, and then fully quit and reopen TeamHUD:
| Variable | Value | Covers |
|---|---|---|
TEAMHUD_SLACK_OAUTH_API_BASE |
https://teamhud.example.com |
Slack |
TEAMHUD_OAUTH_API_BASE |
https://teamhud.example.com |
Gmail, Calendar, Drive |
macOS: apps started from the Dock or Finder do not read your shell profile, so:
launchctl setenv TEAMHUD_SLACK_OAUTH_API_BASE https://teamhud.example.comlaunchctl setenv TEAMHUD_OAUTH_API_BASE https://teamhud.example.com# quit TeamHUD completely (tray → Quit), then reopen it.# launchctl settings do not survive a reboot. For a fleet, push a LaunchAgent that# runs these two commands at login (MDM profile or ~/Library/LaunchAgents).Windows (PowerShell, per user; applies to newly started processes):
setx TEAMHUD_SLACK_OAUTH_API_BASE https://teamhud.example.comsetx TEAMHUD_OAUTH_API_BASE https://teamhud.example.com# quit TeamHUD from the tray and start it again. For a fleet, set them via Group Policy# (User Configuration → Preferences → Windows Settings → Environment).Linux: add both export lines to ~/.profile (or the Exec= line of the .desktop
file as env TEAMHUD_…=… teamhud), then log out and back in.
A user who already connected Slack or Google before these were set must disconnect and reconnect that account. Their existing tokens belong to TeamHUD’s apps, not yours.
Why a variable and not a setting: sign-in brokering is deliberately separate from the server a user signs into, since plenty of servers have no Slack or Google app of their own. What is missing is a place in the app to change it. Until there is one, these variables are the only way.
Order of operations
Section titled “Order of operations”- Stack up on its real hostname,
./verify-stack.shgreen. - Add
ENT_SECRETto.env(openssl rand -hex 32). Slack live updates need it, andgen-keys.mjsdoes not generate it. - Slack → SLACK.md.
- Google → GOOGLE.md.
- Set the two desktop variables above on one test machine, and connect each integration there before rolling out to everyone.
Every variable, in one place
Section titled “Every variable, in one place”All are optional. Server = read by the TeamHUD server; GoTrue = read by the auth service.
| Variable | Read by | Guide |
|---|---|---|
ENT_SECRET |
server | SLACK.md |
SLACK_CLIENT_ID, SLACK_CLIENT_SECRET |
server | SLACK.md |
SLACK_SIGNING_SECRET |
server | SLACK.md |
SLACK_EVENT_SOURCE (events | socket | off) |
server | SLACK.md |
SLACK_APP_AUDIENCE_TOKEN |
server | SLACK.md |
SLACK_APP_TOKEN |
server (Socket Mode only) | SLACK.md |
SLACK_REDIRECT_URI |
server | SLACK.md |
SOCIAL_PROVIDERS |
server | SIGN-IN-AND-CHANNELS.md |
GOTRUE_EXTERNAL_SLACK_OIDC_* |
GoTrue | SLACK.md |
GOTRUE_EXTERNAL_AZURE_*, AZURE_TENANT |
GoTrue | MICROSOFT.md |
AUTH_PUBLIC_URL (local stack only) |
server | MICROSOFT.md |
SIGNUP_MODE, GOTRUE_DISABLE_SIGNUP |
server + GoTrue | SIGN-IN-AND-CHANNELS.md, SLACK.md |
CHANNEL_PROVIDERS |
server | SIGN-IN-AND-CHANNELS.md |
MSTEAMS_TENANT_ID, MSTEAMS_CLIENT_ID, MSTEAMS_CLIENT_SECRET |
server | MICROSOFT.md |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
server | GOOGLE.md |
GOOGLE_REDIRECT_URI |
server | GOOGLE.md |
GMAIL_PUSH_TOPIC, GMAIL_PUSH_SA_EMAIL |
server | GOOGLE.md |
TEAMHUD_SLACK_OAUTH_API_BASE, TEAMHUD_OAUTH_API_BASE |
desktop | above |
What stays on the user’s machine
Section titled “What stays on the user’s machine”Your server holds exactly two kinds of provider token, both encrypted with ENCRYPTION_KEY:
- Slack: the workspace bot token, which is used only to check channel membership.
- Gmail: a second, metadata-only token used to arm Gmail push. It can see that mail arrived, not what it says. The server refuses any broader token, and revokes one that has widened.
The tokens that read and send messages, mail, calendar and files live on each user’s desktop, encrypted with the OS keychain. Your server brokers the OAuth exchange (it holds the client secret, so desktops never do) and hands the result straight back.