summaryrefslogtreecommitdiff
path: root/_posts/2016-10-31-freebsd-mailserver-part-2-mailing-with-postfix.md
blob: 1818c9b6fde1f886d8b09d42260b8e20eff18738 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
---
title: "FreeBSD email server - Part 2: Mailing with Postfix"
date: 2016-10-31 07:57:50
tags: Tutorial FreeBSD Email Postfix
layout: post
---

Welcome to the second part of my FreeBSD email server series. In this series, I
will guide you through setting up your own email service. Be sure to done the
preparations from [part 1][part-1] of this series.

This part will guide you through setting up email service on your machine using
[Postfix][postfix]. Basic installation is pretty straightforward, but there is
a lot to configure. If you are not sure what some configuration options do,
please read up on them. There is a lot to do wrong with a mail server, and
doing things wrong will likely get you on a blacklist which will make other
servers stop processing the mail you are trying to send out.

Setting up Postfix is one of the harder parts of configuring a mail server. If
you have questions after reading the full guide, please find me on IRC. You can
find details on how to do so on [my homepage][home].

## Installing Postfix
Installation procedures on FreeBSD are pretty straightforward. Unlike `certbot`
from the previous part, we will need to compile Postfix from source in order to
use PostgreSQL as a database back-end. Thanks to FreeBSD's
[ports][freebsd-ports], this is not difficult either. If this is your first
port to compile, you probably need to get the ports tree first. You can
download and extract this using the following command.

{% highlight sh %}
portsnap fetch extract
{% endhighlight %}

Once that has finished running, go into the directory containing the build
instructions for Postfix, and start the installation process.

{% highlight sh %}
cd /usr/ports/mail/postfix
make configure install
{% endhighlight %}

This will open a pop up with a number of options you can enable or disable. The
enabled defaults are fine, but you will have to enable the `PGSQL` option. This
will allow you to use the configuration tables created in part 1.

## Enabling Postfix
Enable the Postfix service for rcinit. This allows you to use `service postfix
start` once configuration is done, and will auto start the service on system
boot. In addition, the default mailer on FreeBSD, [sendmail][sendmail] should
be disabled so nothing is in Postfix's way when trying to deal with processing
email traffic.

{% highlight sh %}
# disable the default sendmail system
echo 'daily_clean_hoststat_enable="NO"' >> /etc/periodic.conf.local
echo 'daily_status_mail_rejects_enable="NO"' >> /etc/periodic.conf.local
echo 'daily_status_include_submit_mailq="NO"' >> /etc/periodic.conf.local
echo 'daily_submit_queuerun="NO"' >> /etc/periodic.conf.local
echo 'sendmail_enable="NONE"' >> /etc/rc.conf.local

# enable postfix
echo 'postfix_enable="YES"' >> /etc/rc.conf.local
{% endhighlight %}

## Configuring Postfix
There is a ton to configure for Postfix. This configuration happens in two
files, `main.cf` and `master.cf`. Additionally, as some data is in the
PostgreSQL database, three files with information on how to query for this
information are needed. All of these files are in `/usr/local/etc/postfix`.

The guide has a comment line for most blocks. It is advised that **if** you
decide to just copy and paste the contents, you copy that along so you have
some sort of indication of what is where. This could help you out if you ever
need to change anything later on.

### main.cf
#### Compatibility
The configuration file starts off by setting the compatibility level. If
postfix updates the configuration scheme and deprecates certain options, you
will be notified of this in the logs.

{% highlight ini %}
# compatibility
compatibility_level = 2
{% endhighlight %}

#### Directory paths
These options indicate where Postfix will look and keep certain files required
for correct operation.

{% highlight ini %}
# directory paths
queue_directory = /var/spool/postfix
command_directory = /usr/local/sbin
daemon_directory = /usr/local/libexec/postfix
data_directory = /var/db/postfix
{% endhighlight %}

#### Domain configuration
The domain configuration instruct the server of the domain(s) it should serve
for. Use your FQDN without sub domains for `mydomain`. You can use a sub domain
for `myhostname`, but you are not required to. The most common setting is
using a `mail` sub domain for all mail related activities, which would
result in something like this.

{% highlight ini %}
# domain configuration
myhostname = mail.domain.tld
mydomain = domain.tld
myorigin = $mydomain
{% endhighlight %}

#### Listening directives
All internet devices it should listen on, and all domains this server should
consider itself the endpoint for, should be listed here. The defaults in the
example block are good enough, as we put some of our data in the PostgreSQL
database instead.

{% highlight ini %}
# listening directives
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost
{% endhighlight %}

#### Reject unknown recipients
How to deal with messages sent to an email address whose domain points to your
server's address, but have no actual mailbox. A code of `550` means to inform
the remote server that delivery is not possible and will not be possible. This
should stop the remote server from trying it again.

{% highlight ini %}
# reject unknown recipients
unknown_local_recipient_reject_code = 550
{% endhighlight %}

#### Trust
{% highlight ini %}
# trust
mynetworks_style = host
{% endhighlight %}

#### Address extensions
This block is optional. It allows you to use email address extensions. These
are addresses with an additional character in them that will drop the email in
the non extended address' mailbox, but allows you to quickly filter on them as
the sent-to address contains the extension.

{% highlight ini %}
# address extensions
recipient_delimiter = +
{% endhighlight %}

#### Virtual domain directives
This part is where things get important. Virtual domains allow you to handle
mail for a large number of domains that are different from the actual server's
domain. This is where the database configuration comes in to play. It is
important to note the `static:125` values. The `125` should map to the `UID` of
the `postfix` user account on your system.

{% highlight ini %}
# virtual domain directives
virtual_mailbox_base = /srv/mail
virtual_mailbox_domains = pgsql:/usr/local/etc/postfix/pgsql-virtual-domains.cf
virtual_mailbox_maps = pgsql:/usr/local/etc/postfix/pgsql-virtual-users.cf
virtual_alias_maps = pgsql:/usr/local/etc/postfix/pgsql-virtual-aliases.cf
virtual_uid_maps = static:125
virtual_gid_maps = static:125
virtual_transport = lmtp:unix:private/dovecot-lmtp
{% endhighlight %}

#### TLS setup
The TLS setup configures your server to use secure connections. The keys used
here have been generated in the previous part of this series.

{% highlight ini %}
# TLS setup
smtpd_tls_cert_file = /usr/local/etc/letsencrypt/live/domain.tld/fullchain.pem
smtpd_tls_key_file = /usr/local/etc/letsencrypt/live/domain.tld/privkey.pem
smtpd_use_tls = yes
smtpd_tls_auth_only = yes
{% endhighlight %}

#### SASL setup
SASL deals with the authentication of the users to your email server.

{% highlight ini %}
# SASL setup
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions =
    permit_sasl_authenticated,
    permit_mynetworks,
    reject_unauth_destination
smtpd_relay_restrictions =
    permit_sasl_authenticated,
    permit_mynetworks,
    reject_unauth_destination
{% endhighlight %}

#### Debugging
The debugging options are generally useful in case things break. If you have
little traffic, you could leave them on forever in case you want to debug
something later on. Once your server is working as intended, you should turn
these options off. The postfix logs get pretty big in a short amount of time.

{% highlight ini %}
# debugging
debug_peer_level = 2
debugger_command =
    PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/binary
    ddd $daemon_directory/$process_name $process_id & sleep 5
{% endhighlight %}

#### Installation time defaults
These options should not be touched, but are very important to have for your
server.

{% highlight ini %}
# install-time defaults
sendmail_path = /usr/local/sbin/sendmail
newaliases_path = /usr/local/bin/newaliases
mailq_path = /usr/local/bin/mailq
setgid_group = maildrop
html_directory = /usr/local/share/doc/postfix
manpage_directory = /usr/local/man
sample_directory = /usr/local/etc/postfix
readme_directory = /usr/local/share/doc/postfix
inet_protocols = ipv4
meta_directory = /usr/local/libexec/postfix
shlib_directory = /usr/local/lib/postfix
{% endhighlight %}

### master.cf
For the `master.cf` file, you can use the following configuration block.

{% highlight cfg %}
submission    inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
pickup        unix  n       -       n       60      1       pickup
cleanup       unix  n       -       n       -       0       cleanup
qmgr          unix  n       -       n       300     1       qmgr
tlsmgr        unix  -       -       n       1000?   1       tlsmgr
rewrite       unix  -       -       n       -       -       trivial-rewrite
bounce        unix  -       -       n       -       0       bounce
defer         unix  -       -       n       -       0       bounce
trace         unix  -       -       n       -       0       bounce
verify        unix  -       -       n       -       1       verify
flush         unix  n       -       n       1000?   0       flush
proxymap      unix  -       -       n       -       -       proxymap
proxywrite    unix  -       -       n       -       1       proxymap
smtp          unix  -       -       n       -       -       smtp
relay         unix  -       -       n       -       -       smtp
showq         unix  n       -       n       -       -       showq
error         unix  -       -       n       -       -       error
retry         unix  -       -       n       -       -       error
discard       unix  -       -       n       -       -       discard
local         unix  -       n       n       -       -       local
virtual       unix  -       n       n       -       -       virtual
lmtp          unix  -       -       n       -       -       lmtp
anvil         unix  -       -       n       -       1       anvil
scache        unix  -       -       n       -       1       scache
{% endhighlight %}

### SQL query files
The following three configuration files deal with the SQL query files to make
Postfix able of getting some of its configuration from a database. You
obviously have to change the first 4 directives to match your database
authentication credentials.

#### pgsql-virtual-domains.cf
{% highlight ini %}
user = postgres
password = incredibly-secret!
hosts = 127.1
dbname = mail
query = SELECT 1 FROM domains WHERE name='%s';
{% endhighlight %}

#### pgsql-virtual-users.cf
{% highlight ini %}
user = postgres
password = incredibly-secret!
hosts = 127.1
dbname = mail
query = SELECT 1 FROM users WHERE local='%u' AND domain='%d';
{% endhighlight %}

#### pgsql-virtual-aliases.cf
{% highlight ini %}
user = postfix
password = nope
hosts = 127.1
dbname = mail
query = SELECT destination FROM aliases WHERE origin='%s';
{% endhighlight %}

## Conclusion
This should be enough Postfix configuration, for now. Next part involves
Dovecot, which will enable IMAP. It will also provide the SASL mechanism
defined in this part.

[freebsd-ports]: https://www.freebsd.org/ports/
[home]: {{ "/" | prepend: site.baseurl }}
[part-1]: {{ "/post/2016/10/31/freebsd-mailserver-part-1-preparations/" | prepend: site.baseurl }}
[postfix]: http://www.postfix.org/
[sendmail]: http://www.sendmail.com/sm/open_source/