Deploying Mattermost on Azure with Private MySQL Backend

Table of contents

β¨ Objective :
Deploy a secure, self-hosted team communication platform (Mattermost) using Microsoft Azure services. This includes:
Creating a custom virtual network with public/private subnets
Deploying VMs in each subnet
Hosting MySQL in the private subnet
Hosting Mattermost in the public subnet
ποΈ Architecture Overview
Key Components:
Virtual Network (VNet): Logical network to isolate resources
Subnets:
Public Subnet: Hosts Mattermost (internet-facing)
Private Subnet: Hosts MySQL (no internet exposure)
NSGs (Security Groups):
Public subnet can access internet
Private subnet only accessible from public subnet
π Implementation Steps
Step 1: Set Up Azure Environment
1. . Create Resource Group
Go to the Azure Portal
Search for Resource Groups in the top bar and click + Create
Choose a subscription and enter a unique Resource Group name (e.g.,
rg-mattermost
)Select a region (e.g.,
East US
) and click Review + Create > Create
2. Create Virtual Network (VNet) with two subnets: public-subnet
, private-subnet
In the Azure Portal, search for Virtual Networks and click + Create
Select the previously created Resource Group and give the VNet a name (e.g.,
vnet-mattermost
)Set the region to match your resource group (e.g.,
East US
)Under IP Addresses, define an address space (e.g.,
10.0.0.0/16
)Click + Add subnet:
Subnet name:
public-subnet
Subnet address range:
10.0.1.0/24
Click + Add subnet again:
Subnet name:
private-subnet
Subnet address range:
10.0.2.0/24
Click Review + Create > Create
π Configure NSG Rules
πΉ Public VM NSG: Allow inbound ports 22, 80, 443
Go to Azure Portal β Network Security Groups
Click + Create, give it a name like
public-nsg
, assign the same region and resource groupOnce created, open the public-nsg
Go to Inbound security rules β + Add
Name: Allow-SSH
Port: 22
Protocol: TCP
Source: Any
Priority: 100Name: Allow-HTTP
Port: 80
Protocol: TCP
Source: Any
Priority: 101Name: Allow-HTTPS
Port: 443
Protocol: TCP
Source: Any
Priority: 102
Click Save after adding each rule
Go to Networking tab of the public VM β Attach Network Security Group β select
public-nsg
π‘οΈ Private VM Network Configuration
πΉ Ensure No Public IP for Private VM
During VM creation β on the Networking tab:
Under NIC network configuration, select private-subnet
Public IP: Choose None
Complete the VM creation process
πΉ Ensure VM is Attached to Private Subnet Only
Go to the VM β Networking tab
Confirm the NIC is in the
private-subnet
Confirm there is no associated public IP
π Step 2: Provision Virtual Machines
πΉ VM 1: Public VM (Mattermost)
Go to Azure Portal β Virtual Machines β + Create β Azure virtual machine
Basics Tab:
Subscription: Select your active subscription
Resource Group: Use the one created earlier
Virtual Machine Name:
mattermost-vm
Region: Same as your VNet
Image: Ubuntu Server 20.04 LTS
Size: e.g.,
Standard B1s
(adjust as needed)Authentication type: Password or SSH
Username: your choice (e.g.,
azureuser
)Password/SSH Key: enter accordingly
Inbound Ports:
Select Allow selected ports
Check SSH (22), HTTP (80), HTTPS (443)
Networking Tab:
Virtual Network: Select the one you created
Subnet: Select
public-subnet
Public IP: Create new or use auto-assigned
NIC network security group: Attach
public-nsg
Disks, Management, Monitoring: Leave default or customize
Click Review + Create, then Create
πΉ VM 2: Private VM (MySQL)
Go to Azure Portal β Virtual Machines β + Create
Basics Tab:
Name:
mysql-vm
Same configuration as above: Ubuntu 20.04, same region, same resource group
Authentication type: Password or SSH (same user is okay)
Inbound Ports:
- Select: None (We don't want this VM publicly reachable)
Networking Tab:
Virtual Network: Same VNet
Subnet: Select
private-subnet
Public IP: None (this is critical)
NIC network security group: Attach
private-nsg
Disks, Management, Monitoring: Leave default or configure as needed
Click Review + Create, then Create
β Once both VMs are created:
You can SSH into the public VM using its public IP
Youβll access the private VM via private IP from within the public VM (bastion-style)
Step 3: Install and Configure MySQL (Private VM)
sudo apt update
sudo apt install mysql-server
sudo systemctl start mysql.service
Secure MySQL and set root password:
sudo mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpassword';
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'yourpassword';
exit
sudo mysql_secure_installation
Create a database and a user:
sudo mysql -u root -p
CREATE DATABASE mattermost;
CREATE USER 'mmuser'@'%' IDENTIFIED BY 'mmuser-password';
GRANT ALL PRIVILEGES ON mattermost.* TO 'mmuser'@'%';
FLUSH PRIVILEGES;
exit
Step 4: Install Mattermost (Public VM)
wget https://d6opu47qoi4ee.cloudfront.net/install_mattermost_linux.sh
sudo apt install dos2unix -y
sudo dos2unix install_mattermost_linux.sh
chmod 700 install_mattermost_linux.sh
sudo ./install_mattermost_linux.sh <PRIVATE_IP_OF_MYSQL_VM>
Set correct permissions:
sudo chown -R mattermost:mattermost /opt/mattermost
sudo chmod -R g+w /opt/mattermost
cd /opt/mattermost
sudo -u mattermost ./bin/mattermost
π Access Mattermost via the public VMβs external IP in a browser.
π§ Post-Installation Setup & Configuration
Once Mattermost is accessible in the browser via the public VM IP, complete the following steps:
1. Complete the Initial Setup Wizard
Visit
http://<public_vm_ip>:8065
Fill in:
Admin Email
Username & Password
Click Create Account to proceed to the admin dashboard
2. Configure System Console Settings
Go to
System Console β Environment β Database
Confirm the DB string is:
mysql://mmuser:mmuser-password@<private_mysql_ip>:3306/mattermost
Set:
Site URL to your public IP or custom domain
Optional: Email, file storage, and logging settings
3. Configure Reverse Proxy (Optional)
If you want Mattermost to run on ports 80/443 (standard web ports):
Install Nginx:
sudo apt install nginx
Create an Nginx config:
server { listen 80; server_name your_domain_or_public_ip; location / { proxy_pass http://localhost:8065; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; } }
Restart Nginx:
sudo systemctl restart nginx
4. Enable HTTPS (Optional)
Install Certbot:
sudo apt install certbot python3-certbot-nginx
Run setup:
sudo certbot --nginx
5. Run Mattermost as a systemd Service
- Set up: Create a proper service unit file at /lib/systemd/system/mattermost.service or /etc/systemd/system/mattermost.service:
init
Copy
Edit
[Unit]
Description=Mattermost
After=network.target
[Service]
Type=simple
ExecStart=/opt/mattermost/bin/mattermost
WorkingDirectory=/opt/mattermost
User=mattermost
Group=mattermost
Restart=always
LimitNOFILE=49152
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reexec sudo systemctl enable mattermost sudo systemctl start mattermost
Monitor:
sudo journalctl -u mattermost.service
π Lessons & Observations
Lessons Learned
Architecture must be tailored to workload needs
Security is key: subnet isolation, NSGs, strong passwords
Plan for scalability and monitor performance
Azure managed services reduce complexity
Observations
Azure's flexibility is powerful but requires planning
Understanding networking, compute, and identity is critical
Always balance cost vs. performance
Leverage community and documentation for faster troubleshooting
π Summary
This deployment demonstrates a real-world use case of hosting a secure team chat platform using Azure. It reflects core principles of:
Cloud architecture design
Subnet isolation for security
Real-time app + DB connectivity
This guide is reusable for teams looking to build compliant, scalable, self-hosted collaboration tools.
CloudOps Journal: Practical AWS, DevOps & scripting β one hands-on cloud project at a time.
You can connect with me on LinkedIn here ~ Soham Roy
Subscribe to my newsletter
Read articles from Soham Roy directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Soham Roy
Soham Roy
Hi, Iβm Soham Royβa cloud and DevOps practitioner, passionate about making Cloud(AWS/Azure/GCP) infrastructure and automation accessible to everyone. I write detailed, visual guides on setting up cloud environments, automating operations, and building CI/CD pipelines. My goal: help you master cloud technologies, boost efficiency, and avoid common pitfalls!