Mailcow installeren op VPS: e-mail versturen naar Gmail
Controleer eerst of poort 25 openstaat op uw VPS. Een blokkade zorgt ervoor dat e-mail in de wachtrij blijft. Configureer daarnaast de juiste DNS voor Gmail 550 5.7.25 fouten.
Wat u gaat bouwen
Een complete mailserver op een server in eigen beheer: SMTP voor het verzenden en ontvangen, IMAP zodat uw telefoon en laptop gesynchroniseerd blijven, een webmailclient en een spamfilter dat elk bericht in beide richtingen beoordeelt. mailcow-dockerized bundelt Postfix, Dovecot, Rspamd, SOGo webmail, MariaDB, Redis en een ACME-client in één Docker Compose-stack, waardoor de software zelf niet het lastige onderdeel is. U heeft het binnen een half uur draaiend.
Het lastige gedeelte is alles daaromheen. E-mail is de enige dienst waarbij de rest van het internet een gloednieuwe server actief wantrouwt. Het verschil tussen "het werkt" en "Gmail verwijdert stilletjes elk bericht" hangt af van vier DNS-records en één IP-reputatie-instelling waar u mogelijk niet volledig controle over heeft. Lees de onderstaande vereisten door voordat u ergens serverruimte huurt. Als u na het lezen besluit dat het opbouwen van een reputatie de moeite niet waard is, dan is dat een legitiem standpunt; ons overzicht van wat in 2026 daadwerkelijk de moeite waard is om zelf te hosten classificeert e-mail precies om deze redenen onder "alleen als u het echt meent".
De vereisten ZIJN het project
Mist u een van deze punten, dan zult u e-mail versturen die nooit aankomt. Hieronder staan ze in de volgorde waarin ze het vaakst voor problemen zorgen:
Uitgaande poort 25 moet openstaan. Uw server levert e-mail af bij Gmail en Microsoft via TCP-poort 25. Een groot deel van de VPS- en cloudproviders blokkeert uitgaande poort 25 standaard om spam tegen te gaan. Deze blokkade is stil: er verschijnen geen foutmeldingen bij het opstarten, alles lijkt in orde, maar de e-mail blijft voor eeuwig in de wachtrij staan. Test dit voordat u iets installeert. Als de poort geblokkeerd is, is de enige oplossing een supportticket openen met het verzoek aan uw provider om deze te openen; sommige providers doen dit voor accounts die langere tijd bestaan, andere doen het nooit.
Een schoon IP-adres met een goede reputatie. Hergebruikte VPS-IP-adressen staan vaak al op blocklists vanwege spam van een vorige huurder. Controleer uw IP-adres bij een dienst zoals de Spamhaus-lookup of mxtoolbox voordat u verdergaat. Een IP-adres op een blocklist leidt tot weigeringen waar u met configuratie niets aan kunt veranderen.
Beheer over DNS plus een correct PTR-record. U moet records toevoegen aan de zone van uw domein en u heeft reverse DNS (PTR) nodig voor het IP-adres van de server, dat terugwijst naar uw mail-hostname. PTR-records worden bijna nooit in uw DNS-paneel ingesteld; dit beheer ligt bij de eigenaar van het IP-adres. U stelt dit dus in via het configuratiescherm van uw VPS-provider of via een supportticket.
6 GiB RAM en 2 vCPU is de comfortabele ondergrens. De minimale vereiste van mailcow is 6 GiB RAM plus 1 GiB swap voor een privé-installatie, waarbij 8 GiB wordt geadviseerd zodra een handvol gebruikers ervan afhankelijk is. Onder ongeveer 2,5 GiB biedt generate_config.sh aan om de ClamAV-virusscanner uit te schakelen, zodat de kernel de containers niet beëindigt. Reserveer 20 GB SSD-ruimte om te beginnen.
Een DNS-naam, geen kaal IP-adres. Kies een hostname zoals mail.example.com. Die ene naam wordt uw MAILCOW_HOSTNAME, het onderwerp van uw TLS-certificaat, uw PTR-doel en uw SMTP-banner. Houd dit overal consistent.
Stap 1, Controleer of uitgaande poort 25 openstaat
Voer dit als eerste uit. Al het overige werk is zinloos als dit niet lukt. Probeer vanaf de nieuwe VPS een SMTP-gesprek te openen met een echte mailserver:
sudo apt update && sudo apt install -y netcat-openbsd
nc -vz -w 5 gmail-smtp-in.l.google.com 25Een werkend resultaat is onmiddellijk:
Connection to gmail-smtp-in.l.google.com (142.250.x.x) 25 port [tcp/smtp] succeeded!Een geblokkeerde poort blijft vijf seconden hangen en faalt daarna:
nc: connect to gmail-smtp-in.l.google.com port 25 (tcp) timed out: Operation now in progressDie time-out duidt op de blokkade. Dit is een netwerkfilter aan de kant van de provider, niet uw firewall, dus lokale wijzigingen lossen dit niet op. Open een ticket: "Schakel alstublieft uitgaande TCP-poort 25 in voor mijn VPS op <IP>; ik draai een legitieme mailserver." Installeer mailcow pas nadat dit "succeeded" teruggeeft. Let op: inkomende poort 25 (andere servers die u bereiken) is een apart pad en staat meestal open; het is de uitgaande kant die providers beperken.
Stap 2, DNS-records nu instellen
DNS-wijzigingen hebben tijd nodig om te propageren, dus publiceer alles wat u kunt voordat u met de installatie begint. Ga ervan uit dat uw domein example.com is, uw mailhost mail.example.com en het IP-adres 10.0.0.10. Maak in uw zone het volgende aan:
mail.example.com. A 10.0.0.10
mail.example.com. AAAA 2001:db8::10 ; only if you have IPv6
example.com. MX 10 mail.example.com.
example.com. TXT "v=spf1 mx -all"
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:postmaster@example.com"Het SPF-record geeft aan: "alleen mijn MX mag namens dit domein verzenden, weiger de rest". Start DMARC op p=none zodat u rapporten kunt monitoren zonder uw eigen e-mail te blokkeren; scherp dit aan naar p=quarantine en vervolgens p=reject zodra de alignment is bewezen. Twee records ontbreken nog bewust: DKIM, dat mailcow voor u genereert in stap 6, en PTR, dat u nu instelt in het paneel van uw provider.
Stel de PTR (reverse DNS) voor 10.0.0.10 in op mail.example.com, de exacte waarde van MAILCOW_HOSTNAME. Dit is het enige record dat de meeste mensen vergeten, en grote providers weigeren e-mail op basis hiervan. Als uw paneel geen rDNS-veld heeft, dien dan een supportticket in.
Stap 3, Docker installeren
mailcow vereist Docker Engine met de Compose v2-plugin. Gebruik het officiële installatiescript van Docker in plaats van het docker.io-pakket van Ubuntu, aangezien dit pakket geen Compose-plugin bevat:
curl -fsSL https://get.docker.com | sudo sh
sudo docker compose versionU hoort een Docker Compose version v2.x-regel te zien. Als docker compose version de melding docker: 'compose' is not a docker command geeft, is Docker Engine wel geïnstalleerd, maar de Compose-plugin niet. Installeer de plugin vanuit de repository van Docker, voer het bovenstaande script opnieuw uit, of volg onze handleiding over de basis van Docker Compose, waarin beide onderdelen vanuit de eigen apt-repository van Docker worden geconfigureerd.
Stap 4, mailcow klonen en de configuratie genereren
cd /opt
sudo git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
umask
sudo ./generate_config.shControleer of umask de waarde 0022 weergeeft; mailcow weigert te bouwen met een afwijkend bestandsmasker en een verse Ubuntu 24.04 root-shell geeft u standaard 0022. Het script vraagt vervolgens naar het enige dat er echt toe doet: de fully qualified hostname. Voer mail.example.com in; de waarde moet exact overeenkomen met uw A-record en PTR. Het script schrijft mailcow.conf, het enige omgevingsbestand dat de gehele stack uitleest. Open dit bestand als u de webpoorten (HTTP_PORT, HTTPS_PORT) wilt wijzigen of als u ClamAV op een kleine server wilt uitschakelen:
MAILCOW_HOSTNAME=mail.example.com
HTTP_PORT=80
HTTPS_PORT=443
SKIP_CLAMD=n # set to y to drop the virus scanner on a <2.5 GiB boxSKIP_FTS=y is de andere instelling voor een server met weinig RAM: full-text search is volgens de documentatie van mailcow de tweede grootste geheugenvreter. Het uitschakelen hiervan kost u enkel de mogelijkheid om in webmail op tekst in de body van e-mails te zoeken.
Laat HTTP_PORT=80 en HTTPS_PORT=443 ongewijzigd, tenzij een andere service op de host deze al in gebruik heeft. De ingebouwde ACME-client van mailcow heeft poort 80 nodig, bereikbaar vanaf het internet, om het certificaat te verkrijgen. Dit is de reden waarom u geen aparte nginx-plus-Certbot-opstelling op dezelfde server draait; mailcow geeft intern zijn eigen TLS-certificaten uit en vernieuwt deze ook zelf. Een tweede service die poort 80/443 bezet houdt, verstoort dit proces. Hetzelfde geldt voor elke andere service die een publieke webinterface vereist. Een opstelling zoals Halcyon die een Jellyfin-bibliotheek omvormt tot een videotheek uit de jaren 90, die een eigen reverse proxy op poort 443 verwacht, hoort daarom op een andere host thuis. De uitzondering is een service die nooit om een publieke webpoort vraagt: een zelfgehoste RustDesk-relay luistert alleen op zijn eigen bereik van 21115 tot 21119. Deze kan dus op dezelfde server draaien, mits u voldoende bandbreedte beschikbaar heeft.
Stap 5, De stack starten en inloggen
sudo docker compose pull
sudo docker compose up -d
sudo docker compose psHet pull-proces haalt ongeveer twee dozijn images op; geef dit enkele minuten de tijd. Wanneer docker compose ps aangeeft dat elke container running (of healthy) is, opent u https://mail.example.com in een browser. De standaard inloggegevens voor de beheerder zijn gebruikersnaam admin, wachtwoord moohoo. Wijzig dit wachtwoord onmiddellijk in de beheerinterface onder Access → Administrators. Als de browser de waarschuwing NET::ERR_CERT_AUTHORITY_INVALID geeft, is het ACME-certificaat nog niet uitgegeven. Raadpleeg de sectie over ACME-fouten hieronder voordat u aanneemt dat er iets defect is; een self-signed placeholder is normaal gedurende de eerste minuut of twee.
Stap 6, Een domein toevoegen, een mailbox aanmaken en DKIM publiceren
Open in de beheerinterface de pagina Mail Setup (Configuration → Mail Setup), klik onder het tabblad Domains op Add domain en voer example.com in. Maak vervolgens onder Mailboxes een mailbox aan via Add mailbox om you@example.com met een wachtwoord aan te maken. Dit is een werkende mailbox die al bereikbaar is via IMAP.
Nu de DKIM-sleutel. Ga naar Configuration → ARC/DKIM keys; mailcow heeft mogelijk al een sleutel gegenereerd toen u het domein toevoegde. Als dat niet zo is, genereer er daar een, kies het domein, behoud de selector dkim, kies 2048-bit en klik op Add. Kopieer de lange TXT-waarde die wordt getoond en publiceer deze als:
dkim._domainkey.example.com. TXT "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqh...long-key...QAB"De pagina Domains van mailcow bevat een DNS-knop die elk verwacht record weergeeft en met een groen vinkje of rood kruis aangeeft wat er daadwerkelijk is gepubliceerd. Gebruik dit als checklist en zorg dat elke rij groen is voordat u de afleverbaarheid test. Een rode DKIM-rij na publicatie betekent meestal dat de sleutel onjuist is gesplitst over TXT-chunks; een 2048-bit sleutel is langer dan de limiet van 255 tekens voor een enkele TXT-string. Plak deze daarom als één logische waarde en laat uw DNS-host de splitsing in chunks voor u afhandelen.
Stap 7, Test de afleverbaarheid en streef naar 10/10
Ga naar mail-tester.com, kopieer het willekeurige adres dat daar wordt getoond en stuur een bericht naar dit adres vanuit uw nieuwe mailbox. Log in op de SOGo webmail via https://mail.example.com/SOGo en verstuur het bericht vanaf daar. Klik vervolgens op "Then check your score".
Streef naar een score van 10/10. De meest voorkomende aftrekpunten en hun oorzaken:
- SPF niet correct, uw
MX/SPF-record ontbreekt of het verzendende IP-adres is niet opgenomen. Controleer het SPF TXT-record opnieuw. - DKIM-handtekening niet geverifieerd, het
dkim._domainkeyTXT-record ontbreekt, is nog aan het propageren of is beschadigd. Dit is de meest voorkomende fout. - Geen PTR / PTR-mismatch, de reverse DNS verwijst niet naar
mail.example.com. Los dit op bij uw provider. - Opgenomen in een blocklist, de reputatie van uw IP-adres uit het verleden. Verzoek om verwijdering van de lijst of vraag om een schoner IP-adres.
Verstuur geen echte e-mail naar Gmail of Outlook totdat de score 10/10 is. Een lage score in combinatie met een nieuw IP-adres zorgt er direct voor dat uw domein op de eerste dag wordt gemarkeerd.
Stap 8, Een echte e-mailclient verbinden
Stel Thunderbird, Apple Mail of uw telefoon in op de server met de volgende instellingen. De serverhost is mail.example.com voor alle clients:
- IMAP: poort 993, SSL/TLS (of 143 met STARTTLS)
- SMTP submission: poort 465, SSL/TLS (of 587 met STARTTLS)
- Gebruikersnaam: het volledige adres,
you@example.com - Wachtwoord: het wachtwoord van de mailbox dat u heeft ingesteld
Verstuur nooit client-e-mail via poort 25. Deze poort is uitsluitend bedoeld voor server-naar-server-verkeer. mailcow biedt daar geen geauthenticeerde verzending aan en een client die hierop is ingesteld, wordt geweigerd. Als een client de melding Relay access denied geeft, probeert deze te verzenden via poort 25 of zonder authenticatie; schakel over naar 465 of 587 met uw mailbox-inloggegevens.
Stap 9, Maak back-ups van wat er echt toe doet
mailcow levert een back-upscript dat snapshots maakt van elk stateful volume. Voer dit uit naar een externe schijf of een aangekoppelde externe locatie:
sudo MAILCOW_BACKUP_LOCATION=/opt/mailcow-backups \
./helper-scripts/backup_and_restore.sh backup allall legt zes onderdelen vast; het verlies van een van deze onderdelen betekent dataverlies: vmail (de daadwerkelijke mailboxen), crypt (de sleutels die vmail ontsleutelen, nutteloos zonder de data zelf), mysql (de MariaDB-database met domeinen, gebruikers, aliassen en instellingen), redis (wachtrij- en cachestatus), rspamd (aangeleerde spam/ham) en postfix (de mailwachtrij). Het script draait in een helper-container die gecomprimeerde archieven schrijft, waardoor back-ups consistent blijven terwijl de stack actief is. Automatiseer dit met een dagelijkse cron-job en voeg --delete-days 14 toe om oude sets op te schonen. Een cron-job die stopt met werken faalt zonder melding, dus stuur de exit-status van het script naar een plek waar u het daadwerkelijk opmerkt; een zelfgehoste ntfy-server accepteert een curl-commando van één regel vanuit dezelfde cron-entry en stuurt de foutmelding naar uw telefoon op de avond dat het gebeurt. Herstellen gebeurt met hetzelfde script met restore, waarmee de snapshots worden weergegeven en u kunt kiezen wat u wilt terugzetten. Een back-up die u nooit heeft getest, is een hoop, geen back-up; voer een test uit op een tijdelijke VPS.
Stap 10, Updates inplannen
mailcow wordt bijgewerkt via een eigen script. Dit script haalt nieuwe code op, voert migraties uit voor mailcow.conf, haalt vooraf images op en herstart containers in de juiste volgorde:
cd /opt/mailcow-dockerized
sudo ./update.sh --check # reports whether an update exists, changes nothing
sudo ./update.sh # applies itMaak eerst een back-up (Stap 9), aangezien een schema-migratie lastig ongedaan te maken is. Updates verschijnen regelmatig en bevatten beveiligingspatches voor daemons die direct verbonden zijn met het internet; laat een mailserver daarom niet maandenlang verouderen. Als een update ertoe leidt dat een container niet langer 'healthy' is, geeft sudo docker compose logs --tail=50 <service>-mailcow de naam aan van de daemon die niet correct is opgestart.
Een opmerking over hardening
mailcow draait een eigen netfilter-service (netfilter-mailcow) die IP-adressen blokkeert die de mail- en webmailpoorten bestoken, waardoor de mailomgeving standaard is beveiligd. Dit dekt echter niet de SSH-toegang op de host zelf; deze blijft blootgesteld en onderhevig aan brute-force-aanvallen. Combineer deze installatie daarom met Fail2ban voor het monitoren van het SSH-authenticatie-logbestand en gebruik uitsluitend inloggen met sleutels. Beveilig de mailcow admin-UI met een sterk wachtwoord en stel deze bij voorkeur niet direct bloot aan het openbare internet, of plaats deze achter een VPN.
Foutmodi, met de exacte strings
Mail komt in de wachtrij en wordt nooit afgeleverd. Voer sudo docker compose exec postfix-mailcow postqueue -p uit of lees de mailwachtrij in de beheerinterface; items blijven staan met de status deferred en de melding:
status=deferred (connect to gmail-smtp-in.l.google.com[142.250.x.x]:25: Connection timed out)Dit betekent dat uitgaande poort 25 door uw provider wordt geblokkeerd (Stap 1). Geen enkele configuratiewijziging lost dit op; open een ticket. Het is geen DNS- of TLS-probleem; de aanwijzing is het woord timed out in combinatie met een externe MX op poort 25.
Gmail markeert alles als spam of weigert de mail. Open het bericht in Gmail, kies "Origineel weergeven" en lees de authenticatieresultaten. dkim=fail of dkim=none betekent dat uw dkim._domainkey TXT-record ontbreekt, beschadigd is of nog niet is verspreid. Publiceer exact wat de ARC/DKIM-pagina toont en wacht de TTL af. spf=fail betekent dat de SPF/MX-records uw IP-adres niet dekken. Consistentie is cruciaal; één mislukte controle is voldoende om in de spammap te belanden.
Afgewezen door grote providers bij het verbinden. Bounces of Postfix-logs bevatten de PTR-afwijzing van Gmail:
550-5.7.25 [10.0.0.10] The IP address sending this message does not have a PTR
550-5.7.25 record setup, or the corresponding forward DNS entry does not match
550 5.7.25 the sending IP. As a policy, Gmail does not accept messages from IPs
550 5.7.25 with missing PTR records.De code 550 5.7.25 duidt op een ontbrekende of niet-overeenkomende reverse DNS. Stel de PTR voor uw IP-adres in op mail.example.com bij de provider (Stap 2). Het forward (A) en reverse (PTR) record moeten overeenstemmen en beide moeten verwijzen naar dezelfde hostnaam waarmee mailcow zich aan andere servers presenteert.
De browser toont een certificaatwaarschuwing die niet verdwijnt. De container acme-mailcow is er niet in geslaagd een geldig certificaat te verkrijgen. Controleer het logbestand:
sudo docker compose logs acme-mailcow | tail -n 40Een regel zoals Cannot validate any hostnames, skipping Let's Encrypt for 1 hour. of een mislukte challenge betekent dat poort 80 niet bereikbaar is vanaf het internet, of dat het A-record niet naar deze server wijst. Bevestig dat mail.example.com naar de server resolveert, open poort 80 en 443 in de host-firewall en zorg dat geen ander proces deze poorten bezet houdt. Nadat de oorzaak is verholpen, herstart u de client met sudo docker compose restart acme-mailcow in plaats van het uur wachttijd voor de back-off af te wachten.
FAQ
Is het zelf hosten van e-mail de moeite waard?
Als u streeft naar datasoevereiniteit, onbeperkte aliassen en volledige controle, dan biedt mailcow u een professionele stack voor de prijs van een VPS. De afleverbaarheid is echter een doorlopende taak: IP-reputatie, DNS-configuratie en het monitoren van blocklists stoppen nooit. Voor een bedrijfskritisch e-mailadres waarbij een dag in de spamfolder van een klant direct geld kost, is een beheerde provider de pragmatische keuze. Host zelf wanneer u controle verkiest boven gemak en bereid bent het onderhoud uit te voeren. Als uw voornaamste doel is om uw data van externe servers te halen, begin dan met een dienst waarvoor geen afleverbaarheid vereist is: een fotobibliotheek heeft geen last van spamfilters, en onze vergelijking tussen PhotoPrism en Immich behandelt de minimale RAM-vereisten en backup-commando's voor een dergelijke installatie op hetzelfde type VPS.
Hoe weet ik of uitgaande poort 25 is geblokkeerd?
Voer nc -vz -w 5 gmail-smtp-in.l.google.com 25 uit vanaf de server. "succeeded!" betekent dat de poort open is; een timed out na de pauze betekent dat uw provider de poort blokkeert. Dit is de meest voorkomende reden waarom een zelfgehoste server wel e-mail kan ontvangen maar niet kan versturen. De enige oplossing is dat uw provider de poort opent; lokale instellingen kunnen dit niet verhelpen.
Waarom belandt mijn e-mail nog steeds in de spamfolder van Gmail?
Dit wordt bijna altijd veroorzaakt door een defecte authenticatieketen. Gebruik "Origineel weergeven" (Show original) in Gmail en controleer op spf=pass, dkim=pass en dmarc=pass. Een dkim=fail wijst op een ontbrekend of onjuist dkim._domainkey TXT-record; een mismatch in de PTR-record of een nieuw IP-adres zonder verzendgeschiedenis heeft ook een negatieve invloed. Zorg eerst voor een 10/10 score op mail-tester.com en warm het IP-adres daarna langzaam op door het aantal berichten per dag geleidelijk te verhogen, in plaats van direct grote volumes te versturen.
Wat moet ik precies back-uppen?
Voer backup_and_restore.sh backup all uit en bewaar de volledige set buiten de server. Dit omvat vmail (de mailboxen), crypt (de sleutels voor ontsleuteling), de MariaDB-database (domeinen, gebruikers, aliassen, instellingen), Redis, de geleerde data van Rspamd en de Postfix-wachtrij. De crypt-volume wordt vaak vergeten; zonder deze is de vmail-backup onleesbare ciphertext. Test minimaal één keer een herstelprocedure op een testomgeving.
Kan ik mailcow draaien op een 2 GB VPS?
Niet op een comfortabele manier. generate_config.sh biedt aan om ClamAV uit te schakelen onder ongeveer 2,5 GiB, maar zelfs dan strijden Rspamd, ClamAV, Dovecot en MariaDB om het geheugen. Hierdoor zult u bij enige belasting te maken krijgen met swap-gebruik en OOM-kills (Out of Memory). Hanteer 6 GiB RAM plus 1 GiB swap als ondergrens voor een stabiele installatie voor één gebruiker, en schaal op naar 8 GiB zodra meer dan een paar mensen afhankelijk zijn van de dienst.