Skip to content

Instantly share code, notes, and snippets.

@colegatron
Last active May 12, 2016 09:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save colegatron/00cea2a778cd9448801e9e1e33e4e71e to your computer and use it in GitHub Desktop.
Save colegatron/00cea2a778cd9448801e9e1e33e4e71e to your computer and use it in GitHub Desktop.
saltstack postfix formula as forwarder (for root emails)
This is an update of the Russel's state to use it basically as mail forwarder in auto scaled environments.
The tipycal problem is that if you get notification emails from "webserver@mydomain.com" in an environment where you really have 5 or 6 webservers for the same application, it is difficult to track back the issue to the right server.
I have solved it renaming the server and the headers:
All the emails sent from the server for <myhostname>.domain.com will renamed to <senderuser>@<myhostname-my-ipv4>.domain.com.
Also adds a header replacement to avoid problems with Office365 mail servers, which rejects to send emails with different names on the hostname and the email headers
Original job: http://russell.ballestrini.net/postfix-salt-state-formula/
note: replace "." in file names with "/" to get the right folder structure.
{% set h = salt['grains.get']('host', 'noname') %}
{% set d = salt['grains.get']('domain', 'nodomain') %}
{% set i = salt['grains.get']('ipv4', 'nodomain')[1] %}
{% set myfakehostname = h + "-" + i + "-" + d %}
{% set myhostname = h + "." + d %}
postfix:
# I need this to access to this vars in the states and also in the pillar without having to duplicate var definitions
myhostname: {{ myhostname }}
myfakehostname: {{ myfakehostname }}
# real postfix conf
aliases: |
postmaster: root
root: notify-root@domain.com
sender_canonical_maps: |
/^(.*)@(.*).domain.com$/ ${1}@{{ myfakehostname }}.domain.com
header_check: |
/From:(.*)@{{ myhostname }}.domain.com/ REPLACE From: ${1}@{{ myfakehostname }}.domain.com
# Managed by config management
{{pillar['postfix']['header_check']}}
# Install mutt and postfix mutt packages.
#
# This formula supports setting an optional:
#
# * 'aliases' file
# * 'virtual' map file
#
# Both aliases and virtual use a pillar data schema
# which takes the following form:
#
# postfix:
# aliases: |
# postmaster: root
# root: testuser
# testuser: russell@example.com
# virtual: |
# example.com this is a comment
# test1@example.com me@example.com
# test2@example.com me@example.com
# sender_canonical_maps: |
# /.+/ newsender@address.com
#
# header_check: |
# /From:.*/ REPLACE From: newsender@address.com
#
# install mutt
mutt:
pkg:
- installed
# install postfix have service watch main.cf
postfix:
pkg:
- installed
service:
- running
- enable: True
- watch:
- pkg: postfix
- file: /etc/postfix/main.cf
# postfix main configuration file
/etc/postfix/main.cf:
file.managed:
- source: salt://postfix/main.cf
- user: root
- group: root
- mode: 644
- template: jinja
- require:
- pkg: postfix
# manage /etc/aliases if data found in pillar
{% if 'aliases' in pillar.get('postfix', '') %}
/etc/aliases:
file.managed:
- source: salt://postfix/aliases
- user: root
- group: root
- mode: 644
- template: jinja
- require:
- pkg: postfix
run-newaliases:
cmd.wait:
- name: newaliases
- cwd: /
- watch:
- file: /etc/aliases
{% endif %}
# manage /etc/postfix/virtual if data found in pillar
{% if 'virtual' in pillar.get('postfix', '') %}
/etc/postfix/virtual:
file.managed:
- source: salt://postfix/virtual
- user: root
- group: root
- mode: 644
- template: jinja
- require:
- pkg: postfix
run-postmap:
cmd.wait:
- name: /usr/sbin/postmap /etc/postfix/virtual
- cwd: /
- watch:
- file: /etc/postfix/virtual
{% endif %}
# manage /etc/postfix/sender_canonical_maps if data found in pillar
{% if 'sender_canonical_maps' in pillar.get('postfix', '') %}
/etc/postfix/sender_canonical_maps:
file.managed:
- source: salt://postfix/sender_canonical_maps
- user: root
- group: root
- mode: 644
- template: jinja
- require:
- pkg: postfix
- watch_in:
- service: postfix
{% endif %}
# manage /etc/postfix/header_check if data found in pillar
{% if 'header_check' in pillar.get('postfix', '') %}
/etc/postfix/header_check:
file.managed:
- source: salt://postfix/header_check
- user: root
- group: root
- mode: 644
- template: jinja
- require:
- pkg: postfix
- watch_in:
- service: postfix
{% endif %}
#
# Managed by config management
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
#
{% set myhostname = salt["pillar.get"]("postfix:myhostname") %}
{% set myfakehostname = salt["pillar.get"]("postfix:myfakehostname") %}
{# This file could be dinamycally modified importing with jinja a different "main.cf-grain-hostname", but there are endless posibilities depending of your own use case #}
# Debian specific: Specifying a file name will cause the first
# line of that file to be used as the name. The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname
smtpd_banner = $myhostname ESMTP $mail_name
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h
readme_directory = no
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.
sender_canonical_classes = envelope_sender, header_sender
sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps
smtp_header_checks = regexp:/etc/postfix/header_check
myhostname = {{ myhostname }}
myorigin = {{ myfakehostname }}
mydestination = {{ myhostname }} localhost
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
relayhost =
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
{% if 'virtual' in pillar.get('postfix','') %}
virtual_alias_maps = hash:/etc/postfix/virtual
{% endif %}
# Managed by config management
{{pillar['postfix']['sender_canonical_maps']}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment