{"id":13498,"date":"2026-04-19T03:42:59","date_gmt":"2026-04-19T03:42:59","guid":{"rendered":"https:\/\/zoomdang.com\/?p=13498"},"modified":"2026-04-19T05:25:26","modified_gmt":"2026-04-19T05:25:26","slug":"set-up-docker-mailserver-in-coolify","status":"publish","type":"post","link":"https:\/\/zoomdang.com\/index.php\/2026\/04\/19\/set-up-docker-mailserver-in-coolify\/","title":{"rendered":"Set up Docker-Mailserver in Coolify"},"content":{"rendered":"<div class=\"fusion-fullwidth fullwidth-box fusion-builder-row-1 fusion-flex-container has-pattern-background has-mask-background nonhundred-percent-fullwidth non-hundred-percent-height-scrolling\" style=\"--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;\" ><div class=\"fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap\" style=\"max-width:1216.8px;margin-left: calc(-4% \/ 2 );margin-right: calc(-4% \/ 2 );\"><div class=\"fusion-layout-column fusion_builder_column fusion-builder-column-0 fusion_builder_column_1_1 1_1 fusion-flex-column\" style=\"--awb-bg-size:cover;--awb-width-large:100%;--awb-margin-top-large:0px;--awb-spacing-right-large:1.92%;--awb-margin-bottom-large:20px;--awb-spacing-left-large:1.92%;--awb-width-medium:100%;--awb-order-medium:0;--awb-spacing-right-medium:1.92%;--awb-spacing-left-medium:1.92%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;\"><div class=\"fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column\"><div class=\"fusion-text fusion-text-1\"><p data-path-to-node=\"12\"><b data-path-to-node=\"12\" data-index-in-node=\"0\">Required Environment Variables:<\/b><\/p>\n<ul>\n<li>\n<p data-path-to-node=\"13,0,0\"><code data-path-to-node=\"13,0,0\" data-index-in-node=\"0\">SSL_TYPE=letsencrypt<\/code><\/p>\n<\/li>\n<li>\n<p data-path-to-node=\"13,1,0\"><code data-path-to-node=\"13,1,0\" data-index-in-node=\"0\">ENABLE_DNS_CHALLENGE=1<\/code><\/p>\n<\/li>\n<li>\n<p data-path-to-node=\"13,2,0\"><code data-path-to-node=\"13,2,0\" data-index-in-node=\"0\">DNS_PROVIDER=dns_cf<\/code><\/p>\n<\/li>\n<li>\n<p data-path-to-node=\"13,3,0\"><code data-path-to-node=\"13,3,0\" data-index-in-node=\"0\">PROVIDER_CONFIG=CF_Token=<\/code><\/p>\n<\/li>\n<li data-path-to-node=\"13,4,0\"><code data-path-to-node=\"13,4,0\" data-index-in-node=\"0\">OVERRIDE_HOSTNAME=mail.zoomdang.com<\/code><\/li>\n<\/ul>\n<p>You must get a cloudflare API token. Go to cloudflare, generate an account API tokens, give permission to editi zone DNS for the specific domain.<\/p>\n<p data-path-to-node=\"15\">Docker-Mailserver often crashes if it doesn&#8217;t find a certificate folder before the challenge finishes. We solved this by:<\/p>\n<ol start=\"1\" data-path-to-node=\"16\">\n<li>\n<p data-path-to-node=\"16,0,0\">Creating the folder manually on the host: <code data-path-to-node=\"16,0,0\" data-index-in-node=\"42\">\/mail_certificate\/live\/mail.zoomdang.com<\/code>.<\/p>\n<\/li>\n<li>\n<p data-path-to-node=\"16,1,0\">Mounting it directly: <code data-path-to-node=\"16,1,0\" data-index-in-node=\"22\">\/mail_certificate:\/etc\/letsencrypt:rw<\/code>.<\/p>\n<\/li>\n<li>\n<p data-path-to-node=\"16,2,0\">Adding <code data-path-to-node=\"16,2,0\" data-index-in-node=\"7\">ONE_DIR=1<\/code> to the environment to ensure persistence.<\/p>\n<\/li>\n<\/ol>\n<p><strong>Remember to do port forwarding in local router<\/strong><\/p>\n<\/div><style type=\"text\/css\" scopped=\"scopped\">.fusion-syntax-highlighter-1 > .CodeMirror, .fusion-syntax-highlighter-1 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-1 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-1 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }<\/style><div class=\"fusion-syntax-highlighter-container fusion-syntax-highlighter-1 fusion-syntax-highlighter-theme-light\" style=\"opacity:0;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:14px;border-width:1px;border-style:solid;border-color:var(--awb-color3);\"><div class=\"syntax-highlighter-copy-code\"><span class=\"syntax-highlighter-copy-code-title\" data-id=\"fusion_syntax_highlighter_1\" style=\"font-size:14px;\">Copy to Clipboard<\/span><\/div><label for=\"fusion_syntax_highlighter_1\" class=\"screen-reader-text\">Syntax Highlighter<\/label><textarea class=\"fusion-syntax-highlighter-textarea\" id=\"fusion_syntax_highlighter_1\" data-readOnly=\"nocursor\" data-lineNumbers=\"1\" data-lineWrapping=\"\" data-theme=\"default\" data-mode=\"text\/x-sh\"># Use this code to create fetch profile. Must be set for each email\ncat <<EOF > \/tmp\/docker-mailserver\/fetchmail.cf\npoll imap.purelymail.com with proto IMAP\n    user 'your_name@your_domain.com' there with password 'YourPassword'\n    is 'your_name@your_domain.com' here\n    options ssl mda \"\/usr\/lib\/dovecot\/deliver -d your_name@your_domain.com\"\n    antispam -1\n    flush\nEOF<\/textarea><\/div><style type=\"text\/css\" scopped=\"scopped\">.fusion-syntax-highlighter-2 > .CodeMirror, .fusion-syntax-highlighter-2 > .CodeMirror .CodeMirror-gutters {background-color:var(--awb-color1);}.fusion-syntax-highlighter-2 > .CodeMirror .CodeMirror-gutters { background-color: var(--awb-color2); }.fusion-syntax-highlighter-2 > .CodeMirror .CodeMirror-linenumber { color: var(--awb-color8); }<\/style><div class=\"fusion-syntax-highlighter-container fusion-syntax-highlighter-2 fusion-syntax-highlighter-theme-light\" style=\"opacity:0;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;font-size:14px;border-width:1px;border-style:solid;border-color:var(--awb-color3);\"><div class=\"syntax-highlighter-copy-code\"><span class=\"syntax-highlighter-copy-code-title\" data-id=\"fusion_syntax_highlighter_2\" style=\"font-size:14px;\">Copy to Clipboard<\/span><\/div><label for=\"fusion_syntax_highlighter_2\" class=\"screen-reader-text\">Syntax Highlighter<\/label><textarea class=\"fusion-syntax-highlighter-textarea\" id=\"fusion_syntax_highlighter_2\" data-readOnly=\"nocursor\" data-lineNumbers=\"1\" data-lineWrapping=\"\" data-theme=\"default\" data-mode=\"text\/x-sh\">setup email add your_email@your_domain.com <your_local_password><\/textarea><\/div><div class=\"fusion-text fusion-text-2\"><p>acme.sh isn&#8217;t active in the container by default. You must download it, run it.<br \/>\nUse Cloudflare token to solve DNS challange.<br \/>\nMove .pem file into the \/etc\/letsencrypt\/live\/<\/p>\n<\/div><div class=\"fusion-text fusion-text-3\"><h2 dir=\"ltr\">Final Guide: Real-Time Mail &#8220;Vacuum&#8221; (IDLE) Setup<\/h2>\n<p dir=\"ltr\">This setup ensures your Dell 5810 fetches mail from Purelymail instantly and survives container restarts.<\/p>\n<p dir=\"ltr\">1. The &#8220;Golden&#8221; Configuration<\/p>\n<p dir=\"ltr\">The configuration must include the `mda` fix (to bypass permission issues) and the `idle` command (for real-time sync).<\/p>\n<p dir=\"ltr\">File Content:<\/p>\n<p dir=\"ltr\">&#8220;`<\/p>\n<p dir=\"ltr\">poll <a href=\"http:\/\/imap.purelymail.com\/\" target=\"_blank\" rel=\"noopener\">imap.purelymail.com<\/a> with proto IMAP<\/p>\n<p dir=\"ltr\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0user &#8216;<a href=\"mailto:me@zoomdang.com\" target=\"_blank\" rel=\"noopener\">me@zoomdang.com<\/a>&#8216; there with password &#8216;jjbmycwahtceldiccbav&#8217; is &#8216;<a href=\"mailto:me@zoomdang.com\" target=\"_blank\" rel=\"noopener\">me@zoomdang.com<\/a>&#8216; here options ssl<\/p>\n<p dir=\"ltr\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0mda &#8220;\/usr\/sbin\/sendmail -i -f %F %T&#8221;<\/p>\n<p dir=\"ltr\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0idle<\/p>\n<p dir=\"ltr\">&#8220;`<\/p>\n<p dir=\"ltr\">2. Making it &#8220;Restart-Proof&#8221;<\/p>\n<p dir=\"ltr\">Docker-Mailserver (DMS) regenerates the internal config on every boot. To make our changes stick, we placed the config in the official DMS override location:<\/p>\n<p dir=\"ltr\">\u2022 Path: `\/tmp\/docker-mailserver\/<a href=\"http:\/\/fetchmail.cf\/\" target=\"_blank\" rel=\"noopener\">fetchmail.cf<\/a>`<\/p>\n<p dir=\"ltr\">\u2022 Logic: On startup, DMS checks this file. If it exists, it uses these settings to build the active `\/etc\/fetchmailrc` file.<\/p>\n<p dir=\"ltr\">3. Key Technical Fixes Applied<\/p>\n<p dir=\"ltr\">\u2022 MDA Bypass: Changed delivery from the default (Dovecot) to `sendmail`. This avoids the &#8220;nonzero status 75&#8221; error caused by internal container permission mismatches.<\/p>\n<p dir=\"ltr\">\u2022 User Ownership: Ensured the configuration is owned by the `fetchmail` user. Fetchmail will refuse to run if the config file is owned by `root`.<\/p>\n<p dir=\"ltr\">\u2022 Single Process: Verified that only the official system daemon is running to avoid session conflicts with Purelymail.<\/p>\n<p dir=\"ltr\">4. Coolify Environment Variables<\/p>\n<p dir=\"ltr\">Set these in the Coolify UI to support the background process:<\/p>\n<p dir=\"ltr\">\u2022 `ENABLE_FETCHMAIL=1`<\/p>\n<p dir=\"ltr\">\u2022 `FETCHMAIL_POLL=300` (This acts as a 5-minute &#8220;heartbeat&#8221; to reconnect if the IDLE connection ever drops).<\/p>\n<p dir=\"ltr\">5. Quick Health Check Commands<\/p>\n<p dir=\"ltr\">\u2022 Check process: `ps aux | grep fetchmail` (Should show exactly one process).<\/p>\n<p dir=\"ltr\">\u2022 Check logs: `tail -f \/var\/log\/mail.log` (Look for `fetchmail: IMAP&lt; + Idling`).<\/p>\n<p dir=\"ltr\">\u2022 Force Update: `pkill fetchmail` (The system will automatically restart it with the latest config).<\/p>\n<\/div><\/div><\/div><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-13498","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/posts\/13498","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/comments?post=13498"}],"version-history":[{"count":8,"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/posts\/13498\/revisions"}],"predecessor-version":[{"id":13507,"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/posts\/13498\/revisions\/13507"}],"wp:attachment":[{"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/media?parent=13498"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/categories?post=13498"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zoomdang.com\/index.php\/wp-json\/wp\/v2\/tags?post=13498"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}