This guide assumes you have provisioned your server with a LEMP stack (Nginx, MariaDB, PHP 8.3) using cloud-init-lemp.yml
. It covers secure MariaDB setup, Composer installation, Mautic deployment, and HTTPS configuration for mautic.example.com
.
Set your passwords and database info as needed. Replace all placeholders!
# Secure MariaDB (set root password, remove test DB, etc.)
sudo mysql_secure_installation
# Login as root
sudo mysql -u root -p
# In the MariaDB shell, run:
CREATE DATABASE mautic_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mautic_user'@'localhost' IDENTIFIED BY 'REPLACE_WITH_STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON mautic_db.* TO 'mautic_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
sudo apt update
# Install PHP extensions and dependencies
sudo apt install -y curl unzip php-cli php-mbstring php-xml php-curl php-zip php-intl php-gd php-imap php-bcmath php-ldap php-soap php-xmlrpc php-mysql
# Install Node.js 20.x and npm (recommended for Mautic 5.x)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Install Certbot for Let's Encrypt SSL certificates
sudo apt install -y certbot
# (Optional) Check versions
node -v
npm -v
certbot --version
# Install Composer
cd ~
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer --version
Mautic recommends setting memory_limit
to at least 512M for best performance. Edit your PHP configuration:
sudo sed -i 's/^memory_limit = .*/memory_limit = 512M/' /etc/php/8.3/fpm/php.ini
sudo systemctl reload php8.3-fpm
You can verify the new setting with:
php -i | grep memory_limit
Note: The above command updates the memory limit for PHP-FPM (used by Nginx/web). If you check with
php -i
on the command line, it shows the CLI setting, which may differ. To verify the memory limit for web requests, create a file calledphpinfo.php
in your web root (/var/www/mautic/docroot
):<?php phpinfo();Then visit
https://yourdomain/phpinfo.php
in your browser and search formemory_limit
to confirm it is set to512M
.
sudo mkdir -p /var/www/mautic
sudo chown $USER:www-data /var/www/mautic
cd /var/www/mautic
# Download latest Mautic via Composer
composer create-project mautic/recommended-project .
# To install a specific version (e.g., 5.x), use:
# composer create-project mautic/recommended-project:~5.0 .
# Set permissions
sudo chown -R www-data:www-data /var/www/mautic
sudo find /var/www/mautic -type f -exec chmod 644 {} \;
sudo find /var/www/mautic -type d -exec chmod 755 {} \;
Create /etc/nginx/sites-available/mautic.example.com
:
server {
listen 80;
listen [::]:80;
server_name mautic.example.com;
root /var/www/mautic/docroot;
location ^~ /.well-known/acme-challenge/ {
allow all;
default_type "text/plain";
}
}
Enable the site and reload Nginx:
sudo ln -s /etc/nginx/sites-available/mautic.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot certonly --webroot -w /var/www/mautic/docroot -d mautic.example.com
Edit /etc/nginx/sites-available/mautic.example.com
and add:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name mautic.example.com;
root /var/www/mautic/docroot;
ssl_certificate /etc/letsencrypt/live/mautic.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mautic.example.com/privkey.pem;
# TLS hardening
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;
# Security Headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Content-Security-Policy "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:;" always;
index index.php index.html;
client_max_body_size 20M;
location ^~ /.well-known/acme-challenge/ {
allow all;
default_type "text/plain";
}
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~* ^/index.php {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
include snippets/fastcgi-php.conf;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
access_log /var/log/nginx/mautic_access.log;
error_log /var/log/nginx/mautic_error.log;
}
Redirect HTTP to HTTPS:
server {
listen 80;
listen [::]:80;
server_name mautic.example.com;
root /var/www/mautic/docroot;
location ^~ /.well-known/acme-challenge/ {
allow all;
default_type "text/plain";
}
return 301 https://$host$request_uri;
}
Reload Nginx:
sudo nginx -t
sudo systemctl reload nginx
- Visit
https://mautic.example.com
in your browser. - Complete the web installer:
- Database:
- Host:
localhost
- Database:
mautic_db
- User:
mautic_user
- Password: (your password)
- Host:
- Admin user: Set your admin credentials.
- Email settings: Configure as needed.
- Database:
sudo certbot renew --dry-run
There are a number of cron jobs that should run to benefit the system.
Create /etc/cron.d/mautic
# === MAUTIC CRON JOBS ===
# Update segments every 15 minutes
0,15,30,45 * * * * www-data php /var/www/mautic/bin/console mautic:segments:update
# Update campaigns every 15 minutes, staggered
5,20,35,50 * * * * www-data php /var/www/mautic/bin/console mautic:campaigns:update
# Trigger campaign events every 15 minutes, staggered
10,25,40,55 * * * * www-data php /var/www/mautic/bin/console mautic:campaigns:trigger
# Process email queue every 5 minutes
# NOTE: Only when you install the mail queue option on Mautic
#*/5 * * * * www-data php /var/www/mautic/bin/console mautic:emails:send
# Update MaxMind GeoIP database monthly (first Tuesday of the month at 03:00)
# NOTE: Only if you use Maxmind GeoIP lookup
#0 3 * * 2 [ $(date +\%e) -le 7 ] && www-data php /var/www/mautic/bin/console mautic:iplookup:download
# GDPR Cleanup: delete contacts inactive for 3 years, monthly
0 4 1 * * www-data php /var/www/mautic/bin/console mautic:maintenance:cleanup --gdpr
# MaxMind CCPA Do Not Sell list (weekly)
0 4 * * 1 www-data php /var/www/mautic/bin/console mautic:donotsell:download
10 4 * * 1 www-data php /var/www/mautic/bin/console mautic:max-mind:purge
Ensure correct permissions:
sudo chmod 644 /etc/cron.d/mautic
sudo chown root:root /etc/cron.d/mautic
Confirm the cron service picks it up:
sudo systemctl restart cron
Check it is scheduled:
sudo grep mautic /var/log/syslog | tail -n 50
You have to decide for yourself how to do this in a compliant manner. But if you do, this is how you get it to work with Mautic.
Create an account on Maxmind, setup a license key, and download the Geolite2-City file. Then copy this to your instance, e.g.
scp GeoLite2-City_20250704.tar.gz [email protected]:~
Extract and move the file.
tar -xvzf GeoLite2-City_20250704.tar.gz
mkdir -p /var/www/mautic/var/cache/ip_data
mv ~/GeoLite2-City_20250704.tar.gz /var/www/mautic/var/cache/ip_data
chown -R www-data:www-data /var/www/mautic/var/cache/ip_data/GeoLite2-City.mmdb
chmod 644 /var/www/mautic/var/cache/ip_data/GeoLite2-City.mmdb
You may want to restart and clear the cache.
sudo systemctl restart php8.3-fpm
cd /var/www/mautic
sudo -u www-data php bin/console cache:clear
NOTE Don't forget to configure the online service and set the credentials in the format
account:secret
.
To verify you can check a download from the commandline.
cd /var/www/mautic
sudo -u www-data php bin/console mautic:iplookup:download
You should see Success!
, and the timestamp updated.
- Replace all placeholders (passwords, domain names) before use.
- For production, consider further hardening (fail2ban, firewall, etc.).
- For large installations, review Mautic server requirements.
References: