PTR record set by Breezehost: 38.68.14.188 → mail.firefrostgaming.com DMARC rua tag added (postmaster@firefrostgaming.com) All checks passing: SPF, DKIM, DMARC, PTR, blacklists clean Perfect score achieved March 16, 2026
8.4 KiB
Mailcow Deployment Plan — Billing VPS
Status: ✅ DEPLOYED — March 15, 2026 (ahead of April 1 target) Deployed By: Chronicler #31 Location: Billing VPS (38.68.14.188) Time Estimate: 2-3 hours SSH Login: root@38.68.14.188 Last Updated: March 14, 2026 — The Navigator (Chronicler #30)
Why Billing VPS (Not NC1)
Decision made March 14, 2026. Key reasons:
- Clean IP reputation — only Paymenter on this server, never associated with game traffic
- Email and billing are natural partners (transactional emails, invoices, subscription confirmations)
- Sufficient resources: ~13GB free disk, ~60% free RAM
- Frostwall not needed — IP separation solved by server choice, not GRE tunnels
- NC1 shares IP with game servers = email reputation risk
Pre-Deployment Checklist
- Verify Billing VPS disk space:
df -h / - Verify Billing VPS RAM:
free -h - Confirm Docker is installed:
docker --version - Confirm Docker Compose is installed:
docker compose version - Note current mail.firefrostgaming.com IP (31.56.20.252 — Plesk/Breezehost)
- Run pending system updates:
apt update && apt upgrade -y
Phase 1: System Preparation (15 min)
Update the server first
apt update && apt upgrade -y
Install Docker if not present
curl -fsSL https://get.docker.com | sh
Verify Docker
docker --version
docker compose version
Phase 2: Mailcow Installation (30 min)
Clone Mailcow
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
Generate configuration
./generate_config.sh
When prompted:
- Hostname:
mail.firefrostgaming.com - Timezone:
America/Chicago
Review generated config
cat mailcow.conf
Verify these key settings:
MAILCOW_HOSTNAME=mail.firefrostgaming.com
TZ=America/Chicago
DBPASS=<auto-generated — save this>
DBROOT=<auto-generated — save this>
Pull Docker images (this takes a while)
docker compose pull
Start Mailcow
docker compose up -d
Verify all containers running
docker compose ps
All containers should show "Up". Key ones:
- mailcow-postfix (SMTP)
- mailcow-dovecot (IMAP)
- mailcow-nginx (web UI)
- mailcow-rspamd (spam filter)
- mailcow-clamd (antivirus)
Phase 3: DNS Configuration (15 min — instant with Cloudflare)
Update these DNS records in Cloudflare:
Change MX record:
firefrostgaming.com MX 10 mail.firefrostgaming.com
(Already exists — no change needed)
Update A record for mail subdomain:
OLD: mail.firefrostgaming.com A 31.56.20.252 (Plesk)
NEW: mail.firefrostgaming.com A 38.68.14.188 (Billing VPS)
Add DKIM record (get from Mailcow admin after startup):
- Go to Mailcow admin → Configuration → ARC/DKIM Keys
- Copy the DKIM public key
- Add as TXT record:
dkim._domainkey.firefrostgaming.com
Verify existing records (already configured):
SPF: firefrostgaming.com TXT "v=spf1 +a +mx +a:plesk.breezehost.io -all"
DMARC: _dmarc.firefrostgaming.com TXT "v=DMARC1; p=quarantine; adkim=s; aspf=s"
Update SPF after Mailcow is live:
OLD: "v=spf1 +a +mx +a:plesk.breezehost.io -all"
NEW: "v=spf1 mx a:mail.firefrostgaming.com -all"
Phase 4: Mailcow Admin Setup (20 min)
Access Mailcow admin panel
https://mail.firefrostgaming.com
Default credentials: admin / moohoo (CHANGE IMMEDIATELY)
Change admin password
- Go to Access → Edit → Change password
- Store in Vaultwarden
Create initial mailboxes
Priority order:
frostystyle@firefrostgaming.com— Michael (Owner)gingerfury@firefrostgaming.com— Meg (Emissary)unicorn20089@firefrostgaming.com— Holly (Lead Builder)hello@firefrostgaming.com— General contactsupport@firefrostgaming.com— Support ticketsnoreply@firefrostgaming.com— Automated emails
For each mailbox:
- Mailboxes → Add Mailbox
- Set quota (1GB per staff mailbox is plenty)
- Generate strong password, store in Vaultwarden
Create aliases
michael@firefrostgaming.com→ frostystyle@firefrostgaming.commeg@firefrostgaming.com→ gingerfury@firefrostgaming.comholly@firefrostgaming.com→ unicorn20089@firefrostgaming.comadmin@firefrostgaming.com→ frostystyle@firefrostgaming.com
Phase 5: Ghost SMTP Configuration (15 min)
SSH to Ghost VPS
ssh architect@64.50.188.14
Update Ghost mail config
cd /var/www/firefrost
ghost config --mail SMTP \
--mailservice custom \
--mailhost mail.firefrostgaming.com \
--mailport 587 \
--mailsecure false \
--mailuser noreply@firefrostgaming.com \
--mailpass YOUR_NOREPLY_PASSWORD
Set from address
ghost config --mail.from "'Firefrost Gaming' <noreply@firefrostgaming.com>"
Restart Ghost
ghost restart
Test email
- Go to Ghost admin → Settings → Email newsletter
- Send a test email to verify
Phase 6: Resend Holly's Invite (5 min)
Once Ghost SMTP is working:
- Ghost Admin → Settings → Staff → Invited tab
- Holly's invite should still be there
- Resend invite — this time it will actually send
If the old invite expired, delete it and create a new one for unicorn20089@firefrostgaming.com.
Phase 7: Deliverability Testing (15 min)
Test with mail-tester.com
- Go to https://mail-tester.com
- Send an email to the address shown
- Check your score (aim for 9+/10)
✅ RESULT (March 16, 2026): 10/10 — PERFECT SCORE
- SPF: ✅ Pass
- DKIM: ✅ Valid
- DMARC: ✅ Pass (p=quarantine, rua added)
- PTR/rDNS: ✅ 38.68.14.188 → mail.firefrostgaming.com (set by Breezehost)
- Blacklists: ✅ Clean
- SpamAssassin: ✅ Pass
Test with Gmail
- Send test email to a Gmail account
- Check if it lands in inbox (not spam)
- Check email headers for SPF/DKIM/DMARC pass
Check blacklists
- https://mxtoolbox.com/blacklists.aspx
- Enter mail.firefrostgaming.com
- Verify not on any blacklists
Phase 8: Nginx SSL (if needed — 15 min)
Mailcow handles its own SSL via Let's Encrypt internally. Should work automatically.
If SSL cert doesn't auto-provision:
cd /opt/mailcow-dockerized
docker compose exec acme-mailcow /scripts/acme.sh
Post-Deployment Tasks
- Store all mailbox passwords in Vaultwarden
- Update tasks.md — mark Mailcow complete
- Update Ghost Servers page footer with support@firefrostgaming.com
- Update Billing VPS footer (Citadel Editor) with contact email
- Notify Holly her email is ready (via Discord)
- Notify Meg her email is ready
- Update Paymenter email settings to use Mailcow SMTP
- Configure Mailcow backups (daily, retention 30 days)
Paymenter SMTP Configuration (bonus — while on Billing VPS)
While Mailcow is being set up on the same server:
Go to Paymenter Admin → Settings → Mail:
- Driver: SMTP
- Host: localhost (same server!)
- Port: 587
- Username: noreply@firefrostgaming.com
- Password: noreply mailbox password
- Encryption: TLS
- From: noreply@firefrostgaming.com
- From Name: Firefrost Gaming
Local SMTP = fastest possible delivery for billing emails.
Known Issues / Gotchas
SPF record needs updating — current SPF includes plesk.breezehost.io which will be irrelevant after migration. Update after Mailcow is confirmed working.
DNS propagation — Cloudflare is near-instant for DNS changes, but mail servers around the world cache MX records. Give it 24 hours before declaring full success.
ClamAV memory — ClamAV (antivirus) uses ~500MB RAM on startup. If Billing VPS RAM is tight, can disable it: set SKIP_CLAMD=y in mailcow.conf before first start.
Port 25 may be blocked — Some VPS providers block outbound port 25. Check with Breezehost if sending fails. Alternative: use port 587 for all outbound.
Success Criteria
- Mailcow running on Billing VPS
- mail.firefrostgaming.com resolving to 38.68.14.188
- All staff mailboxes created
- Ghost sending email via Mailcow SMTP
- Holly's invite delivered successfully
- Mail-tester.com score 9+/10
- Gmail delivery confirmed (inbox, not spam)
- SPF, DKIM, DMARC all passing
- Credentials stored in Vaultwarden
Target Date: April 1, 2026 Estimated Time: 2-3 hours Prepared By: The Navigator (Chronicler #30) For: Chronicler #31 and beyond
Fire + Frost + Foundation = Where Love Builds Legacy 💙🔥❄️