How To Install MailPit on Laravel Forge

So you have a staging environment set up, and want to catch all emails that go out? You might use MailTrap for that. It's a great hoste...

Cristian Tabacitu
Cristian Tabacitu
Share:

So you have a staging environment set up, and want to catch all emails that go out? You might use MailTrap for that. It's a great hosted solution. But if you have an app that sends a lot of emails, and undergoes a lot of testing... you will soon hit MailTrap's 1000 emails/month limit... and even the 10.000 or 100.000 emails/month limit. What do you then?

Well... what if I told you that you can use MailPit, the same tiny software you might use on localhost? Yup, you can install it on your staging server, and have a FREE solution to test outgoing emails. I haven't found any tutorial online on how to do this for a default Laravel setup, so here's me giving you step-by-step instructions.

In this tutorial, I'm going to focus on my setup:

  • Laravel Forge
  • Ubuntu 24+ server
  • dedicated server that only serves the staging app

Step 1. SSH to your server

ssh [email protected]

Step 2. Download and run the installer:

sudo bash < <(curl -sL https://raw.githubusercontent.com/axllent/mailpit/develop/install.sh)

(it will ask for your sudo password)


Step 3. Run Mailpit as a Background Service

sudo nano /etc/systemd/system/mailpit.service

Then inside the editor:

[Unit]
Description=MailPit Email Catching Service
After=network.target

[Service]
ExecStart=/usr/local/bin/mailpit --listen 127.0.0.1:8025
Restart=always

[Install]
WantedBy=multi-user.target

To save, press Ctrl+O, then Enter. To exit, press Ctrl+X.


Step 4. Start & enable the service

sudo systemctl enable mailpit
sudo systemctl start mailpit

Step 5. Allow external access to port 8025 (web interface) and 1025 (SMTP):

sudo ufw allow 8025
sudo ufw allow 1025

You can then check that the rule works with sudo ufw status.

Note: We're only doing this to easily test that it's working. We will remove these in the last step of this tutorial.


Step 6. Verify MailPit is running

MailPit should now be running and accessible via the default port 8025 (web interface) and 1025 (SMTP).

Go to your IP, port 8025 and see if it loads (eg. http://167.87.78.123:8025).


Step 7. Verify MailPit receives emails

In your staging environment, change your MAIL configuration to use this Mailpit installation:

MAIL_MAILER=smtp
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

Send an email, then see it in the web interface.

Note: If you're having problems receiving an email, please run php artisan cache:clear. If that still doesn't work, please send an email manually by installing swaks with sudo apt install swaks, then running swaks --to [email protected] --server 127.0.0.1:1025. This will send an email directly from your server to MailPit. If this manual email works, then the problem is misconfiguration in Laravel - fix your env file and cache until it works. A manual deployment usually fixes things, because it clears everything (php artisan optimize:clear).


Step 8. Add a new DNS record

I use Cloudflare, so I've added an A record that points from mailpit.mydomain.com to my server's external IP (167.87.78.123). And yes, I've enabled Cloudflare's SSL.


Step 9. Add a site on Laravel Forge

We could manually set up Nginx, but I think it'll be cleaner to have mailpit show up as an application on Forge. So go to your server and create a new simple app:

You don't need to install anything afterwards (no Git repo, no WP, no phpMyAdmin).


Step 10. Add a new SSL Certificate

Use "Let's Encrypt" in Forge to set up an SSL certificate for that subdomain:


Step 11. Proxy your subdomain to Mailpit

Edit your Nginx configuration:

And within the existing location / {}, instead of the default, add your proxy:

    location / {
        # No longer needed:
        # try_files $uri $uri/ /index.php?$query_string;
        
        # Proxy requests to MailPit
        proxy_pass http://localhost:8025;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

Step 12. Add Basic HTTP Authentication

In Forge, go to Security and add a new HTTP Basic authentication:


Now it all works! Now when you go to your subdomain (eg. mailpit.mydomain.com), you will be asked for username & password:

Then you'll have access to any emails your applications send:

But we're not 100% done yet. One more thing to do:


Step 13. Beef up security - only allow local access

Yes, everything works now! You can go to mailpit.mydomain.com, authenticate and see your emails... BUT! Your IP is exposed:

  • if anybody goes to http://167.87.78.123:8025/, they will see all emails too;
  • if anybody sends emails to 167.87.78.123:1025, they will end up in your inbox;

To restrict access from the public, let's make your Mailtrap instance only receive input from apps on the same server. Let's remove the two rules we added in step 5:

sudo ufw delete allow 8025
sudo ufw delete allow 1025

Now we're really done. Let's test:

  • http://167.87.78.123:8025/ should no longer work;
  • https://mailpit.mydomain.com should still work;
  • ✅ sending an email from your app should end up in mailpit;

That's it. Hope you enjoyed this tutorial, and find it useful. Personally, after setting this up, I've never used MailTrap again. Ok fine it happened yesterday, you make a good point. But still!

Want to receive more articles like this?

Subscribe to our "Article Digest". We'll send you a list of the new articles, every week, month or quarter - your choice.

Reactions & Comments

What do you think about this?

Latest Articles

Wondering what our community has been up to?