# Deploy Mattermost with the mattermost-team-chat template

Source: https://docs.quake.ai/resources/deployments/deploy-mattermost-team-chat-template
Markdown: https://docs.quake.ai/resources/deployments/deploy-mattermost-team-chat-template.md

---

# Deploy Mattermost with the mattermost-team-chat template

Stand up [Mattermost](https://mattermost.com) Team Edition, an open-source team-chat platform, on a single Quake AI instance using the [validated OpenTofu template](/docs/platform/validation#how-infrastructure-templates-are-checked) `mattermost-team-chat`. You apply the template, serve it over HTTPS through Caddy, set the public site URL, sign up the first admin account, create a team and a channel, and invite a teammate.

Mattermost keeps your team's chat on infrastructure you own. You run it yourself; this is a self-hosted tool you operate, not a managed multi-tenant service.



Mattermost's app server plus its bundled PostgreSQL need more headroom than a single-process tool. This deployment's default sizing (4 vCPU, 4 GiB RAM) suits a small-to-mid team. Mattermost's own scaling guidance recommends significantly more compute for large enterprise deployments; size up the flavor and split PostgreSQL onto its own instance as your team grows.



<Figure size="md" caption="What you'll build: a Mattermost host on a single instance with a bundled PostgreSQL, served over HTTPS through a Caddy reverse proxy">

```d2
direction: right

user: Team member {shape: person}
fip: Floating IP
instance: Ubuntu instance {
  caddy: Caddy\nreverse proxy
  mattermost: Mattermost\napp
  db: PostgreSQL
  caddy -> mattermost: proxies 443 to 8065
  mattermost -> db: teams, channels, messages
}

user -> fip: HTTPS
fip -> instance.caddy
```

</Figure>

<PricingCompanion
  components={[
    { kind: "template", slug: "mattermost-team-chat", required: true },
  ]}
/>

## Prerequisites

You need:

- OpenTofu 1.6.0 or later (or Terraform 1.6.0 or later) installed locally.
- Your OpenStack credentials sourced into the shell (`source openrc.sh`). See [the OpenStack CLI guide](/docs/tools/openstack-cli).
- An SSH keypair that already exists in your project. Record its name for the `key_name` variable.
- A copy of the `mattermost-team-chat` template directory from [the template reference page](/resources/iac-templates/mattermost-team-chat).
- A domain you can point at the instance.

## Step 1: Apply the template

Copy the template's example variables file and set `key_name`:

```bash
cp terraform.tfvars.example terraform.tfvars
```

```hcl
key_name = "YOUR_KEY_NAME"
```

Initialize, preview, and apply:

```bash
tofu init
tofu plan
tofu apply
```

OpenTofu provisions a private network, a router, a security group, a block volume mounted at `/var/lib/docker`, an instance, and a floating IP. On first boot, cloud-init installs Docker Engine, generates the PostgreSQL password into `/opt/mattermost/.env`, and starts only `postgres`. Mattermost needs a real public URL before invite links, OAuth, and calls work, so the app container waits until you finish configuration.

Read the outputs and record `floating_ip`:

```bash
tofu output
```

## Step 2: Point a domain at the host and serve HTTPS with Caddy

1. Create a DNS **A record** for your domain (for example `chat.example.com`) pointing at `YOUR_FLOATING_IP`. Follow [How to point a domain at a Quake AI resource](/docs/network/how-to/point-domain-to-quake-ai). Wait until it resolves:

```bash
dig +short chat.example.com
```

2. SSH to the instance and create `/opt/mattermost/Caddyfile`:

```text
chat.example.com {
  reverse_proxy 127.0.0.1:8065
}
```

3. Add Caddy to `/opt/mattermost/docker-compose.yml`:

```yaml
services:
  caddy:
    image: caddy:2
    restart: unless-stopped
    network_mode: host
    volumes:
      - /opt/mattermost/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
volumes:
  caddy_data:
```

For background on certificates, see [How to issue and auto-renew a TLS certificate with Let's Encrypt](/docs/network/how-to/lets-encrypt-certificate).

## Step 3: Set the site URL and start Mattermost

Edit `/opt/mattermost/.env` and set:

```text
MM_SERVICESETTINGS_SITEURL=https://chat.example.com
```

Start the full stack:

```bash
cd /opt/mattermost
sudo docker compose up -d
```

## Step 4: Sign up the first admin account

Open `https://chat.example.com` and sign up. The first account to sign up becomes the System Console admin.

## Step 5: Create a team and a channel

1. Select **Create a team**, name it, and confirm.
2. Inside the team, select **+** next to **Channels** > **Create new channel**, name it (for example `general-eng`), and create it.

## Step 6: Invite a teammate

1. Inside the team, select **Invite people**.
2. Enter a teammate's email, or copy the generated invite link and share it directly.
3. The teammate follows the link to sign up and joins the team.

## What you built

- **Applied the `mattermost-team-chat` template** to provision a network, security group, data volume, instance, and floating IP, with PostgreSQL started automatically by cloud-init
- **Served Mattermost over HTTPS** by pointing a domain at the floating IP and routing it through a Caddy reverse proxy
- **Set the public site URL** and started the Mattermost app container
- **Signed up the first admin account**
- **Created a team and a channel**
- **Invited a teammate**

## Scope of this deployment

This template runs a single-VM Mattermost host, not a managed team-chat cloud. The instance is CPU-only and runs in one region, and it bundles PostgreSQL as a container on the same host, sized for a small-to-mid team. You operate the instance, Docker, Mattermost, the database, and the data volume yourself: back them up, patch them, and size up the flavor as your team grows. Mattermost's own scaling guidance recommends significantly more compute for large enterprise deployments.

## Next steps

- [Mattermost team-chat template](/resources/iac-templates/mattermost-team-chat): the template reference, parameters, and resource map
- [Self-managed PostgreSQL template](/resources/iac-templates/self-managed-postgres): the database to point at when you outgrow the bundled one
- [Security hardening checklist](/docs/security/hardening-checklist): tighten SSH access and exposure before you connect production traffic

## Clean up

When you no longer need the deployment, destroy everything the template created:

```bash
tofu destroy
```

Then remove the DNS A record you created in step 2. Because Mattermost and its database both live on the instance and its attached volume, `tofu destroy` removes them along with the infrastructure.
