Technology Encyclopedia Home >Run Your Own Email Server with Mailcow on a VPS — Full Control Over Your Inbox

Run Your Own Email Server with Mailcow on a VPS — Full Control Over Your Inbox

I've been curious about self-hosting email for a long time. The idea of owning the entire mail stack — no third-party scanning your messages, no sending limits, no "per-user" pricing — is genuinely appealing if you run a small team or want privacy for your personal domain.

I finally set it up last year using Mailcow, and it's been running reliably ever since. Fair warning upfront: email is the most complex self-hosting project you can take on. DNS misconfiguration will get you flagged as spam. But if you follow this guide carefully, you'll have a fully functional mail server with webmail, spam filtering, and DKIM/DMARC signing running in a few hours.

I run Mailcow on Tencent Cloud Lighthouse. For email, the 4 GB RAM / 2 vCPU plan is needed — Mailcow's Docker stack is substantial. Two things matter specifically for email deliverability on Lighthouse: the instances come with dedicated IPs (not shared with other customers' traffic), which means a clean IP reputation by default. Port 25 (outbound SMTP) is blocked by default on cloud servers to prevent spam abuse, but Tencent Cloud supports port 25 unblocking requests via a support ticket for verified legitimate email servers — this is covered in the guide.


Table of Contents

  1. Why Self-Host Email?
  2. What You Need Before Starting
  3. Part 1: Server Preparation
  4. Part 2: DNS Configuration
  5. Part 3: Install Mailcow
  6. Part 4: SSL and Initial Setup
  7. Part 5: Create Mailboxes and Test
  8. Part 6: DKIM, DMARC, and Deliverability
  9. The Thing That Tripped Me Up
  10. Troubleshooting
  11. Is Self-Hosted Email Worth It?

  • Key Takeaways
  • Use the appropriate Lighthouse application image to skip manual installation steps where available
  • Lighthouse snapshots provide one-click full-server backup before major changes
  • OrcaTerm browser terminal lets you manage the server from any device
  • CBS cloud disk expansion handles growing storage needs without server migration
  • Console-level firewall + UFW = two independent protection layers

Why Self-Host Email? {#why-self-host-email}

Running your own mail server makes sense in specific situations:

  • Domain email for a small team — no per-user SaaS fees, full control over accounts
  • Privacy — messages stored on your own server, not processed by third parties
  • No sending limits — useful for transactional email or newsletters at moderate volume
  • Learning — understanding how SMTP, IMAP, DKIM, and SPF actually work
  • Custom domains — full branding without paying per-seat enterprise pricing

The real requirements: a VPS with a dedicated IP, willingness to configure DNS carefully, and patience for the initial setup. Mailcow handles most of the hard parts (spam filtering, webmail, SSL) through Docker Compose.


What You Need Before Starting {#prerequisites}

Requirement Details
Server 4 GB RAM minimum (6 GB recommended), 2 vCPU
OS Ubuntu 22.04 LTS
Domain A domain you control — you'll be adding DNS records
Dedicated IP Your Lighthouse instance IP — check it's not on major blocklists
Ports 25, 80, 443, 110, 143, 465, 587, 993, 995 must be open
Reverse DNS Set PTR record for your IP (request from Lighthouse support if needed)

Important: Check your IP isn't blocklisted before starting. Run it through MXToolbox Blacklist Check. Fresh cloud IPs are usually clean.


Part 1: Server Preparation {#part-1}

1.1 — Set the Hostname

Mailcow uses your system hostname as the mail server name. Set it to your mail domain:

sudo hostnamectl set-hostname mail.yourdomain.com

Verify:

hostname -f
# Should output: mail.yourdomain.com

1.2 — Update the System

sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl wget

1.3 — Install Docker and Docker Compose

💡 Faster start: Select the Lighthouse Docker CE application image when creating your instance and Docker will already be installed and running. Skip this section and verify with docker --version.

curl -fsSL https://get.docker.com | sh
sudo systemctl enable docker
sudo systemctl start docker

Verify:

docker --version
docker compose version

1.4 — Open Firewall Ports

sudo ufw allow 25/tcp    # SMTP
sudo ufw allow 80/tcp    # HTTP (for Certbot)
sudo ufw allow 443/tcp   # HTTPS (webmail)
sudo ufw allow 110/tcp   # POP3
sudo ufw allow 143/tcp   # IMAP
sudo ufw allow 465/tcp   # SMTPS
sudo ufw allow 587/tcp   # Submission
sudo ufw allow 993/tcp   # IMAPS
sudo ufw allow 995/tcp   # POP3S
sudo ufw reload

Also open these ports in your Lighthouse firewall console under Firewall → Add Rule.


Part 2: DNS Configuration {#part-2}

Get this right before installing Mailcow. Bad DNS = rejected mail.

Required DNS Records

Go to your domain registrar's DNS management panel and add:

Type Name Value TTL
A mail YOUR_SERVER_IP 300
MX @ mail.yourdomain.com 300
TXT @ v=spf1 mx ~all 300
CNAME autoconfig mail.yourdomain.com 300
CNAME autodiscover mail.yourdomain.com 300

The DKIM TXT record comes after Mailcow generates it — you'll add it in Part 6.

Reverse DNS (PTR Record)

This is critical. Your IP's PTR record should resolve to mail.yourdomain.com.

In your Lighthouse console, look for Reverse DNS settings. If it's not available in the UI, open a support ticket — Tencent Cloud support can set PTR records for Lighthouse IPs.

Without a matching PTR record, Gmail and other providers will reject or heavily filter your outgoing mail.


Part 3: Install Mailcow {#part-3}

3.1 — Clone the Repository

cd /opt
sudo git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized

3.2 — Generate Configuration

sudo ./generate_config.sh

You'll be prompted for your mail server hostname:

Mail server hostname (FQDN): mail.yourdomain.com
Timezone: America/New_York

This creates mailcow.conf with your settings.

3.3 — Review Key Settings

Open mailcow.conf and verify:

sudo nano mailcow.conf

Key fields:

MAILCOW_HOSTNAME=mail.yourdomain.com
TZ=America/New_York
DBPASS=<auto-generated — save this>

3.4 — Pull and Start Containers

sudo docker compose pull
sudo docker compose up -d

This pulls about 2–3 GB of images. The first startup takes 3–5 minutes as containers initialize.

Check status:

sudo docker compose ps

All containers should show Up.


Part 4: SSL and Initial Setup {#part-4}

4.1 — Access the Admin Panel

Navigate to https://mail.yourdomain.com in your browser.

You'll see a certificate warning on first access — that's normal, Mailcow is fetching the Let's Encrypt certificate. Wait 2–3 minutes and refresh.

Default admin credentials:

  • Username: admin
  • Password: moohoo

Change this immediately after logging in: Configuration → Access → Administrator → Change Password.

4.2 — Add Your Domain

In the admin panel:

  1. Configuration → Mail Setup → Domains → Add domain
  2. Enter yourdomain.com
  3. Set quota and mailbox limits as needed
  4. Click Add

4.3 — Verify SSL Certificate

Go to System → SSL/TLS → Certificates. You should see a valid Let's Encrypt certificate for your domain. If it shows "pending", wait a few minutes — Mailcow automatically requests it.


Part 5: Create Mailboxes and Test {#part-5}

5.1 — Create a Mailbox

  1. Configuration → Mail Setup → Mailboxes → Add mailbox
  2. Username: you (becomes you@yourdomain.com)
  3. Set a strong password
  4. Click Add

5.2 — Access Webmail (SOGo)

Mailcow includes SOGo webmail at https://mail.yourdomain.com/SOGo.

Log in with you@yourdomain.com and the password you set.

5.3 — Configure a Mail Client

Use these settings for Thunderbird, Apple Mail, or any IMAP client:

Incoming (IMAP):

  • Server: mail.yourdomain.com
  • Port: 993
  • Security: SSL/TLS
  • Username: you@yourdomain.com

Outgoing (SMTP):

  • Server: mail.yourdomain.com
  • Port: 587
  • Security: STARTTLS
  • Username: you@yourdomain.com

5.4 — Send a Test Email

Send a test email to a Gmail address. Check:

  1. It arrives in the inbox (not spam)
  2. Reply comes back to your mail server
  3. Check headers for DKIM and SPF pass

If it lands in spam, the DKIM setup in Part 6 usually fixes it.


Part 6: DKIM, DMARC, and Deliverability {#part-6}

6.1 — Get Your DKIM Key

In the Mailcow admin panel:

  1. Configuration → Configuration & Details → ARC/DKIM keys
  2. Select your domain
  3. Click Generate (if no key exists)
  4. Copy the TXT record value

6.2 — Add DKIM DNS Record

Back in your domain's DNS panel, add:

Type Name Value
TXT dkim._domainkey v=DKIM1;k=rsa;t=s;s=email;p=YOUR_PUBLIC_KEY

6.3 — Add DMARC Record

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

6.4 — Verify Everything

Use mail-tester.com — send a test email to their address and you'll get a deliverability score. Target 9/10 or higher.

Common issues and fixes:

  • SPF fail → Check your SPF record matches your IP
  • DKIM fail → Wait 24 hours for DNS propagation, then retest
  • PTR missing → Contact Lighthouse support to set reverse DNS

The Thing That Tripped Me Up {#gotcha}

Port 25 was blocked by my cloud provider.

Many cloud providers block outbound port 25 by default to prevent spam abuse — and Tencent Cloud Lighthouse is no exception. Without outbound port 25, your server can receive mail but can't send to other servers.

How I discovered it:

telnet smtp.gmail.com 25
# Connection timed out

The fix: Submit a support ticket to Tencent Cloud requesting port 25 be unblocked for your instance. Explain you're running a legitimate mail server for your own domain. In my experience, approval takes 1–2 business days. You'll need to provide your instance ID and the domain name.

While waiting, you can still receive mail and test internal delivery. Once port 25 is unblocked, outbound delivery to external servers starts working.


Troubleshooting {#troubleshooting}

Issue Likely Cause Fix
Container won't start Port 25 or 80 already in use sudo lsof -i :25, stop conflicting process
SSL certificate not issued DNS not propagated yet Wait 30 min, run ./renew-ssl.sh
Mail goes to spam Missing DKIM/SPF/DMARC Complete Part 6, run mail-tester.com
Can't send outbound Port 25 blocked Open support ticket with cloud provider
Login fails Wrong credentials Reset via ./helper-scripts/mailcow-reset-admin.sh
High memory usage Too many containers Check docker stats, increase to 6 GB RAM
PTR mismatch PTR not set correctly Verify with nslookup YOUR_IP, contact support

Is Self-Hosted Email Worth It? {#verdict}

Here's the honest picture after running it for a year:

Aspect Reality
Reliability Excellent — 99.9%+ uptime on a cloud VPS
Deliverability Good once DKIM/DMARC/PTR are configured correctly
Maintenance Low — docker compose pull && docker compose up -d for updates
Setup complexity High — DNS configuration takes the most time
Cost ~$6–12/month for the server (vs per-user SaaS pricing)
Privacy Complete — data stays on your server

Best suited for: developers and sysadmins who want control over their mail infrastructure, small teams with a fixed number of users, privacy-conscious individuals.

The key insight: Mailcow does the hard work. The Docker stack handles spam filtering, webmail, SSL, and DKIM signing out of the box. Your job is to configure DNS correctly and get port 25 unblocked. After that, it runs with minimal intervention.


Summary — What You Built

  • Full mail server: SMTP + IMAP + webmail
  • Spam filtering via Rspamd
  • DKIM/SPF/DMARC signing for deliverability
  • SSL certificates via Let's Encrypt (auto-renewal)
  • SOGo webmail accessible from any browser
  • Works with any mail client (Thunderbird, Apple Mail, mobile)

Frequently Asked Questions {#faq}

Is self-hosted email difficult to set up?
It's the most complex self-hosting project in this series. DNS configuration must be precise, and port 25 may need to be unblocked by contacting support. Mailcow handles most complexity through Docker, but DNS setup requires careful attention.

What DNS records are required for email to work correctly?
MX record (mail routing), SPF (authorized senders), DKIM (cryptographic signature), DMARC (policy), and PTR (reverse DNS/rDNS). Missing or misconfigured records result in email being rejected as spam.

Why is outbound port 25 blocked on cloud servers?
Cloud providers block port 25 by default to prevent spam. Submit a support ticket to Tencent Cloud explaining you're running a legitimate email server for your domain. Approval typically takes 1–2 business days.

How do I check if my email is likely to go to spam?
Use mail-tester.com — send a test email to their address and you'll get a deliverability score and specific issues to fix. Target 9/10 or higher before sending production email.

What is reverse DNS (PTR record) and why does it matter for email?
The PTR record resolves your server's IP address back to a hostname. Most email servers check that the PTR record matches the server's hostname. Without it, your email is likely to be flagged as spam.

👉 Get started with Tencent Cloud Lighthouse
👉 View current pricing and launch promotions
👉 Explore all active deals and offers