<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Dovecot – Serverküche</title><link>https://serverkueche.de/en/tags/dovecot/</link><description>Dovecot – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>en-US</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Mon, 10 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/en/tags/dovecot/index.xml" rel="self" type="application/rss+xml"/><item><title>Your own mail server with Mailcow: setup from scratch</title><link>https://serverkueche.de/en/tutorials/mailcow-mail-server/</link><pubDate>Mon, 10 Aug 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/en/tutorials/mailcow-mail-server/</guid><description>Set up Mailcow (dockerized) on your own server: Postfix, Dovecot, Rspamd and SOGo webmail under your domain – a complete mail server stack with HTTPS.</description><content:encoded><![CDATA[<p>Your email is the backbone of your digital identity – password resets, invoices, contracts all run through it. Yet for most people it sits at a corporation in the US. With <strong>Mailcow</strong> you bring the complete mail server onto your own server: Postfix, Dovecot, spam filter and webmail, neatly packed in Docker. This tutorial gets the stack running – the tricky <strong>deliverability</strong> (SPF, DKIM, DMARC, reverse DNS) we handle afterwards in the <a href="/en/tutorials/email-deliverability/" data-track-event="Navigation|Tutorial-Link|/en/tutorials/email-deliverability/ ← /en/tutorials/mailcow-mail-server/">deliverability recipe</a>.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Running your own mail server is work – be honest with yourself
  </p>
  <div class="prose-kitchen text-sm">A mail server is not &ldquo;set up once and forget&rdquo;. From now on you&rsquo;re responsible for deliverability, reputation, backups and updates. If your mails land in spam or the server fails, it affects your most important communication. If you don&rsquo;t want to maintain this regularly, a reputable mail host is often the better choice – that&rsquo;s no weakness but an honest trade-off. Whoever really wants control is in the right place here.</div>
</div>
<h2 id="what-are-we-building">What are we building?</h2>
<p>By the end, a <strong>complete mail server stack</strong> runs on your server, reachable as webmail at <code>https://mail.YOUR_DOMAIN</code> with a valid Let&rsquo;s Encrypt certificate. Included are:</p>
<ul>
<li><strong>Postfix</strong> as the SMTP server (send/receive),</li>
<li><strong>Dovecot</strong> for IMAP/POP3 (retrieval by mail programs),</li>
<li><strong>Rspamd</strong> as a modern spam and signature filter,</li>
<li><strong>SOGo</strong> as webmail including calendar and contacts (CalDAV/CardDAV),</li>
<li>an <strong>admin interface</strong> to create domains, mailboxes and aliases.</li>
</ul>
<p>The whole thing comes as <strong>mailcow-dockerized</strong> – a ready-bundled Compose project of <strong>18 containers</strong> that makes the notoriously complicated mail server setup manageable. We build on <strong>Debian 13</strong> with <strong>Docker 29.6</strong> and <strong>Compose v5.3</strong>; mailcow is a <em>rolling release</em> maintained through monthly tags (you update via <code>update.sh</code>, there&rsquo;s no classic version number). We tested against the <strong>2026-07b</strong> state with <strong>Postfix 3.10.12</strong>, <strong>Dovecot 2.3.21.1</strong>, <strong>Rspamd 4.1.4</strong> and <strong>SOGo 5.12.10</strong>.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-paprika-400 bg-paprika-50 dark:border-paprika-700 dark:bg-paprika-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🔥</span>Mailcow needs its own server
  </p>
  <div class="prose-kitchen text-sm">Unlike most recipes here, mailcow does <strong>not</strong> run behind the shared <a href="/en/tutorials/traefik-reverse-proxy/">Traefik reverse proxy</a>. It brings its <strong>own</strong> web server and occupies ports <strong>80/443</strong> itself, plus the mail ports <strong>25, 465, 587, 143, 993</strong> (and more). So run mailcow on a <strong>dedicated server</strong> where nothing else needs these ports – not on the same host as your Traefik stack.</div>
</div>
<h2 id="prerequisites">Prerequisites</h2>
<ul>
<li>A <strong>dedicated server</strong> with <strong>Debian 13</strong> on which <a href="/en/tutorials/install-docker/">Docker is installed</a> and that is <strong>only</strong> for mailcow (ports 80/443 and the mail ports free).</li>
<li><strong>At least 6 GB RAM</strong> – the spam filter (Rspamd) and the optional virus scanner (ClamAV) need room. With less it gets sluggish or ClamAV has to go.</li>
<li>A <strong>domain</strong> whose <a href="/en/tutorials/connect-domain-to-server/">DNS you control yourself</a>. Without matching records (especially <strong>MX</strong> and <strong>reverse DNS</strong>), no other mail server accepts your mail.</li>
<li><strong>Outbound port 25 must be open.</strong> Many providers block it by default against spam – at netcup you enable it via a support ticket. Without an open port 25 you can deliver <strong>no</strong> mail to other servers.</li>
<li>A <strong>PTR/reverse-DNS entry</strong> for the server IP, which you set in the provider panel (at netcup in the SCP). It must point to <code>mail.YOUR_DOMAIN</code>.</li>
</ul>
<p>Mailcow is RAM-hungry, so we recommend at least the VPS 2000. What your specific need is, the <a href="/en/server-calculator/">server calculator</a> estimates for you.</p>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20"
     data-track-content data-content-name="Affiliate-Box · /en/tutorials/mailcow-mail-server/" data-content-piece="VPS 2000 G12">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Recommendation</span>
    <span title="Links marked with * are affiliate links.">Ad</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 2000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">8 vCores · 16 GB RAM · 512 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">from €19.24/month</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">For mailcow including spam and virus filter it should be 8 GB RAM.</p>
    </div>
    <a href="https://www.netcup.com/en/server/vps/vps-2000-g12-iv-12m?ref=44083" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 2000 G12 · {page}"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Go to netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € voucher</strong> for new netcup customers:</span><code data-track-voucher="36nc17844976032"
        class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(new customers only, no domains)</span>
</p></div>
</div>

<h2 id="step-by-step">Step by step</h2>
<h3 id="step-1-create-the-dns-records">Step 1: Create the DNS records</h3>
<p>Before you install anything, set up the DNS entries – they need time to propagate, and mailcow fetches the TLS certificate for the hostname at startup. At your DNS provider (see <a href="/en/tutorials/connect-domain-to-server/">connecting a domain to your server</a>), create these entries. <code>YOUR_DOMAIN</code> is your mail domain (e.g. <code>example.com</code>), <code>YOUR_SERVER_IPV4</code> the server&rsquo;s IPv4 address:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">mail.YOUR_DOMAIN.   A      YOUR_SERVER_IPV4
</span></span><span class="line"><span class="cl">mail.YOUR_DOMAIN.   AAAA   YOUR_SERVER_IPV6      (if you use IPv6)
</span></span><span class="line"><span class="cl">YOUR_DOMAIN.        MX     10 mail.YOUR_DOMAIN.</span></span></code></pre></div>
</div>
<p>The <strong>MX record</strong> tells other mail servers: &ldquo;Mail for <code>@YOUR_DOMAIN</code> is accepted by <code>mail.YOUR_DOMAIN</code>.&rdquo; The hostname <code>mail.YOUR_DOMAIN</code> is the <strong>FQDN of the mail server</strong> – not to be confused with the mail domain itself. The further records for deliverability (SPF, DKIM, DMARC) and the <strong>PTR entry</strong> we cover in detail in the follow-up tutorial on deliverability; the PTR entry should be set already now, though, because many servers otherwise don&rsquo;t accept at all.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>Tip
  </p>
  <div class="prose-kitchen text-sm">Set the <strong>TTL</strong> of the records low before the migration (e.g. 300 seconds). Then later corrections take effect quickly while you test. After the fine-tuning you can raise them again.</div>
</div>
<h3 id="step-2-install-prerequisites-on-the-server">Step 2: Install prerequisites on the server</h3>
<p>Log in via SSH to the <a href="/en/tutorials/harden-ssh/">hardened server</a>. Mailcow&rsquo;s config generator needs <code>git</code> and <code>jq</code> besides Docker – the latter is easily forgotten, and the generator otherwise aborts with <code>Cannot find command 'jq'</code>. Install both:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt update <span class="o">&amp;&amp;</span> sudo apt install -y git jq</span></span></code></pre></div>
</div>
<p>Check that Docker and the Compose plugin are running:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker --version <span class="o">&amp;&amp;</span> docker compose version</span></span></code></pre></div>
</div>
<p>You should see two version lines – for us <code>Docker version 29.6.1</code> and <code>Docker Compose version v5.3.1</code>. Mailcow requires at least <strong>Docker 24</strong>; below that the config generator aborts. If something&rsquo;s missing, catch up on the <a href="/en/tutorials/install-docker/">Docker setup</a> before continuing.</p>
<h3 id="step-3-clone-and-configure-mailcow">Step 3: Clone and configure Mailcow</h3>
<p>Mailcow is delivered as a Git repository and <strong>not</strong> maintained via a single image tag. Clone it to <code>/opt</code> and change into it. The <code>umask 0022</code> is important so the generated files get the right permissions:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo su
</span></span><span class="line"><span class="cl"><span class="nb">umask</span> <span class="m">0022</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> /opt
</span></span><span class="line"><span class="cl">git clone https://github.com/mailcow/mailcow-dockerized
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> mailcow-dockerized</span></span></code></pre></div>
</div>
<p>Now you generate the central configuration file <code>mailcow.conf</code> with the interactive generator:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">./generate_config.sh</span></span></code></pre></div>
</div>
<p>It first checks whether your server&rsquo;s IP is on the <strong>Spamhaus bad ASN list</strong> – a useful early warning, because hardly any mail server accepts post from some networks:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">Detecting if your IP is listed on Spamhaus Bad ASN List...
</span></span><span class="line"><span class="cl">Check completed! Your IP is clean</span></span></code></pre></div>
</div>
<p>Then it asks you these questions in turn:</p>
<ul>
<li><strong>Mail server hostname (FQDN):</strong> Enter <code>mail.YOUR_DOMAIN</code> here – the server&rsquo;s <strong>hostname</strong>, not your mail domain. The value must match the A record from step 1.</li>
<li><strong>Timezone:</strong> usually already correctly pre-filled (e.g. <code>Europe/Berlin</code>) – confirm with Enter.</li>
<li><strong>Choose the Branch with it&rsquo;s number [1/2/3]:</strong> Choose <strong><code>1</code></strong> for the <code>master</code> branch – that&rsquo;s the stable, recommended state. <code>2</code> is <code>nightly</code> (testing), <code>3</code> the deprecated <code>legacy</code> branch.</li>
</ul>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>You only see the ClamAV question on small servers
  </p>
  <div class="prose-kitchen text-sm">The generator asks about the virus scanner (<em>Do you want to disable ClamAV now?</em>) <strong>only</strong> if the server has <strong>at most 2.5 GiB of RAM</strong>. On a machine with 6–8 GB it quietly sets <code>SKIP_CLAMD=n</code>, so ClamAV runs from the start. You can switch it off any time by setting <code>SKIP_CLAMD=y</code> in <code>mailcow.conf</code> and restarting the stack.</div>
</div>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>IPv6 hosts: Docker gets restarted
  </p>
  <div class="prose-kitchen text-sm"><p>If the generator finds a working <strong>IPv6 connection</strong> (default route plus a reachable peer), Docker has to speak IPv6 too – otherwise mailcow could become an <strong>open relay</strong>. If <code>/etc/docker/daemon.json</code> is missing, it therefore asks:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">/etc/docker/daemon.json not found. Create it with IPv6 settings? [Y/n]</span></span></code></pre></div>
</div>
<p>Confirm with Enter and it creates the file itself (on Docker ≥ 28 <code>{&quot;ipv6&quot;: true}</code> is enough) and restarts Docker <strong>right away</strong>. This is exactly why mailcow belongs on its <strong>own</strong> server: that restart takes every other container on the host down with it. Answer <code>n</code> and the generator aborts, leaving you to add the setting by hand. If you deliberately want to run without IPv6, set <code>ENABLE_IPV6=false</code> in <code>mailcow.conf</code> later.</p>
</div>
</div>
<p>Afterwards take a look at the generated <code>mailcow.conf</code>. The most important values are at the top:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">grep -E <span class="s2">&#34;^(MAILCOW_HOSTNAME|TZ|HTTP_PORT|HTTPS_PORT|SKIP_CLAMD|ENABLE_IPV6)=&#34;</span> mailcow.conf</span></span></code></pre></div>
</div>
<p>On our test server it looked like this – <code>SKIP_CLAMD=n</code> means &ldquo;ClamAV is running&rdquo;:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">MAILCOW_HOSTNAME=mail.YOUR_DOMAIN
</span></span><span class="line"><span class="cl">HTTP_PORT=80
</span></span><span class="line"><span class="cl">HTTPS_PORT=443
</span></span><span class="line"><span class="cl">TZ=Europe/Berlin
</span></span><span class="line"><span class="cl">SKIP_CLAMD=n
</span></span><span class="line"><span class="cl">ENABLE_IPV6=true</span></span></code></pre></div>
</div>
<p>The file also contains all <strong>port assignments</strong>. In the standard configuration mailcow claims these host ports:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">25    SMTP     (server-to-server delivery)
</span></span><span class="line"><span class="cl">465   SMTPS    (send with implicit TLS)
</span></span><span class="line"><span class="cl">587   Submission (send by mail programs, STARTTLS)
</span></span><span class="line"><span class="cl">143   IMAP  /  993 IMAPS   (retrieval by mail programs)
</span></span><span class="line"><span class="cl">110   POP3  /  995 POP3S
</span></span><span class="line"><span class="cl">4190  Sieve    (server-side filter rules)
</span></span><span class="line"><span class="cl">80    HTTP  /  443 HTTPS   (webmail + admin + ACME)</span></span></code></pre></div>
</div>
<p>These ports must be <strong>free</strong> on the host – hence the dedicated server. If a reverse proxy already runs on 80/443 there, mailcow collides with it.</p>
<h3 id="step-4-open-the-firewall">Step 4: Open the firewall</h3>
<p>Your <a href="/en/tutorials/firewall-ufw-setup/">UFW firewall</a> must let the mail and web ports through. Besides SSH, you allow:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo ufw allow 25/tcp
</span></span><span class="line"><span class="cl">sudo ufw allow 80,443/tcp
</span></span><span class="line"><span class="cl">sudo ufw allow 465,587/tcp
</span></span><span class="line"><span class="cl">sudo ufw allow 143,993/tcp
</span></span><span class="line"><span class="cl">sudo ufw allow 110,995/tcp
</span></span><span class="line"><span class="cl">sudo ufw allow 4190/tcp</span></span></code></pre></div>
</div>
<p>If you additionally use the <a href="/en/tutorials/netcup-firewall-setup/">netcup firewall in the SCP</a>, allow the same ports there too – otherwise the perimeter firewall blocks the traffic before it reaches the server.</p>
<h3 id="step-5-start-the-stack">Step 5: Start the stack</h3>
<p>Now you download the images and start the stack. Expect <strong>about 4.5 GB</strong> on disk – the stack consists of 18 services, the biggest being SOGo, Dovecot and Postfix:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose pull
</span></span><span class="line"><span class="cl">docker compose up -d</span></span></code></pre></div>
</div>
<p>The first boot takes a few minutes – the database, search index and the individual services initialize. Watch the progress with:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose ps</span></span></code></pre></div>
</div>
<p>The <code>STATUS</code> column shows <code>Up …</code> for every service; the containers with their own health check (such as <code>unbound-mailcow</code> and <code>clamd-mailcow</code>) additionally report <code>(healthy)</code>. During this time, mailcow fetches the <strong>Let&rsquo;s Encrypt certificate</strong> for <code>mail.YOUR_DOMAIN</code> in the background via its built-in ACME client. For that, the A record and port 80 must be reachable from outside – if that&rsquo;s not the case, the <code>acme-mailcow</code> container stays in a retry loop and you see it in its logs (<code>docker compose logs acme-mailcow</code>).</p>
<h3 id="step-6-first-login-to-the-admin-interface">Step 6: First login to the admin interface</h3>
<p>Open <code>https://mail.YOUR_DOMAIN</code> in the browser. You land in the mailcow UI. Log in with the <strong>default credentials</strong>:</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">User:      admin
</span></span><span class="line"><span class="cl">Password:  moohoo</span></span></code></pre></div>
</div>
<p>If the form shows &ldquo;Sign in as user&rdquo;, click <strong>&ldquo;Sign in as admin&rdquo;</strong> at the bottom – the login form on the home page otherwise logs you in as a mailbox user, not as an administrator.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-paprika-400 bg-paprika-50 dark:border-paprika-700 dark:bg-paprika-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🔥</span>Change the default password immediately
  </p>
  <div class="prose-kitchen text-sm"><code>admin</code> / <code>moohoo</code> is publicly known. <strong>Change the admin password immediately</strong> under <em>System → Configuration → Access</em>: in the <strong>Administrators</strong> table, click <strong>Edit</strong> next to the <code>admin</code> user. In the same tab, enable <strong>two-factor authentication</strong> (TOTP or WebAuthn) right away. As long as the default password applies, your mail server is wide open like a barn door.</div>
</div>
<p>After logging in you land in the mailcow dashboard with the overview of your services:</p>
<p><figure class="my-6"><img src="/en/tutorials/mailcow-mail-server/mailcow-dashboard_hu_8014b3cfa3617aca.webp" srcset="/en/tutorials/mailcow-mail-server/mailcow-dashboard_hu_6fe3e0a2a9604cdf.webp 480w, /en/tutorials/mailcow-mail-server/mailcow-dashboard_hu_8014b3cfa3617aca.webp 768w, /en/tutorials/mailcow-mail-server/mailcow-dashboard_hu_6a055ddf84b66fec.webp 1200w, /en/tutorials/mailcow-mail-server/mailcow-dashboard_hu_4d842187c17f7bfe.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/mailcow-mail-server/mailcow-dashboard_hu_c21d6d42804f4104.webp"
    alt="The mailcow dashboard after the first login with a system overview." title="The mailcow dashboard right after login."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">The mailcow dashboard right after login.</figcaption></figure></p>
<h3 id="step-7-create-a-mail-domain-and-first-mailbox">Step 7: Create a mail domain and first mailbox</h3>
<p>In mailcow you separate <strong>domain</strong> (e.g. <code>example.com</code>) and <strong>mailbox</strong> (e.g. <code>contact@example.com</code>).</p>
<p>Via <strong>E-Mail → Configuration</strong> in the top navigation bar you manage domains and mailboxes in separate tabs:</p>
<p><figure class="my-6"><img src="/en/tutorials/mailcow-mail-server/mailcow-mail-setup_hu_ee7870251e7c4932.webp" srcset="/en/tutorials/mailcow-mail-server/mailcow-mail-setup_hu_7b0e5f56d73a2bd6.webp 480w, /en/tutorials/mailcow-mail-server/mailcow-mail-setup_hu_ee7870251e7c4932.webp 768w, /en/tutorials/mailcow-mail-server/mailcow-mail-setup_hu_bbf8b0ff34a1ea4e.webp 1200w, /en/tutorials/mailcow-mail-server/mailcow-mail-setup_hu_d3d79d04b8538cb5.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/mailcow-mail-server/mailcow-mail-setup_hu_18a26bfea89c5845.webp"
    alt="The mail setup interface of mailcow with tabs for domains and mailboxes." title="E-Mail → Configuration: manage domains and mailboxes."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">E-Mail → Configuration: manage domains and mailboxes.</figcaption></figure></p>
<ol>
<li>
<p>On the <strong>Domains</strong> tab, click <strong>Add domain</strong> and enter your domain <code>YOUR_DOMAIN</code>. The default values (mailbox and alias quotas) are fine for the start. Save with <strong>&ldquo;Add domain and restart SOGo&rdquo;</strong> at the bottom – not with &ldquo;Add domain only&rdquo;. Why, see the box below.</p>
<p><figure class="my-6"><img src="/en/tutorials/mailcow-mail-server/mailcow-domain-anlegen_hu_b4e814a01e088b7a.webp" srcset="/en/tutorials/mailcow-mail-server/mailcow-domain-anlegen_hu_6797ae0d500fc55f.webp 480w, /en/tutorials/mailcow-mail-server/mailcow-domain-anlegen_hu_b4e814a01e088b7a.webp 768w, /en/tutorials/mailcow-mail-server/mailcow-domain-anlegen_hu_1c0cf036d4519ce6.webp 1200w, /en/tutorials/mailcow-mail-server/mailcow-domain-anlegen_hu_1dfe7c2671827c6d.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/mailcow-mail-server/mailcow-domain-anlegen_hu_7f3e36bf7ca0ce0b.webp"
    alt="The dialog for adding a mail domain in mailcow." title="Create a new mail domain."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Create a new mail domain.</figcaption></figure></p>
</li>
<li>
<p>Switch to the <strong>Mailboxes</strong> tab and click <strong>Add mailbox</strong> – username, domain, full name and a <strong>strong</strong> password (password manager!). This mailbox can then log in to the webmail and via IMAP/SMTP.</p>
<p><figure class="my-6"><img src="/en/tutorials/mailcow-mail-server/mailcow-mailbox-anlegen_hu_d5141bd3c844c32b.webp" srcset="/en/tutorials/mailcow-mail-server/mailcow-mailbox-anlegen_hu_dc36f0654a230a63.webp 480w, /en/tutorials/mailcow-mail-server/mailcow-mailbox-anlegen_hu_d5141bd3c844c32b.webp 768w, /en/tutorials/mailcow-mail-server/mailcow-mailbox-anlegen_hu_8cdbd935d19994f7.webp 1200w, /en/tutorials/mailcow-mail-server/mailcow-mailbox-anlegen_hu_3393c2a56dbfed30.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/en/tutorials/mailcow-mail-server/mailcow-mailbox-anlegen_hu_28dc86b765b98908.webp"
    alt="The dialog for creating a new mailbox in mailcow." title="Create a new mailbox."
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Create a new mailbox.</figcaption></figure></p>
</li>
</ol>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Without a SOGo restart the webmail stays shut
  </p>
  <div class="prose-kitchen text-sm">SOGo reads the list of mail domains <strong>only when its container starts</strong>. If you create the first domain with &ldquo;Add domain only&rdquo;, SOGo logs <code>No authentication sources defined - nobody will be able to login</code>, and every webmail login ends on a bare <strong><code>Unauthorized</code></strong> page – even though password and mailbox are correct. Hence the second button; after the fact you get there via <strong>E-Mail → Restart SOGo</strong>. If a failed login has already been cached, restarting memcached as well helps (see &ldquo;When things go wrong&rdquo;).</div>
</div>
<p>After creating the domain, mailcow shows you the <strong>DKIM key</strong> and the recommended DNS records under the domain entry. You need those for deliverability – more on that shortly.</p>
<h3 id="step-8-test-the-webmail">Step 8: Test the webmail</h3>
<p>Open <code>https://mail.YOUR_DOMAIN/SOGo/</code> (or click <strong>Apps → Webmail</strong> at the top right in the mailcow UI). If you aren&rsquo;t signed in yet, you first land on the mailcow &ldquo;User Login&rdquo; mask – log in there with your <strong>full mail address</strong> and the mailbox password and you are passed straight through to the SOGo webmailer with inbox, calendar and contacts. A test mail from you to yourself should be in the inbox immediately – that proves that <strong>local delivery</strong>, IMAP and webmail work.</p>
<p>The real acid test, however, is sending <strong>to the outside</strong> and receiving <strong>from the outside</strong> – and that&rsquo;s exactly where it&rsquo;s decided whether your mails land in the recipient&rsquo;s inbox or spam folder. That depends on SPF, DKIM, DMARC and the PTR entry and is substantial enough for its <a href="/en/tutorials/email-deliverability/" data-track-event="Navigation|Tutorial-Link|/en/tutorials/email-deliverability/ ← /en/tutorials/mailcow-mail-server/">own recipe</a>.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Note
  </p>
  <div class="prose-kitchen text-sm">If you want to check your deliverability right away, send a mail after the setup to a test service like <a href="https://www.mail-tester.com">mail-tester.com</a> – it rates SPF, DKIM, DMARC, reverse DNS and block lists. Below 10/10 there&rsquo;s room for improvement; how you reach the full score is the topic of the deliverability tutorial.</div>
</div>
<h2 id="when-things-go-wrong">When things go wrong</h2>
<div class="troubleshoot not-prose">
<p><strong><code>generate_config.sh</code> aborts with <code>Cannot find command 'jq'</code>.</strong> the <code>jq</code> package is missing. <code>sudo apt install -y jq</code> and start the generator again.</p>
<p><strong>The generator reports &ldquo;User declined to create daemon.json&rdquo; and aborts.</strong> On hosts with active
IPv6 you answered the question about the IPv6-capable Docker configuration with <code>n</code> – without it
mailcow won&rsquo;t run there, and an open relay looms. Create <code>/etc/docker/daemon.json</code> containing
<code>{&quot;ipv6&quot;: true}</code> (Docker 28 and newer), restart Docker with <code>sudo systemctl restart docker</code> and run
<code>./generate_config.sh</code> again – or simply confirm the question with Enter on the second attempt, then
the generator does both itself.</p>
<p><strong>The webmail only answers <code>Unauthorized</code>.</strong> SOGo doesn&rsquo;t know your mail domain: it reads the domain
list exclusively at startup and wasn&rsquo;t restarted after the domain was created – its logs say <code>No authentication sources defined - nobody will be able to login</code>. Restart SOGo via <strong>E-Mail → Restart
SOGo</strong>. If that doesn&rsquo;t help, a failed login is still stuck in the cache: <code>docker compose restart memcached-mailcow sogo-mailcow</code>.</p>
<p><strong>No certificate, <code>acme-mailcow</code> keeps restarting.</strong> Let&rsquo;s Encrypt can&rsquo;t reach your server on port
80, or the A record of <code>mail.YOUR_DOMAIN</code> is wrong. check with <code>docker compose logs acme-mailcow</code>
whether the hostname and IP match, and that port 80 is open through UFW <strong>and</strong> the netcup firewall.</p>
<p><strong>Mails to the outside aren&rsquo;t delivered, logs show timeouts on port 25.</strong> Your provider blocks
outbound SMTP traffic on port 25 (common as spam protection). have port 25 enabled outbound at the
provider (at netcup via a support ticket). Without it you can&rsquo;t send mail to other servers –
receiving and local delivery still work.</p>
<p><strong>Ports 80/443 can&rsquo;t be bound (<code>address already in use</code>).</strong> A web server or reverse proxy (e.g.
Traefik) already runs on the host. mailcow belongs on its own server. At a pinch,
<code>HTTP_PORT</code>/<code>HTTPS_PORT</code> in <code>mailcow.conf</code> can be bent and mailcow put behind a proxy – but that&rsquo;s
advanced and no solution for the mail ports anyway.</p>
<p><strong>Containers start slowly or are killed by the kernel (OOM).</strong> Too little RAM. go to at least 6–8 GB
or disable ClamAV in <code>mailcow.conf</code> (<code>SKIP_CLAMD=y</code>) – the virus scanner is the biggest memory
eater.</p>

</div>

<h2 id="maintenance--backups">Maintenance &amp; backups</h2>
<p>A mail server lives off maintenance – plan it firmly.</p>
<p><strong>Updates.</strong> Mailcow brings its own update script. Run it regularly (about monthly); it updates the Compose file and all images to the latest state:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/mailcow-dockerized
</span></span><span class="line"><span class="cl">sudo ./update.sh</span></span></code></pre></div>
</div>
<p>The script automatically makes a backup of the configuration before the update and restarts the stack. Read the release notes shown – on bigger jumps, manual steps are occasionally listed there.</p>
<p><strong>Backups.</strong> Your mails, the database and the crypto keys (DKIM!) live in Docker volumes. Mailcow brings a ready-made backup script for this:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/mailcow-dockerized/helper-scripts
</span></span><span class="line"><span class="cl">sudo <span class="nv">BACKUP_LOCATION</span><span class="o">=</span>/opt/mailcow-backups ./backup_and_restore.sh backup all</span></span></code></pre></div>
</div>
<p>Then back up the target directory <strong>away from the server</strong> – cleanest encrypted with <a href="/en/tutorials/restic-backups/">Restic</a>. Especially important are the <strong>DKIM keys</strong>: if they&rsquo;re lost, your signatures break after a restore until you reset the DNS records. A backup you&rsquo;ve never restored is just a hopeful guess – test the restoration once on a test system.</p>
<p><strong>Keep an eye on reputation.</strong> Occasionally check whether your server IP has landed on a block list (e.g. via one of the common block-list checkers) and take a look at the Rspamd dashboard in the mailcow UI now and then. A hacked or misconfigured mailbox that sends spam quickly ruins the reputation of your entire domain.</p>
]]></content:encoded></item></channel></rss>