{"id":35658,"date":"2026-01-08T01:23:25","date_gmt":"2026-01-07T18:23:25","guid":{"rendered":"https:\/\/dps.media\/huong-dan-cai-dat-mailcow-phien-ban-cuoi\/"},"modified":"2026-01-08T01:23:25","modified_gmt":"2026-01-07T18:23:25","slug":"mailcow-installation-guide-latest-version","status":"publish","type":"post","link":"https:\/\/dps.media\/en\/mailcow-installation-guide-latest-version\/","title":{"rendered":"Mailcow Installation Guide (Final Version)"},"content":{"rendered":"<p>This guide is optimized for installing Mailcow: Dockerized on a VPS running Nginx Proxy Manager (NPM) and Portainer. It includes fixes for common issues like Redirect Loops and 504 Gateway Timeout Errors.<\/p>\n<p><figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch.jpg\" alt=\"Mailcow Architecture\" class=\"wp-image-35655\" title=\"\" srcset=\"https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch.jpg 1024w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch-300x300.jpg 300w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch-150x150.jpg 150w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch-768x768.jpg 768w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch-12x12.jpg 12w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch-754x754.jpg 754w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch-356x356.jpg 356w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch-200x200.jpg 200w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_arch-70x70.jpg 70w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption><\/figcaption><\/figure>\n<\/p>\n<h2>1. Prerequisites<\/h2>\n<ul>\n<li>VPS with Docker &amp; Docker Compose pre-installed.<\/li>\n<li>Domain name: <code data-no-translation=\"\">mail.khaisanfood.vn<\/code> (pointing to VPS IP).<\/li>\n<li>Nginx Proxy Manager is running in a Docker container.<\/li>\n<\/ul>\n<h3>DNS record<\/h3>\n<table class=\"wp-block-table\">\n<thead>\n<tr>\n<th>Type<\/th>\n<th>Name<\/th>\n<th>Value<\/th>\n<th>Proxy Status<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>A<\/td>\n<td>mail<\/td>\n<td>Your VPS IP<\/td>\n<td>DNS Only<\/td>\n<\/tr>\n<tr>\n<td>CNAME<\/td>\n<td>autodiscover<\/td>\n<td>mail.khaisanfood.vn<\/td>\n<td>DNS Only<\/td>\n<\/tr>\n<tr>\n<td>CNAME<\/td>\n<td>autoconfig<\/td>\n<td>mail.khaisanfood.vn<\/td>\n<td>DNS Only<\/td>\n<\/tr>\n<tr>\n<td>MX<\/td>\n<td>@<\/td>\n<td>mail.khaisanfood.vn<\/td>\n<td>Priority 10<\/td>\n<\/tr>\n<tr>\n<td>TXT<\/td>\n<td>@<\/td>\n<td>v=spf1 mx ~all<\/td>\n<td>\u2013<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>2. Installation Steps<\/h2>\n<h3>Step 1: Clone Mailcow<\/h3>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">cd \/opt\ngit clone https:\/\/github.com\/mailcow\/mailcow-dockerized\ncd mailcow-dockerized<\/code><\/pre>\n<h3>Step 2: Generate Configuration<\/h3>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">.\/generate_config.sh\nHostname: mail.khaisanfood.vn\nTimezone: Asia\/Ho<em>Chi<\/em>Minh\nClamAV: Y (n\u1ebfu RAM > 4GB) ho\u1eb7c N.<\/code><\/pre>\n<h3>Step 3: Configure mailcow.conf (Important)<\/h3>\n<p>Edit the configuration to avoid conflicts and loops.<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">nano mailcow.conf<\/code><\/pre>\n<p>Change the following variables:<\/p>\n<ul>\n<li><strong>Prevent Redirect Loops:<\/strong><br \/>\n<code data-no-translation=\"\">HTTP_REDIRECT=n<\/code><br \/>\n(We let Nginx Proxy Manager handle HTTPS, so turn off Mailcow's internal redirection).<\/li>\n<li><strong>Bind to All Interfaces (so NPM can see it):<\/strong>\n<p><code data-no-translation=\"\">HTTP_BIND=0.0.0.0<\/code><\/p>\n<p><code data-no-translation=\"\">HTTPS_BIND=0.0.0.0<\/code><\/li>\n{<br>  \"slug\": \"blog\",<br>  \"translations\": [<br>    \"<\/p>\"<br>  ]<br>}\n<li><strong>Change Ports (to avoid 80\/443 conflicts):<\/strong>\n<p><code data-no-translation=\"\">HTTP_PORT=8080<\/code><\/p>\n<p><code data-no-translation=\"\">HTTPS_PORT=8443<\/code><\/li>\n{<br>  \"slug\": \"blog\",<br>  \"translations\": [<br>    \"<\/p>\"<br>  ]<br>}\n<li><strong>Avoid IP Conflicts (Fix \u201cPool overlaps\u201d):<\/strong>\n<p><code data-no-translation=\"\">IPV4_NETWORK=192.168.201<\/code><\/li>\n<p>\n<\/ul>\n{<br>  \"slug\": \"blog\",<br>  \"translations\": [<br>    \"<\/p>\"<br>  ]<br>}\n<p><figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal.jpg\" alt=\"Mailcow Installation Terminal\" class=\"wp-image-35656\" title=\"\" srcset=\"https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal.jpg 1024w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal-300x300.jpg 300w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal-150x150.jpg 150w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal-768x768.jpg 768w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal-12x12.jpg 12w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal-754x754.jpg 754w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal-356x356.jpg 356w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal-200x200.jpg 200w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_terminal-70x70.jpg 70w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption><\/figcaption><\/figure>\n<\/p>\n<h3>Step 4: Firewall Setup (Fix 504 Error)<\/h3>\n<p>Ensure Docker containers can communicate with each other.<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">ufw allow from 172.16.0.0\/12 to any<\/code><\/pre>\n<h3>Step 5: Start Mailcow<\/h3>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">docker compose pull\ndocker compose up -d<\/code><\/pre>\n<h2>3. Nginx Proxy Manager Configuration<\/h2>\n<p>Access Nginx Proxy Manager and add a new Proxy Host.<\/p>\n<h3>Details Tab<\/h3>\n<ul>\n<li>Domain Names: <code data-no-translation=\"\">mail.khaisanfood.vn<\/code><\/li>\n<li>Scheme: <code data-no-translation=\"\">http<\/code> (Important! Connect via HTTP)<\/li>\n<li>Forward Hostname \/ IP: <code data-no-translation=\"\">172.17.0.1<\/code><br \/>\n(This is the standard Docker Gateway IP. Check <code data-no-translation=\"\">ip addr show docker0<\/code> to confirm).<\/li>\n<li>Forward Port: <code data-no-translation=\"\">8080<\/code><\/li>\n<li>Cache Assets: Disabled<\/li>\n<li>Block Common Exploits: Enabled<\/li>\n<\/ul>\n<h3>SSL Tab<\/h3>\n<ul>\n<li>SSL Certificate: Request a new Let's Encrypt certificate.<\/li>\n<li>Force SSL: Enabled.<\/li>\n<li>HTTP\/2 Support: Enabled.<\/li>\n<\/ul>\n<p>Click Save. Now you can access <code data-no-translation=\"\">https:\/\/mail.khaisanfood.vn<\/code>.<\/p>\n<p><figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security.jpg\" alt=\"SSL Security\" class=\"wp-image-35657\" title=\"\" srcset=\"https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security.jpg 1024w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security-300x300.jpg 300w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security-150x150.jpg 150w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security-768x768.jpg 768w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security-12x12.jpg 12w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security-754x754.jpg 754w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security-356x356.jpg 356w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security-200x200.jpg 200w, https:\/\/dps.media\/wp-content\/uploads\/2026\/01\/mailcow_security-70x70.jpg 70w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption><\/figcaption><\/figure>\n<\/p>\n<h2>4. Post-Installation<\/h2>\n<h3>Sync SSL Certificates (For Email Clients)<\/h3>\n<p>NPM handles web SSL, but Mailcow needs certificates for SMTP\/IMAP. You need to copy them from the NPM Docker volume on the host.<\/p>\n<p>Find your NPM Certificate ID: Check the NPM dashboard or look in the directory. Example Host Path: <code data-no-translation=\"\">\/var\/lib\/docker\/volumes\/nginx-proxy-manager<em>npm<\/em>letsencrypt\/_data\/live\/npm-21<\/code> (id 21 will be different for each domain).<\/p>\n<p>Sync Command:<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\"># C\u1eadp nh\u1eadt \u0111\u01b0\u1eddng d\u1eabn n\u00e0y kh\u1edbp v\u1edbi Host Path c\u1ee7a b\u1ea1n t\u00ecm th\u1ea5y \u1edf tr\u00ean\nNPM<em>CERT<\/em>PATH=\"\/var\/lib\/docker\/volumes\/nginx-proxy-manager<em>npm<\/em>letsencrypt\/_data\/live\/npm-21\"\ncp \"$NPM<em>CERT<\/em>PATH\/fullchain.pem\" \/opt\/mailcow-dockerized\/data\/assets\/ssl\/cert.pem\ncp \"$NPM<em>CERT<\/em>PATH\/privkey.pem\" \/opt\/mailcow-dockerized\/data\/assets\/ssl\/key.pem\ncd \/opt\/mailcow-dockerized\ndocker compose restart postfix-mailcow dovecot-mailcow nginx-mailcow<\/code><\/pre>\n<h3>Reset Admin Password<\/h3>\n<p>If <code data-no-translation=\"\">admin \/ moohoo<\/code> not working:<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">cd \/opt\/mailcow-dockerized\/helper-scripts\nbash mailcow-reset-admin.sh<\/code><\/pre>\n<h3>DNS \/ DKIM<\/h3>\n<p>Log in to Mailcow UI -&gt; Configuration -&gt; Mail Setup -&gt; DNS to get the DKIM record and add it to your DNS provider.<\/p>\n<h2>5. Adding Additional Domains (Multi-Domain Setup)<\/h2>\n<p>You can host multiple email domains (e.g., <code data-no-translation=\"\">@dpsmedia.vn<\/code>) on this same server.<\/p>\n<h3>A. Add Domain in Mailcow<\/h3>\n<ul>\n<li>Log in to Mailcow UI as Admin.<\/li>\n<li>Go to Configuration -&gt; Mail Setup -&gt; Domains.<\/li>\n<li>Click Add Domain.<\/li>\n<li>Domain: <code data-no-translation=\"\">dpsmedia.vn<\/code> (or your new domain).<\/li>\n<li>Click Add Domain and restart SOGo.<\/li>\n<\/ul>\n<h3>B. DNS for New Domain (dpsmedia.vn)<\/h3>\n<p>Go to the DNS provider for <code data-no-translation=\"\">dpsmedia.vn<\/code> and add these records. Important: Point them to your current mail server URL (<code data-no-translation=\"\">mail.khaisanfood.vn<\/code>).<\/p>\n<table class=\"wp-block-table\">\n<thead>\n<tr>\n<th>Type<\/th>\n<th>Name<\/th>\n<th>Value<\/th>\n<th>Status<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>MX<\/td>\n<td>@<\/td>\n<td>mail.khaisanfood.vn<\/td>\n<td>Priority 10<\/td>\n<\/tr>\n<tr>\n<td>TXT<\/td>\n<td>@<\/td>\n<td>v=spf1 mx include:mail.khaisanfood.vn ~all<\/td>\n<td>\u2013<\/td>\n<\/tr>\n<tr>\n<td>CNAME<\/td>\n<td>autodiscover<\/td>\n<td>mail.khaisanfood.vn<\/td>\n<td>DNS Only<\/td>\n<\/tr>\n<tr>\n<td>CNAME<\/td>\n<td>autoconfig<\/td>\n<td>mail.khaisanfood.vn<\/td>\n<td>DNS Only<\/td>\n<\/tr>\n<tr>\n<td>TXT<\/td>\n<td>dkim._domainkey<\/td>\n<td>(Copy value from Mailcow UI -&gt; DNS)<\/td>\n<td>\u2013<\/td>\n<\/tr>\n<tr>\n<td>TXT<\/td>\n<td>_dmarc<\/td>\n<td>v=DMARC1; p=none;<\/td>\n<td>\u2013<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>(You do NOT need a new IP address. Everything goes through the main IPs).<\/p>\n<h3>C. (Optional) Access Mailcow UI via mail.dpsmedia.vn<\/h3>\n<p>If you want to access the Admin UI via <code data-no-translation=\"\">https:\/\/mail.dpsmedia.vn<\/code>:<\/p>\n<p>Edit Config:<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">nano mailcow.conf\nADDITIONAL<em>SERVER<\/em>NAMES=mail.dpsmedia.vn\ndocker compose up -d<\/code><\/pre>\n<p>Nginx Proxy Manager: Copy the exact settings of <code data-no-translation=\"\">mail.khaisanfood.vn<\/code>.<\/p>\n<h3>D. SSL Certificates for Additional Domains<\/h3>\n<p><strong>Option 1:<\/strong> (Recommended) Use <code data-no-translation=\"\">mail.khaisanfood.vn<\/code> for Incoming\/Outgoing Server.<\/p>\n<p><strong>Option 2:<\/strong> (Advanced) Enable <code data-no-translation=\"\">ENABLE<em>SSL<\/em>SNI=y<\/code> in config, create a separate SSL directory and sync the new certificate there.<\/p>\n<h2>6. Fix Email Sending (Gmail Block)<\/h2>\n<p>If you encounter an error <code data-no-translation=\"\">550-5.7.1<\/code>, it means your IP has low reputation.<\/p>\n<h3>A. Set Up Reverse DNS (PTR) \u2013 Mandatory<\/h3>\n<p>Go to your VPS provider's Dashboard, set the PTR Record for your IP to <code data-no-translation=\"\">mail.khaisanfood.vn<\/code>.<\/p>\n<h3>B. Use SMTP Relay<\/h3>\n<p>If the IP is blacklisted, use Amazon SES, SendGrid, or Mailgun as a Relay.<\/p>\n<h2>7. Uninstallation Guide<\/h2>\n<p>Warning: This will delete ALL email data.<\/p>\n<pre data-no-translation=\"\"><code data-no-translation=\"\">cd \/opt\/mailcow-dockerized\ndocker compose down -v\ncd \/opt\nrm -rf mailcow-dockerized<\/code><\/pre>\n<p>Delete Proxy Host in NPM.<\/p>","protected":false},"excerpt":{"rendered":"<p>H\u01b0\u1edbng d\u1eabn n\u00e0y \u0111\u01b0\u1ee3c t\u1ed1i \u01b0u h\u00f3a \u0111\u1ec3 c\u00e0i \u0111\u1eb7t Mailcow: Dockerized tr\u00ean VPS ch\u1ea1y Nginx Proxy Manager (NPM) v\u00e0 Portainer. N\u00f3 bao g\u1ed3m c\u00e1c s\u1eeda l\u1ed7i cho c\u00e1c v\u1ea5n \u0111\u1ec1 ph\u1ed5 bi\u1ebfn nh\u01b0 V\u00f2ng l\u1eb7p Chuy\u1ec3n h\u01b0\u1edbng (Redirect Loops) v\u00e0 L\u1ed7i Gateway Timeout 504. 1. Y\u00eau c\u1ea7u Ti\u00ean quy\u1ebft VPS c\u00e0i s\u1eb5n Docker &#038; [&hellip;]<\/p>","protected":false},"author":1,"featured_media":35655,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1758,1793,1794],"tags":[],"class_list":["post-35658","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-guides","category-mailcow"],"acf":[],"rankmath_keywords":{"primary":"","secondary":[""]},"yoast_keywords":{"primary":"","secondary":[]},"yoast_focuskw":"","rankmath_focuskw":"","seo_keywords":{"primary":"","secondary":[""]},"_links":{"self":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts\/35658","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/comments?post=35658"}],"version-history":[{"count":0,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/posts\/35658\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/media\/35655"}],"wp:attachment":[{"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/media?parent=35658"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/categories?post=35658"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dps.media\/en\/wp-json\/wp\/v2\/tags?post=35658"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}