team-chat
Slack logo

Should I self-host Slack?

KINDAworth it if…

Per-seat pricing means the math flips hard around 4 seats — a 10-person team escapes $1,050/yr for one weekend of setup. Worth it if someone genuinely owns the pager; chat is the one service your team notices being down within 90 seconds.

The math (nothing hidden, including your time)

Slack (Pro, per seat)$8.75/mo
VPS share + storage−$2.50/mo
Your maintenance: 45 min/mo at $20/h−$15.00/mo
Net saving$-8.75/mo
Setup: 65 min measured (one-time)$21.67
Break-evennever
Markup Index (price ÷ real self-host cost)0.5×

Price: source, checked 2026-08-05. Inputs are stored in git; every number above is derived, never hand-written.

What you lose

  • Slack's mobile push reliability — Mattermost push routes through their relay or you build your own, and half-working push kills adoption
  • The integration directory: webhooks exist, but every SaaS ships a Slack app and maybe a Mattermost one
  • Huddles-grade calls without extra setup
  • Message history import is one-way and lossy — the escape is easier before the archive matters

What you're paying Slack for

  • channels & DMs
  • mobile apps with reliable push
  • search across full history
  • integrations & incoming webhooks
  • huddles/calls
Mattermost running from the boot-verified compose file
Mattermost, running from the compose file on this page — screenshot from our verified instance, not marketing material.

Ranked alternatives

Channels, threads and file sharing for a team, on a server you own, with no per-seat meter and no ninety-day history cliff.

mattermost/mattermost · ★ 38,721 · last commit 0d ago · MIT

Hardware

Runs comfortably on a real VPS (2 GB+).

The tested compose file (our evidence, CI-booted)

# Mattermost Team Edition — self-hosted team chat (replaces Slack)
services:
  mattermost:
    image: mattermost/mattermost-team-edition:latest
    container_name: mattermost
    restart: unless-stopped
    depends_on:
      mm-postgres:
        condition: service_healthy
    environment:
      MM_SQLSETTINGS_DRIVERNAME: postgres
      MM_SQLSETTINGS_DATASOURCE: postgres://mmuser:mmpass@mm-postgres:5432/mattermost?sslmode=disable&connect_timeout=10
      MM_SERVICESETTINGS_SITEURL: http://localhost:8065
      MM_SERVICESETTINGS_ENABLELOCALMODE: "true"
    ports:
      - "8065:8065"
    volumes:
      - mm-data:/mattermost/data
      - mm-logs:/mattermost/logs
      - mm-config:/mattermost/config
      - mm-plugins:/mattermost/plugins
      - mm-client-plugins:/mattermost/client/plugins
      - mm-bleve:/mattermost/bleve-indexes
    healthcheck:
      # The image ships no shell, curl or wget — exec-form mmctl over the local socket
      # is the only probe that works (requires MM_SERVICESETTINGS_ENABLELOCALMODE above).
      test: ["CMD", "/mattermost/bin/mmctl", "system", "status", "--local"]
      interval: 5s
      timeout: 10s
      retries: 36
      start_period: 30s

  mm-postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: mmuser
      POSTGRES_PASSWORD: mmpass
      POSTGRES_DB: mattermost
    volumes:
      - mm-pg:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mmuser"]
      interval: 5s
      timeout: 5s
      retries: 12

volumes:
  mm-data:
  mm-logs:
  mm-config:
  mm-plugins:
  mm-client-plugins:
  mm-bleve:
  mm-pg:

Want a guided install instead? caniselfhostit.com/slack has AI-agent prompts that assume a bare machine — that's their half of the stool, and it's good.

Verification

Protocol v1 · verified by zernonia on 2026-08-10 · setup measured at 65 min · AI assistant: claude-code (allowed & stated)

What broke

  • The image ships no shell, curl or wget, so a CMD-SHELL healthcheck fails forever while the server is fine — exec-form mmctl system status --local (with local mode enabled) is the probe that works
  • First admin account creation is a UI step — plan it into the rollout, whoever clicks first owns the workspace
Full timed log
# Timed setup log: Slack → Mattermost

**Protocol:** v1 · **Verified by:** zernonia · **Date:** 2026-08-10
**Assistant:** claude-code · **Environment:** containerized runner, 2 vCPU class, Docker 29.3 / Compose v5.1

## Timeline

| Step | Time |
|---|---|
| Draft compose (mattermost + postgres, datasource string, site URL) | 15 min |
| **Boot #1: server up and serving, but never reported healthy** (see What broke) | 15 min to diagnose |
| Switch healthcheck to `mmctl system status --local`, re-up | 3 min |
| Boot #2 to healthy + core workflow: create admin + team, post in a channel, second browser sees it live | 25 min |
| Re-run from clean volumes | 7 min |
| **Total: ~65 min** | |

## Measurements

- 2 containers · Mattermost idle RAM ~450 MB + postgres ~40 MB — wants the full 2 GB box
- Server boots and serves within ~60 s; plugin unpacking continues for a while after

## What broke

1. **The image ships no shell, curl or wget** — a `CMD-SHELL` healthcheck fails with
   "stat /bin/sh: no such file or directory" forever while the server is actually fine.
   Exec-form `mmctl system status --local` (with `MM_SERVICESETTINGS_ENABLELOCALMODE=true`)
   is the healthcheck that works.
2. **First admin is a race**: whoever completes the first-run screen owns the workspace.
   Plan the rollout; don't send the URL to the team before you've clicked through.

## Verdict-relevant notes

- Channels, DMs, search, webhooks: solid. Mobile push routes through Mattermost's relay (or
  you run your own push proxy) — test it before you migrate anyone who matters.
- The KINDA is arithmetic: per-seat pricing versus a flat server cost. At 1 seat you're
  losing money; at 10 seats you're keeping ~$1,000/yr for one weekend plus ops ownership.

Verdict history

  • 2026-08-10: unscored → KINDA — Initial verdict: per-seat math flips hard at ~4 seats, if someone owns the pager.