I decided to use Arch Linux ARM (ALARM) as the OS for a few reasons - Arch Linux has very good support for the ARM SoC ecosystem, by default it installs as a minimal OS so you only add components you need, and it is a rolling-release OS. There are positives and negatives to both rolling updates and standard versions, but in this case I am interested in removing as many barriers to maintaining a secure system as possible, as my IT support time is limited. Upgrading between major releases often requires coordinating backups, downtime, updating conf files, etc. and hence tends to be put off creating a security risk. This can be avoided with rolling updates.
By default, ALARM partitions the SD card for the pi with a 2GB main partition regardless of the size of the SD card, which is sufficient for the OS, but not for our server. You can either add another partition, or simply increase the size of the main partition. Jan has a very good post outlining how to grow the pi main partition under Arch, which can even be done on a live boot.
By default, the pi reserves a large fraction of the memory for video processing or GPIO connections. For our server we don't need any memory for the GPU, and we are tight for memory on the model A, so we need to modify the boot config. With the latest firmware, the pi is supposed to automagically adjust the GPU memory based upon load using the cma_lwm and cma_hwm (low/high water mark) variables in /boot/config.txt. In my testing with Arch Linux, this did not happen, and the majority of the memory is never accessible to the cpu. I adjusted this behavior using the gpu_mem_256 variable in /boot/config.txt. By default this is set to 128, which reserves 128M of memory for the GPU. It appears the OS is maintaining gpu_mem_256 + cam_lwm for the OS, so by default the model A is left with only 112M, which is not enough even for a small server. On a test card I increased gpu_mem_256 by 16M increments starting at 16M, until I got the system to boot. It required gpu_mem_256=48 to boot, and testing has verified that roughly 64M is reserved for the GPU, but this leaves enough free for our server needs.
The pi does not have a hardware clock. I installed fake-hwclock, which fixes some problems, but not all. The default UNIX date is midnight Dec. 31, 1969. openssl would not budge on this date, so I ended up creating my ssl certs on another box and copying them over. In the end, this is a probably an inadvertent security feature.
postfix+dovecot+dspam
There are many pages that cover configuring postfix, dovecot, and dspam, so I'll only focus here on specifics for the ALARM pi.
The pi disables IPv6 by default, so both dovecot and postfix need to be told to only use IPv4. For postfix, set "inet_protocols = ipv4" in /etc/postfix/main.cf. For dovecot, set "listen = *" in /etc/dovecot/dovecot.conf.
dovecot uses internal protection to avoid runaway memory allocation. For the model A I set "default_vsz_limit = 192M" in /etc/dovecot/conf.d/10-master.conf, which, as noted above, is the memory available for the cpu.
I don't use virtual mailboxes. For local delivery I'm using dovecot's lmtp program by setting "mailbox_transport = lmtp:unix:private/dovecot-lmtp" in /etc/postfix/main.cf.
The two main choices for spam filtering are dspam and spamassassin. I chose dspam mainly because it uses far less memory than spamassassin. Just firing up spamassassin was using roughly 20M of memory, which is significant on the pi.
I configured dspam to act as a postfix content filter and then re-inject the mail back to postfix. This simplifies the configuration as dspam and dovecot are decoupled - postfix and dspam communicate, and postfix and dovecot communicate, and each can be configured separately.
smtp inet n - n - - smtpd
-o content_filter=lmtp:unix:/run/dspam/dspam.sock
The pi disables IPv6 by default, so both dovecot and postfix need to be told to only use IPv4. For postfix, set "inet_protocols = ipv4" in /etc/postfix/main.cf. For dovecot, set "listen = *" in /etc/dovecot/dovecot.conf.
dovecot uses internal protection to avoid runaway memory allocation. For the model A I set "default_vsz_limit = 192M" in /etc/dovecot/conf.d/10-master.conf, which, as noted above, is the memory available for the cpu.
I don't use virtual mailboxes. For local delivery I'm using dovecot's lmtp program by setting "mailbox_transport = lmtp:unix:private/dovecot-lmtp" in /etc/postfix/main.cf.
The two main choices for spam filtering are dspam and spamassassin. I chose dspam mainly because it uses far less memory than spamassassin. Just firing up spamassassin was using roughly 20M of memory, which is significant on the pi.
I configured dspam to act as a postfix content filter and then re-inject the mail back to postfix. This simplifies the configuration as dspam and dovecot are decoupled - postfix and dspam communicate, and postfix and dovecot communicate, and each can be configured separately.
This is done by telling dspam to send output to a port on the localhost, in this case we use port 10026. The relevant lines in /etc/dspam/dspam.conf are
DeliveryHost 127.0.0.1
DeliveryPort 10026
DeliveryIdent localhost
DeliveryProto SMTP
The two relevant lines in /etc/postfix/master.cf are
-o content_filter=lmtp:unix:/run/dspam/dspam.sock
# reinjection from dspam
localhost:10026 inet n - n - - smtpd
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
The first line sends incoming mail to dspam, and the second receives the dspam output on port 10026. postfix then sends the mail to dovecot for delivery.
That's about it. For my domain this setup typically consumes about 140M of memory.
No comments:
Post a Comment