Compare commits
No commits in common. "dc3e15e433189004d9ace47296c019ce122d7041" and "acc089f798d50054ad1dcc673e95ea0f6bca90b0" have entirely different histories.
dc3e15e433
...
acc089f798
2 changed files with 9 additions and 86 deletions
|
@ -1,6 +1,6 @@
|
||||||
+++
|
+++
|
||||||
date = '2024-11-24T16:29:01Z'
|
date = '2024-11-19T16:29:01Z'
|
||||||
draft = false
|
draft = true
|
||||||
title = 'How to Set up a Mail Server on Alpine Linux with Postfix and Dovecot'
|
title = 'How to Set up a Mail Server on Alpine Linux with Postfix and Dovecot'
|
||||||
tags = ['mail server', 'alpine linux', 'postfix', 'dovecot']
|
tags = ['mail server', 'alpine linux', 'postfix', 'dovecot']
|
||||||
+++
|
+++
|
||||||
|
@ -493,41 +493,7 @@ Now let's enable IMAP by editing `/etc/dovecot/dovecot.conf`. Find a `protocols
|
||||||
protocols = imap
|
protocols = imap
|
||||||
```
|
```
|
||||||
|
|
||||||
## Logging
|
## Configure how to store emails
|
||||||
|
|
||||||
By default, Dovecot logs to the syslog (`/var/log/messages`). It would be easier to monitor Dovecot if it logged to its
|
|
||||||
own log file, so we'll configure that at `/etc/dovecot/conf.d/10-logging.conf`:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
log_path = /var/log/dovecot.log
|
|
||||||
```
|
|
||||||
|
|
||||||
The file also has various settings on logging verbosity you can configure. I set:
|
|
||||||
|
|
||||||
```conf
|
|
||||||
auth_verbose = yes
|
|
||||||
auth_debug = yes
|
|
||||||
mail_debug = yes
|
|
||||||
```
|
|
||||||
|
|
||||||
You should already have an `/etc/logrotate.d/dovecot` file. If not, create it with the following contents:
|
|
||||||
|
|
||||||
```logrotate
|
|
||||||
/var/log/dovecot*.log {
|
|
||||||
daily
|
|
||||||
missingok
|
|
||||||
copytruncate
|
|
||||||
rotate 7
|
|
||||||
compress
|
|
||||||
notifempty
|
|
||||||
sharedscripts
|
|
||||||
postrotate
|
|
||||||
/etc/init.d/dovecot --quiet --ifstarted reopen
|
|
||||||
endscript
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configure IMAP and email storage
|
|
||||||
|
|
||||||
You probably want to use the Maildir format for storing emails, where each user's mail is stored at `~/Maildir` (this
|
You probably want to use the Maildir format for storing emails, where each user's mail is stored at `~/Maildir` (this
|
||||||
can be set to another location if desired).
|
can be set to another location if desired).
|
||||||
|
@ -1368,7 +1334,7 @@ The `fo` tag indicates when you would like to receive reports. The options are:
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### OpenDMARC[^spf_processing_redundancy] {#opendmarc}
|
### OpenDMARC
|
||||||
|
|
||||||
We can use software called OpenDMARC to enforce DMARC policies for incoming mail. OpenDMARC is another milter. Let's
|
We can use software called OpenDMARC to enforce DMARC policies for incoming mail. OpenDMARC is another milter. Let's
|
||||||
install it and enable its service:
|
install it and enable its service:
|
||||||
|
@ -1478,14 +1444,14 @@ Restart Postfix for the changes to take effect:
|
||||||
And when you receive emails from a legitimate source that implements DMARC, you should see the following headers in
|
And when you receive emails from a legitimate source that implements DMARC, you should see the following headers in
|
||||||
your emails:
|
your emails:
|
||||||
|
|
||||||
<pre id="double-spf-headers">
|
```
|
||||||
<code>Received-SPF: pass (protonmail.com: Sender is authorized to use 'revsuine@protonmail.com' in 'mfrom' identity (mechanism 'include:_spf.protonmail.ch' matched)) receiver=master.revsuine.xyz; identity=mailfrom; envelope-from="revsuine@protonmail.com"; helo=mail-40130.protonmail.ch; client-ip=185.70.40.130
|
Received-SPF: pass (protonmail.com: Sender is authorized to use 'revsuine@protonmail.com' in 'mfrom' identity (mechanism 'include:_spf.protonmail.ch' matched)) receiver=master.revsuine.xyz; identity=mailfrom; envelope-from="revsuine@protonmail.com"; helo=mail-40130.protonmail.ch; client-ip=185.70.40.130
|
||||||
DMARC-Filter: OpenDMARC Filter v1.4.2 master.revsuine.xyz 88CFF1288D1
|
DMARC-Filter: OpenDMARC Filter v1.4.2 master.revsuine.xyz 88CFF1288D1
|
||||||
Authentication-Results: OpenDMARC; dmarc=pass (p=quarantine dis=none) header.from=protonmail.com
|
Authentication-Results: OpenDMARC; dmarc=pass (p=quarantine dis=none) header.from=protonmail.com
|
||||||
Authentication-Results: OpenDMARC; spf=pass smtp.mailfrom=protonmail.com
|
Authentication-Results: OpenDMARC; spf=pass smtp.mailfrom=protonmail.com
|
||||||
Authentication-Results: master.revsuine.xyz;
|
Authentication-Results: master.revsuine.xyz;
|
||||||
dkim=pass (2048-bit key; secure) header.d=protonmail.com header.i=@protonmail.com header.a=rsa-sha256 header.s=protonmail3 header.b=nc4YWVM/</code>
|
dkim=pass (2048-bit key; secure) header.d=protonmail.com header.i=@protonmail.com header.a=rsa-sha256 header.s=protonmail3 header.b=nc4YWVM/
|
||||||
</pre>
|
```
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
TODO: switch SPF filter to a milter e.g. https://www.acme.com/software/spfmilter/ so that SPF isn't checked twice
|
TODO: switch SPF filter to a milter e.g. https://www.acme.com/software/spfmilter/ so that SPF isn't checked twice
|
||||||
|
@ -1857,25 +1823,6 @@ you would write `"Inbox.Spam"` in that case.
|
||||||
|
|
||||||
# Miscellaneous suggestions
|
# Miscellaneous suggestions
|
||||||
|
|
||||||
To use fail2ban for your mail server, create `/etc/fail2ban/jail.d/mail.local`:
|
|
||||||
|
|
||||||
```ini
|
|
||||||
[postfix]
|
|
||||||
enabled = true
|
|
||||||
logpath = /var/log/postfix.log
|
|
||||||
|
|
||||||
[dovecot]
|
|
||||||
enabled = true
|
|
||||||
logpath = /var/log/dovecot.log
|
|
||||||
|
|
||||||
[sieve]
|
|
||||||
enabled = true
|
|
||||||
logpath = /var/log/dovecot.log
|
|
||||||
```
|
|
||||||
|
|
||||||
These are the log file locations we configured above, but you can set them to the syslog if you didn't give Postfix and
|
|
||||||
Dovecot their own log files.
|
|
||||||
|
|
||||||
You may want to get your domain whitelisted on [dnswl.org](https://www.dnswl.org/), an email whitelist service where
|
You may want to get your domain whitelisted on [dnswl.org](https://www.dnswl.org/), an email whitelist service where
|
||||||
admins can submit their domain and IP address to indicate trustworthiness.
|
admins can submit their domain and IP address to indicate trustworthiness.
|
||||||
|
|
||||||
|
@ -1910,26 +1857,3 @@ admins can submit their domain and IP address to indicate trustworthiness.
|
||||||
|
|
||||||
to find out where this file should be.
|
to find out where this file should be.
|
||||||
|
|
||||||
[^spf_processing_redundancy]: The OpenDMARC milter will be run before the SPF policy daemon, meaning that OpenDMARC
|
|
||||||
must do its own SPF checking. This makes postfix-policyd-spf-perl redundant, and results in multiple SPF checks in
|
|
||||||
our email headers (e.g. see email headers [here](#double-spf-headers)).
|
|
||||||
|
|
||||||
To get around this, you'd probably have to use a milter to validate SPF, and just list the milter before OpenDMARC.
|
|
||||||
I had a bit of a look around for SPF milters and found [ACME's
|
|
||||||
spfmilter](https://www.acme.com/software/spfmilter/), but had issues compiling it on Alpine; it complained about
|
|
||||||
|
|
||||||
```
|
|
||||||
spfmilter.c:1623:2: error: #error "neither libspf nor libspf2 is present - please provide one"
|
|
||||||
1623 | #error "neither libspf nor libspf2 is present - please provide one"
|
|
||||||
| ^~~~~
|
|
||||||
```
|
|
||||||
|
|
||||||
despite having `libspf2` installed. Potentially this is a musl issue, but I'm doubtful that a project like this
|
|
||||||
would be tied to glibc specifically.
|
|
||||||
|
|
||||||
I tried compiling it on Artix Linux and it compiled just fine with the right dependencies installed, so the program
|
|
||||||
does compile.
|
|
||||||
|
|
||||||
If anyone can either [suggest](/contact) a way to get ACME's spfmilter to compile on Alpine, or an alternative
|
|
||||||
solution to this problem, that would be helpful.
|
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,7 @@ theme = 'terminal'
|
||||||
|
|
||||||
# set post to show the last updated
|
# set post to show the last updated
|
||||||
# If you use git, you can set `enableGitInfo` to `true` and then post will automatically get the last updated
|
# If you use git, you can set `enableGitInfo` to `true` and then post will automatically get the last updated
|
||||||
showLastUpdated = true
|
showLastUpdated = false
|
||||||
enableGitInfo = true
|
|
||||||
|
|
||||||
# Provide a string as a prefix for the last update date. By default, it looks like this: 2020-xx-xx [Updated: 2020-xx-xx] :: Author
|
# Provide a string as a prefix for the last update date. By default, it looks like this: 2020-xx-xx [Updated: 2020-xx-xx] :: Author
|
||||||
# updatedDatePrefix = "Updated"
|
# updatedDatePrefix = "Updated"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue