Skip to content

TutorialsCommunication

How to install Mattermost on Ubuntu with PostgreSQL and HTTPS

Install Mattermost from its official apt repository on Ubuntu 24.04 with a local PostgreSQL database, HTTPS through Caddy, a tight firewall and backups.

  • Intermediate
  • 40 min read
  • Updated

Tested on: Ubuntu 24.04 LTS

This guide is not available in your language yet, so it is shown in English.

On this page
  1. Prerequisites
  2. Step 1 — Install PostgreSQL and create the database
  3. Step 2 — Add Mattermost's apt repository and install the package
  4. Step 3 — Configure the database connection and Site URL
  5. Step 4 — Start Mattermost
  6. Step 5 — Publish Mattermost over HTTPS with Caddy
  7. Step 6 — Close every port except SSH and the web
  8. Step 7 — Create the first administrator and lock down sign-up
  9. Back up and restore
  10. Update Mattermost
  11. Troubleshooting
  12. The service stops right after you edit config.json
  13. pq: password authentication failed for user "mmuser"
  14. permission denied for schema public
  15. The page loads but messages only appear after a refresh
  16. Calls connect but nobody can hear each other
  17. Next steps

Mattermost is a self-hosted team messaging platform with channels, threads, direct messages, file sharing and built-in voice calls. Running it on your own server keeps conversations and files on infrastructure you control. This guide installs Mattermost from Mattermost's signed apt repository on Ubuntu 24.04 LTS, connects it to a local PostgreSQL database, publishes it over HTTPS through Caddy, closes every port except SSH and web traffic, and shows how to create the first administrator, back up, restore and upgrade the server.

Prerequisites

  • A server running Ubuntu 24.04 LTS on x86_64 (amd64). Mattermost's install guide lists Ubuntu 20.04, 22.04 and 24.04 LTS. Its repository already publishes packages for Ubuntu 26.04, but the guide does not list that release yet, and the repository setup script accepts Ubuntu releases only.
  • A non-root user with sudo rights and SSH key login: see Secure a new Linux server and Set up SSH keys.
  • A domain name such as chat.example.com with an A record (and AAAA record if you use IPv6) pointing to the server.
  • Caddy installed on the server as described in Caddy reverse proxy.
  • An SMTP account for email notifications and invitations. Mattermost runs without it, but users then get no email.

Sizing from Mattermost's requirements page:

ResourceMinimum (official)Suggested starting point
CPU1 vCPU for up to about 1,000 users2 vCPU, so PostgreSQL and Mattermost do not compete
RAM2 GB for up to about 1,000 users4 GB with PostgreSQL on the same server
DiskNot published for small deployments20 GB plus the file uploads you expect
DatabasePostgreSQL 14 or later (15 or later from Mattermost v12.0)Ubuntu's own PostgreSQL package

Step 1 — Install PostgreSQL and create the database

Install PostgreSQL from Ubuntu's archive. Ubuntu 24.04 ships PostgreSQL 16, which meets Mattermost's requirement, and the server only listens on localhost by default:

Bash
sudo apt update
sudo apt install postgresql
openssl rand -hex 24

The last command prints a random password for the database user; copy it. Then open the PostgreSQL shell:

Bash
sudo -u postgres psql

Run these statements from Mattermost's database guide, replacing change-me with the password you generated. The last three lines are required on PostgreSQL 15 and later, where ordinary users can no longer create tables in the public schema:

SQL
CREATE DATABASE mattermost WITH ENCODING 'UTF8' LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' TEMPLATE=template0;
CREATE USER mmuser WITH PASSWORD 'change-me';
GRANT ALL PRIVILEGES ON DATABASE mattermost TO mmuser;
ALTER DATABASE mattermost OWNER TO mmuser;
\c mattermost
ALTER SCHEMA public OWNER TO mmuser;
GRANT USAGE, CREATE ON SCHEMA public TO mmuser;
\q

Check that the new user can log in over TCP; psql asks for the password and then prints the connection details:

Bash
psql -h localhost -U mmuser -d mattermost -c '\conninfo'

Step 2 — Add Mattermost's apt repository and install the package

Mattermost provides a repository setup script. It checks that you run a supported Ubuntu release, downloads Mattermost's signing key, verifies its fingerprint, writes /etc/apt/sources.list.d/mattermost.list and runs apt update. Download it and read it before you run it:

Bash
curl -fsSL https://deb.packages.mattermost.com/repo-setup.sh -o mattermost-repo-setup.sh
less mattermost-repo-setup.sh
sudo bash mattermost-repo-setup.sh mattermost
sudo apt install mattermost

The mattermost argument adds only the Mattermost repository. Without it, the script also adds the Nginx, PostgreSQL and Certbot repositories, which this guide does not need. The official one-line equivalent is curl -o- https://deb.packages.mattermost.com/repo-setup.sh | sudo bash -s mattermost.

The package installs into /opt/mattermost and creates a mattermost system user. The service is not enabled or started yet. Check the installed version:

Bash
apt-cache policy mattermost

Step 3 — Configure the database connection and Site URL

Create the configuration file from the shipped defaults, readable only by the mattermost user, and open it in an editor:

Bash
sudo install -C -m 600 -o mattermost -g mattermost /opt/mattermost/config/config.defaults.json /opt/mattermost/config/config.json
sudo nano /opt/mattermost/config/config.json

Find the following keys inside their existing sections and change only their values. The snippet shows the keys, not the whole file:

JSON
{
  "ServiceSettings": {
    "SiteURL": "https://chat.example.com"
  },
  "SqlSettings": {
    "DriverName": "postgres",
    "DataSource": "postgres://mmuser:change-me@localhost:5432/mattermost?sslmode=disable&connect_timeout=10"
  },
  "SupportSettings": {
    "SupportEmail": "[email protected]"
  }
}
  • SiteURL must be the exact public address users open, including https://. Links in emails, notifications and the WebSocket connection depend on it.
  • DataSource contains the database password from Step 1. A hex password needs no URL encoding.
  • sslmode=disable is fine because PostgreSQL runs on the same server and the connection never leaves localhost.

Mattermost's guide recommends tying the service to PostgreSQL when both run on the same host. Add this through a systemd drop-in, which survives package upgrades, instead of editing the packaged unit file:

Bash
sudo systemctl edit mattermost

Paste these lines into the editor between the comment markers, then save:

INI
[Unit]
After=postgresql.service
BindsTo=postgresql.service

Step 4 — Start Mattermost

Bash
sudo systemctl start mattermost
sudo systemctl status mattermost --no-pager
curl -s http://localhost:8065 | head -n 5
sudo systemctl enable mattermost.service

The first start creates the database schema and can take a minute. The curl command should print the beginning of the Mattermost HTML page. If the service stops instead, read the log with sudo journalctl -u mattermost -n 50 --no-pager; see Troubleshooting below.

Step 5 — Publish Mattermost over HTTPS with Caddy

Add a site block for your domain to /etc/caddy/Caddyfile:

Caddyfile
chat.example.com {
    reverse_proxy 127.0.0.1:8065
}

Reload Caddy and check the response:

Bash
sudo systemctl reload caddy
curl -I https://chat.example.com

You should see HTTP/2 200 and a valid certificate. Caddy obtains the certificate from Let's Encrypt, proxies WebSocket upgrades automatically and sets the X-Forwarded-For and X-Forwarded-Proto headers, so no extra options are needed.

If you prefer Nginx, follow Nginx with Certbot and use the server block from Mattermost's NGINX proxy documentation. It has a separate location for the WebSocket path with the Upgrade and Connection headers, a client_max_body_size for uploads and longer proxy timeouts; without those parts, Mattermost connects but stops updating in real time.

Step 6 — Close every port except SSH and the web

Mattermost runs as a normal system service, not in Docker, so ufw does protect port 8065:

Bash
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

From another machine, nc -vz your-server-ip 8065 should now be refused or time out, while https://chat.example.com keeps working.

The Calls plugin (voice calls and screen sharing) is enabled by default. Its media server listens on port 8443 over UDP, with TCP 8443 as a fallback for clients that cannot use UDP. If you plan to use Calls, open both:

Bash
sudo ufw allow 8443/udp
sudo ufw allow 8443/tcp

Step 7 — Create the first administrator and lock down sign-up

Open https://chat.example.com in a browser and create an account. On a new server the first account becomes the system administrator. Mattermost then asks you to create your first team.

Before you invite anyone, open System Console from the product menu and check these settings:

  • Authentication > Signup: keep Enable Open Server set to false, which is the default. Users then need an invitation link to create an account.
  • Authentication > MFA: allow multi-factor authentication and turn it on for every administrator account.

Then open Environment > SMTP. Invitations, password resets and email notifications depend on it. Enter your relay's server (for example smtp.example.com), port 587, STARTTLS as the connection security, and the SMTP user and password, then click Test Connection.

Back up and restore

Mattermost's state lives in three places: the PostgreSQL database, the configuration in /opt/mattermost/config, and uploaded files in /opt/mattermost/data (when you use local storage, the default). Mattermost's backup guide says to stop the server for the duration of a backup so that the database and the files match.

Bash
sudo mkdir -p /opt/backups
sudo chown $USER:$USER /opt/backups
chmod 700 /opt/backups
sudo systemctl stop mattermost
sudo -u postgres pg_dump -Fc mattermost > /opt/backups/mattermost-db-$(date +%F).dump
sudo tar czf /opt/backups/mattermost-files-$(date +%F).tar.gz -C /opt/mattermost config data
sudo systemctl start mattermost
ls -lh /opt/backups

To restore on a new server, complete Steps 1 to 3 with the same Mattermost version (sudo apt install mattermost=VERSION, where apt-cache madison mattermost lists the versions) and the same database password, but do not start the service. Then load the dump into the empty database and put the files back:

Bash
sudo systemctl stop mattermost
sudo -u postgres pg_restore -d mattermost < /opt/backups/mattermost-db-2026-10-09.dump
sudo tar xzf /opt/backups/mattermost-files-2026-10-09.tar.gz -C /opt/mattermost
sudo chown -R mattermost:mattermost /opt/mattermost/config /opt/mattermost/data
sudo systemctl start mattermost

Replace the dates with those of your backup files. Copy backups off the server as well, for example with rsync to another machine or to object storage.

Update Mattermost

Read Mattermost's important upgrade notes for every version between yours and the target, and take a backup first. Mattermost's documentation warns that apt upgrade replaces the binary while it is running, so stop the service before you upgrade:

Bash
sudo systemctl stop mattermost
sudo apt update && sudo apt upgrade
sudo systemctl start mattermost

Two habits make upgrades predictable:

  • Mattermost guarantees backward compatibility only with the last Extended Support Release (ESR). If you have fallen behind, upgrade to the closest ESR first and then to the next one. apt-cache madison mattermost lists the available versions, and sudo apt install mattermost=11.7.12-0 installs a specific one (replace the version with the ESR you need).
  • To stop routine apt upgrade runs from upgrading Mattermost unplanned, hold the package with sudo apt-mark hold mattermost and release it with sudo apt-mark unhold mattermost when you are ready.

Troubleshooting

The service stops right after you edit config.json

A missing comma or quote makes the file invalid JSON. Check it with sudo python3 -m json.tool /opt/mattermost/config/config.json > /dev/null; the command prints the line of the first error. Also read sudo journalctl -u mattermost -n 50 --no-pager and /opt/mattermost/logs/mattermost.log.

pq: password authentication failed for user "mmuser"

The password in DataSource does not match the database user. Set a new one with sudo -u postgres psql -c "ALTER USER mmuser WITH PASSWORD 'new-hex-password';", update DataSource and restart the service.

permission denied for schema public

On PostgreSQL 15 and later the database owner and schema grants from Step 1 are required. Run the ALTER DATABASE, ALTER SCHEMA and GRANT USAGE, CREATE statements again as the postgres user and restart Mattermost.

The page loads but messages only appear after a refresh

The WebSocket connection fails. Make sure SiteURL matches the address in the browser exactly, including https://. A 403 response on the WebSocket URL in the browser's developer tools usually means a SiteURL mismatch. With Nginx, check that the WebSocket location block from Mattermost's configuration is present.

Calls connect but nobody can hear each other

The call signalling works over HTTPS, but media needs port 8443. Open 8443/udp (and 8443/tcp) in ufw and in any provider or network firewall in front of the server.

Next steps

Frequently asked questions

Where does Mattermost write its logs?

The service writes to the systemd journal, which you read with sudo journalctl -u mattermost -n 50 --no-pager, and Mattermost keeps its own log file at /opt/mattermost/logs/mattermost.log. Check both first when the service stops or a setting does not take effect.

Why not use Mattermost's Docker setup?

Mattermost's container guide says its Docker deployment should not be used in production because it does not support clustering or high availability out of the box, and presents it for testing and development. For Ubuntu servers the documentation recommends the signed apt repository, which also delivers security updates through apt.

Does the reverse proxy need WebSocket support?

Yes. New messages, typing indicators and presence updates arrive over a WebSocket on the api/v4/websocket path. Caddy proxies WebSocket upgrades without extra settings; with Nginx, use Mattermost's official configuration, which sets the Upgrade and Connection headers.

Which ports must be open to the internet?

SSH, 80 and 443. Mattermost itself listens on port 8065, which stays closed and is reached only through the reverse proxy. If you use the built-in Calls feature, also open 8443/udp and 8443/tcp for call media.

Which HyperDC servers can run Mattermost?

Any HyperDC Linux VPS, VDS or dedicated server with root access and Ubuntu 24.04 LTS. Mattermost publishes 1 vCPU and 2 GB RAM for up to about 1,000 users; give PostgreSQL and file uploads some headroom on top of that.

Gerar senha

Please confirm