Build Mattermost Professional

KINDAreplaces $10/mosaves $120/yrback to the verdict

0%0 of 21 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

Mattermost on a server you own, behind TLS with a real certificate, connected to an email provider that delivers, with a deliberate decision about mobile push, retention and moderation policies written down, backups of the database and the uploaded files together, and a restore you have performed.

estimated effort multi-daythe files for this build are in the project pack

ApplicationMattermost, self-hostedDatabasePostgreSQLFilesLocal disk or S3-compatible storageEdgeA reverse proxy with automatic certificates and WebSocket supportEmailA transactional provider with a verified sending domain

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. have readytypically 10 to 30 US dollars a month for a small team

    Why Chat is latency sensitive in a way people notice, and an undersized server produces a sluggish client that everyone comments on.

    Get it Check the project's current requirements for your team size, then provision accordingly.

    Verify The application starts and a client connects promptly

  2. have readya few US dollars if deleted the same day

    Why Restoring onto the machine that already has the files proves nothing, and the missing file storage is exactly what a database-only backup leaves out.

    Get it The same provider, smallest suitable plan, destroyed after the drill.

    Verify You can SSH to it

  3. have readyroughly 10 to 15 US dollars a year

    Why Needed for the certificate, the site URL and the email sending records.

    Get it Any registrar, then add the A record and the email verification records.

    Verify The hostname resolves and serves a valid certificate

  4. API keyfree tiers cover a small team

    Why Invitations and password resets both depend on delivery, and mail sent from the server directly will land in spam.

    Get it Create an account, add the DNS records, take the credentials. Verification is the slow step.

    Verify An invitation arrives at three providers and is not in spam

  5. decidevaries by arrangement; check current pricing rather than assuming

    Why This is the constraint that surprises people after migration. Notification certificates belong to the published applications, so a self-hosted server cannot send to them directly.

    Get it Check the project's current options for push, including any hosted proxy service and its cost, or the effort of building and distributing your own mobile applications. Decide before the team migrates.

    Verify A backgrounded mobile application receives a notification, or the limitation is documented and communicated

  6. decidefree

    Why Chat accumulates informal conversation quickly, and both what you keep and who decides what is acceptable are decisions with weight once a team relies on it.

    Get it Write both before inviting anyone. One page each is enough.

    Verify Both are written and the settings match them

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- The application owns its schema. What you own is the operational state, and it is worth recording.
- instance · version, host, database, file storage location and the deployment method
- identity · how people sign in, and whether accounts are invite-only
- push · which arrangement you chose for mobile notifications, and what it costs
- retention · per channel kind, with the reason and the policy that requires it
- backups · database and files, with the date of the last restore

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
MM_SERVICESETTINGS_SITEURLrequiredhttps://chat.example.comAppears in every link and email. Correct before the first invitation.
MM_SQLSETTINGS_DATASOURCEsecretrequiredpostgres://user:pass@db:5432/mattermost?sslmode=disableDatabase connection. Half of what a restore needs.
MM_FILESETTINGS_DIRECTORYrequired./data/filesUploaded files. The other half of a restore, and the half people forget.
MM_EMAILSETTINGS_SMTPSERVERrequiredsmtp.provider.comTransactional provider host.
MM_EMAILSETTINGS_SMTPPASSWORDsecretrequiredreplace-with-provider-passwordProvider credential, on the server only.
PUSH_ARRANGEMENTrequireddocumented-in-docs-pushWhich push arrangement you chose. Recorded here so it is not forgotten.
BACKUP_DESTrequireds3://your-bucket/chatWhere both nightly artefacts go.

The build, in order

  1. Running behind a proxy that understands sockets

    Chat works, and it keeps working when a conversation goes quiet for an hour.

    1. Non-root user, key-only SSH, firewall allowing SSH and web ports only.

      terminal
      ufw allow OpenSSH && ufw allow 80,443/tcp && ufw enable
    2. Following the project's own deployment guidance for the version you are using.

      Files docker-compose.yml

    3. Upgrade headers and a generous idle timeout. Verify by leaving a client idle for an hour.

      Files Caddyfile

    done when · tick each as it passes
    watch out
    • A reverse proxy with a short idle timeout closes the WebSocket during a quiet period, and the client reconnects without saying anything, so messages appear late and nobody knows why. Set the timeout deliberately and verify by leaving a client idle rather than by reading the configuration.
  2. Email that arrives

    Invitations and resets reach inboxes, because everything else depends on them.

    1. The DNS records your provider specifies. Propagation takes hours, so this is why it is early.

    2. Three different ones, checking spam in each. One provider proves nothing.

    3. Not just the invitation. It is the one people need when they cannot get in.

    done when · tick each as it passes
    watch out
    • Sending from the server directly rather than through a provider produces mail that lands in spam almost everywhere, and the symptom is people saying they never got the invitation. Use a provider, verify the domain, and check the spam folder at three providers rather than one.
  3. The mobile push decision

    Mobile notifications work, or the team knows in advance that they will not.

    1. Check the current options and costs. Write down what you chose and why.

      Files docs/push.md

    2. Backgrounded application, real message, real phone. This is the only test that counts.

    3. Message previews appear on lock screens. Decide whether that is acceptable for your team.

    done when · tick each as it passes
    watch out
    • Migrating a team and then discovering that mobile notifications do not arrive is how a self-hosted chat deployment gets abandoned in week two. Notification certificates belong to the published mobile applications, so a self-hosted server cannot send directly to them; resolve this before anyone depends on it.
  4. Access, retention and moderation

    The right people are in, old messages do not accumulate forever, and someone is responsible.

    1. Invitation only or a verified domain. Test with an outside address.

    2. Per channel kind with the reason. Chat accumulates and much of it should not be kept forever.

      Files docs/retention.md

    3. What is not allowed, who decides, how to appeal. Before the first incident rather than during it.

      Files docs/moderation.md

    done when · tick each as it passes
    watch out
    • Open signup on a publicly reachable chat server is discovered by scanners and produces accounts you did not invite, sometimes within days. Restrict signup before the server is reachable rather than after the first unexpected member appears.
  5. Backups of both halves

    The database and the uploaded files are both backed up, off the machine.

    1. Dated, compressed, off the machine.

      Files scripts/backup.sh

      terminal
      pg_dump "$DATABASE_URL" | gzip > chat-$(date +%F).sql.gz
    2. Same schedule, same destination. Uploads are half the content people care about.

      Files scripts/backup.sh

    3. Silence is not evidence a backup ran.

      Files scripts/check_backup.sh

    done when · tick each as it passes
    watch out
    • A database dump without the file storage produces a restore where every conversation is intact and every shared file is a broken link, which is exactly the material people needed. Back up both on the same schedule and restore both together.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more community.