Secure the system
 
# Install UFW

(sudo apt install ufw) and enable the following ports
 
|   |   |   |   |   |
|---|---|---|---|---|
|Service|Protocol|Port|Container|Variable|
|Postfix SMTP|TCP|25|postfix-mailcow|${SMTP_PORT}|
|Postfix SMTPS|TCP|465|postfix-mailcow|${SMTP_PORT}|
|Postfix Submission|TCP|587|postfix-mailcow|${SUBMISSION_PORT}|
|Dovecot IMAP|TCP|143|dovecot-mailcow|${IMAP_PORT}|
|Dovecot IMAPS|TCP|993|dovecot-mailcow|${IMAPS_PORT}|
|Dovecot POP3|TCP|110|dovecot-mailcow|${POP_PORT}|
|Dovecot POP33S|TCP|995|dovecot-mailcow|${POPS_PORT}|
|Dovecot ManageSieve|TCP|4190|dovecot-mailcow|${SIEVE_PORT}|
|HTTP(S)|TCP|80/443|nginx-mailcow|${HTTP_PORT}` / `${HTTPS_PORT}|
   

# The minimal DNS configuration

[https://docs.mailcow.email/getstarted/prerequisite-dns/#the-minimal-dns-configuration](https://docs.mailcow.email/getstarted/prerequisite-dns/#the-minimal-dns-configuration)
 
This example shows you a set of records for one domain managed by mailcow. Each domain that is added to mailcow needs at least this set of records to function correctly.
 
`# Name Type Value mail IN A 1.2.3.4 autodiscover IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) autoconfig IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME}) @ IN MX 10 mail.example.org. (your ${MAILCOW_HOSTNAME})`
   

**Note:** The `mail` DNS record which binds the subdomain to the given ip address must only be set for the domain on which mailcow is running and that is used to access the web interface. For every other mailcow managed domain, the `MX` record will route the traffic.
   

# DKIM, SPF and DMARC

[https://docs.mailcow.email/getstarted/prerequisite-dns/#dkim-spf-and-dmarc](https://docs.mailcow.email/getstarted/prerequisite-dns/#dkim-spf-and-dmarc)
 
In the example DNS zone file snippet below, a simple **SPF** TXT record is used to only allow THIS server (the MX) to send mail for your domain. Every other server is disallowed but able to ("`~all`"). Please refer to [SPF Project](http://www.open-spf.org/) for further reading.
 
`# Name Type Value @ IN TXT "v=spf1 mx a -all"`
 
It is highly recommended to create a **DKIM** TXT record in your mailcow UI and set the corresponding TXT record in your DNS records. Please refer to [OpenDKIM](http://www.opendkim.org/) for further reading.
 
`# Name Type Value dkim._domainkey IN TXT "v=DKIM1; k=rsa; t=s; s=email; p=..."`
 
The last step in protecting yourself and others is the implementation of a **DMARC** TXT record, for example by using the [DMARC Assistant](http://www.kitterman.com/dmarc/assistant.html) ([check](https://dmarcian.com/dmarc-inspector/google.com)).
 
`# Name Type Value _dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:mailauth-reports@example.org"`
 
# Testing

[https://docs.mailcow.email/getstarted/prerequisite-dns/#testing](https://docs.mailcow.email/getstarted/prerequisite-dns/#testing)
 
Here are some tools you can use to verify your DNS configuration:
 
MX Toolbox [https://mxtoolbox.com/SuperTool.aspx](https://mxtoolbox.com/SuperTool.aspx)   (DNS, SMTP, RBL)  
port25.com [https://www.port25.com/dkim-wizard/](https://www.port25.com/dkim-wizard/)  (DKIM, SPF)  
Mail-tester [https://www.mail-tester.com/](https://www.mail-tester.com/)  (DKIM, DMARC, SPF)  
DMARC Analyzer [https://www.dmarcanalyzer.com/spf/checker/](https://www.dmarcanalyzer.com/spf/checker/)  (DMARC, SPF)  
MultiRBL.valli.org [http://multirbl.valli.org/](http://multirbl.valli.org/)  (DNSBL, RBL, FCrDNS)
 
Insure that docker and docker-compose is install and running
   

Install mailcow  
[https://docs.mailcow.email/getstarted/install/#install-mailcow](https://docs.mailcow.email/getstarted/install/#install-mailcow)
 
Clone the master branch of the repository, make sure your umask equals 0022. Please clone the repository as root user and also control the stack as root. We will modify attributes - if necessary - while bootstrapping the containers automatically and make sure everything is secured. The update.sh script must therefore also be run as root. It might be necessary to change ownership and other attributes of files you will otherwise not have access to. **We drop permissions for every exposed application** and will not run an exposed service as root! Controlling the Docker daemon as non-root user does not give you additional security. The unprivileged user will spawn the containers as root likewise. The behaviour of the stack is identical.
 
`$ su # umask 0022 # \<- Verify it is 0022  
cd /opt  
git clone [https://github.com/mailcow/mailcow-dockerized](https://github.com/mailcow/mailcow-dockerized)  
cd mailcow-dockerized`
   

# Initialize mailcow

[https://docs.mailcow.email/getstarted/install/#initialize-mailcow](https://docs.mailcow.email/getstarted/install/#initialize-mailcow)
 
Generate a configuration file. Use a FQDN (`host.domain.tld`) as hostname when asked.
 
`./generate_config.sh`
   

# Start mailcow

[https://docs.mailcow.email/getstarted/install/#start-mailcow](https://docs.mailcow.email/getstarted/install/#start-mailcow)
 
Pull the images and run the compose file. The parameter `-d` will start mailcow: dockerized detached:
 
[docker compose (Plugin)](https://docs.mailcow.email/getstarted/install/#__tabbed_1_1)[docker-compose (Standalone)](https://docs.mailcow.email/getstarted/install/#__tabbed_1_2)
 
`docker compose pull docker compose up -d`
   

- **Administrators**:  
You can now log in as an administrator using the default credentials `admin` and the password `moohoo` at:  
**`https://${MAILCOW_HOSTNAME}/admin`**   - **Regular mailbox users**:  
Continue logging in at the usual URL:  
**`https://${MAILCOW_HOSTNAME}`** (FQDN only)   - **Domain administrators**:  
Log in at the dedicated URL:  
**`https://${MAILCOW_HOSTNAME}/domainadmin