How to Install Mautic On Ubuntu 22.04 LTS

Before installing Mautic, you need to make sure that the PHP version running on your server is compatible with Mautic version. Check the requirements here. The latest release of Mautic until today is 4.4.10 and my server has php8.1 came by default with iRedMail installation. So, we will install php8.0 which is supported by Mautic as php8.1 is unsupported. Follow the below commands:

Add an A Record on the registrar DNS settings for the domain you will use as below:

DNS Record TypeHostContent, Value or the AnswerTTL (Time To Live)
A Recordmautic144.91.72.551 min (or the minimum allowed)

PHP Version

1. Install the Software Properties Common package by running the command:

root@mail:~# apt install software-properties-common

2. Add the APT repository for the PHP. This step will allow the PHP version to be upgraded automatically when you upgrade the packages on your server (when running: apt upgrade). But in our case, we need to remove the APT repository after installing the PHP version that’s compatible with Mautic, because we don’t need any automatic upgrade for the php when running apt-upgrade command. Also, upgrading PHP needs to update the file /etc/php/8.x/fpm/pool.d/www.conf (for the upgraded PHP) for iRedMail as it’s mentioned here to prevent from “502 bad gateway” error when accessing Roundcube.

root@mail:~# add-apt-repository ppa:ondrej/php

3. Install the desired php version by running the command:

root@mail:~# apt install php8.0-fpm

4. Once you finish the installation, remove the repository we added by running the command:

 root@mail:~# add-apt-repository ppa:ondrej/php --remove

Notice that after removing it, when you run apt-upgrade, it will not offer you to upgrade to php8.2 from php8.1 (default one from iRedMail installation).

If you want to check all PHP versions on your server and choose one of them as default, run the below command:

root@mail:~# update-alternatives --config php
root@mail:~# update-alternatives --config php
There are 3 choices for the alternative php (providing /usr/bin/php).

  Selection    Path                  Priority   Status
------------------------------------------------------------
* 0            /usr/bin/php.default   100       auto mode
  1            /usr/bin/php.default   100       manual mode
  2            /usr/bin/php8.0        80        manual mode
  3            /usr/bin/php8.1        81        manual mode

Press <enter> to keep the current choice[*], or type selection number:

You don’t need to change anything, because we can use php8.0 by including it in Nginx virtual host file (sites-available file) for Mautic as you will see in the instructions below.

Mautic Installation

1. Find the latest release by going to this link: https://www.mautic.org/mautic-releases. The latest release until writing this article is: 4.4.10

2. Download it by running the below command:

root@mail:~# wget https://github.com/mautic/mautic/releases/download/4.4.10/4.4.10-update.zip

3. Install the unzip utility and unzip it to /var/www/html/mautic/ directory by running the below commands:

root@mail:~# apt install unzip
root@mail:~# mkdir -p /var/www/html/mautic/
root@mail:~# unzip 4.4.10-update.zip -d /var/www/html/mautic/

4. Then make the web server user (www-data) as the owner of this directory by running the below command:

root@mail:~# chown -R www-data:www-data /var/www/html/mautic/

5. Create a new database for Mautic using the following command.

MariaDB [(none)]> CREATE DATABASE mautic_db DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

6. The following command will create a database user and password, and at the same time grant all permission of the new database to the new user so later on Mautic can write to the database. USE YOUR OWN PASSWORD _ DON’T COPY PASTE.

MariaDB [(none)]> GRANT ALL ON mautic_db.* TO 'mautic_user'@'localhost' IDENTIFIED BY '12345678';

7. Flush privileges table and exit MariaDB console.

MariaDB [(none)]> FLUSH PRIVILEGES;

MariaDB [(none)]> EXIT;

8. (SKIP now) Make sure the below PHP modules exist, but don’t install themnow until we see what Mautic will require after the installation.

php-imagick php8.0-fpm php8.0-mysql php8.0-common php8.0-gd php8.0-imap php8.0-imap php8.0-json php8.0-curl php8.0-zip php8.0-xml php8.0-mbstring php8.0-bz2 php8.0-intl php8.0-gmp

Run the below command to see all the modules installed:

root@mail:~# php -m

You can install them by running the below command:

root@mail:~# apt install php-imagick php8.0-fpm php8.0-mysql php8.0-common php8.0-gd php8.0-imap php8.0-imap php8.0-json php8.0-curl php8.0-zip php8.0-xml php8.0-mbstring php8.0-bz2 php8.0-intl php8.0-gmp

Nginx Virtual Hosts Configuration

9. Run the below command to open a virtual host file for your domain. Note that the file has .conf extension which is used to define the virtual host files. You can check our previous blog post about Nginx Virtual Hosts Configuration for WordPress websites.

root@mail:~# nano /etc/nginx/sites-available/mautic.vpsprof.com.conf

Or you can create Mautic virtual hosts inside sites-enabled directory directly and you won’t need to create a symbolic link by adding the code here:

root@mail:~# nano /etc/nginx/sites-enabled/mautic.conf

10. We need to add the directives inside the file and we have two cases:

A. If iRedMail Exists

Then, add the below if iRedMail exists on the same server (and if you will use the same PHP version that iRedMail uses). Note that fastcgi_pass parameter value should be 127.0.0.1:9999. If you don’t use the value: 127.0.0.1:9999 for the fastcgi_pass parameter, you will get bad gateway 502 error when visiting the website: mautic.vpsprof.com/installer.

server {
   listen 80;
   listen [::]:80;
   server_name mautic.vpsprof.com;

   root /var/www/html/mautic;
   error_log /var/log/nginx/mautic.error;
   access_log /var/log/nginx/mautic.access;
   client_max_body_size 20M;

   index index.php index.html index.htm index.nginx-debian.html;

   location / {
     # try to serve file directly, fallback to app.php
     try_files $uri /index.php$is_args$args;
   }

   location ~ /(mtc.js|1.js|mtracking.gif|.*\.gif|mtc) {
       # default_type "application/javascript";
       try_files $uri /index.php$is_args$args;
   }

   # redirect some entire folders
     rewrite ^/(vendor|translations|build)/.* /index.php break;

   location ~ \.php$ {
     include snippets/fastcgi-php.conf;
     #fastcgi_pass unix:/run/php/php8.0-fpm.sock;
     #Note: If you install Mautic on iRedMail server, you should use the TCP socket instead. 
     fastcgi_pass 127.0.0.1:9999;
   }

   location ~* ^/index.php {
     # try_files $uri =404;
     fastcgi_split_path_info ^(.+\.php)(/.+)$;
     # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
     
     #Note: If you install Mautic on iRedMail server, you should use the TCP socket instead.
     fastcgi_pass 127.0.0.1:9999;
     fastcgi_index index.php;
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
     include fastcgi_params;

     fastcgi_buffer_size 128k;
     fastcgi_buffers 256 16k;
     fastcgi_busy_buffers_size 256k;
     fastcgi_temp_file_write_size 256k;
   }

    # Deny everything else in /app folder except Assets folder in bundles
    location ~ /app/bundles/.*/Assets/ {
        allow all;
        access_log off;
    }
    location ~ /app/ { deny all; }

    # Deny everything else in /addons or /plugins folder except Assets folder in bundles
    location ~ /(addons|plugins)/.*/Assets/ {
        allow all;
        access_log off;
    }
    # location ~ /(addons|plugins)/ { deny all; }

    # Deny all php files in themes folder
      location ~* ^/themes/(.*)\.php {
        deny all;
    }

    # Don't log favicon
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    # Don't log robots
    location = /robots.txt  {
        access_log off;
        log_not_found off;
    }

    # Deny yml, twig, markdown, init file access
    location ~* /(.*)\.(?:markdown|md|twig|yaml|yml|ht|htaccess|ini)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

  # Allow access to certbot directory in order to obtain TLS certificate
     location ~ /.well-known/acme-challenge {
      allow all;
   }

  # Deny all attempts to access hidden files/folders such as .htaccess, .htpasswd, .DS_Store (Mac), etc...
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Deny all grunt, composer files
    location ~* (Gruntfile|package|composer)\.(js|json)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Deny access to any files with a .php extension in the uploads directory
        location ~* /(?:uploads|files)/.*\.php$ {
                deny all;
    }

     # A long browser cache lifetime can speed up repeat visits to your page
  location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
       access_log        off;
       log_not_found     off;
       expires           360d;
  }
}

B. If iRedMail Doesn’t Exists

If iRedMail doesn’t exist OR if you don’t want to use the same PHP version of current iRedMail (in case it’s incompatible with Mautic), use the below code with another php version and notice the change is only the fastcgi_pass parameter. Until this moment, the latest iRedMail release uses php8.1 but the latest php version that Mautic supports is php8.0. So, you should install the PHP version that’s supported by Mautic.

server {
   listen 80;
   listen [::]:80;
   server_name mautic.vpsprof.com;

   root /var/www/html/mautic;
   error_log /var/log/nginx/mautic.error;
   access_log /var/log/nginx/mautic.access;
   client_max_body_size 20M;

   index index.php index.html index.htm index.nginx-debian.html;

   location / {
     # try to serve file directly, fallback to app.php
     try_files $uri /index.php$is_args$args;
   }

   location ~ /(mtc.js|1.js|mtracking.gif|.*\.gif|mtc) {
       # default_type "application/javascript";
       try_files $uri /index.php$is_args$args;
   }

   # redirect some entire folders
     rewrite ^/(vendor|translations|build)/.* /index.php break;

   location ~ \.php$ {
     fastcgi_pass    unix:/run/php/php8.0-fpm.sock;
     fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
     include         fastcgi_params;
   }

   location ~* ^/index.php {
     # try_files $uri =404;
     fastcgi_split_path_info ^(.+\.php)(/.+)$;
     # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

     fastcgi_pass unix:/run/php/php8.0-fpm.sock;
     fastcgi_index index.php;
     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
     include fastcgi_params;

     fastcgi_buffer_size 128k;
     fastcgi_buffers 256 16k;
     fastcgi_busy_buffers_size 256k;
     fastcgi_temp_file_write_size 256k;
   }

    # Deny everything else in /app folder except Assets folder in bundles
    location ~ /app/bundles/.*/Assets/ {
        allow all;
        access_log off;
    }
    location ~ /app/ { deny all; }

    # Deny everything else in /addons or /plugins folder except Assets folder in bundles
    location ~ /(addons|plugins)/.*/Assets/ {
        allow all;
        access_log off;
    }
    # location ~ /(addons|plugins)/ { deny all; }

    # Deny all php files in themes folder
      location ~* ^/themes/(.*)\.php {
        deny all;
    }

    # Don't log favicon
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    # Don't log robots
    location = /robots.txt  {
        access_log off;
        log_not_found off;
    }

    # Deny yml, twig, markdown, init file access
    location ~* /(.*)\.(?:markdown|md|twig|yaml|yml|ht|htaccess|ini)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

  # Allow access to certbot directory in order to obtain TLS certificate
     location ~ /.well-known/acme-challenge {
      allow all;
   }

  # Deny all attempts to access hidden files/folders such as .htaccess, .htpasswd, .DS_Store (Mac), etc...
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Deny all grunt, composer files
    location ~* (Gruntfile|package|composer)\.(js|json)$ {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Deny access to any files with a .php extension in the uploads directory
        location ~* /(?:uploads|files)/.*\.php$ {
                deny all;
    }

     # A long browser cache lifetime can speed up repeat visits to your page
  location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
       access_log        off;
       log_not_found     off;
       expires           360d;
  }
}

Symbolic Link

11. Make symbolic link between the virtual host in sites-available directory and sites-enabled directory by running the command:

root@mail:~# ln -s /etc/nginx/sites-available/mautic.vpsprof.com.conf /etc/nginx/sites-enabled

Save and close the file. Then test Nginx configuration.

root@mail:~# nginx -t

If the test is successful, reload Nginx for the changes to take effect.

root@mail:~# systemctl reload nginx

Now you should be able to see the Mautic web-based install wizard at http://mautic.vpsprof.com/installer.

If the PHP version is incompatible, like what happened with us (iRedMail uses php8.1 and Mautic supports php8.0 maximum), as you see below. We need to install a previous version of PHP to run Mautic. Refer to Install PHP on Ubuntu article to do this. Then, use the second sites-available file (iRedMail Doesn’t Exist case) with the supported PHP version.

Mautic doesn't support PHP 8.1 version

After you install a compatible PHP and update sites-available file. If you will get a message from Mautic that Site is Offline as below:

Don’t worry. Check Nginx error log, by running the below commmand:

root@mail:~# tail -f /var/log/nginx/mautic.error

Note that we added the error path file in sites-available file. We shouldn’t search for the error in the file: /var/log/nginx/error.log

2023/03/28 17:13:44 [error] 228579#228579: *75983 FastCGI sent in stderr: "PHP message: PHP Warning - Undefined variable $inline - in file /var/www/html/mautic/offline.php - at line 77PHP message: PHP Warning: Undefined variable $inline in /var/www/html/mautic/offline.php on line 77PHP message: LogicException: Extension DOM is required. - in file /var/www/html/mautic/vendor/symfony/config/Util/XmlUtils.php - at line 50" while reading response header from upstream, client: 37.17.196.144, server: mautic.vpsprof.com, request: "GET /installer HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.0-fpm.sock:", host: "mautic.vpsprof.com"

12. It means, we should install DOM extension by running the command. Note that the command will not run if add-apt-repository ppa:ondrej/php was removed, so add it again by running:

root@mail:~# add-apt-repository ppa:ondrej/php

Then, add dom module:

root@mail:~# apt install php8.0-dom

After that, it should work when we visit: http://mautic.vpsprof.com/installer, and you will see like the screenshot below. PDO drivers means the php8.0-mysql extension, so install it and also install curl extension php8.0-curl. You will notice no styles on the non SSL link but when you install SSL, styles will be fine.

13. Run the below two commands to install the required extensions:

root@mail:~# apt install php8.0-mysql
root@mail:~# apt install php8.0-curl

14. Once you finish the installation of the two modules above and if no more installations, remove the repository we added by running the command:

 root@mail:~# add-apt-repository ppa:ondrej/php --remove

Below are default php modules that come with the iRedMail installation:

root@mail:~# php -m
[PHP Modules]
calendar
Core
ctype
curl
date
dom
exif
FFI
fileinfo
filter
ftp
gd
gettext
hash
iconv
intl
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
Phar
posix
readline
Reflection
session
shmop
SimpleXML
sockets
sodium
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
xsl
Zend OPcache
zip
zlib

[Zend Modules]
Zend OPcache

Enable HTTPS Connection

15. Enable HTTPS by installing Certbot Nginx plugin.

root@mail:~# apt install python3-certbot-nginx

16. Next, run the following command to obtain and install TLS certificate.

root@mail:~# certbot --nginx --agree-tos --redirect --hsts --staple-ocsp -d mautic.vpsprof.com

If you want to include your email to receive updates, run the below code instead of the above:

root@mail:~# certbot --nginx --agree-tos --redirect --hsts --staple-ocsp --email youremail@vpsprof.com -d mautic.vpsprof.com
root@mail:~# certbot --nginx --agree-tos --redirect --hsts --staple-ocsp -d mautic.vpsprof.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for connect.pickleballtalent.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/mautic.vpsprof.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/mautic.vpsprof.com/privkey.pem
This certificate expires on 2024-03-03.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for mautic.vpsprof.com to /etc/nginx/sites-enabled/mautic.vpsprof.com.conf
Congratulations! You have successfully enabled HTTPS on https://mautic.vpsprof.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Installation Wizard

17. Now, Mautic should look like below when you visit mautic.vpsprof.com/installer, but I don’t know why the logo doesn’t show up. I tried it multiple times on different servers but the logo doesn’t show up.

Mautic installer ready to install now

18. Click on Next Step, then fill the info as below and click on Next Step.

19. Then fill the admin info and click on NextStep as below:

Mautic installation administrative user

Local Email Server Configuration

20. On last window, If you will use the local email server which is installed on the same server where mautic is installed, use the below configuration:

Mautic installation local email configuration

Remote Email Server Configuration

If you want to use another remote SMTP server that is not installed on the same server where mautic is installed, folow the configuration as below:

Mautic installation remote email configuration

Once you finish the last step (step #3), you will be directed to login page as below:

Mautic installation done login page

Enable HTTP2 Protocol for a Better Performance

21. Enable HTTP2 protocol in Nginx virtual host, go the file:

root@mail:~# nano /etc/nginx/sites-enabled/mautic.conf

Then, find the following line.

listen 443 ssl; # managed by Certbot

Simply add http2 after ssl.

listen 443 ssl http2; # managed by Certbot

Save and close the file. Then reload Nginx.

root@mail:~# systemctl reload nginx

Note: if you get Pending kernel update message when you upgrade your server, just click on ESC to skip it.

Thanks for LinuxBabe for the great toturial which helped with creating this blog post.