joeyh

joeyh at

Doing a from-scratch rebuild of my mail server this evening. These 90 lines of haskell code set everything up.

A little OTT perhaps, but I think I understand my setup better now, and can find it all in one place when I need to refresh. Also, I'll never forget to run postmap or newaliases when changing a file, since that's automated too.

Also, I'll probably refactor this initial code dump into something less horrrible later.

kiteMailServer :: Property
kiteMailServer = propertyList "kitenet.net mail server"
    [ Postfix.installed
    , Apt.installed ["postfix-pcre"]
    , Apt.serviceInstalledRunning "postgrey"

    , Apt.serviceInstalledRunning "spamassassin"
    , "/etc/default/spamassassin" `File.containsLines`
        [ "ENABLED=1"
        , "OPTIONS=\"--create-prefs --max-children 5 --helper-home-dir\""
        , "CRON=1"
        , "NICE=\"--nicelevel 15\""
        ] `onChange` Service.restarted "spamassassin"
        `describe` "spamd enabled"

    , Apt.serviceInstalledRunning "spamass-milter"
    -- Add -m to prevent modifying messages Subject or body.
    , "/etc/default/spamass-milter" `File.containsLine`
        "OPTIONS=\"-m -u spamass-milter -i 127.0.0.1\""
        `onChange` Service.restarted "spamass-milter"
        `describe` "spamass-milter configured"

    , Apt.installed ["maildrop"]
    , "/etc/maildroprc" `File.hasContent`
        [ "# Global maildrop filter file (deployed with propellor)"
        , "DEFAULT=\"$HOME/Maildir\""
        , "MAILBOX=\"$DEFAULT/.\""
        , "# Filter spam to a spam folder, unless .keepspam exists"
        , "if (/^X-Spam-Status: Yes/)"
        , "{"
        , "  `test -e \"$HOME/.keepspam\"`"
        , "  if ( $RETURNCODE != 0 )"
        , "  to ${MAILBOX}spam"
        , "}"
        ]
        `describe` "maildrop configured"

    , "/etc/aliases" `File.hasPrivContentExposed` ctx
        `onChange` cmdProperty "newaliases" ["newaliases"]
    , hasJoeyCAChain
    , "/etc/ssl/certs/postfix.pem" `File.hasPrivContentExposed` ctx
    , "/etc/ssl/private/postfix.pem" `File.hasPrivContent` ctx

    , "/etc/postfix/mydomain" `File.containsLines`
        [ "/.*\\.kitenet\\.net/\tOK"
        , "/ikiwiki\\.info/\tOK"
        , "/joeyh\\.name/\tOK"
        ]
        `onChange` Service.restarted "postfix"
        `describe` "postfix mydomain file configured"
    , "/etc/postfix/obscure_client_relay.pcre" `File.containsLine`
        "/^Received: from ([^.]+)\\.kitenet\\.net.*using TLS.*by kitenet\\.net \\(([^)]+)\\) with (E?SMTPS?A?) id ([A-F[:digit:]]+)(.*)/ IGNORE"
        `onChange` Service.restarted "postfix"
        `describe` "postfix obscure_client_relay file configured"
    , Postfix.mappedFile "/etc/postfix/virtual"
        (flip File.containsLines
            [ "# *@joeyh.name to joey"
            , "@joeyh.name\tjoey"
            ]
        ) `describe` "postfix virtual file configured"
    , Postfix.mappedFile "/etc/postfix/relay_clientcerts" $
        flip File.hasPrivContentExposed ctx
    , Postfix.mainCf `File.containsLines`
        [ "myhostname = kitenet.net"
        , "mydomain = $myhostname"
        , "append_dot_mydomain = no"
        , "myorigin = kitenet.net"
        , "mydestination = $myhostname, localhost.$mydomain, $mydomain, kite.$mydomain., localhost, regexp:$config_directory/mydomain"
        , "mailbox_command = maildrop"
        , "virtual_alias_maps = hash:/etc/postfix/virtual"

        , "# Allow clients with trusted certs to relay mail through."
        , "relay_clientcerts = hash:/etc/postfix/relay_clientcerts"
        , "smtpd_relay_restrictions = permit_mynetworks,permit_tls_clientcerts,permit_sasl_authenticated,reject_unauth_destination"

        , "# Filter out client relay lines from headers."
        , "header_checks = pcre:$config_directory/obscure_client_relay.pcre"

        , "# Enable postgrey."
        , "smtpd_recipient_restrictions = permit_mynetworks,reject_unauth_destination,check_policy_service inet:127.0.0.1:10023"

        , "# Enable spamass-milter."
        , "smtpd_milters = unix:/spamass/spamass.sock"
        , "milter_connect_macros = j {daemon_name} v {if_name} _"

        , "# TLS setup -- server"
        , "smtpd_tls_CAfile = /etc/ssl/certs/joeyca.pem"
        , "smtpd_tls_cert_file = /etc/ssl/certs/postfix.pem"
        , "smtpd_tls_key_file = /etc/ssl/private/postfix.pem"
        , "smtpd_tls_loglevel = 1"
        , "smtpd_tls_received_header = yes"
        , "smtpd_use_tls = yes"
        , "smtpd_tls_ask_ccert = yes"
        , "smtpd_tls_session_cache_database = sdbm:/etc/postfix/smtpd_scache"

        , "# TLS setup -- client"
        , "smtp_tls_CAfile = /etc/ssl/certs/joeyca.pem"
        , "smtp_tls_cert_file = /etc/ssl/certs/postfix.pem"
        , "smtp_tls_key_file = /etc/ssl/private/postfix.pem"
        , "smtp_tls_loglevel = 1"
        , "smtp_use_tls = yes"
        , "smtp_tls_session_cache_database = sdbm:/etc/postfix/smtp_scache"
        ]
        `onChange` Postfix.dedupMainCf
        `onChange` Service.restarted "postfix"
        `describe` "postfix configured"

    , Apt.serviceInstalledRunning "dovecot-imapd"
    , Apt.serviceInstalledRunning "dovecot-pop3d"

    , Apt.serviceInstalledRunning "cron"
    , Apt.installed ["bsd-mailx"]
    ]
  where
    ctx = Context "kitenet.net"

Raúl Benencia, uıɐɾ ʞ ʇɐɯɐs, Mike Linksvayer, David Thompson and 2 others likes this.

That's awesome.  Reproducibility is good!

David Thompson at 2014-07-18T11:44:37Z

Rebuilding mine after years of crap. Your way looks better!

Amitai Schleier at 2014-07-18T19:01:49Z