Skip to content

Commit

Permalink
First implementation of a basic Postfix role (#2)
Browse files Browse the repository at this point in the history
Basic features including relay host and alias hash map mangling is implemented.

Fixes #1
  • Loading branch information
mrolli authored Jun 2, 2023
1 parent 3940f2e commit 25e1cce
Show file tree
Hide file tree
Showing 33 changed files with 1,602 additions and 119 deletions.
9 changes: 9 additions & 0 deletions .ansible-lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Ansible-Lint configuration
# Options: https://github.com/ansible/ansible-lint#configuration-file

profile: production
use_default_rules: true

enable_list:
- no-log-password
- no-same-owner
63 changes: 63 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
name: CI
on:
pull_request:
push:
branches:
- main

jobs:

lint:
name: Lint
runs-on: ubuntu-latest

steps:

- name: Checkout the codebase
uses: actions/checkout@v3

- name: Setup Python 3
uses: actions/setup-python@v3
with:
python-version: '3.x'

- name: Install test dependencies.
run: pip3 install yamllint ansible-lint

- name: Lint code.
run: |
set -e
yamllint .
ansible-lint
molecule:
name: Molecule
runs-on: ubuntu-latest
# See https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs#using-a-matrix-strategy
strategy:
matrix:
distro: [rockylinux8, rockylinux9, ubuntu2004, ubuntu2204]
scenario: [default, local, remove-alias, uninstall]
include:
- playbook: converge.yml

steps:
- name: Checkout the codebase
uses: actions/checkout@v3

- name: Setup Python 3
uses: actions/setup-python@v3
with:
python-version: '3.x'

- name: Install test dependencies.
run: pip3 install ansible molecule 'molecule-plugins[podman]' podman

- name: Run Molecule tests.
run: molecule test -s ${{ matrix.scenario }}
env:
PY_COLORS: '1'
ANSIBLE_FORCE_COLOR: '1'
MOLECULE_DISTRO: ${{ matrix.distro }}
MOLECULE_PLAYBOOK: ${{ matrix.playbook }}
20 changes: 20 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
The MIT License (MIT)

Copyright (c) 2023 IT-Services Offices, University of Bern

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
193 changes: 171 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,187 @@
Role Name
=========
# Ansible Role: Postfix

A brief description of the role goes here.
An Ansible role that manages Postfix. Currently the role has the following
features:

Requirements
------------
* Install Postfix
* Manage config settings in `/etc/postfix/main.cf`, see
[role variables](#role-variables)
* Manage the file-base alias db `/etc/alias`.
* Completely uninstall Postfix

Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
## Requirements

Role Variables
--------------
No prerequisites necessary at the moment.

A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
## Role Variables

Dependencies
------------
Available variables are listed below, along with default values (see also `defaults/main.yml`):

A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
Variables of the form `$varname` are literally transported to the config file as
Postfix is internally interpolating these on service startup. In other words,
technically, setting an `postfix_myorigin` to "$nyhostname" has the very same outcome
as setting it to `"{{ ansible_fqdn }}"`.

Example Playbook
----------------
### postfix_myhostname

Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
postfix_myhostname: "{{ ansible_fqdn }}"

The `myhostname` parameter specifies the internet hostname of this mail system.
The default is to use the fully-qualified domain name

### postfix_mydomain

postfix_mydomain: "undef"

The `mydomain` parameter specifies the local internet domain name. The default
is "undef" that meas Postfix will compute the value based on its defaults, which
results in $myhostname minus the first component.

### postfix_myorigin

postfix_myorigin: "undef"

The `myorigin` parameter specifies the domain that locally-posted mail appears to
come from. The default is to append $myhostname, which is fine for small
sites.

### postfix_mydestination

postfix_mydestination: "$myhostname, localhost.$mydomain, localhost"

The `mydestination` parameter specifies the list of domains that this machine
considers itself the final destination for.
The default is \$myhostname + localhost.$mydomain + localhost. On a mail domain
gateway, you should also include $mydomain.

### postfix_inet_interfaces

postfix_inet_interfaces: localhost

The `inet_interfaces` parameter specifies the network interfaces addresses that
this mail system receives mail on. The default is to listen only on `localhost`.
You can specify more than one by comma separating them. Set to `all` for all
available interfaces or to a comma-separated list of IP addresses. See [postconf
manpage](https://www.postfix.org/postconf.5.html#inet_interfaces) for the
details about this option.

### postfix_inet_protocols

postfix_inet_protocols: all

This parameter specifies the internet protocols to support. The default is
`all`, which means IPv4, and IPv6 if supported. See [postconf
manpage](https://www.postfix.org/postconf.5.html#inet_protocols) manpage for the
details about this option.

### postfix_relayhost

postfix_relayhost: undef

The relayhost parameter specifies the default host to send mail to. Specify a
domain, host, host:port, [host]:port, [address] or [address]:port; the form
[host] turns off MX lookups. Examples:

# Set to $mydomain => mail will be sent to the smtp found in the MX entry of
$mydomain
postfix_relayhost = $mydomain

# No MX lookup is done, all mails are sent the given MTA
postfix_relayhost = [gateway.my.domain]

# Same as above, MTA set by IP address
postfix_relayhost = [an.ip.add.ress]

postfix_state: started

### Manipulating Postfix Lookup Maps

#### Alias Map

postfix_alias_map: {}

This allows manipulations of the `hash:/etc/alises` map. The default is not to edit
this file in any way. Use this to forward local mails to external addresses,
which is useful for mails to the local root account.

Examples:

postfix_alias_map:
www: "[email protected]"
root: ["[email protected]", "[email protected]"]

Use the local account you want to forward mails for as the key and either a
string or list of strings for the mail addresses to forward these mails to. In
the above example, mails to root are forwarded to two external addresses instead.

### Configuring Package and Service State

postfix_enabled: true

This sets the boot time status of the Postfix daemon. Should remain to `true`
unless the daemon shouldn't be automatically started at boot time.

postfix_state: started

Set the initial state of the postfix daemon when this role is run. This should
generally remain `started`. There occasions where setting this to `stopped`
might come in handy, i.e. during a maintenance down. In combination with the
`postfix_packages_state` this also allows to purge Postfix from a system.

postfix_restart_state: restarted

This determines the measure that is taken when the `postfix` handlers
called. The default is to restart the Postfix process, when the handlers kicks
in. Can be set to `reloaded` to only reload the Postfix process.

postfix_packages_state: present

The state of the Postfix installation packages. Defaults to `present` to make
sure it's installed. Can also be set to `latest` if Postfix should get removed
from the machine or prior switching repo or the like.

## Dependencies

This role has no dependencies to other roles.

## Example Playbook

Including an example of how to use your role (for instance, with variables
passed in as parameters) is always nice for users too:

- hosts: servers

roles:
- { role: username.rolename, x: 42 }
- unibe_idsys.postifx

<!-- add an example which illustrates a standard usage internally? -->

The following example illustrates how to remove Postfix from the systems again:

- hosts: servers

roles:
- role: unibe_idsys.postifx
vars:
postfix_service_state: stopped
postfix_packages_state: absent

**Note:** Removing Postfix from the system will also purge any configuration in
`/etc/postfix`. If you want to preserve it, make a backup before applying the
above play.

## Compatibility

This role has been written for and tested on and is therefore compatible with:

* CentOS-7
* Rocky-8, Rocky-9
* Ubuntu-20.04, Ubuntu-22.04

License
-------
## License

BSD
MIT

Author Information
------------------
## Author Information

An optional section for the role authors to include contact information, or a website (HTML is not allowed).
The role was created in 2023 by the IT-Services Office of the University of Bern
47 changes: 46 additions & 1 deletion defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,47 @@
---
# defaults file for postfix

# The myhostname parameter specifies the internet hostname of this mail system.
postfix_myhostname: "{{ ansible_fqdn }}"

# The mydomain parameter specifies the local internet domain name.
postfix_mydomain: "undef"

# The myorigin parameter specifies the domain that locally-posted mail appears
# to come from.
postfix_myorigin: "undef"

# The mydestination parameter specifies the list of domains that this
# machine considers itself the final destination for.
postfix_mydestination: "$myhostname, localhost.$mydomain, localhost"

# The inet_interfaces parameter specifies the network interface
# addresses that this mail system receives mail on.
postfix_inet_interfaces: localhost

# Enable IPv4, and IPv6 if supported; valid value include `all`, `ipv4`,
postfix_inet_protocols: all

# Dictionary with mail aliases that are managed in /etc/aliases
postfix_alias_map: {}

# The relayhost parameter specifies the default host to send mail to.
# Specify a domain, host, host:port, [host]:port, [address] or [address]:port;
# the form [host] turns off MX lookups.
#postfix_relayhost = $mydomain
#postfix_relayhost = [gateway.my.domain]
#postfix_relayhost = [an.ip.add.ress]
postfix_relayhost: undef

# Set initial postfix state. Recommended values: `started` or `stopped`
postfix_state: started

# Set initial postfix service status. Recommended values: `yes` or `no`
postfix_enabled: true

# Set postfix state when configuration changes are made. Recommended values:
# `restarted` or `reloaded`
postfix_restart_state: restarted

# postfix package state; use `present` to make sure it's installed, or `latest`
# if you want to upgrade or switch versions using a new repo.
postfix_packages_state: present
14 changes: 13 additions & 1 deletion handlers/main.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
---
# handlers file for postfix
- name: Rebuild alias database
ansible.builtin.command:
cmd: postalias "{{ postfix_alias_path }}"
changed_when: false
listen: rebuild_aliases_db

# Restart postfix service
- name: Restart postfix service
ansible.builtin.service:
name: "{{ postfix_service }}"
state: "{{ postfix_restart_state }}"
listen: "restart-postifx"
when: postfix_state | default('started') == 'started'
14 changes: 7 additions & 7 deletions molecule/default/converge.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
- name: Converge
- name: Converge to a Postfix server that has the role defaults set.
hosts: all

tasks:
# replace these tasks with whatever you find suitable to test
- name: Copy something to test use of synchronize module
ansible.builtin.copy:
src: /etc/hosts
dest: /tmp/hosts-from-controller
mode: "0644"
- name: "Set ansible_fqdn and ansible_domain something static for the tests"
ansible.builtin.set_fact:
ansible_fqdn: mail.test
ansible_domain: test

- name: "Include unibe_idsys.postfix"
ansible.builtin.include_role:
name: "unibe_idsys.postfix"
Loading

0 comments on commit 25e1cce

Please sign in to comment.