Skip to main content

Self-Host Mautic: Open Source Marketing Automation 2026

·OSSAlt Team
mauticmarketing-automationself-hostingdockeremail-marketinghubspot-alternative

How to Self-Host Mautic: Open Source Marketing Automation in 2026

TL;DR

HubSpot Marketing Professional costs €880/month and locks your contacts in a proprietary system. Mautic is the open source alternative — the world's largest open source marketing automation platform, with 9,300+ GitHub stars, Apache 2.0 license, and unlimited contacts for the price of a VPS. It does email campaigns, contact scoring, visual campaign builder, landing pages, multi-channel automation, and CRM integration — all self-hosted, data on your servers. The break-even vs HubSpot happens around 40,000 contacts. If you're technically capable, this guide has a production Mautic instance running in 30 minutes.

Key Takeaways

  • Open source marketing automation: email, SMS, social, push notifications — all in one self-hosted platform
  • 9,300+ GitHub stars: the most-starred open source marketing automation project, 1,000+ contributors
  • Unlimited contacts: Mautic doesn't meter contacts — you pay for infrastructure, not databases
  • Visual campaign builder: drag-and-drop automation workflows with conditional branching, delays, and multi-channel actions
  • PHP/Symfony stack: mature, battle-tested — version 7.x in active development as of 2026
  • GDPR-friendly by design: host in EU, no third-party tracking, full data portability
  • 3-year cost vs HubSpot: ~€58,000 vs €135,000 — a 57% reduction for mid-market teams

Why Teams Choose Mautic Over HubSpot

HubSpot is a well-engineered product. It's also a pricing trap that gets more expensive as you grow — the exact moment you need it most.

HubSpot Marketing Hub Professional starts at €880/month. By the time you factor in implementation, onboarding, and scaling to 50,000+ contacts, real-world spend averages €15,000–€45,000/year. Enterprise tier starts at €3,530/month. And your contacts, email templates, workflows, and behavioral data all live in HubSpot's cloud — migration out is deliberately painful.

Mautic inverts the model. The software is free. You pay for infrastructure (a $20-50/month VPS), email delivery (AWS SES at $0.10/1,000 emails), and your own time or an agency's time to maintain it. At 10,000 contacts: Mautic costs ~$300/month, HubSpot costs $890+/month. At 100,000 contacts: Mautic costs ~$300/month, HubSpot costs thousands.

The trade-off is real: Mautic requires PHP/server administration skills, proactive maintenance, and email deliverability management. HubSpot works out of the box. But for technically capable teams or agencies managing multiple clients, the economics strongly favor self-hosting.

FeatureMautic (Self-hosted)HubSpot ProfessionalActiveCampaign
Monthly cost (10k contacts)~$100-300 (infra)$890$149
Monthly cost (100k contacts)~$300 (infra)$3,500+$499
Contact limitUnlimitedPer-tier limitPer-tier limit
Data ownership✅ Your servers❌ HubSpot cloud❌ AC cloud
Visual campaign builder
Email A/B testing
Contact scoring✅ Professional+✅ Plus+
Landing pages
SMS/push notifications✅ (plugins)✅ Enterprise
CRM integration✅ Salesforce, Sugar✅ Native✅ Native
GDPR/EU hosting✅ Full control⚠️ US-based⚠️ US-based
Open source✅ Apache 2.0

System Requirements

Mautic is a PHP application backed by MySQL/MariaDB. Resource needs scale with your contact list size and email volume.

Minimum for small lists (< 50,000 contacts):

  • CPU: 2 vCPU
  • RAM: 2GB (4GB recommended)
  • Storage: 20GB SSD
  • PHP: 8.1+
  • MySQL: 8.0+ or MariaDB 10.5+

Recommended for mid-size lists (50K–500K contacts):

  • CPU: 4 vCPU
  • RAM: 8GB
  • Storage: 50GB+ SSD (email attachments and contact data accumulate)
  • Dedicated cron worker container for queue processing

Infrastructure for production:

  • Hetzner CX22: 2 vCPU, 4GB RAM, €4.35/month — small lists
  • Hetzner CX32: 4 vCPU, 8GB RAM, €8.70/month — mid-size lists
  • Separate transactional email service: AWS SES, Mailgun, SendGrid, Postmark

Ports to open: 80, 443


Self-Hosting with Docker Compose

The Stack

Mautic 5+ with Docker Compose runs four containers:

  1. mauticdb — MySQL database
  2. mautic_web — PHP-FPM + Mautic application
  3. mautic_worker — background job processor (handles queued emails)
  4. mautic_cron — scheduled task runner (contact scoring, campaign triggers)

docker-compose.yml

version: "3.8"

services:

  mauticdb:
    image: mysql:8.0
    container_name: mauticdb
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: mautic
      MYSQL_USER: mautic
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "mautic", "-p${MYSQL_PASSWORD}"]
      interval: 10s
      timeout: 5s
      retries: 5

  mautic_web:
    image: mautic/mautic:5-apache
    container_name: mautic_web
    volumes:
      - mautic_data:/var/www/html
    environment:
      MAUTIC_DB_HOST: mauticdb
      MAUTIC_DB_PORT: 3306
      MAUTIC_DB_DATABASE: mautic
      MAUTIC_DB_USER: mautic
      MAUTIC_DB_PASSWORD: ${MYSQL_PASSWORD}
      MAUTIC_RUN_CRON_JOBS: "false"       # Handled by dedicated cron container
      MAUTIC_TRUSTED_PROXIES: "0.0.0.0/0" # Adjust for your reverse proxy
    ports:
      - "80:80"
    depends_on:
      mauticdb:
        condition: service_healthy
    restart: unless-stopped

  mautic_worker:
    image: mautic/mautic:5-apache
    container_name: mautic_worker
    volumes:
      - mautic_data:/var/www/html
    environment:
      MAUTIC_DB_HOST: mauticdb
      MAUTIC_DB_PORT: 3306
      MAUTIC_DB_DATABASE: mautic
      MAUTIC_DB_USER: mautic
      MAUTIC_DB_PASSWORD: ${MYSQL_PASSWORD}
      MAUTIC_MESSENGER_CONSUMER_ENABLED: "true"
    command: php /var/www/html/bin/console messenger:consume email --time-limit=3600
    depends_on:
      - mauticdb
      - mautic_web
    restart: unless-stopped

  mautic_cron:
    image: mautic/mautic:5-apache
    container_name: mautic_cron
    volumes:
      - mautic_data:/var/www/html
    environment:
      MAUTIC_DB_HOST: mauticdb
      MAUTIC_DB_PORT: 3306
      MAUTIC_DB_DATABASE: mautic
      MAUTIC_DB_USER: mautic
      MAUTIC_DB_PASSWORD: ${MYSQL_PASSWORD}
    command: >
      sh -c "while true; do
        php /var/www/html/bin/console mautic:segments:update
        php /var/www/html/bin/console mautic:campaigns:trigger
        php /var/www/html/bin/console mautic:emails:send
        php /var/www/html/bin/console mautic:social:monitoring
        sleep 300
      done"
    depends_on:
      - mauticdb
      - mautic_web
    restart: unless-stopped

volumes:
  mysql_data:
  mautic_data:

.env File

# .env — copy and customize before first launch
MYSQL_ROOT_PASSWORD=change-this-root-password
MYSQL_PASSWORD=change-this-mautic-password

Generate strong passwords:

openssl rand -hex 24  # Run twice for both passwords

Launch

mkdir -p ~/mautic && cd ~/mautic
# Create docker-compose.yml and .env from above

docker compose up -d

# Watch startup
docker compose logs -f mautic_web

First startup takes 2-4 minutes while Mautic initializes the database schema. Then open http://your-server-ip in your browser.


First-Run Setup Wizard

Mautic's web installer walks through four steps:

Step 1: Environment Checks

The installer validates PHP version, extensions, and directory permissions. All items should show green. Common issue: if var/cache or var/logs show as not writable, fix with:

docker exec mautic_web chown -R www-data:www-data /var/www/html/var

Step 2: Database Configuration

Database Driver: MySQL PDO
Host: mauticdb          ← the container name
Port: 3306
Name: mautic
Username: mautic
Password: [your MYSQL_PASSWORD]
Table Prefix: (leave empty or set 'mautic_')

Click Next — Mautic creates all tables (takes ~30 seconds).

Step 3: Admin Account

First Name: Your Name
Last Name: Your Last Name
Email: admin@yourcompany.com    ← this becomes your default sender address
Password: [strong password]

Important: The email you enter here becomes your default From address. Use a real deliverable address — ideally one on your sending domain.

Step 4: Email Configuration

Configure your transactional email provider immediately — Mautic without SMTP can't send anything.

AWS SES (recommended — $0.10/1,000 emails):

Mailer Transport: SMTP
Host: email-smtp.us-east-1.amazonaws.com
Port: 587
Encryption: TLS
Username: [SES SMTP username from IAM]
Password: [SES SMTP password]
From Name: Your Company
From Email: marketing@yourcompany.com

SendGrid:

Host: smtp.sendgrid.net
Port: 587
Encryption: TLS
Username: apikey
Password: [your SendGrid API key]

Mailgun:

Host: smtp.mailgun.org
Port: 587
Encryption: TLS
Username: postmaster@mg.yourcompany.com
Password: [Mailgun SMTP password]

Click Finish to complete setup.


Core Features: What Mautic Can Do

Contact Management

Mautic's contact database is the foundation of everything. Contacts are enriched automatically:

Contacts → Import CSV → Map fields
  Name, Email, Company, Phone → Standard fields
  Any custom fields you've defined → Custom fields

Or capture automatically via:
  → Mautic forms embedded on your website
  → API (push contacts from your app)
  → CRM sync (Salesforce, SugarCRM, Dynamics)

Contact timeline shows every touchpoint: emails opened, links clicked, pages visited, forms submitted, and campaign steps completed. This is the data HubSpot charges thousands to collect — it's all yours.

Segments

Segments are dynamic contact lists that update automatically based on rules:

Contacts → Segments → New Segment

Name: "Enterprise Leads - Not Yet Contacted"
Rules:
  Company Size → is → Enterprise (1000+)
  AND Lead Status → is not → Contacted
  AND Last Active → is greater than → 7 days ago
  AND Email → is valid → true

Segments rebuild automatically every time the cron job runs (every 5 minutes in our Docker setup). All campaigns target segments, not individual contacts.

Email Builder

Mautic's drag-and-drop email builder creates responsive HTML emails:

Channels → Emails → New Email

Type: Template Email (for campaigns) or Segment Email (one-time broadcast)

Builder:
  → Drag in text blocks, images, buttons, dividers
  → Personalization tokens: {contactfield=firstname} {contactfield=company}
  → Dynamic content: show different content blocks based on contact fields
  → A/B testing: split by subject line, content, or send time

Subject: Your {contactfield=company} trial is about to expire
Preview text: Don't lose access to [feature] — here's what you need to know

Campaign Builder (Visual Automation)

This is Mautic's flagship feature — a visual, event-driven campaign builder that rivals HubSpot's workflow tool:

Campaigns → New Campaign → Canvas

Start:
  → Contact joins segment: "Trial Users - Day 7"

Step 1 (immediately):
  → Send email: "Day 7 trial check-in"

Decision point:
  → Did they open the email?

  YES branch:
    → Wait: 2 days
    → Send email: "Upgrade now — 15% off"
    → Modify contact field: "Campaign = Trial Nurtured"

  NO branch:
    → Wait: 1 day
    → Send email: "Did this get lost in your inbox?"
    → Decision: Did they open the retry?
      YES → Continue to upgrade offer
      NO  → Add tag: "Low Engagement" → Remove from segment

End actions:
  → Notify sales owner
  → Push to CRM
  → Update lead score

The campaign canvas supports unlimited branches, delays (minutes, hours, days, specific dates), conditional logic based on any contact field or behavior, and multi-channel actions (email, SMS, push notifications, webhooks to external systems).

Contact Scoring

Assign points to behaviors to automatically identify hot leads:

Settings → Scoring → Points

Email opened:       +1 point
Link clicked:       +5 points
Form submitted:     +10 points
Pricing page visit: +15 points
Demo requested:     +25 points
Email bounced:      -5 points
Unsubscribed:       -20 points

Combine scoring with campaign triggers: "When contact reaches 50 points, notify sales and start the sales outreach campaign."

Landing Pages

Build GDPR-compliant lead capture pages within Mautic:

Landing Pages → New Landing Page

Builder: Same drag-and-drop as email builder
Forms: Embed Mautic forms that auto-capture leads into contact database
Tracking: Built-in page view and conversion tracking
A/B testing: Split test two page variants

Publish to a subdomain: landing.yourcompany.com/offer-name


Custom Domain and TLS

DNS Setup

# DNS A record:
marketing.yourcompany.com → your.server.ip.address

Add Caddy to your Docker Compose for automatic TLS:

# Add to docker-compose.yml
  caddy:
    image: caddy:2-alpine
    container_name: mautic_caddy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - mautic_web
    restart: unless-stopped

# Update mautic_web: remove ports: - "80:80" (Caddy handles ingress)

# Add to volumes:
volumes:
  caddy_data:
  caddy_config:
# Caddyfile
marketing.yourcompany.com {
    reverse_proxy mautic_web:80
}

Caddy automatically fetches and renews Let's Encrypt certificates. No certbot needed.

Update Mautic's site URL:

Settings → System Settings → Site URL
→ https://marketing.yourcompany.com

Email Deliverability: The Critical Step Most Guides Skip

Self-hosted email is only as good as your deliverability. Without proper setup, your campaigns land in spam.

DNS Records to Configure

Set these in your domain registrar for your sending domain (e.g., yourcompany.com):

SPF record — authorize your email provider to send on your behalf:

Type: TXT
Name: @
Value: v=spf1 include:amazonses.com ~all
# Replace with your provider's include string

DKIM — cryptographic signature on all outgoing email:

# AWS SES: Go to SES console → Verified identities → DKIM
# Copy the three CNAME records and add them to your DNS
# Example:
# xxxxxxxxxxxx._domainkey.yourcompany.com → CNAME → xxxx.dkim.amazonses.com

DMARC — policy for email authentication failures:

Type: TXT
Name: _dmarc
Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourcompany.com; pct=100

Configure Tracking Domain

Mautic tracks email opens with pixel images and link clicks via redirect. Configure a tracking subdomain:

Settings → Email Settings → Tracking Domain
→ t.yourcompany.com

DNS:
t.yourcompany.com → CNAME → marketing.yourcompany.com

This keeps tracking URLs on your domain rather than mautic.io subdomains.

Warm Up Your IP/Domain

Never blast 50,000 emails on day one from a new sending domain. ESP (Email Service Provider) reputation takes weeks to build:

Week 1: Maximum 500 emails/day → your most engaged contacts
Week 2: Maximum 2,000 emails/day
Week 3: Maximum 10,000 emails/day
Week 4+: Scale based on metrics

Monitor bounce rate, spam rate, and open rate from your ESP dashboard. Stop if bounce rate exceeds 2% — clean your list.


CRM Integration

Salesforce

Settings → Plugins → Salesforce

Client ID: [Salesforce connected app client ID]
Client Secret: [Salesforce connected app secret]
Instance URL: https://yourcompany.my.salesforce.com

Sync settings:
  → Push Mautic contacts to Salesforce leads/contacts
  → Pull Salesforce changes back to Mautic
  → Map fields: Mautic "Lead Score" → Salesforce "Lead Score"
  → Sync interval: every 15 minutes

Webhooks (any CRM or tool)

Settings → Webhooks → New Webhook

Trigger: Contact score changes above 50
URL: https://your-crm.internal/api/hot-lead
Method: POST
Headers: Authorization: Bearer your-api-token
Payload:
{
  "contact_id": "{contact.id}",
  "email": "{contact.email}",
  "score": "{contact.points}",
  "company": "{contact.company}"
}

Use webhooks to push events to your CRM, Slack, n8n workflows, or any system with an HTTP endpoint.


Production Hardening

Backups

#!/bin/bash
# backup-mautic.sh
DATE=$(date +%Y%m%d_%H%M)
BACKUP_DIR="/backups/mautic"

mkdir -p $BACKUP_DIR

# Database backup
docker exec mauticdb mysqldump \
  -u mautic \
  -p"${MYSQL_PASSWORD}" \
  mautic | gzip > "$BACKUP_DIR/mautic_db_$DATE.sql.gz"

# Mautic files (media, config, custom assets)
tar -czf "$BACKUP_DIR/mautic_files_$DATE.tar.gz" \
  ~/mautic/mautic_data/

# Upload to S3
rclone copy "$BACKUP_DIR/" s3remote:backups/mautic/

# Retain 30 days
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete

echo "Backup complete"

Updates

cd ~/mautic

# Pull latest images
docker compose pull

# Restart (Mautic runs DB migrations automatically on startup)
docker compose up -d

# Verify migration completed
docker compose logs mautic_web | grep -E "migration|Migrating|error"

Check Mautic releases before major version upgrades. The 5.x → 6.x and 6.x → 7.x upgrades require following the official migration guide.

Rate Limiting and Security

# docker-compose.yml — add to mautic_web environment
environment:
  MAUTIC_TRACK_PRIVATE_IP_RANGES: "false"  # Don't track internal IPs
  MAUTIC_CORS_VALID_HOSTS: "yourcompany.com, *.yourcompany.com"
# Caddyfile — rate limit the API
marketing.yourcompany.com {
    rate_limit {
        zone api {
            key    {remote_host}
            events 100
            window 1m
        }
        match path /api/*
    }
    reverse_proxy mautic_web:80
}

Scaling Mautic

The default setup handles up to ~200,000 contacts and moderate email volumes. For larger lists:

Queue-Based Email Sending

Enable asynchronous email processing (recommended for any production setup):

Settings → System Settings → Queue Emails
→ Enable: Yes
→ Message Limit Per Batch: 100
→ Pause Between Batches: 1 second

With the worker container running, emails queue and process asynchronously. The web container stays responsive even during large sends.

Redis for Caching

For higher traffic:

  redis:
    image: redis:7-alpine
    container_name: mautic_redis
    restart: unless-stopped

# In mautic_web environment:
  MAUTIC_REDIS_DSN: redis://redis:6379

Horizontal Scaling

For very large deployments (1M+ contacts, 100K+ daily emails):

  • Run 2-4 mautic_web containers behind a load balancer
  • Run 4-8 mautic_worker containers for parallel queue processing
  • Use RDS/Aurora MySQL instead of containerized MySQL
  • Use ElastiCache Redis for session and cache storage

Mautic vs Listmonk vs Mailtrain: Which Tool?

MauticListmonkMailtrain
Best forFull marketing automationNewsletter broadcastsList management
LanguagePHP/SymfonyGoNode.js
GitHub stars9,300+16,000+4,500+
Campaign builder✅ Visual, drag-and-drop❌ Sequential only❌ Basic
Contact scoring
Landing pages
CRM integration✅ Salesforce, Sugar, Dynamics
ComplexityHigh (full marketing suite)Low (focused tool)Medium
Resource usageHigh (PHP + MySQL + workers)Low (Go binary)Medium

Choose Mautic if you need the full marketing automation stack — lead scoring, multi-step campaigns, CRM sync, and behavioral tracking. Choose Listmonk if you primarily send newsletters or transactional email broadcasts and want simplicity.


3-Year Cost Analysis: Mautic vs HubSpot

Cost ComponentMautic Self-HostedHubSpot Professional
Software license$0$890/month base
Hosting (4 vCPU/8GB)~$25/monthIncluded
Email delivery (100k/month)~$10/month (SES)Included
Implementation (one-time)$2,000–$5,000$3,000–$6,000
Ongoing maintenance$200–$500/month (internal)$0
Year 1 total~$12,000–$18,000~$18,000–$30,000
Year 2 total~$4,000–$9,000~$15,000–$20,000
Year 3 total~$4,000–$9,000~$15,000–$20,000
3-year total~$20,000–$36,000~$48,000–$70,000

At scale (250K+ contacts, enterprise pricing), the HubSpot cost multiples: €3,530/month base + overage for contacts. Mautic scales linearly with infrastructure, not contact count.


Methodology


Find more open source HubSpot alternatives on OSSAlt — self-hosting guides, community ratings, and feature comparisons.

Related: How to Self-Host Listmonk: Mailchimp Alternative 2026 · Best Open Source Alternatives to HubSpot in 2026 · Best Open Source Email Marketing Tools in 2026

Comments