SSD Nodes Learn
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-07-23

cách cài mailcow trên VPS để Gmail không chặn

Kiểm tra port 25 trước khi cài mailcow để tránh lỗi queue. Hướng dẫn cấu hình DNS để không bị Gmail từ chối lỗi 550 5.7.25 PTR khi gửi thư.

Những gì bạn sẽ xây dựng

Một mail server hoàn chỉnh trên VPS riêng của bạn: SMTP để gửi và nhận thư, IMAP để đồng bộ hóa điện thoại và laptop, một webmail client, và một spam filter để chấm điểm mọi tin nhắn ở cả hai chiều. mailcow-dockerized đóng gói Postfix, Dovecot, Rspamd, SOGo webmail, MariaDB, Redis và một ACME client vào trong một Docker Compose stack, nên phần cài đặt phần mềm không phải là phần khó nhất. Bạn sẽ chạy được nó trong vòng nửa tiếng.

Phần khó nhất là mọi thứ xung quanh nó. Email là dịch vụ duy nhất mà phần còn lại của internet luôn nghi ngờ một server mới tinh. Khoảng cách giữa việc "nó hoạt động" và việc "Gmail âm thầm xóa mọi tin nhắn" nằm ở bốn bản ghi DNS và một thiết lập IP-reputation mà bạn có thể không kiểm soát hoàn toàn được. Hãy đọc các điều kiện tiên quyết bên dưới trước khi thuê bất kỳ dịch vụ nào. Nếu sau khi đọc, bạn thấy việc xử lý reputation quá tốn công sức, đó là một quyết định hợp lý — danh sách những thứ thực sự đáng để tự host vào năm 2026 của chúng tôi liệt kê email trong mục "chỉ khi bạn thực sự quyết tâm" vì chính những lý do này.

Các điều kiện tiên quyết CHÍNH LÀ dự án

Thiếu bất kỳ điều kiện nào dưới đây, bạn sẽ gửi mail mà không bao giờ tới nơi. Dưới đây là danh sách theo thứ tự mức độ gây lỗi phổ biến nhất:

Cổng outbound 25 phải được mở. Server của bạn gửi mail tới Gmail và Microsoft qua TCP port 25. Rất nhiều VPS và cloud provider chặn outbound 25 theo mặc định để chống spam, và việc chặn này diễn ra âm thầm — không có lỗi khi boot, mọi thứ trông vẫn bình thường, nhưng mail chỉ nằm mãi trong queue. Hãy kiểm tra trước khi cài đặt bất cứ thứ gì. Nếu bị chặn, cách duy nhất là gửi support ticket yêu cầu provider mở cổng; một số nơi sẽ mở cho các tài khoản lâu năm, một số nơi thì không bao giờ.

IP sạch và có reputation tốt. Các IP VPS được tái sử dụng thường đã nằm trong blocklist do spam từ người dùng trước đó. Hãy kiểm tra IP của bạn tại các dịch vụ như Spamhaus lookup hoặc mxtoolbox trước khi bắt đầu. Một IP nằm trong blocklist sẽ khiến mail bị từ chối mà bạn không thể dùng code để xử lý được.

Quyền kiểm soát DNS và bản ghi PTR chính xác. Bạn cần thêm các bản ghi vào zone của domain, và bạn cần reverse DNS (PTR) cho IP của server để trỏ ngược về mail hostname của bạn. PTR hầu như không bao giờ được thiết lập trong DNS panel — nó thuộc quyền quản lý của bên sở hữu IP, vì vậy nó được thiết lập trong control panel của VPS provider hoặc thông qua ticket.

6 GiB RAM và 2 vCPU là mức tối thiểu để chạy ổn định. Mức tối thiểu của chính mailcow là 6 GiB RAM cộng với 1 GiB swap cho một bản cài đặt riêng tư, và khuyên dùng 8 GiB khi có một vài người dùng sử dụng. Dưới khoảng 2.5 GiB, generate_config.sh sẽ đề xuất tắt virus scanner ClamAV để kernel không bắt đầu kill các container. Hãy cấp cho nó 20 GB SSD để bắt đầu.

Một DNS name, không phải chỉ là IP trống. Hãy chọn một hostname như mail.example.com. Cái tên duy nhất đó sẽ trở thành MAILCOW_HOSTNAME, là subject của TLS certificate, là mục tiêu của PTR, và là SMTP banner của bạn. Hãy giữ nó nhất quán ở mọi nơi.

Bước 1 — Kiểm tra xem port 25 outbound đã mở chưa

Hãy làm việc này đầu tiên. Mọi bước tiếp theo sẽ vô ích nếu bước này thất bại. Từ VPS mới, hãy thử thiết lập kết nối SMTP với một mail server thực tế:

sudo apt update && sudo apt install -y netcat-openbsd
nc -vz -w 5 gmail-smtp-in.l.google.com 25

Nếu thành công, kết quả sẽ trả về ngay lập tức:

Connection to gmail-smtp-in.l.google.com (142.250.x.x) 25 port [tcp/smtp] succeeded!

Nếu port bị chặn, lệnh sẽ treo trong suốt 5 giây rồi mới báo lỗi:

nc: connect to gmail-smtp-in.l.google.com port 25 (tcp) timed out: Operation now in progress

Lỗi timeout đó chính là do bị chặn. Đây là bộ lọc mạng từ phía nhà cung cấp, không phải do firewall của bạn, nên không có thay đổi local nào có thể khắc phục được. Hãy mở ticket hỗ trợ: "Please enable outbound TCP port 25 for my VPS at <IP>; I am running a legitimate mail server." Đừng cài đặt mailcow cho đến khi nhận được phản hồi "succeeded". Lưu ý rằng port 25 inbound (các server khác kết nối đến bạn) là một luồng khác và thường luôn mở — nhà cung cấp thường chỉ giới hạn port 25 outbound.

Bước 2 — Thiết lập các bản ghi DNS ngay bây giờ

Thay đổi DNS cần thời gian để propagate, vì vậy hãy publish mọi thứ có thể trước khi cài đặt. Giả sử domain của bạn là example.com, mail host là mail.example.com, và IP là 10.0.0.10. Trong zone của bạn, hãy tạo:

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"

Bản ghi SPF có nội dung "chỉ MX của tôi mới được phép gửi mail cho domain này, reject các nguồn còn lại". Hãy bắt đầu DMARC ở mức p=none để bạn có thể theo dõi report mà không bị bounce mail của chính mình; sau đó thắt chặt lên p=quarantine rồi p=reject khi đã xác nhận được alignment. Vẫn còn hai bản ghi được cố ý để trống: DKIM, cái mà mailcow sẽ tự generate cho bạn ở Bước 6, và PTR, cái mà bạn cần thiết lập ngay bây giờ trong panel của nhà cung cấp.

Thiết lập PTR (reverse DNS) cho 10.0.0.10 thành mail.example.com — giá trị chính xác của MAILCOW_HOSTNAME. Đây là bản ghi duy nhất mà nhiều người hay quên, và các nhà cung cấp lớn sẽ reject nếu thiếu nó. Nếu panel của bạn không có trường rDNS, hãy raise một ticket.

Bước 3 — Cài đặt Docker

mailcow cần Docker Engine kèm theo plugin Compose v2. Bạn nên dùng script cài đặt chính thức của Docker thay vì dùng package docker.io của Ubuntu, vì package này không đi kèm plugin Compose:

curl -fsSL https://get.docker.com | sudo sh
sudo docker compose version

Bạn sẽ thấy một dòng Docker Compose version v2.x. Nếu docker compose version in ra docker: 'compose' is not a docker command, nghĩa là Docker Engine đã được cài đặt nhưng thiếu plugin Compose. Hãy cài đặt plugin từ repository của Docker — chạy lại script ở trên, hoặc xem hướng dẫn cơ bản về Docker Compose của chúng tôi, hướng dẫn này sẽ cài đặt cả hai từ apt repository của chính Docker.

Bước 4 — Clone mailcow và tạo config

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

Hãy kiểm tra xem umask có in ra 0022 hay không — mailcow sẽ từ chối build nếu file mask không khớp, và một shell root trên Ubuntu 24.04 mới sẽ có sẵn 0022. Script sau đó sẽ hỏi thông tin quan trọng nhất: fully qualified hostname. Hãy nhập mail.example.com — giá trị này phải khớp chính xác với A record và PTR của bạn. Script sẽ tạo ra mailcow.conf, đây là file environment duy nhất mà toàn bộ stack sử dụng. Hãy mở file này nếu bạn cần đổi web ports (HTTP_PORT, HTTPS_PORT) hoặc tắt ClamAV trên các máy cấu hình thấp:

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 box

SKIP_FTS=y là một tùy chọn khác cho máy có RAM thấp: full-text search là thành phần ngốn RAM thứ hai mà tài liệu của mailcow có nhắc tới, và nếu tắt nó, bạn sẽ mất tính năng tìm kiếm nội dung văn bản trong webmail.

Hãy để nguyên HTTP_PORT=80HTTPS_PORT=443 trừ khi máy host đã có dịch vụ khác đang sử dụng chúng — ACME client tích hợp của mailcow cần port 80 có thể truy cập được từ internet để lấy certificate. Đây là lý do tại sao bạn không nên chạy một thiết lập nginx-plus-Certbot riêng biệt trên cùng một máy; mailcow tự cấp phát và gia hạn TLS nội bộ, và một dịch vụ thứ hai chiếm dụng port 80/443 sẽ làm hỏng quy trình này.

Bước 5 — Khởi chạy stack và đăng nhập

sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps

Quá trình pull sẽ tải về khoảng hai mươi mấy images; hãy đợi vài phút. Khi docker compose ps hiển thị mọi container ở trạng thái running (hoặc healthy), hãy mở https://mail.example.com trên trình duyệt. Tài khoản admin mặc định là username admin, password moohoo. Hãy đổi password ngay lập tức trong giao diện admin tại mục Access → Administrators. Nếu trình duyệt cảnh báo NET::ERR_CERT_AUTHORITY_INVALID, có nghĩa là certificate ACME chưa được cấp — hãy kiểm tra lỗi ACME ở phần dưới trước khi kết luận hệ thống bị lỗi; việc hiển thị một placeholder tự ký (self-signed) là bình thường trong một hoặc hai phút đầu.

Bước 6 — Thêm domain, mailbox và publish DKIM

Trong admin UI, mở trang Mail Setup (Configuration → Mail Setup), tại tab Domains, nhấn Add domain và nhập example.com. Sau đó, tại mục Mailboxes, nhấn Add mailbox để tạo you@example.com kèm mật khẩu. Mailbox này đã có thể sử dụng ngay qua giao thức IMAP.

Tiếp theo là DKIM key. Truy cập Configuration → ARC/DKIM keys; mailcow có thể đã tự tạo key khi bạn thêm domain, nếu chưa, hãy tạo mới tại đó — chọn domain, giữ nguyên selector dkim, chọn 2048-bit và nhấn Add. Copy giá trị TXT dài mà hệ thống hiển thị và publish dưới dạng:

dkim._domainkey.example.com.  TXT  "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqh...long-key...QAB"

Trang Domains của mailcow có nút DNS liệt kê tất cả các record cần thiết và hiển thị dấu tích xanh hoặc dấu X đỏ cho các record đã được publish thực tế. Hãy dùng nó như một checklist — đảm bảo mọi dòng đều có màu xanh trước khi kiểm tra khả năng gửi nhận thư. Nếu dòng DKIM hiển thị màu đỏ sau khi đã publish, thường là do key bị chia nhỏ các đoạn TXT không đúng cách; một key 2048-bit sẽ dài hơn giới hạn 255 ký tự của một chuỗi TXT đơn lẻ, vì vậy bạn hãy paste nó dưới dạng một giá trị logic duy nhất và để DNS host tự chia thành các đoạn cho bạn.

Bước 7 — Kiểm tra khả năng gửi thư và đạt điểm 10/10

Truy cập mail-tester.com, copy địa chỉ ngẫu nhiên mà nó hiển thị, sau đó gửi một tin nhắn từ mailbox mới của bạn — hãy đăng nhập vào SOGo webmail tại https://mail.example.com/SOGo để gửi. Sau đó nhấn "Then check your score".

Mục tiêu là đạt 10/10. Các lỗi thường gặp và nguyên nhân:

  • SPF không khớp (not aligned) — bản ghi MX/SPF bị thiếu hoặc IP gửi thư không nằm trong danh sách cho phép. Hãy kiểm tra lại SPF TXT.
  • Chữ ký DKIM không xác thực được — thiếu bản ghi dkim._domainkey TXT, bản ghi đang trong quá trình cập nhật (propagating), hoặc bị sai định dạng. Đây là lỗi phổ biến nhất.
  • Không có PTR / PTR không khớp — reverse DNS không phân giải về mail.example.com. Hãy xử lý tại nhà cung cấp.
  • Nằm trong blocklist — do reputation trước đó của IP. Hãy yêu cầu gỡ bỏ (delisting) hoặc yêu cầu một IP sạch hơn.

Đừng gửi mail thật đến Gmail hay Outlook cho đến khi đạt điểm 10/10. Điểm thấp kết hợp với một IP mới là cách nhanh nhất khiến domain của bạn bị đánh dấu (flagged) ngay từ ngày đầu tiên.

Bước 8 — Kết nối mail client thực tế

Hãy cấu hình Thunderbird, Apple Mail hoặc điện thoại của bạn theo các thiết lập sau. Server host cho tất cả các loại là mail.example.com:

  • IMAP: port 993, SSL/TLS (hoặc 143 với STARTTLS)
  • SMTP submission: port 465, SSL/TLS (hoặc 587 với STARTTLS)
  • Username: địa chỉ đầy đủ, you@example.com
  • Password: mật khẩu mailbox bạn đã thiết lập

Đừng bao giờ gửi mail từ client qua port 25 — port đó chỉ dành cho server-to-server, mailcow không hỗ trợ authenticated submission tại đó, và client kết nối vào sẽ bị từ chối. Nếu client báo lỗi Relay access denied, có nghĩa là nó đang cố gắng gửi qua port 25 hoặc không có authentication; hãy chuyển sang port 465 hoặc 587 kèm theo thông tin đăng nhập mailbox của bạn.

Bước 9 — Sao lưu những dữ liệu thực sự quan trọng

mailcow đi kèm một script sao lưu giúp snapshot mọi volume có lưu trữ trạng thái (stateful volume). Hãy chạy nó vào một ổ đĩa ngoài hoặc một mount point từ xa:

sudo MAILCOW_BACKUP_LOCATION=/opt/mailcow-backups \
  ./helper-scripts/backup_and_restore.sh backup all

all sẽ capture sáu thành phần, nếu mất bất kỳ thành phần nào cũng sẽ mất dữ liệu: vmail (các mailbox thực tế), crypt (các key để decrypt vmail — sẽ vô dụng nếu thiếu nó), mysql (MariaDB chứa domains, users, aliases và settings), redis (trạng thái queue và cache), rspamd (dữ liệu học về spam/ham), và postfix (mail queue). Script chạy bên trong một helper container để ghi các file archive đã nén, giúp bản backup luôn nhất quán ngay cả khi stack đang hoạt động. Hãy tự động hóa nó bằng một cron job hàng đêm, và thêm --delete-days 14 để xóa các bản backup cũ. Việc restore cũng sử dụng script này với tham số restore, nó sẽ liệt kê các snapshot và cho phép bạn chọn dữ liệu cần khôi phục. Một bản backup mà bạn chưa từng test-restore thì chỉ là hy vọng, không phải là backup — hãy chạy thử một lần (dry run) trên một VPS trống.

Bước 10 — Cập nhật theo lịch trình

mailcow cập nhật thông qua script riêng. Script này sẽ kéo code mới, migrate mailcow.conf, prefetch images, và restart các container theo thứ tự sau:

cd /opt/mailcow-dockerized
sudo ./update.sh --check   # reports whether an update exists, changes nothing
sudo ./update.sh           # applies it

Hãy backup trước (Bước 9), vì việc rollback schema migration rất khó khăn. Các bản cập nhật được phát hành thường xuyên và bao gồm các bản vá bảo mật cho các daemon kết nối internet, vì vậy đừng để mail server không được cập nhật trong nhiều tháng. Nếu một bản cập nhật khiến container ở trạng thái unhealthy, sudo docker compose logs --tail=50 <service>-mailcow sẽ chỉ ra daemon nào không khởi động lại được.

Lưu ý về hardening

mailcow chạy dịch vụ netfilter riêng (netfilter-mailcow) để ban các IP liên tục tấn công các port mail và webmail, nên phần mail đã được bảo vệ sẵn. Tuy nhiên, thiết lập này không bao gồm SSH trên chính host, nơi vẫn đang bị lộ và vẫn bị brute-force — bạn nên kết hợp bản build này với Fail2ban theo dõi log SSH auth và chỉ cho phép đăng nhập bằng key. Hãy đặt mailcow admin UI dưới một password mạnh, và lý tưởng nhất là không để nó lộ trên internet công cộng hoặc đặt sau một VPN.

Các lỗi thường gặp và chuỗi thông báo chính xác

Mail queue bị kẹt và không gửi được. Chạy lệnh sudo docker compose exec postfix-mailcow postqueue -p, hoặc kiểm tra mail queue trên admin UI; các entry sẽ ở trạng thái deferred với thông báo:

status=deferred (connect to gmail-smtp-in.l.google.com[142.250.x.x]:25: Connection timed out)

Lỗi này do nhà cung cấp đã chặn port 25 outbound (Bước 1). Không có cấu hình nào sửa được lỗi này — hãy mở ticket hỗ trợ. Đây không phải lỗi DNS hay TLS; dấu hiệu nhận biết là từ timed out khi kết nối với remote MX trên port 25.

Gmail đánh dấu tất cả là spam, hoặc trả về mail (bounce). Mở email trong Gmail, chọn "Show original", và kiểm tra phần auth results. dkim=fail hoặc dkim=none nghĩa là bản ghi dkim._domainkey TXT của bạn đang bị thiếu, sai định dạng, hoặc chưa được cập nhật (propagate) — hãy cấu hình chính xác như trang ARC/DKIM hiển thị và đợi hết thời gian TTL. spf=fail nghĩa là các bản ghi SPF/MX không bao gồm IP của bạn. Sự đồng nhất (alignment) là quan trọng nhất; chỉ cần một check thất bại là mail sẽ bị vào spam.

Bị các nhà cung cấp lớn từ chối khi kết nối. Các thông báo bounce hoặc log của Postfix sẽ hiển thị lỗi PTR rejection từ 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.

550 5.7.25 nghĩa là thiếu hoặc sai lệch reverse DNS. Hãy thiết lập PTR cho IP của bạn thành mail.example.com tại nhà cung cấp (Bước 2). Bản ghi Forward (A) và reverse (PTR) phải khớp nhau, và cả hai phải cùng trỏ về một hostname mà mailcow dùng để giao tiếp với các server khác.

Trình duyệt báo lỗi chứng chỉ (certificate warning) không hết. Container acme-mailcow không lấy được cert thật. Kiểm tra log của nó:

sudo docker compose logs acme-mailcow | tail -n 40

Một dòng như Cannot validate any hostnames, skipping Let's Encrypt for 1 hour. hoặc lỗi challenge nghĩa là port 80 không thể truy cập được từ internet, hoặc bản ghi A không trỏ về server này. Hãy xác nhận mail.example.com trỏ về đúng máy chủ, mở port 80 và 443 trên firewall của host, và đảm bảo không có dịch vụ nào khác đang chiếm dụng các port này. Sau khi sửa lỗi, hãy restart client bằng lệnh sudo docker compose restart acme-mailcow thay vì ngồi đợi cơ chế back-off kéo dài cả tiếng đồng hồ.

FAQ

Tự host email có thực sự đáng không?

Nếu bạn muốn sở hữu dữ liệu, dùng không giới hạn alias và có toàn quyền kiểm soát, thì câu trả lời là có — mailcow cung cấp một stack chuyên nghiệp với chi phí chỉ bằng một VPS. Tuy nhiên, việc duy trì khả năng deliverability là một công việc không hồi kết: bạn phải liên tục theo dõi IP reputation, DNS alignment và blocklist. Đối với các địa chỉ email quan trọng của doanh nghiệp mà việc bị rơi vào spam dù chỉ một ngày cũng gây thiệt hại, thì sử dụng nhà cung cấp dịch vụ (managed provider) là lựa chọn thực tế hơn. Hãy tự host khi bạn ưu tiên quyền kiểm soát hơn sự tiện lợi và bạn thực sự có thời gian để quản lý nó.

Làm sao để biết port 25 outbound có bị chặn không?

Chạy lệnh nc -vz -w 5 gmail-smtp-in.l.google.com 25 từ server. Nếu nhận được thông báo "succeeded!" nghĩa là port đang mở; nếu nhận được timed out sau một khoảng chờ nghĩa là nhà cung cấp của bạn đang chặn port này. Đây là lý do phổ biến nhất khiến một server tự host có thể nhận mail nhưng không thể gửi mail, và cách duy nhất để khắc phục là yêu cầu nhà cung cấp mở port — không có cài đặt local nào có thể thay đổi được việc này.

Tại sao mail của tôi vẫn bị rơi vào spam của Gmail?

Hầu hết các trường hợp là do chuỗi xác thực (authentication chain) bị lỗi. Hãy dùng tính năng "Show original" trong Gmail và kiểm tra spf=pass, dkim=pass, và dmarc=pass. Một lỗi dkim=fail cho thấy bạn đang thiếu hoặc cấu hình sai dkim._domainkey TXT record; việc sai lệch PTR hoặc dùng IP mới chưa có lịch sử gửi mail cũng là nguyên nhân. Hãy đảm bảo đạt điểm 10/10 trên mail-tester.com trước, sau đó thực hiện warm up IP một cách chậm rãi — bắt đầu với vài email mỗi ngày rồi tăng dần — thay vì gửi số lượng lớn ngay ngày đầu tiên.

Tôi chính xác cần phải backup những gì?

Chạy lệnh backup_and_restore.sh backup all và lưu trữ toàn bộ tập tin này ở ngoài server. Lệnh này sẽ backup vmail (các mailbox), crypt (các key để giải mã mail), database MariaDB (domains, users, aliases, settings), Redis, dữ liệu học của Rspamd, và Postfix queue. Volume crypt là phần mà mọi người hay bỏ qua — nếu thiếu nó, bản backup vmail sẽ chỉ là các ký tự mã hóa không thể đọc được. Hãy thử khôi phục (restore) trên một máy ảo tạm thời ít nhất một lần.

Tôi có thể chạy mailcow trên VPS 2 GB không?

Không nên. generate_config.sh sẽ đề xuất tắt ClamAV nếu dung lượng dưới khoảng 2.5 GiB, và ngay cả khi đó, Rspamd, ClamAV, Dovecot và MariaDB vẫn sẽ tranh chấp RAM, dẫn đến tình trạng tràn swap và bị OOM kill khi có tải thực tế. Hãy coi mức 6 GiB RAM cộng với 1 GiB swap là mức tối thiểu để cài đặt ổn định cho một người dùng; hãy nâng cấp lên 8 GiB ngay khi có thêm nhiều người cùng sử dụng.