Team chat. Channels, threads, DMs, file sharing, slash commands. The communications layer for PMA itself — release notifications, alerts, n8n posts, AI agent messages all land here.
Mattermost is the team chat where humans + AI + automation
meet. n8n posts release notifications + alerts to channels.
Grafana alerts go through Mattermost via n8n. AI agents
participating in PMA work post status messages here. Slash
commands trigger n8n workflows.
Upstream: mattermost.com. Image:
mattermost-team-edition:10.x. Backend: Postgres.
| Use case | Verdict |
|---|---|
| Real-time team chat | ✓ — Mattermost's core |
| Threaded discussions on a topic / ticket | ✓ — first-class threads |
| File sharing within a team | ✓ — drop in a channel |
| Voice / video calls | △ — Mattermost Calls plugin exists; PMA doesn't bundle a SFU |
| Customer support inbox | ✗ — use Zammad (separate service) |
| Long-form documentation | ✗ — use Wiki.js |
| Async approvals / forms | △ — use Mattermost slash commands → n8n workflow, OR file in Redmine |
For "the team's running conversation", Mattermost is the
default. Zammad handles external support tickets; Wiki.js holds
the persistent knowledge; Mattermost is where day-to-day work
happens.
Already in the enterprise, development, and support
profiles.
just status mattermost
# [asd-dev-mattermost] ✓ healthy
# [asd-dev-mattermost-postgres] ✓ healthy
grep ^MATTERMOST_URL= .env
# MATTERMOST_URL=https://mattermost-xyz1.eu2.tn.example.com
If your profile doesn't include it:
just profile enable mattermost
just compose-generate
just up
Manifest declares sso.type: oauth. After bootstrap, "Sign in
with OIDC" on the Mattermost login page redirects to Authentik
→ authenticated → back to Mattermost. Same Authentik session
unlocks Redmine, ERPNext, Wiki.js, Superset, Grafana.
If you're testing locally and want to also enable Mattermost's
built-in local accounts (for the admin user): manifest's SSO
config keeps both strategies live in parallel.
PMA ships n8n workflows that post to Mattermost on events from
other services:
| Event | Channel | Content |
|---|---|---|
| New Redmine ticket in watched project | #dev-tickets |
Title + assignee + link |
| Closed Redmine ticket | #dev-tickets |
Title + resolver |
| Grafana alert fired | #alerts |
Metric name + threshold + current value |
| Grafana alert resolved | #alerts |
Same metric, status: cleared |
| Zammad ticket → Mattermost handoff | #support |
Customer email + summary |
| Release-run started / completed / failed | #releases |
Ticket # + phase + duration |
These are all in packages/n8n/workflows/. Edit one + re-import
to customise.
Mattermost slash commands trigger n8n webhooks:
| Command | What it does |
|---|---|
/ticket create <subject> |
Creates a Redmine ticket via n8n → Redmine API |
/ticket close <id> |
Closes a Redmine ticket |
/standup |
Posts a structured "what did I do / what am I doing / blockers" template |
/oncall |
Pings the current on-call rotation |
To add a new slash command: register it in Mattermost
(Integrations → Slash Commands), point at an n8n webhook URL,
write the n8n workflow.
The claude_ai_PMA MCP server exposes Mattermost operations to
AI agents via — actually, Mattermost-specific tools aren't
shipped today; the n8n route covers most needs (agents call n8n
webhooks which then post to Mattermost). File an issue if you
need direct Mattermost tools.
just mattermost-status # container health
just mattermost-restart # restart mattermost + postgres
just mattermost-logs # follow container logs
just mattermost-psql # psql shell as mattermost user
just mattermost-create-user EMAIL # create a Mattermost user
just mattermost-list-users # list all users
just backup mattermost # take a backup
just restore mattermost TIMESTAMP # restore from a specific backup
Mattermost-specific CLI (via mmctl, the official admin CLI):
docker exec -it asd-${ASD_ENV}-mattermost mmctl auth login \
--name local --username admin --password $MATTERMOST_ADMIN_PASSWORD \
"http://localhost:8065"
docker exec -it asd-${ASD_ENV}-mattermost mmctl channel list myteam
# … any mmctl subcommand
Manifest declares backup.type: database. Same shape as Redmine:
postgres dump goes to
.asd/workspace/backups/mattermost/<timestamp>/dump.sql.
Post-restore quirks for Mattermost:
fixes:
post_restore:
functions:
- name: regenerate_session_secret
description: Sessions from the dump are invalid; generate a fresh secret
targets: config
- name: rebuild_search_index
description: Search index ElasticSearch sidecar (if enabled) gets reseeded
targets: container
Restored Mattermost may require all users to re-login (because
the session secret rotates). That's expected.
backup.type: database captures the DBbackup.volumes entry to theteam-edition image has different feature gatingimage.env_var (you'll need a Mattermost license).flush_interval: -1caddy.rawRoutes — already handled in PMA'spackages/mattermost/net.manifest.yaml, but be aware/pma/learn/04-sso-everywhere — how OAuth wires Mattermost to Authentik./pma/services/redmine — the ticket side that Mattermost notifies about./pma/services/n8n — the workflow engine that bridges Mattermost ↔ other services.