⚠️ Service Interruption: Our site is under maintenance. Some features and the mobile interface may be temporarily unresponsive. Thank you for your patience.

Full Step-by-Step Guide: Installing Mailcow via Dokploy (No SSH)

Tuwan Roshan ( Naveen )

Part 1 — Check your server has enough resources

Step 1.1 — Confirm RAM and disk

  1. Open Dokploy’s dashboard in your browser.
  2. Go to the Server section (usually in the left sidebar, sometimes under “Monitoring” or “Settings → Server”).
  3. Look at current RAM usage and disk usage, since Dokploy + Nextcloud are already running there.
  4. Mailcow needs roughly 6 GB of RAM minimum, 8 GB recommended for real use, plus around 10–15 GB of disk for containers, mail storage, and databases.
  5. If your server is close to its limits, note this now — you may need to set SKIP_CLAMD=y and SKIP_FTS=y later (Part 4) to reduce RAM usage, or upgrade the server before continuing.

Step 1.2 — Confirm which ports are already in use

  1. In Dokploy, check each existing service (Nextcloud, Dokploy itself) for which ports/domains they’re bound to.
  2. Note whether ports 8080 and 8443 are free. These are the two ports mailcow’s web interface will use internally (Part 4 sets this).
  3. If either is already taken by another service, you’ll pick different numbers in Part 4 — just keep this in mind.

Part 2 — Set up DNS in Cloudflare

Step 2.1 — Log into Cloudflare

  1. Go to https://dash.cloudflare.com in your browser.
  2. Select the domain you want to use for mail (e.g. yourdomain.com).
  3. Click into the DNS section from the left sidebar.

Step 2.2 — Add the mail subdomain A record

  1. Click Add record.
  2. Set Type to A.
  3. Set Name to mail (this creates mail.yourdomain.com).
  4. Set IPv4 address to your server’s public IP address.
  5. Set Proxy status to DNS only (grey cloud icon, not orange). This step matters a lot — if it’s left orange/proxied, Cloudflare will try to route the traffic through its HTTP proxy, which breaks SMTP/IMAP entirely and can also break the TLS certificate issuance later.
  6. Click Save.

Step 2.3 — Add the MX record

  1. Click Add record again.
  2. Set Type to MX.
  3. Set Name to @ (this represents your root domain, yourdomain.com).
  4. Set Mail server to mail.yourdomain.com.
  5. Set Priority to 10.
  6. Click Save.

Step 2.4 — Add the SPF record

  1. Click Add record.
  2. Set Type to TXT.
  3. Set Name to @.
  4. Set Content to:
   v=spf1 mx ~all
  1. Click Save.

Step 2.5 — Add the DMARC record

  1. Click Add record.
  2. Set Type to TXT.
  3. Set Name to _dmarc.
  4. Set Content to (replace the email with your own inbox where you want DMARC reports sent):
   v=DMARC1; p=quarantine; rua=mailto:[email protected]
  1. Click Save.

Step 2.6 — Leave DKIM for later

You cannot create the DKIM record yet — mailcow generates the actual key itself after it’s running (Part 7 covers this). Just keep the Cloudflare DNS tab open or bookmarked, since you’ll come back to it.


Part 3 — Set up reverse DNS (PTR) with your hosting provider

Cloudflare cannot do this part — PTR records belong to whoever owns your server’s IP address block, which is your VPS/hosting provider, not your DNS registrar.

Step 3.1 — Find the PTR/rDNS setting

  1. Log into your hosting provider’s dashboard (Hetzner, DigitalOcean, Contabo, Vultr, etc. — whichever one hosts your server).
  2. Navigate to your specific server/instance.
  3. Look for a section named Reverse DNS, rDNS, PTR Record, or sometimes found under Networking or IP Management.

Step 3.2 — Set the PTR value

  1. Enter mail.yourdomain.com as the reverse DNS value for your server’s IP address.
  2. Save the change.
  3. Note that propagation for PTR records can take anywhere from a few minutes to a few hours depending on the provider.

Step 3.3 — If your provider doesn’t expose this in their panel

  1. Open a support ticket with your provider through their web-based support system (still no SSH required).
  2. Ask them to set the PTR record for your IP to mail.yourdomain.com.
  3. Wait for their confirmation before moving on to sending real mail — inbound mail servers check this and will often reject or spam-flag mail from IPs without matching rDNS.

Part 4 — Create the Compose service in Dokploy

Step 4.1 — Start a new project (or use an existing one)

  1. In Dokploy’s dashboard, click Projects in the sidebar.
  2. Either click into your existing project (if you want mailcow alongside Nextcloud) or click Create Project to make a dedicated one for mailcow.

Step 4.2 — Create the Compose service

  1. Inside the project, click Create Service.
  2. Choose Compose as the service type (not “Application” and not “Database” and not “Template”).
  3. Give it a name, e.g. mailcow.

Step 4.3 — Set the source to raw/paste

  1. In the service’s Source settings, look for the source-type selector.
  2. Choose the option for pasting the compose file directly (sometimes labeled “Raw”, “Editor”, or you simply get a code-editor box by default when you don’t connect a Git provider).
  3. Open the docker-compose.yml file you downloaded earlier on your own computer.
  4. Copy its entire contents.
  5. Paste the entire contents into Dokploy’s compose editor, replacing any placeholder/default content that was there.
  6. Click Save on that section.

Part 5 — Set environment variables in Dokploy

Step 5.1 — Open the Environment tab

  1. In the same Compose service, click the Environment (or Env Vars) tab.
  2. You’ll see a text box or key/value list where you can enter variables.

Step 5.2 — Enter the core required variables

Add each of these on its own line (or its own key/value row, depending on Dokploy’s UI):

MAILCOW_HOSTNAME=mail.yourdomain.com

Replace yourdomain.com with your actual domain — this must exactly match the A record you created in Step 2.2.

DBNAME=mailcow
DBUSER=mailcow

These can stay as-is unless you have a reason to change them.

DBPASS=<generate a strong password>
DBROOT=<generate a different strong password>

Use a password generator (Dokploy’s UI may have a built-in random-value button — look for a dice/refresh icon next to the field). Make sure DBPASS and DBROOT are different from each other. Store both somewhere safe, like a password manager, since you won’t be shown them again through the Dokploy UI after saving.

TZ=Continent/City

Replace with your actual timezone, e.g. Europe/Berlin or Asia/Colombo.

Step 5.3 — Enter the port variables

HTTP_PORT=8080
HTTPS_PORT=8443

These control the internal port mailcow’s web UI listens on. They were already set as the ports mapping default in your compose file, but setting them explicitly here avoids any ambiguity. If you found in Step 1.2 that 8080 or 8443 are already used by another service, change these to something else free, e.g. 8081/8444.

Step 5.4 — Enter the certificate variable

SKIP_LETS_ENCRYPT=y

This is important. It tells mailcow’s own certificate container not to try to issue a Let’s Encrypt certificate itself — because Traefik (via Dokploy) is going to handle that instead, using the labels already built into your compose file. If you skip this, mailcow’s ACME container and Dokploy’s Traefik will both try to grab port 443/80 and conflict with each other.

Step 5.5 — Optional: reduce resource usage

If Step 1.1 showed your server is tight on RAM, also add:

SKIP_CLAMD=y
SKIP_FTS=y

SKIP_CLAMD disables antivirus scanning of incoming mail. SKIP_FTS disables full-text search indexing of mailbox contents. Both are safe to skip for a small personal setup, though SKIP_CLAMD=y does mean incoming attachments won’t be virus-scanned.

Step 5.6 — Save

  1. Click Save on the Environment tab.
  2. Dokploy will write these into a .env file that sits next to your compose file — this is what the ${VARIABLE} references throughout the compose file will pick up automatically.

Part 6 — Deploy

Step 6.1 — Trigger the deployment

  1. Go back to the Compose service’s main page.
  2. Click the Deploy button (usually top-right).

Step 6.2 — Watch the logs

  1. Click into the Logs or Deployments tab.
  2. You’ll see Docker pulling around 15–18 images (unbound, mysql, redis, postfix, dovecot, nginx, sogo, rspamd, and several others). This can take several minutes depending on your server’s internet speed.
  3. Once images are pulled, containers start one by one. Watch for any container repeatedly restarting/crashing — that usually points to a missing or wrong environment variable from Part 5.

Step 6.3 — Confirm all containers are healthy

  1. In the service’s Overview or Containers tab, check that each of the ~18 containers shows a “running” or “healthy” status.
  2. mysql-mailcow and unbound-mailcow typically start first, since other containers depend on them.
  3. Give it 3–5 minutes after all containers show “running” before testing — some internal setup (database migrations, key generation) happens automatically on first boot.

Part 7 — Point the domain and check the certificate

Step 7.1 — Add the domain in Dokploy (if not automatic)

  1. Because the Traefik labels are already baked into your compose file, Dokploy should route mail.yourdomain.com automatically. Check the Domains tab on the Compose service to confirm it’s listed.
  2. If it isn’t listed automatically, click Add Domain, enter mail.yourdomain.com, select the nginx-mailcow service/container, and set the port to 8443 (or whatever you set HTTPS_PORT to in Step 5.3).

Step 7.2 — Confirm the certificate issued correctly

  1. Open https://mail.yourdomain.com in your browser.
  2. If the certificate is valid (padlock icon, no warning), Traefik successfully issued a Let’s Encrypt certificate.
  3. If you get a certificate warning, check: (a) that the Cloudflare A record from Step 2.2 is set to DNS only, not proxied — Let’s Encrypt needs to reach the server directly to verify domain ownership, and (b) that enough time has passed for DNS to propagate (can take up to a few hours, though usually much faster).

Part 8 — First login and initial mailcow setup

Step 8.1 — Log in

  1. At https://mail.yourdomain.com, you’ll see the mailcow login screen.
  2. Username: admin
  3. Password: moohoo

Step 8.2 — Change the admin password immediately

  1. Once logged in, click the admin/gear icon (top right).
  2. Go to Admin Details or Edit Admin Details.
  3. Set a new, strong password.
  4. Save.

Step 8.3 — Add your mail domain inside mailcow

  1. Go to Email → Domains (or similar, under the admin panel’s mail section).
  2. Click Add domain.
  3. Enter yourdomain.com (without the mail. prefix — this is the domain mail will actually be sent/received from, e.g. [email protected]).
  4. Leave the default quota/mailbox settings unless you have specific limits in mind.
  5. Save.

Step 8.4 — Generate the DKIM key

  1. Go to Configuration → ARC/DKIM keys (exact menu wording can vary slightly by version).
  2. Select the domain you just added.
  3. Click Add DKIM key (2048-bit is the standard recommended size).
  4. Mailcow will display a DNS record it wants you to add — it’ll look like a long TXT value under a name like dkim._domainkey.yourdomain.com.
  5. Copy this value — you’ll need the exact selector name and the exact content.

Step 8.5 — Add the DKIM record in Cloudflare

  1. Go back to your open Cloudflare DNS tab.
  2. Click Add record.
  3. Set Type to TXT.
  4. Set Name to exactly what mailcow showed you (e.g. dkim._domainkey).
  5. Set Content to exactly the value mailcow generated (usually starts with v=DKIM1; k=rsa; p=...).
  6. Click Save.
  7. Back in mailcow’s admin panel, there’s usually a “Verify DKIM” or similar check button — use it once DNS has propagated to confirm it’s picked up correctly.

Step 8.6 — Create your first mailbox

  1. Go to Email → Mailboxes.
  2. Click Add mailbox.
  3. Fill in the local part (e.g. you), select the domain (yourdomain.com), and set a password for this mailbox.
  4. Save.
  5. This mailbox ([email protected]) is now ready to send/receive mail, and can be added to any email client using IMAP/SMTP settings shown in mailcow’s documentation panel.

Part 9 — Verify everything end-to-end

Step 9.1 — Test deliverability

  1. Go to https://www.mail-tester.com in your browser.
  2. It will give you a temporary email address.
  3. From your new mailcow mailbox (either via the built-in webmail at https://mail.yourdomain.com/SOGo/ or a mail client), send a test email to that address.
  4. Go back to mail-tester.com and check your score — it will separately confirm whether SPF, DKIM, DMARC, and rDNS all pass.

Step 9.2 — Fix anything that’s flagged

Step 9.3 — Confirm mail ports are reachable from outside

  1. From a different network (e.g. your phone on mobile data, not the same WiFi as your server), try connecting to mail.yourdomain.com on ports 25, 465, 587, 993 using any online “port checker” tool (search for “open port checker” and enter your domain and each port number one at a time).
  2. If any of these show closed, double-check your server/provider’s external firewall (separate from Docker) isn’t blocking them — this is usually a setting in your hosting provider’s dashboard, again no SSH needed.

You’re done. From here, ongoing management (adding more mailboxes, aliases, spam settings, quotas) all happens through the https://mail.yourdomain.com admin panel — no further server-level configuration needed for day-to-day use.

Leave a Reply

Your email address will not be published. Required fields are marked *