Marketing automation is a powerful tool for businesses looking to nurture leads, engage customers, and streamline marketing efforts. Mautic stands out as a leading open-source marketing automation platform, offering a robust alternative to expensive proprietary solutions.
What is Mautic? It’s a comprehensive platform that allows you to manage your marketing campaigns, track user interactions, segment your audience, and automate communications across various channels. Key features include detailed lead tracking (website visits, form submissions, email opens), sophisticated email campaign builders, dynamic content, audience segmentation tools, landing page and form creation, and in-depth reporting.
Self-hosting Mautic gives you complete control over your data, avoids vendor lock-in, offers limitless customization possibilities, and can be significantly more cost-effective than SaaS alternatives. It’s particularly helpful for businesses that prioritize data privacy, need specific integrations, or want to deeply tailor their marketing automation workflows without the constraints of closed platforms.
This guide will walk you through installing Mautic 5.2.4 on an Oracle Cloud Infrastructure (OCI) ARM-based virtual machine running Ubuntu 24.04 Noble Numbat. We’ll use Caddy as a reverse proxy for automatic HTTPS, Composer for the Mautic installation (as recommended), and Docker for the database.
Prerequisites
Before starting, ensure you have the following set up:
- Oracle ARM VM: An Ubuntu 24.04 instance running on OCI’s Ampere A1 platform.
- Basic Server Setup: sudo privileges and SSH access.
- Docker: Installed and running (sudo systemctl status docker).
- Caddy: Installed directly on the host (not in Docker) and configured to manage SSL for your main domain (sudo systemctl status caddy).
- Domain Name: A registered domain (we’ll use yourdomain.com as an example).
- Subdomain: A subdomain for Mautic (e.g., mautic.yourdomain.com).
- DNS Records: An ‘A’ record pointing mautic.yourdomain.com to your server’s public IP address (xxx.xxx.xxx.xxx).
- Cloudflare (Optional but Recommended): If using Cloudflare, ensure it’s configured for your domain, pointing to your server’s IP. Set the SSL/TLS mode to Full (Strict).
- Block Volume: A block volume attached and mounted, for persistent data storage (e.g., at /mnt/myvolume).
Table of Contents
- Step 1: Install PHP 8.1/8.2 & Prerequisites
- Step 2: Configure PHP-FPM
- Step 3: Set up MariaDB Database (Docker)
- Step 4: Install Mautic (Composer)
- Step 5: Configure Caddy
- Step 6: Run Mautic Web Installer
- Step 7: Configure Cron Jobs
- Upgrading to Mautic 6 (Future Consideration – Updated with Real-World Steps)
- Conclusion
Step 1: Install PHP 8.1/8.2 & Prerequisites
Mautic 5 requires PHP 8.1 or 8.2. Ubuntu 24.04 ships with 8.3, so we’ll use Ondřej Surý’s PPA for a specific version and install necessary extensions, plus Composer.
# Add Ondřej Surý's PPA for PHP sudo add-apt-repository ppa:ondrej/php -y sudo apt update # Install PHP 8.1 and necessary extensions (check Mautic docs for latest) # (You can use php8.2 if preferred, just change all '8.1' references) sudo apt install -y php8.1 php8.1-fpm php8.1-mysql php8.1-curl php8.1-gd php8.1-intl \ php8.1-mbstring php8.1-xml php8.1-zip php8.1-imap php8.1-bcmath \ php8.1-soap php8.1-opcache php8.1-cli php8.1-common php8.1-readline # Switch default CLI version (optional but helpful) sudo update-alternatives --set php /usr/bin/php8.1 sudo update-alternatives --set phar /usr/bin/phar8.1 sudo update-alternatives --set phar.phar /usr/bin/phar.phar8.1 # Verify PHP installation php -v # Install Composer globally cd /tmp php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" # Optional: Verify installer hash from getcomposer.org/download/ # EXPECTED_SIGNATURE=$(php -r "echo hash_file('sha384', 'composer-setup.php');"); echo $EXPECTED_SIGNATURE sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer php -r "unlink('composer-setup.php');" # Verify Composer installation composer --version # Install DB client (useful for debugging) sudo apt install -y mariadb-client
Step 2: Configure PHP-FPM
Adjust PHP settings for better performance and reliability with Mautic.
# Edit the PHP-FPM configuration file sudo nano /etc/php/8.1/fpm/php.ini
Find and modify these values (use Ctrl+W in nano):
memory_limit = 256M upload_max_filesize = 64M post_max_size = 64M max_execution_time = 300 date.timezone = YOUR_TIMEZONE ; e.g., America/New_York or UTC
(Replace YOUR_TIMEZONE with your actual timezone: timedatectl list-timezones)
Save (Ctrl+X, Y, Enter) and restart PHP-FPM:
sudo systemctl restart php8.1-fpm sudo systemctl status php8.1-fpm
Step 3: Set up MariaDB Database (Docker)
We’ll run the database in a Docker container, storing data on the block volume for persistence.
# Create directories on the block volume sudo mkdir -p /mnt/myvolume/mautic_app # App code will go here sudo mkdir -p /mnt/myvolume/mautic_db_data # DB data will go here # Define database credentials (REPLACE passwords and save them securely!) DB_ROOT_PASSWORD="<YOUR_VERY_SECURE_ROOT_PASSWORD>" MAUTIC_DB_USER="mautic_user" MAUTIC_DB_PASSWORD="<YOUR_SECURE_MAUTIC_DB_PASSWORD>" MAUTIC_DB_NAME="mautic_db" # Run MariaDB container # NOTE: We use host port 3307 because 3306 might be in use by other containers. # If 3306 is free on your host, you can use 127.0.0.1:3306:3306. sudo docker run -d \ --name mautic-db \ -p 127.0.0.1:3307:3306 \ -v /mnt/myvolume/mautic_db_data:/var/lib/mysql \ -e MARIADB_ROOT_PASSWORD="$DB_ROOT_PASSWORD" \ -e MARIADB_DATABASE="$MAUTIC_DB_NAME" \ -e MARIADB_USER="$MAUTIC_DB_USER" \ -e MARIADB_PASSWORD="$MAUTIC_DB_PASSWORD" \ --restart=always \ mariadb:10.11 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci # Wait for the database to initialize echo "Waiting for database container to initialize..." sleep 60 # Verify container is running sudo docker ps
Remember the DB User, Password, Name, and Port (3307) for the Mautic installer.
Step 4: Install Mautic (Composer)
Use Composer to download Mautic and its dependencies. Then install Node.js/npm to build frontend assets.
# Navigate to the parent directory on the block volume cd /mnt/myvolume # Create the Mautic project using Composer sudo composer create-project mautic/recommended-project:^5 mautic_app --no-dev --no-interaction # This might initially fail on the 'npm' step if Node.js isn't installed yet. # Install Node.js (LTS version, e.g., 20.x) and npm sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg sudo mkdir -p /etc/apt/keyrings curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg NODE_MAJOR=20 echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list sudo apt-get update sudo apt-get install nodejs -y node -v npm -v # Re-run composer install within the Mautic directory to build assets cd /mnt/myvolume/mautic_app # Allow plugins as root for the npm scripts to run sudo COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --prefer-dist --no-interaction # Set ownership and permissions after successful install sudo chown -R www-data:www-data /mnt/myvolume/mautic_app sudo chmod -R 755 /mnt/myvolume/mautic_app # Set writable permissions for specific directories sudo find /mnt/myvolume/mautic_app/var -type d -exec chmod 775 {} \; sudo find /mnt/myvolume/mautic_app/var -type f -exec chmod 664 {} \; sudo find /mnt/myvolume/mautic_app/config -type d -exec chmod 775 {} \; sudo find /mnt/myvolume/mautic_app/config -type f -exec chmod 664 {} \; # Ensure media/translations dirs exist (if needed later) and set permissions sudo mkdir -p /mnt/myvolume/mautic_app/docroot/media/files # Media usually lives under docroot sudo chown -R www-data:www-data /mnt/myvolume/mautic_app/docroot/media sudo chmod -R 775 /mnt/myvolume/mautic_app/docroot/media
Step 5: Configure Caddy
Add a block to your Caddyfile to serve Mautic over HTTPS.
sudo nano /etc/caddy/Caddyfile
Add this block (adjust alongside your existing configurations):
mautic.yourdomain.com { # Set the web root to Mautic's public directory root * /mnt/myvolume/mautic_app/docroot # Enable PHP-FPM handling via the correct socket php_fastcgi unix//run/php/php8.1-fpm.sock { split .php } file_server encode zstd gzip header { Strict-Transport-Security "max-age=31536000;" X-Content-Type-Options "nosniff" X-Frame-Options "SAMEORIGIN" Referrer-Policy "strict-origin-when-cross-origin" Permissions-Policy "interest-cohort=()" -Server } # Block access to sensitive files/directories OUTSIDE the docroot @forbidden { # path /app/* # REMOVED - Caused issues with Mautic 5 assets path /bin/* path /config/* path /vendor/* path /var/* path /translations/* # If it existed at project root path /upgrade/* # If it existed at project root path /.env path /.env.local path /.git* path /composer.json path /composer.lock path /phpunit.xml.dist } respond @forbidden 403 # Rewrite rules for Mautic's front controller (index.php in docroot) try_files {path} {path}/ /index.php?{query} # Optional: Configure logging log { output file /var/log/caddy/mautic.yourdomain.com.access.log { roll_size 10mb roll_keep 5 roll_keep_for 720h } level INFO } } # Ensure your other domain blocks (like yourdomain.com) are still present # yourdomain.com { ... }
Save the file, then format, validate, and reload Caddy:
# Ensure log directory exists and has correct permissions for Caddy sudo mkdir -p /var/log/caddy sudo chown caddy:caddy /var/log/caddy # Or the user Caddy runs as # Format and validate the Caddyfile sudo caddy fmt --overwrite /etc/caddy/Caddyfile sudo caddy validate --config /etc/caddy/Caddyfile # Reload Caddy service sudo systemctl reload caddy sudo systemctl status caddy # Check it reloaded okay
Troubleshooting Note: If you get 403 errors on assets later, ensure the Caddy user (caddy) is part of the www-data group: sudo usermod -a -G www-data caddy and restart Caddy (sudo systemctl restart caddy).
Step 6: Run Mautic Web Installer
Open your browser and navigate to https://mautic.yourdomain.com.
- Environment Check: Should show green checks. Review any recommendations.
- Database Setup:
- Database Driver: MySQL PDO
- Database Host: 127.0.0.1
- Database Port: 3307 (or 3306 if you didn’t change it in Step 3)
- Database Name: mautic_db
- Database Username: mautic_user
- Database Password: <YOUR_SECURE_MAUTIC_DB_PASSWORD> (from Step 3)
- Database Table Prefix: mau_ (or leave default)
- Administrative User: Create your Mautic admin login.
- Email Configuration: Configure your mail settings (SMTP, etc.). Crucially, under “How should email be handled?”, select “Queue” for better performance. You can configure the details later if needed.
- Login: Access your Mautic dashboard!
Step 7: Configure Cron Jobs
Mautic requires background jobs to function correctly.
- Configure Queue Transport: Since we selected “Queue” for email handling, we need to tell Mautic to use the database for the queue. Create/edit the .env.local file:
sudo nano /mnt/myvolume/mautic_app/.env.local
Add this line:
MAUTIC_MESSENGER_DSN_EMAIL=doctrine://default?auto_setup=true
Save and exit (Ctrl+X, Y, Enter).
2. Clear Cache: Apply the configuration change.
cd /mnt/myvolume/mautic_app sudo -u www-data php bin/console cache:clear --no-warmup sudo -u www-data php bin/console cache:warmup
3. Edit www-data Crontab:
sudo crontab -u www-data -e
(Choose nano if prompted).
4. Add Cron Job Lines: Paste the following, ensuring paths and the DSN variable match your setup:
# Mautic Cron Jobs v5+ (Based on Official Documentation) # Mandatory core jobs (Run every 5 minutes) */5 * * * * /usr/bin/php /mnt/myvolume/mautic_app/bin/console mautic:segments:update --no-interaction >> /mnt/myvolume/mautic_app/var/logs/cron_segments.log 2>&1 */5 * * * * /usr/bin/php /mnt/myvolume/mautic_app/bin/console mautic:campaigns:update --no-interaction >> /mnt/myvolume/mautic_app/var/logs/cron_campaigns_update.log 2>&1 */5 * * * * /usr/bin/php /mnt/myvolume/mautic_app/bin/console mautic:campaigns:trigger --no-interaction >> /mnt/myvolume/mautic_app/var/logs/cron_campaigns_trigger.log 2>&1 # Process Message Queue (Handles queued emails & other tasks - Run every 5 minutes) # Note the prepended environment variable to ensure Doctrine DSN is used */5 * * * * MAUTIC_MESSENGER_DSN_EMAIL='doctrine://default?auto_setup=true' /usr/bin/php /mnt/myvolume/mautic_app/bin/console messenger:consume email --limit=300 --memory-limit=512M --time-limit=300 --no-interaction >> /mnt/myvolume/mautic_app/var/logs/cron_queue.log 2>&1 # Maintenance (Run daily at 3:30 AM) 30 3 * * * /usr/bin/php /mnt/myvolume/mautic_app/bin/console mautic:maintenance:cleanup --days-old=365 --no-interaction >> /mnt/myvolume/mautic_app/var/logs/cron_maintenance.log 2>&1 # Update MaxMind GeoIP database (Run weekly at 4:00 AM on Monday) 0 4 * * 1 /usr/bin/php /mnt/myvolume/mautic_app/bin/console mautic:iplookup:download --no-interaction >> /mnt/myvolume/mautic_app/var/logs/cron_geoip.log 2>&1
5. Save and Exit the crontab editor.
6. Verify Logs: After 15-30 minutes, check the log files in /mnt/myvolume/mautic_app/var/logs/ to ensure jobs run without errors (especially cron_queue.log).
tail /mnt/myvolume/mautic_app/var/logs/cron_queue.log
Upgrading to Mautic 6 (Future Consideration – Updated with Real-World Steps)
You initially installed Mautic 5.x using the mautic/recommended-project template. This template often pins the core library, plugins, and themes to the specific version installed (e.g., “5.2.4” in composer.json). When you decide to upgrade to Mautic 6, the process requires careful steps, and standard documentation commands might need adjustments for this project structure.
Strongly Recommended: Always perform upgrades on a staging/test environment first before attempting on your live production site!
Here are the steps that worked for upgrading this specific setup:
- BACKUP EVERYTHING: This cannot be stressed enough. Before starting any upgrade, create:
- File Backup: A complete backup of your Mautic application directory (e.g., /mnt/myvolume/mautic_app).
- Database Backup: A full dump of your Mautic database (e.g., docker exec mautic-db mariadb-dump -u root -p –all-databases > mautic_backup_M5_YYYYMMDD.sql). Replace placeholders with your actual container name, DB user/password, and desired backup filename.
- Store these backups securely, preferably off the server.
- Read Official Docs (for Context): Review the Mautic 6 release notes and the official upgrade guide on docs.mautic.org. Pay attention to breaking changes, new server requirements (PHP version, extensions), and the general workflow, even if the specific Composer commands differ slightly from what follows.
- Check & Meet Requirements: Ensure your server (PHP version, extensions) meets Mautic 6’s documented requirements. If you need to upgrade PHP (e.g., from 8.1 to 8.2), do so first using the PPA (sudo apt install php8.2 php8.2-fpm php8.2-[…]) and update your Caddyfile (php_fastcgi unix//run/php/php8.2-fpm.sock) and cron jobs (/usr/bin/php should point to the correct version via update-alternatives or specify the path like /usr/bin/php8.2) accordingly.
- Update Composer Constraints & Packages:
# Navigate to your Mautic directory cd /mnt/myvolume/mautic_app # Optional: Ensure composer is v2+ and update it composer --version sudo composer self-update --2 # === KEY STEP 1: Modify composer.json === # Manually edit composer.json to allow Mautic 6 versions. sudo nano composer.json # In the "require" section, find ALL lines starting with "mautic/" # (core-lib, plugins, themes, grapes-js-builder-bundle). # Change their version constraint from the exact version (e.g., "5.2.4") # to allow version 6. Using the caret (^) is recommended: "^6.0" # # Example - Change: # "mautic/core-lib": "5.2.4", # "mautic/plugin-focus": "5.2.4", # "mautic/theme-blank": "5.2.4", # To: # "mautic/core-lib": "^6.0", # "mautic/plugin-focus": "^6.0", # "mautic/theme-blank": "^6.0", # ... (do this for ALL mautic/* packages) ... # IMPORTANT: Leave "mautic/core-composer-scaffold": "4.x-dev" as is, # unless official Mautic 6 docs specifically require changing it. # Save and close the editor (Ctrl+X, Y, Enter in nano). # ======================================= # === KEY STEP 2: Run Composer Update === # Now run a general update command. sudo COMPOSER_ALLOW_SUPERUSER=1 composer update --with-all-dependencies --no-dev # Composer will attempt to update all packages according to your edits. # This step might take a while. # ======================================= # === TROUBLESHOOTING 1: Git Ownership Error === # If composer update fails with a "fatal: detected dubious ownership" error # related to vendor subdirectories (like lightsaml, friendsofsymfony): # Add the specific directories mentioned in the error message to Git's safe list: # sudo git config --global --add safe.directory /mnt/myvolume/mautic_app/vendor/[repository_path_1] # sudo git config --global --add safe.directory /mnt/myvolume/mautic_app/vendor/[repository_path_2] # ... (add one for each directory causing the error) ... # Then, re-run the composer update command: # sudo COMPOSER_ALLOW_SUPERUSER=1 composer update --with-all-dependencies --no-dev # ============================================= # === TROUBLESHOOTING 2: Modified Files Prompt === # If composer update prompts you with "[package] has modified files... Discard changes [y,n,v,d,?]?": # Type 'y' and press Enter. It's usually safe to discard these changes # within the vendor directory. You might need to do this for multiple packages. # =============================================== # === POST-UPDATE SCRIPT WARNINGS === # After composer finishes downloading/updating, the post-update scripts # (like npm ci, assets:generate) will run. You MAY see warnings or errors here # about missing classes or type mismatches. This is often okay at this stage, # as the application cache is inconsistent. Proceed to the next steps unless # the 'composer update' command itself failed entirely before scripts. # ===================================
5. Force Cache Clear (CRITICAL STEP): Before running the Mautic update script, forcefully remove the old cache to prevent errors caused by outdated configurations.
# Still in /mnt/myvolume/mautic_app sudo rm -rf var/cache # Ensure permissions are correct after cache removal sudo chown -R www-data:www-data /mnt/myvolume/mautic_app sudo find /mnt/myvolume/mautic_app -type d -exec chmod 775 {} \; sudo find /mnt/myvolume/mautic_app -type f -exec chmod 664 {} \; sudo chmod +x /mnt/myvolume/mautic_app/bin/console # Ensure console is executable
6. Apply Mautic Update (Includes Migrations): Now, run Mautic’s dedicated update script. With the cache properly cleared, this should succeed.
# Apply Mautic upgrade script (runs migrations, updates schemas, etc.) sudo -u www-data php bin/console mautic:update:apply --finish
Output should end with Success! You are now running version 6.x.x of Mautic. Follow any different instructions if –finish fails.
7. Final Cache Clear: Clear the cache one last time for good measure.
sudo -u www-data php bin/console cache:clear
8. Test Thoroughly: Log in to your Mautic instance (https://mautic.yourdomain.com). Navigate extensively, checking contacts, segments, campaigns, emails, forms, reports, and settings. Monitor Mautic logs (var/logs/mautic_prod-*.php) and server logs for any new errors.
Conclusion
You should now have a fully functional Mautic 5 installation running on your Oracle ARM Ubuntu server, managed by Caddy and using Docker for the database. By setting up the cron jobs correctly using the database queue, you’ve ensured reliable background processing for your marketing automation tasks. Remember to keep Mautic, PHP, Caddy, Docker, and your server updated for security and performance.
Happy automating! Let us know in the comments if you have any questions or ran into different issues.