Instalacja Mailcow na VPS i konfiguracja DNS
Sprawdź port 25 przed instalacją mailcow-dockerized. Dowiedz się, jak uniknąć błędu Gmail 550 5.7.25 PTR poprzez poprawną konfigurację rekordów DNS.
Cel projektu
Pełny serwer pocztowy na własnym serwerze: SMTP do wysyłania i odbierania wiadomości, IMAP zapewniający synchronizację między telefonem a laptopem, klient webmail oraz filtr antyspamowy oceniający każdą wiadomość w obu kierunkach. Pakiet mailcow-dockerized zawiera Postfix, Dovecot, Rspamd, webmail SOGo, MariaDB, Redis oraz klienta ACME w ramach jednej stosu Docker Compose, co eliminuje trudności związane z instalacją oprogramowania. Konfiguracja zostanie zakończona w 30 minut.
Najtrudniejszym elementem jest konfiguracja środowiska. E-mail to jedyna usługa, w której internet wykazuje brak zaufania do nowych serwerów. Różnica między poprawnym działaniem a cichym odrzucaniem wiadomości przez Gmail sprowadza się do czterech rekordów DNS oraz jednego ustawienia reputacji IP, nad którym użytkownik może nie mieć pełnej kontroli. Przed wynajęciem serwera należy zapoznać się z poniższymi wymaganiami wstępnymi. Jeśli po ich lekturze uznasz, że proces budowania reputacji jest nieopłacalny, jest to uzasadniona decyzja — nasze zestawienie tego, co warto hostować samodzielnie w 2026 zawiera sekcję e-mail w kategorii „tylko jeśli podchodzisz do tego poważnie” właśnie z tych powodów.
Wymagania wstępne stanowią fundament projektu
Brak któregokolwiek z poniższych elementów spowoduje, że wysyłane wiadomości nie zostaną dostarczone. Poniższa lista została ułożona według częstotliwości występowania problemów:
Port wychodzący 25 musi być otwarty. Serwer przesyła wiadomości do Gmail oraz Microsoft poprzez TCP port 25. Wielu dostawców VPS i chmury blokuje port 25 dla ruchu wychodzącego domyślnie w celu walki ze spamem. Blokada ta nie generuje błędów podczas uruchamiania systemu; wszystkie usługi działają poprawnie, a wiadomości pozostają w kolejce. Należy przeprowadzić test przed instalacją. W przypadku blokady jedynym rozwiązaniem jest zgłoszenie do wsparcia technicznego z prośbą o otwarcie portu; niektórzy dostawcy robią to dla starszych kont, inni nigdy nie otwierają tego portu.
Czysty adres IP o dobrej reputacji. Adresy IP w usługach VPS są często reużywane i mogą znajdować się na listach blokujących (blocklists) z powodu spamu wysyłanego przez poprzednich użytkowników. Przed rozpoczęciem prac należy sprawdzić adres IP w serwisach takich jak Spamhaus lookup lub mxtoolbox. Adres IP na liście oznacza odrzucanie wiadomości, czego nie da się naprawić poprzez konfigurację oprogramowania.
Kontrola nad DNS oraz poprawny rekord PTR. Należy dodać odpowiednie rekordy w strefie domeny oraz skonfigurować reverse DNS (PTR) dla adresu IP serwera, tak aby wskazywał on na nazwę hosta poczty. Rekordy PTR rzadko są konfigurowane w panelu DNS domeny — są one zarządzane przez właściciela adresu IP, czyli w panelu sterowania dostawcy VPS lub poprzez zgłoszenie techniczne.
6 GiB RAM i 2 vCPU to minimalne zalecane parametry. Minimalne wymagania mailcow dla instalacji prywatnej to 6 GiB RAM oraz 1 GiB swap. Zaleca się 8 GiB RAM, gdy system obsługuje wielu użytkowników. Przy zasobach poniżej 2.5 GiB, generate_config.sh oferuje możliwość wyłączenia skanera wirusów ClamAV, aby zapobiec zabijaniu kontenerów przez mechanizm OOM killer. Na start należy przeznaczyć 20 GB na dysk SSD.
Nazwa DNS, a nie sam adres IP. Należy wybrać nazwę hosta, np. mail.example.com. Ta nazwa staje się MAILCOW_HOSTNAME, podmiotem certyfikatu TLS, celem rekordu PTR oraz bannerem SMTP. Należy zachować spójność nazwy we wszystkich konfiguracjach.
Krok 1 — Sprawdzenie dostępności portu wyjściowego 25
Należy wykonać tę czynność w pierwszej kolejności. Jeśli test zakończy się niepowodzeniem, dalsze działania nie przyniosą rezultatu. Z poziomu nowego VPS należy spróbować nawiązać połączenie SMTP z rzeczywistym serwerem pocztowym:
sudo apt update && sudo apt install -y netcat-openbsd
nc -vz -w 5 gmail-smtp-in.l.google.com 25Poprawne połączenie następuje natychmiast:
Connection to gmail-smtp-in.l.google.com (142.250.x.x) 25 port [tcp/smtp] succeeded!Zablokowany port powoduje zawieszenie połączenia na pełne pięć sekund, a następnie błąd:
nc: connect to gmail-smtp-in.l.google.com port 25 (tcp) timed out: Operation now in progressPrzekroczenie czasu oczekiwania (timeout) oznacza blokadę. Jest to filtr sieciowy po stronie dostawcy, a nie błąd lokalnego firewall'a, zatem zmiany lokalne nie rozwiążą problemu. Należy otworzyć zgłoszenie techniczne: "Please enable outbound TCP port 25 for my VPS at <IP>; I am running a legitimate mail server." Nie należy instalować mailcow, dopóki wynik nie będzie brzmiał "succeeded". Należy pamiętać, że port 25 dla ruchu przychodzącego (połączenia od innych serwerów) to oddzielna ścieżka i zazwyczaj jest on otwarty — dostawcy ograniczają ruch wychodzący.
Krok 2 — Skonfiguruj teraz rekordy DNS
Propagacja zmian DNS wymaga czasu, dlatego należy opublikować wszystkie możliwe rekordy przed instalacją. Przyjmij, że domena to example.com, host pocztowy to mail.example.com, a adres IP to 10.0.0.10. W strefie należy utworzyć:
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"Rekord SPF określa, że tylko serwer MX może wysyłać wiadomości dla tej domeny, a pozostałe należy odrzucać. Należy ustawić politykę DMARC na p=none, aby umożliwić monitorowanie raportów bez odrzucania własnych wiadomości; po potwierdzeniu zgodności należy zmienić politykę na p=quarantine, a następnie na p=reject. Celowo pominięto dwa rekordy: DKIM, który zostanie wygenerowany przez mailcow w Kroku 6, oraz PTR, który należy skonfigurować teraz w panelu dostawcy.
Ustaw rekord PTR (reverse DNS) dla 10.0.0.10 na mail.example.com — czyli dokładną wartość MAILCOW_HOSTNAME. Jest to rekord, o którym najczęściej zapominają użytkownicy, a który jest wymagany przez dużych dostawców. Jeśli panel nie posiada pola rDNS, należy otworzyć zgłoszenie techniczne.
Step 3 — Install Docker
mailcow wymaga Docker Engine wraz z wtyczką Compose v2. Należy użyć oficjalnego skryptu instalacyjnego Docker zamiast pakietu docker.io z repozytorium Ubuntu, ponieważ pakiet ten nie zawiera wtyczki Compose:
curl -fsSL https://get.docker.com | sudo sh
sudo docker compose versionNależy oczekiwać linii Docker Compose version v2.x. Jeśli docker compose version wyświetli docker: 'compose' is not a docker command, oznacza to, że Docker Engine został zainstalowany, ale brakuje wtyczki Compose. Należy zainstalować wtyczkę z repozytorium Docker — należy ponownie uruchomić powyższy skrypt lub skorzystać z naszego przewodnika po Docker Compose basics, który instaluje oba komponenty z oficjalnego repozytorium apt Docker.
Krok 4 — Klonowanie mailcow i generowanie konfiguracji
cd /opt
sudo git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
umask
sudo ./generate_config.shNajpierw sprawdź, czy umask wypisuje 0022 — mailcow nie przeprowadzi budowania przy nieprawidłowej masce plików, a czysty shell root w Ubuntu 24.040 posiada już 0022. Skrypt zada następnie jedyne istotne pytanie: w pełni kwalifikowaną nazwę hosta (FQDN). Wprowadź mail.example.com — wartość musi być identyczna z rekordem A oraz rekordem PTR. Skrypt utworzy mailcow.conf, czyli jedyny plik środowiskowy używany przez cały stos usług. Otwórz go, jeśli wymagana jest zmiana portów webowych (HTTP_PORT, HTTPS_PORT) lub wyłączenie ClamAV na maszynach o małych zasobach:
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 to kolejna opcja dla maszyn z małą ilością pamięci RAM: pełnotekstowe wyszukiwanie (full-text search) jest drugą najbardziej zasobochłonną funkcją wymienioną w dokumentacji mailcow; jej wyłączenie ogranicza jedynie możliwość przeszukiwania treści wiadomości w webmailu.
Pozostaw HTTP_PORT=80 oraz HTTPS_PORT=443 bez zmian, chyba że inne usługi na hoście już z nich korzystają — wbudowany klient ACME w mailcow wymaga dostępności portu 80 z internetu w celu pobrania certyfikatu. Z tego powodu nie należy uruchamiać osobnej konfiguracji nginx-plus-Certbot na tej samej maszynie; mailcow samodzielnie wystawia i odnawia własne certyfikaty TLS, a druga usługa zajmująca porty 80/443 uniemożliwi ten proces.
Step 5 — Uruchomienie stosu i logowanie
sudo docker compose pull
sudo docker compose up -d
sudo docker compose psPobieranie obejmuje około dwóch tuzinów obrazów; należy odczekać kilka minut. Gdy docker compose ps wyświetli wszystkie kontenery running (lub healthy), należy otworzyć https://mail.example.com w przeglądarce. Domyślne dane logowania administratora to użytkownik admin oraz hasło moohoo. Należy niezwłocznie zmienić to hasło w interfejsie administratora w sekcji Access → Administrators. Jeśli przeglądarka wyświetli ostrzeżenie NET::ERR_CERT_AUTHORITY_INVALID, oznacza to, że certyfikat ACME nie został jeszcze wystawiony — przed uznaniem błędu należy sprawdzić sekcję poniżej dotyczącą błędów ACME; wyświetlanie certyfikatu typu self-signed jest normalne przez pierwsze dwie minuty.
Krok 6 — Dodawanie domeny, skrzynki pocztowej oraz publikacja DKIM
W interfejsie administracyjnym należy otworzyć stronę Mail Setup (Configuration → Mail Setup). W zakładce Domains należy kliknąć Add domain i wpisać example.com. Następnie w sekcji Mailboxes należy wybrać Add mailbox, aby utworzyć you@example.com wraz z hasłem. Skrzynka będzie gotowa do pracy i dostępna przez protokół IMAP.
Następnie należy skonfigurować klucz DKIM. Należy przejść do Configuration → ARC/DKIM keys. System mailcow mógł już wygenerować klucz podczas dodawania domeny. Jeśli tak się nie stało, należy wygenerować nowy w tym miejscu — należy wybrać domenę, pozostawić selektor dkim, wybrać długość 2048-bit i kliknąć Add. Należy skopiować wyświetlony długi ciąg znaków TXT i opublikować go jako:
dkim._domainkey.example.com. TXT "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqh...long-key...QAB"Strona Domains w systemie mailcow posiada przycisk DNS, który wyświetla wszystkie wymagane rekordy oraz status ich publikacji (zielony znacznik lub czerwony krzyżyk). Należy używać tej listy jako kontroli — wszystkie wiersze muszą być zielone przed rozpoczęciem testów dostarczalności. Czerwony wiersz DKIM po publikacji zazwyczaj oznacza błędny podział klucza na fragmenty TXT. Klucz 2048-bitowy przekracza limit 255 znaków dla pojedynczego ciągu TXT, dlatego należy wkleić go jako jedną wartość logiczną, pozwalając serwerowi DNS na automatyczny podział na fragmenty.
Krok 7 — Testowanie dostarczalności i uzyskanie wyniku 10/10
Należy przejść na stronę mail-tester.com, skopiować wyświetlony losowy adres i wysłać na niego wiadomość ze swojego nowego konta — należy zalogować się do webmail SOGo pod adresem https://mail.example.com/SOGo i wysłać wiadomość stamtąd. Następnie należy kliknąć przycisk "Then check your score".
Należy dążyć do uzyskania wyniku 10/10. Typowe powody obniżenia punktacji:
- SPF not aligned — brakuje rekordu
MX/SPF lub adres IP nadawcy nie jest w nim uwzględniony. Należy ponownie sprawdzić rekord SPF TXT. - DKIM signature does not verify — rekord
dkim._domainkeyTXT nie istnieje, jest w trakcie propagacji lub jest błędnie sformatowany. Jest to najczęstszy błąd. - No PTR / PTR mismatch — reverse DNS nie rozwiązuje się do
mail.example.com. Należy to naprawić u dostawcy. - Listed on a blocklist — wynika z wcześniejszej reputacji adresu IP. Należy poprosić o usunięcie z listy lub o czystszy adres IP.
Nie należy wysyłać rzeczywistych wiadomości do Gmail lub Outlook, dopóki wynik nie wyniesie 10/10. Niski wynik połączony z nowym adresem IP powoduje oznaczenie domeny jako podejrzanej już pierwszego dnia.
Krok 8 — Połączenie z rzeczywistym klientem poczty
W programie Thunderbird, Apple Mail lub w telefonie należy skonfigurować serwer przy użyciu poniższych ustawień. Host serwera dla wszystkich usług to mail.example.com:
- IMAP: port 993, SSL/TLS (lub 143 z STARTTLS)
- SMTP submission: port 465, SSL/TLS (lub 587 z STARTTLS)
- Nazwa użytkownika: pełny adres,
you@example.com - Hasło: hasło do skrzynki pocztowej
Nie należy wysyłać poczty z klienta przez port 25 — port ten służy wyłącznie do komunikacji serwer-serwer. System mailcow nie oferuje tam uwierzytelnionej subskrypcji, a połączenie klienta na tym porcie zostanie odrzucone. Jeśli klient zgłasza błąd Relay access denied, próbuje wysłać wiadomość przez port 25 lub bez uwierzytelnienia; należy zmienić port na 465 lub 587 i użyć danych uwierzytelniających skrzynki.
Krok 9 — Wykonanie kopii zapasowej kluczowych danych
mailcow dostarcza skrypt do tworzenia kopii zapasowych, który wykonuje migawki wszystkich wolumenów stanowych. Należy uruchomić go na zewnętrznym dysku lub zamontowanym zasobie zdalnym:
sudo MAILCOW_BACKUP_LOCATION=/opt/mailcow-backups \
./helper-scripts/backup_and_restore.sh backup allall obejmuje sześć elementów, których utrata powoduje utratę danych: vmail (skrzynki pocztowe), crypt (klucze deszyfrujące vmail — niezbędne do odczytu danych), mysql (baza MariaDB przechowująca domeny, użytkowników, aliasy i ustawienia), redis (stan kolejek i pamięci cache), rspamd (wyuczone wzorce spam/ham) oraz postfix (kolejka pocztowa). Skrypt działa wewnątrz kontenera pomocniczego i tworzy skompresowane archiwa, co zapewnia spójność kopii nawet podczas pracy stosu usług. Proces należy zautomatyzować za pomocą zadania cron uruchamianego co noc, dodając flagę --delete-days 14 w celu usuwania starych zestawów. Przywracanie danych odbywa się za pomocą tego samego skryptu z flagą restore, która wyświetla listę migawek i umożliwia wybór danych do przywrócenia. Kopia zapasowa, która nie została przetestowana, nie gwarantuje bezpieczeństwa — należy przeprowadzić próbę przywracania na osobnym VPS.
Step 10 — Aktualizacja harmonogramowa
mailcow aktualizuje się za pomocą własnego skryptu. Skrypt pobiera nowy kod, przeprowadza migrację mailcow.conf, pobiera obrazy (prefetch) i restartuje kontenery w następującej kolejności:
cd /opt/mailcow-dockerized
sudo ./update.sh --check # reports whether an update exists, changes nothing
sudo ./update.sh # applies itNajpierw należy wykonać kopię zapasową (Step 9), ponieważ migracji schematu nie można łatwo cofnąć. Aktualizacje są wydawane często i zawierają poprawki bezpieczeństwa dla usług wystawionych na sieć. Nie należy dopuszczać do braku aktualizacji serwera pocztowego przez wiele miesięcy. Jeśli aktualizacja spowoduje błąd stanu kontenera (unhealthy), sudo docker compose logs --tail=50 <service>-mailcow wskaże nazwę usługi, która nie uruchomiła się poprawnie.
Uwaga dotycząca utwardzania systemu
mailcow uruchamia własną usługę netfilter (netfilter-mailcow), która blokuje adresy IP wykonujące liczne próby połączeń z portami poczty oraz webmaila. Dzięki temu ochrona poczty jest aktywna domyślnie. Nie obejmuje to jednak protokołu SSH na samym hoście, który pozostaje wystawiony na ataki typu brute-force. Należy połączyć tę instalację z rozwiązaniem Fail2ban monitorującym logi uwierzytelniania SSH oraz logowaniem wyłącznie za pomocą kluczy. Panel administracyjny mailcow powinien być zabezpieczony silnym hasłem i, najlepiej, znajdować się poza publicznym internetem lub za siecią VPN.
Tryby awarii i dokładne komunikaty
Kolejki mailowe i brak dostarczania wiadomości. Należy uruchomić sudo docker compose exec postfix-mailcow postqueue -p lub sprawdzić kolejkę mailową w interfejsie admin UI; wpisy o statusie deferred zawierają:
status=deferred (connect to gmail-smtp-in.l.google.com[142.250.x.x]:25: Connection timed out)Oznacza to blokadę portu 25 dla ruchu wychodzącego przez dostawcę (Krok 1). Błąd nie wynika z konfiguracji — należy otworzyć zgłoszenie techniczne. Przyczyną nie jest DNS ani TLS; wskaźnikiem jest fraza timed out przy zdalnym rekordzie MX na porcie 25.
Gmail oznacza wszystkie wiadomości jako spam lub je odrzuca. Należy otworzyć wiadomość w Gmail, wybrać "Pokaż oryginał" i sprawdzić wyniki uwierzytelniania. dkim=fail lub dkim=none oznacza, że rekord dkim._domainkey TXT jest brakujący, błędny lub nie został jeszcze rozpropagowany — należy ponownie opublikować dokładnie te dane, które widnieją na stronie ARC/DKIM, i odczekać na wygaśnięcie TTL. spf=fail oznacza, że rekordy SPF/MX nie obejmują danego adresu IP. Kluczowa jest zgodność (alignment); pojedynczy nieudany test wystarczy, aby wiadomość trafiła do spamu.
Odrzucenie przez dużych dostawców podczas połączenia. Komunikaty o błędach lub logi Postfix zawierają błąd PTR od 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.Kod 550 5.7.25 oznacza brakujący lub niezgodny reverse DNS. Należy ustawić rekord PTR dla adresu IP na mail.example.com u dostawcy (Krok 2). Rekordy Forward (A) oraz reverse (PTR) muszą być zgodne; oba muszą wskazywać na tę samą nazwę hosta, którą mailcow podaje innym serwerom.
Przeglądarka wyświetla ostrzeżenie o certyfikacie, które nie znika. Kontener acme-mailcow nie uzyskał poprawnego certyfikatu. Należy sprawdzić log:
sudo docker compose logs acme-mailcow | tail -n 40Linia taka jak Cannot validate any hostnames, skipping Let's Encrypt for 1 hour. lub błąd wyzwania (challenge failure) oznacza, że port 80 jest nieosiągalny z internetu lub rekord A nie wskazuje na ten serwer. Należy potwierdzić, że mail.example.com rozwiązuje się na ten serwer, otworzyć porty 80 i 443 w firewallu hosta oraz upewnić się, że żadna inna usługa nie zajmuje tych portów. Po usunięciu przyczyny należy zrestartować klienta za pomocą sudo docker compose restart acme-mailcow, zamiast czekać na zakończenie godzinowego okresu wyczekiwania (back-off).
FAQ
Czy self-hosting poczty e-mail jest opłacalny?
Tak, jeśli wymagana jest własność danych, nieograniczona liczba aliasów oraz pełna kontrola — mailcow zapewnia profesjonalny stos technologiczny w cenie VPS. Należy jednak pamiętać o konieczności ciągłego zarządzania dostarczalnością: monitorowanie reputacji IP, zgodności DNS oraz list blokad (blocklists) jest procesem ciągłym. W przypadku krytycznych adresów biznesowych, gdzie trafienie do spamu generuje straty, bardziej pragmatycznym rozwiązaniem jest dostawca zarządzany. Self-hosting jest zalecany, gdy priorytetem jest kontrola nad wygodą i gdy użytkownik jest gotowy na samodzielną administrację.
Jak sprawdzić, czy port wychodzący 25 jest blokowany?
Należy uruchomić nc -vz -w 5 gmail-smtp-in.l.google.com 25 z serwera. Komunikat "succeeded!" oznacza, że port jest otwarty; komunikat timed out po pauzie oznacza blokadę ze strony dostawcy. Jest to najczęstsza przyczyna sytuacji, w której serwer własny może odbierać wiadomości, ale nie może ich wysyłać. Jedynym rozwiązaniem jest odblokowanie portu przez dostawcy — lokalne zmiany konfiguracji nie pomogą.
Dlaczego moje wiadomości trafiają do spamu w Gmail?
Przyczyną jest najczęściej błędny łańcuch uwierzytelniania. Należy użyć funkcji "Pokaż oryginał" w Gmail i sprawdzić rekordy spf=pass, dkim=pass oraz dmarc=pass. Wynik dkim=fail wskazuje na brakujący lub błędny rekord TXT dkim._domainkey. Problemem może być również niezgodność rekordu PTR lub brak historii wysyłki nowego adresu IP. Najpierw należy uzyskać wynik 10/10 w serwisie mail-tester.com, a następnie stopniowo zwiększać wolumen wysyłanych wiadomości (tzw. IP warming), zamiast wysyłać dużą liczbę maili pierwszego dnia.
Co dokładnie należy tworzyć kopie zapasowe?
Należy uruchomić backup_and_restore.sh backup all i przechowywać cały zestaw danych poza serwerem. Backup obejmuje vmail (skrzynki pocztowe), crypt (klucze deszyfrujące), bazę danych MariaDB (domeny, użytkownicy, aliasy, ustawienia), Redis, dane wyuczone Rspamd oraz kolejkę Postfix. Najczęściej pomijanym elementem jest wolumen crypt — bez niego kopia vmail pozostaje nieczytelnym szyfrogramem. Należy co najmniej raz przetestować proces przywracania danych na czystym systemie.
Czy można uruchomić mailcow na VPS z 2 GB RAM?
Nie jest to zalecane. generate_config.sh sugeruje wyłączenie ClamAV przy zasobach poniżej około 2.5 GiB. Nawet wtedy procesy Rspamd, ClamAV, Dovecot oraz MariaDB rywalizują o pamięć, co przy większym obciążeniu prowadzi do wykorzystania swapu i błędów OOM (Out of Memory). Minimalna konfiguracja dla stabilnej instalacji dla jednego użytkownika to 6 GiB RAM oraz 1 GiB swap. Należy przejść na 8 GiB, gdy liczba użytkowników wzrośnie.