{"id":142859,"date":"2026-03-26T16:15:50","date_gmt":"2026-03-26T13:15:50","guid":{"rendered":"https:\/\/computingforgeeks.com\/?p=142859"},"modified":"2026-03-26T16:15:51","modified_gmt":"2026-03-26T13:15:51","slug":"deploying-mattermost-server-on-debian","status":"publish","type":"post","link":"https:\/\/computingforgeeks.com\/deploying-mattermost-server-on-debian\/","title":{"rendered":"Deploy Mattermost Server on Debian 13 \/ 12 with SSL"},"content":{"rendered":"\n<p>Mattermost gives you a self-hosted Slack alternative with full control over your data, integrations, and compliance. If your team needs real-time messaging without handing everything to a third-party SaaS provider, this is the platform to deploy. It runs on PostgreSQL, supports webhooks and bot integrations, and the open-source edition covers what most teams actually need.<\/p>\n\n\n\n<p>This guide walks through a complete Mattermost deployment on <strong>Debian 13 (Trixie)<\/strong> and <strong>Debian 12 (Bookworm)<\/strong> with PostgreSQL as the database backend, Nginx as a reverse proxy, and Let&#8217;s Encrypt for SSL. The setup is nearly identical on both releases, with one minor Nginx syntax difference noted below. If you&#8217;re running Ubuntu instead, see our <a href=\"https:\/\/computingforgeeks.com\/how-to-deploy-mattermost-with-postgresql-on-ubuntu\/\">Mattermost deployment guide for Ubuntu<\/a>.<\/p>\n\n\n\n<p><em>Tested <strong>March 2026<\/strong> | Debian 13.4 \/ 12.5, Mattermost 11.5.1, PostgreSQL 17.9 \/ 15.16, Nginx 1.26 \/ 1.22<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Debian 13 or Debian 12 server with at least <strong>2 GB RAM<\/strong>, <strong>2 CPU cores<\/strong>, and <strong>10 GB disk<\/strong><\/li>\n\n\n\n<li>Root or sudo access<\/li>\n\n\n\n<li>A domain name (or subdomain) with a DNS A record pointing to your server&#8217;s public IP<\/li>\n\n\n\n<li>Ports <strong>80<\/strong> and <strong>443<\/strong> open on your firewall<\/li>\n\n\n\n<li>Tested on: Mattermost 11.5.1, PostgreSQL 17.9 (Debian 13) \/ 15.16 (Debian 12), Nginx 1.26 \/ 1.22<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Install PostgreSQL<\/h2>\n\n\n\n<p>Debian 13 ships PostgreSQL 17 from its default repositories, while Debian 12 ships PostgreSQL 15. The install command is the same on both releases:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update\nsudo apt install -y postgresql postgresql-contrib<\/code><\/pre>\n\n\n\n<p>Confirm the installed version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>psql --version<\/code><\/pre>\n\n\n\n<p>On Debian 13, this returns:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>psql (PostgreSQL) 17.9<\/code><\/pre>\n\n\n\n<p>On Debian 12:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>psql (PostgreSQL) 15.16<\/code><\/pre>\n\n\n\n<p>Check that the service is running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl status postgresql<\/code><\/pre>\n\n\n\n<p>The status shows <code>active (exited)<\/code> because PostgreSQL runs through <code>pg_ctlcluster<\/code> rather than as a direct systemd process. This is normal on Debian. For a deeper look at PostgreSQL on Debian, see our <a href=\"https:\/\/computingforgeeks.com\/install-postgresql-debian\/\">PostgreSQL 17 installation guide for Debian<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create the Mattermost Database<\/h2>\n\n\n\n<p>Mattermost needs a dedicated PostgreSQL database and user. Run these commands to create both and grant the required permissions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -u postgres psql -c \"CREATE DATABASE mattermost;\"\nsudo -u postgres psql -c \"CREATE USER mmuser WITH PASSWORD 'YourStrongPassword';\"\nsudo -u postgres psql -c \"GRANT ALL PRIVILEGES ON DATABASE mattermost TO mmuser;\"\nsudo -u postgres psql -c \"ALTER DATABASE mattermost OWNER TO mmuser;\"\nsudo -u postgres psql -d mattermost -c \"GRANT ALL ON SCHEMA public TO mmuser;\"<\/code><\/pre>\n\n\n\n<p>The last two commands are essential on PostgreSQL 15+ because the default privileges on the <code>public<\/code> schema changed in that version. Without them, Mattermost cannot create tables.<\/p>\n\n\n\n<p>Verify the database exists and is owned by <code>mmuser<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -u postgres psql -c \"\\l\" | grep mattermost<\/code><\/pre>\n\n\n\n<p>You should see the database listed with the correct owner:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code> mattermost | mmuser   | UTF8     | C.UTF-8 | C.UTF-8 |<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Download and Install Mattermost<\/h2>\n\n\n\n<p>Fetch the latest stable version number from the <a href=\"https:\/\/mattermost.com\/download\/\" target=\"_blank\" rel=\"noreferrer noopener\">Mattermost download page<\/a> using the GitHub API:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>VER=$(curl -sL https:\/\/api.github.com\/repos\/mattermost\/mattermost\/releases\/latest | grep tag_name | head -1 | sed 's\/.*\"v\\([^\"]*\\)\".*\/\\1\/')\necho $VER<\/code><\/pre>\n\n\n\n<p>At the time of writing, this outputs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>11.5.1<\/code><\/pre>\n\n\n\n<p>Download and extract the archive to <code>\/opt<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>wget https:\/\/releases.mattermost.com\/$VER\/mattermost-$VER-linux-amd64.tar.gz -O \/tmp\/mattermost.tar.gz\nsudo tar -xzf \/tmp\/mattermost.tar.gz -C \/opt\/\nsudo mkdir -p \/opt\/mattermost\/data<\/code><\/pre>\n\n\n\n<p>Create a dedicated system user and set directory ownership:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo useradd --system --user-group mattermost\nsudo chown -R mattermost:mattermost \/opt\/mattermost\nsudo chmod -R g+w \/opt\/mattermost<\/code><\/pre>\n\n\n\n<p>The <code>\/opt\/mattermost\/data<\/code> directory stores uploaded files, plugins, and other user data. Back this up regularly in production.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Configure Mattermost<\/h2>\n\n\n\n<p>Open the main configuration file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/opt\/mattermost\/config\/config.json<\/code><\/pre>\n\n\n\n<p>Find and update these two settings. Set <code>SiteURL<\/code> to your domain and <code>DataSource<\/code> to the PostgreSQL connection string with the password you created earlier:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"SiteURL\": \"https:\/\/mattermost.example.com\",<\/code><\/pre>\n\n\n\n<p>Under <code>SqlSettings<\/code>, replace the existing <code>DataSource<\/code> value:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"DataSource\": \"postgres:\/\/mmuser:YourStrongPassword@localhost:5432\/mattermost?sslmode=disable&amp;connect_timeout=10\",<\/code><\/pre>\n\n\n\n<p>Replace <code>YourStrongPassword<\/code> with the actual password you set in the database step, and <code>mattermost.example.com<\/code> with your real domain. The <code>sslmode=disable<\/code> is fine here because PostgreSQL and Mattermost are on the same host, so the connection never leaves localhost.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create the Systemd Service<\/h2>\n\n\n\n<p>Create a unit file so Mattermost starts automatically on boot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/etc\/systemd\/system\/mattermost.service<\/code><\/pre>\n\n\n\n<p>Add the following content:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[Unit]\nDescription=Mattermost\nAfter=syslog.target network.target postgresql.service\n\n[Service]\nType=notify\nWorkingDirectory=\/opt\/mattermost\nUser=mattermost\nExecStart=\/opt\/mattermost\/bin\/mattermost\nTimeoutStartSec=3600\nKillMode=mixed\nRestart=always\nRestartSec=10\nLimitNOFILE=49152\n\n[Install]\nWantedBy=multi-user.target<\/code><\/pre>\n\n\n\n<p>The <code>LimitNOFILE=49152<\/code> raises the open file descriptor limit, which Mattermost needs when handling many concurrent WebSocket connections. The <code>After=postgresql.service<\/code> ensures the database is available before Mattermost starts.<\/p>\n\n\n\n<p>Reload systemd and start the service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl daemon-reload\nsudo systemctl enable --now mattermost<\/code><\/pre>\n\n\n\n<p>Verify it&#8217;s running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl status mattermost<\/code><\/pre>\n\n\n\n<p>The output should confirm an active state:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\u25cf mattermost.service - Mattermost\n     Loaded: loaded (\/etc\/systemd\/system\/mattermost.service; enabled; preset: enabled)\n     Active: active (running)\n   Main PID: 3859 (mattermost)\n     Memory: 371.2M<\/code><\/pre>\n\n\n\n<p>Mattermost listens on port 8065 by default. Confirm with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ss -tlnp | grep 8065<\/code><\/pre>\n\n\n\n<p>Expected output:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>LISTEN 0      4096               *:8065             *:*    users:((\"mattermost\",pid=3859,fd=19))<\/code><\/pre>\n\n\n\n<p>If the service fails to start, check the logs with <code>sudo journalctl -u mattermost -n 50<\/code>. The most common issue is a wrong database password in <code>config.json<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Set Up Nginx Reverse Proxy with SSL<\/h2>\n\n\n\n<p>Mattermost listens on HTTP port 8065, which is not suitable for production. Nginx handles SSL termination and proxies requests to the Mattermost backend. For more on Nginx configuration, see our <a href=\"https:\/\/computingforgeeks.com\/install-configure-nginx-ubuntu-debian\/\">Nginx installation guide for Debian and Ubuntu<\/a>.<\/p>\n\n\n\n<p>Install Nginx and certbot:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y nginx certbot python3-certbot-nginx<\/code><\/pre>\n\n\n\n<p>Obtain an SSL certificate from Let&#8217;s Encrypt. The <code>--standalone<\/code> method temporarily binds to port 80, so the pre\/post hooks stop and start Nginx around the challenge:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo certbot certonly --standalone --pre-hook 'systemctl stop nginx' --post-hook 'systemctl start nginx' -d mattermost.example.com --non-interactive --agree-tos -m admin@example.com<\/code><\/pre>\n\n\n\n<p>Certbot confirms with <code>Successfully received certificate.<\/code> and stores the files under <code>\/etc\/letsencrypt\/live\/mattermost.example.com\/<\/code>.<\/p>\n\n\n\n<p>Create the Nginx virtual host:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo vi \/etc\/nginx\/sites-available\/mattermost<\/code><\/pre>\n\n\n\n<p>Paste the following configuration. This handles both regular HTTP requests and WebSocket connections, which Mattermost uses for real-time messaging:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>upstream mattermost_backend {\n    server 127.0.0.1:8065;\n    keepalive 32;\n}\n\nserver {\n    listen 80;\n    server_name mattermost.example.com;\n    return 301 https:\/\/$host$request_uri;\n}\n\nserver {\n    listen 443 ssl;\n    http2 on;\n    server_name mattermost.example.com;\n\n    ssl_certificate \/etc\/letsencrypt\/live\/mattermost.example.com\/fullchain.pem;\n    ssl_certificate_key \/etc\/letsencrypt\/live\/mattermost.example.com\/privkey.pem;\n    ssl_protocols TLSv1.2 TLSv1.3;\n    ssl_prefer_server_ciphers on;\n\n    location ~ \/api\/v[0-9]+\/(users\/)?websocket$ {\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header X-Frame-Options SAMEORIGIN;\n        proxy_buffers 256 16k;\n        proxy_buffer_size 16k;\n        client_max_body_size 50M;\n        proxy_read_timeout 600s;\n        proxy_pass http:\/\/mattermost_backend;\n    }\n\n    location \/ {\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        proxy_set_header X-Frame-Options SAMEORIGIN;\n        client_max_body_size 50M;\n        proxy_read_timeout 600s;\n        proxy_pass http:\/\/mattermost_backend;\n    }\n}<\/code><\/pre>\n\n\n\n<p><strong>Debian 12 note:<\/strong> If you&#8217;re running Debian 12 with Nginx 1.22, replace <code>http2 on;<\/code> with the older syntax: <code>listen 443 ssl http2;<\/code> on the listen line. Nginx 1.26 in Debian 13 deprecated the combined directive.<\/p>\n\n\n\n<p>Enable the site, remove the default virtual host, test the configuration, and restart Nginx:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ln -sf \/etc\/nginx\/sites-available\/mattermost \/etc\/nginx\/sites-enabled\/\nsudo rm -f \/etc\/nginx\/sites-enabled\/default\nsudo nginx -t\nsudo systemctl restart nginx<\/code><\/pre>\n\n\n\n<p>The <code>nginx -t<\/code> output should show <code>syntax is ok<\/code> and <code>test is successful<\/code>. If it reports errors, double-check the certificate paths and server_name value.<\/p>\n\n\n\n<p>Verify the SSL certificate is serving correctly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo | openssl s_client -connect mattermost.example.com:443 -servername mattermost.example.com 2>\/dev\/null | openssl x509 -noout -dates -subject<\/code><\/pre>\n\n\n\n<p>The output confirms the certificate details:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>notBefore=Mar 26 11:52:23 2026 GMT\nnotAfter=Jun 24 11:52:22 2026 GMT\nsubject=CN=mattermost.computingforgeeks.com<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Configure the Firewall<\/h2>\n\n\n\n<p>Debian does not enable a firewall by default. Install <code>ufw<\/code> and allow the necessary ports:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y ufw\nsudo ufw allow ssh\nsudo ufw allow 80\/tcp\nsudo ufw allow 443\/tcp\nsudo ufw enable<\/code><\/pre>\n\n\n\n<p>Confirm the rules are active:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw status<\/code><\/pre>\n\n\n\n<p>Port 8065 is intentionally not opened to the public. All external traffic goes through Nginx on 443, and Nginx proxies to Mattermost on localhost:8065.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Access the Web Interface<\/h2>\n\n\n\n<p>Open <code>https:\/\/mattermost.example.com<\/code> in your browser. The first user to register becomes the system administrator, so do this immediately after deployment.<\/p>\n\n\n\n<p>The login page appears with options to create an account or sign in:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"941\" src=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/02-mattermost-login.png\" alt=\"Mattermost login page with email and password fields\" class=\"wp-image-164703\" title=\"\" srcset=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/02-mattermost-login.png 1920w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/02-mattermost-login-300x147.png 300w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/02-mattermost-login-1024x502.png 1024w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/02-mattermost-login-768x376.png 768w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/02-mattermost-login-1536x753.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Click <strong>Don&#8217;t have an account?<\/strong> to create the admin user. Fill in your email, username, and a strong password:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"941\" src=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-signup-filled.png\" alt=\"Mattermost signup form with email username and password filled in\" class=\"wp-image-164704\" title=\"\" srcset=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-signup-filled.png 1920w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-signup-filled-300x147.png 300w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-signup-filled-1024x502.png 1024w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-signup-filled-768x376.png 768w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-signup-filled-1536x753.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>After signing up, you land in the <strong>Town Square<\/strong> channel, which is the default public channel:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"941\" src=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-channels.png\" alt=\"Mattermost Town Square channel view after first login\" class=\"wp-image-164705\" title=\"\" srcset=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-channels.png 1920w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-channels-300x147.png 300w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-channels-1024x502.png 1024w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-channels-768x376.png 768w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/03-mattermost-channels-1536x753.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Send a test message to confirm everything works end to end, from the browser through Nginx to Mattermost to PostgreSQL and back:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"941\" src=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/04-mattermost-message.png\" alt=\"Test message sent in Mattermost Town Square channel\" class=\"wp-image-164706\" title=\"\" srcset=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/04-mattermost-message.png 1920w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/04-mattermost-message-300x147.png 300w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/04-mattermost-message-1024x502.png 1024w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/04-mattermost-message-768x376.png 768w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/04-mattermost-message-1536x753.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>The System Console is where you manage server settings, users, and integrations. Access it from the menu in the top-left corner:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"941\" src=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/05-mattermost-admin.png\" alt=\"Mattermost System Console admin dashboard\" class=\"wp-image-164707\" title=\"\" srcset=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/05-mattermost-admin.png 1920w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/05-mattermost-admin-300x147.png 300w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/05-mattermost-admin-1024x502.png 1024w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/05-mattermost-admin-768x376.png 768w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/05-mattermost-admin-1536x753.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>Under <strong>Environment > Web Server<\/strong>, verify that the Site URL matches your domain and that the connection security shows TLS:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"941\" src=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/06-mattermost-web-config.png\" alt=\"Mattermost System Console web server configuration showing site URL\" class=\"wp-image-164708\" title=\"\" srcset=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/06-mattermost-web-config.png 1920w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/06-mattermost-web-config-300x147.png 300w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/06-mattermost-web-config-1024x502.png 1024w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/06-mattermost-web-config-768x376.png 768w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/06-mattermost-web-config-1536x753.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>The database configuration page under <strong>Environment > Database<\/strong> shows the active PostgreSQL connection:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"941\" src=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/07-mattermost-database.png\" alt=\"Mattermost System Console database configuration with PostgreSQL\" class=\"wp-image-164709\" title=\"\" srcset=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/07-mattermost-database.png 1920w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/07-mattermost-database-300x147.png 300w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/07-mattermost-database-1024x502.png 1024w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/07-mattermost-database-768x376.png 768w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/07-mattermost-database-1536x753.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p>The user management section lists all registered users and their roles. The first user shows the System Admin badge:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"941\" src=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/08-mattermost-users.png\" alt=\"Mattermost user management page showing admin user\" class=\"wp-image-164710\" title=\"\" srcset=\"https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/08-mattermost-users.png 1920w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/08-mattermost-users-300x147.png 300w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/08-mattermost-users-1024x502.png 1024w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/08-mattermost-users-768x376.png 768w, https:\/\/computingforgeeks.com\/wp-content\/uploads\/2026\/03\/08-mattermost-users-1536x753.png 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Create Admin User via CLI (Optional)<\/h2>\n\n\n\n<p>For automated or headless deployments, you can create the first admin user from the command line instead of the web UI. This requires <code>EnableLocalMode: true<\/code> in <code>config.json<\/code> under <code>ServiceSettings<\/code>.<\/p>\n\n\n\n<p>Create the admin user:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo \/opt\/mattermost\/bin\/mmctl user create --email admin@example.com --username admin --password 'YourPassword' --system-admin --local<\/code><\/pre>\n\n\n\n<p>Then create a team for users to join:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo \/opt\/mattermost\/bin\/mmctl team create --name myteam --display-name \"My Team\" --email admin@example.com --local<\/code><\/pre>\n\n\n\n<p>The <code>--local<\/code> flag connects to the Mattermost socket directly, bypassing authentication. This only works from the server itself.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Debian 13 vs Debian 12 Differences<\/h2>\n\n\n\n<p>The installation steps are identical on both releases. The table below summarizes the version differences you&#8217;ll encounter:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Component<\/th><th>Debian 13 (Trixie)<\/th><th>Debian 12 (Bookworm)<\/th><\/tr><\/thead><tbody><tr><td>PostgreSQL<\/td><td>17.9<\/td><td>15.16<\/td><\/tr><tr><td>Python<\/td><td>3.13.5<\/td><td>3.11.2<\/td><\/tr><tr><td>OpenSSL<\/td><td>3.5.5<\/td><td>3.0.11<\/td><\/tr><tr><td>Kernel<\/td><td>6.12<\/td><td>6.1<\/td><\/tr><tr><td>Nginx<\/td><td>1.26 (use <code>http2 on;<\/code>)<\/td><td>1.22 (use <code>listen 443 ssl http2<\/code>)<\/td><\/tr><tr><td>Mattermost<\/td><td>11.5.1<\/td><td>11.5.1<\/td><\/tr><tr><td>Certbot<\/td><td>Same<\/td><td>Same<\/td><\/tr><tr><td>Install steps<\/td><td>Identical<\/td><td>Identical<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>The only difference that affects the setup is the Nginx HTTP\/2 directive. On Debian 13 with Nginx 1.26+, use the separate <code>http2 on;<\/code> directive. On Debian 12 with Nginx 1.22, use the older combined syntax <code>listen 443 ssl http2;<\/code> on the listen line. Everything else, from package names to file paths to systemd commands, is the same.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Production Hardening<\/h2>\n\n\n\n<p>Before handing this deployment off to your team, take care of these items:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Automatic SSL renewal<\/strong> &#8211; Verify certbot&#8217;s timer works by running <code>sudo certbot renew --dry-run<\/code>. Let&#8217;s Encrypt certificates expire every 90 days, and certbot handles renewal automatically if the timer is active<\/li>\n\n\n\n<li><strong>Email notifications<\/strong> &#8211; Configure SMTP in System Console > Environment > SMTP so Mattermost can send email notifications, password resets, and invitations. Without this, users have no way to recover their accounts<\/li>\n\n\n\n<li><strong>Automated backups<\/strong> &#8211; Back up <code>\/opt\/mattermost\/data<\/code> (uploaded files and plugins) and the PostgreSQL database regularly. For PostgreSQL, use <code>pg_dump mattermost<\/code> in a cron job. Losing either one without a backup means losing all team conversations<\/li>\n\n\n\n<li><strong>Performance monitoring<\/strong> &#8211; Enable the built-in metrics endpoint under System Console > Environment > Performance Monitoring. This exposes Prometheus-compatible metrics on port 8067 for tracking response times, active connections, and database query performance<\/li>\n\n\n\n<li><strong>Rate limiting<\/strong> &#8211; Mattermost enables rate limiting by default. Review the settings under System Console > Environment > Rate Limiting and adjust the per-second limits if your team is large<\/li>\n<\/ul>\n\n\n\n<p>The <a href=\"https:\/\/docs.mattermost.com\/install\/install-debian.html\" target=\"_blank\" rel=\"noreferrer noopener\">official Mattermost documentation for Debian<\/a> covers additional configuration options including LDAP authentication, high availability clustering, and plugin management.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mattermost gives you a self-hosted Slack alternative with full control over your data, integrations, and compliance. If your team needs real-time messaging without handing everything to a third-party SaaS provider, this is the platform to deploy. It runs on PostgreSQL, supports webhooks and bot integrations, and the open-source edition covers what most teams actually need. &#8230; <a title=\"Deploy Mattermost Server on Debian 13 \/ 12 with SSL\" class=\"read-more\" href=\"https:\/\/computingforgeeks.com\/deploying-mattermost-server-on-debian\/\" aria-label=\"Read more about Deploy Mattermost Server on Debian 13 \/ 12 with SSL\">Read more<\/a><\/p>\n","protected":false},"author":21,"featured_media":142894,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,299,50],"tags":[11647,12442],"class_list":["post-142859","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-debian","category-how-to","category-linux-tutorials","tag-collaboration","tag-mattermost"],"_links":{"self":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/142859","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/comments?post=142859"}],"version-history":[{"count":2,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/142859\/revisions"}],"predecessor-version":[{"id":164711,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/posts\/142859\/revisions\/164711"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/media\/142894"}],"wp:attachment":[{"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/media?parent=142859"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/categories?post=142859"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/computingforgeeks.com\/wp-json\/wp\/v2\/tags?post=142859"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}