feat: implement dovecot backend server with postfix virtual mailbox integration
- create profiles::dovecot::backend class for IMAPS server configuration - add virtual mailbox support to profiles::postfix::gateway with enable_dovecot parameter - restructure common hieradata elements into mail.yaml - add virtual mailbox and alias map templates with ERB generation - add comprehensive type validation using Stdlib::Email, Stdlib::Fqdn, Stdlib::IP types - configure vmail user (UID/GID 5000) with shared storage on /shared/apps/maildata - update roles::infra::mail::backend to include both dovecot and postfix profiles
This commit is contained in:
parent
78adef0eee
commit
528fbe4190
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
sources/
|
||||||
20
hieradata/roles/infra/mail.yaml
Normal file
20
hieradata/roles/infra/mail.yaml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
# Common mail server configuration
|
||||||
|
|
||||||
|
# base postfix configuration (passed to postfix class)
|
||||||
|
postfix::relayhost: 'direct'
|
||||||
|
postfix::myorigin: 'main.unkin.net'
|
||||||
|
postfix::manage_aliases: true
|
||||||
|
|
||||||
|
# Common postfix virtuals for all mail servers
|
||||||
|
postfix::virtuals:
|
||||||
|
'root':
|
||||||
|
ensure: present
|
||||||
|
destination: 'ben@main.unkin.net'
|
||||||
|
'postmaster':
|
||||||
|
ensure: present
|
||||||
|
destination: 'ben@main.unkin.net'
|
||||||
|
'abuse':
|
||||||
|
ensure: present
|
||||||
|
destination: 'ben@main.unkin.net'
|
||||||
87
hieradata/roles/infra/mail/backend.yaml
Normal file
87
hieradata/roles/infra/mail/backend.yaml
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
---
|
||||||
|
# additional altnames
|
||||||
|
profiles::pki::vault::alt_names:
|
||||||
|
- mail.main.unkin.net
|
||||||
|
|
||||||
|
# manage dovecot
|
||||||
|
dovecot::install::packages:
|
||||||
|
- dovecot
|
||||||
|
- dovecot-pgsql
|
||||||
|
profiles::dovecot::server::maildir_path: "%{hiera('profiles::postfix::gateway::virtual_mailbox_base')}"
|
||||||
|
|
||||||
|
#dovecot::config:
|
||||||
|
# auth.conf:
|
||||||
|
# values:
|
||||||
|
# auth_mechanisms: 'plain login'
|
||||||
|
# auth_username_format: '%Lu'
|
||||||
|
# auth_default_realm: 'main.unkin.net'
|
||||||
|
# auth-vmail.conf:
|
||||||
|
# values:
|
||||||
|
# passdb: |
|
||||||
|
# {
|
||||||
|
# driver = pam
|
||||||
|
# }
|
||||||
|
# userdb: |
|
||||||
|
# {
|
||||||
|
# driver = passwd
|
||||||
|
# override_fields = uid=vmail gid=vmail home=/shared/apps/maildata/%u
|
||||||
|
# }
|
||||||
|
# mail.conf:
|
||||||
|
# values:
|
||||||
|
# mail_plugins: '$mail_plugins'
|
||||||
|
# namespace inbox: |
|
||||||
|
# {
|
||||||
|
# inbox = yes
|
||||||
|
# location =
|
||||||
|
# mailbox Drafts {
|
||||||
|
# special_use = \Drafts
|
||||||
|
# }
|
||||||
|
# mailbox Junk {
|
||||||
|
# special_use = \Junk
|
||||||
|
# }
|
||||||
|
# mailbox Sent {
|
||||||
|
# special_use = \Sent
|
||||||
|
# }
|
||||||
|
# mailbox "Sent Messages" {
|
||||||
|
# special_use = \Sent
|
||||||
|
# }
|
||||||
|
# mailbox Trash {
|
||||||
|
# special_use = \Trash
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# sections:
|
||||||
|
# - name: 'namespace inbox'
|
||||||
|
# values:
|
||||||
|
# 'inbox': 'yes'
|
||||||
|
# 'seperator': '.'
|
||||||
|
# 'prefix': 'INBOX'
|
||||||
|
|
||||||
|
# backend-specific postfix configuration
|
||||||
|
postfix::mydestination: 'localhost'
|
||||||
|
postfix::mynetworks: '127.0.0.0/8 [::1]/128 10.10.12.0/24'
|
||||||
|
postfix::smtp_listen: ['0.0.0.0', '::']
|
||||||
|
postfix::use_dovecot_lda: true # use built-in dovecot LDA support
|
||||||
|
postfix::mail_user: 'vmail:vmail'
|
||||||
|
profiles::postfix::gateway::enable_postscreen: false # disable postscreen (backend doesn't need it)
|
||||||
|
profiles::postfix::gateway::myhostname: 'mail.main.unkin.net'
|
||||||
|
profiles::postfix::gateway::enable_dovecot: true # enable dovecot integration
|
||||||
|
profiles::postfix::gateway::virtual_mailbox_domains:
|
||||||
|
- 'main.unkin.net'
|
||||||
|
profiles::postfix::gateway::virtual_mailbox_base: '/shared/apps/maildata'
|
||||||
|
|
||||||
|
profiles::postfix::gateway::virtual_mailbox_maps:
|
||||||
|
'ben@main.unkin.net': 'main.unkin.net/ben/'
|
||||||
|
'root@main.unkin.net': 'main.unkin.net/ben/'
|
||||||
|
'postmaster@main.unkin.net': 'main.unkin.net/ben/'
|
||||||
|
'abuse@main.unkin.net': 'main.unkin.net/ben/'
|
||||||
|
|
||||||
|
profiles::postfix::gateway::smtpd_client_restrictions:
|
||||||
|
- 'permit_mynetworks'
|
||||||
|
- 'reject_unauth_destination'
|
||||||
|
profiles::postfix::gateway::smtpd_sender_restrictions:
|
||||||
|
- 'permit_mynetworks'
|
||||||
|
- 'reject_non_fqdn_sender'
|
||||||
|
profiles::postfix::gateway::smtpd_recipient_restrictions:
|
||||||
|
- 'permit_mynetworks'
|
||||||
|
- 'reject_non_fqdn_recipient'
|
||||||
|
- 'reject_unauth_destination'
|
||||||
@ -1,21 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
# additional altnames
|
# additional altnames
|
||||||
profiles::pki::vault::alt_names:
|
profiles::pki::vault::alt_names:
|
||||||
- in-mta.main.unkin.net
|
- in-mta.main.unkin.net
|
||||||
|
|
||||||
# base postfix configuration (passed to postfix class)
|
# gateway-specific postfix configuration
|
||||||
postfix::relayhost: 'direct'
|
|
||||||
postfix::myorigin: 'main.unkin.net'
|
|
||||||
postfix::mydestination: 'blank'
|
postfix::mydestination: 'blank'
|
||||||
postfix::mynetworks: '127.0.0.0/8 [::1]/128'
|
postfix::mynetworks: '127.0.0.0/8 [::1]/128'
|
||||||
|
postfix::smtp_listen: '0.0.0.0'
|
||||||
postfix::mta: true
|
postfix::mta: true
|
||||||
postfix::manage_aliases: true
|
|
||||||
|
|
||||||
# profile parameters for customization
|
|
||||||
profiles::postfix::gateway::myhostname: 'in-mta.main.unkin.net'
|
profiles::postfix::gateway::myhostname: 'in-mta.main.unkin.net'
|
||||||
|
|
||||||
# postfix map content (templates)
|
|
||||||
profiles::postfix::gateway::relay_recipients_maps:
|
profiles::postfix::gateway::relay_recipients_maps:
|
||||||
'@main.unkin.net': 'OK'
|
'@main.unkin.net': 'OK'
|
||||||
|
|
||||||
@ -38,15 +32,3 @@ postfix::transports:
|
|||||||
ensure: present
|
ensure: present
|
||||||
destination: 'relay'
|
destination: 'relay'
|
||||||
nexthop: 'ausyd1nxvm2120.main.unkin.net:25'
|
nexthop: 'ausyd1nxvm2120.main.unkin.net:25'
|
||||||
|
|
||||||
# postfix virtuals
|
|
||||||
postfix::virtuals:
|
|
||||||
'root':
|
|
||||||
ensure: present
|
|
||||||
destination: 'ben@main.unkin.net'
|
|
||||||
'postmaster':
|
|
||||||
ensure: present
|
|
||||||
destination: 'ben@main.unkin.net'
|
|
||||||
'abuse':
|
|
||||||
ensure: present
|
|
||||||
destination: 'ben@main.unkin.net'
|
|
||||||
|
|||||||
99
site/profiles/manifests/dovecot/server.pp
Normal file
99
site/profiles/manifests/dovecot/server.pp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
class profiles::dovecot::server (
|
||||||
|
Stdlib::Absolutepath $tls_cert_file = '/etc/pki/tls/vault/certificate.pem',
|
||||||
|
Stdlib::Absolutepath $tls_key_file = '/etc/pki/tls/vault/certificate.pem',
|
||||||
|
Stdlib::Absolutepath $tls_ca_file = '/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem',
|
||||||
|
Stdlib::Absolutepath $maildir_path = '/var/vmail',
|
||||||
|
String $maildir_var = '%d/%n',
|
||||||
|
String $hostname = $trusted['certname'],
|
||||||
|
Array[String] $listen = ['*', '::'],
|
||||||
|
Array[String] $protocols = ['imap'],
|
||||||
|
) {
|
||||||
|
|
||||||
|
# Ensure the maildata directory exists
|
||||||
|
file { $maildir_path:
|
||||||
|
ensure => directory,
|
||||||
|
owner => 'vmail',
|
||||||
|
group => 'vmail',
|
||||||
|
mode => '0755',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create vmail user for dovecot
|
||||||
|
user { 'vmail':
|
||||||
|
ensure => present,
|
||||||
|
uid => 5000,
|
||||||
|
gid => 5000,
|
||||||
|
home => $maildir_path,
|
||||||
|
shell => '/usr/sbin/nologin',
|
||||||
|
managehome => false,
|
||||||
|
system => true,
|
||||||
|
}
|
||||||
|
|
||||||
|
group { 'vmail':
|
||||||
|
ensure => present,
|
||||||
|
gid => 5000,
|
||||||
|
system => true,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main dovecot configuration
|
||||||
|
$main_config = {
|
||||||
|
values => {
|
||||||
|
'listen' => join($listen, ', '),
|
||||||
|
'protocols' => join($protocols, ' '),
|
||||||
|
'default_login_user' => 'vmail',
|
||||||
|
'default_internal_user' => 'vmail',
|
||||||
|
'first_valid_uid' => '5000',
|
||||||
|
'last_valid_uid' => '5000',
|
||||||
|
'first_valid_gid' => '5000',
|
||||||
|
'last_valid_gid' => '5000',
|
||||||
|
'mail_uid' => 'vmail',
|
||||||
|
'mail_gid' => 'vmail',
|
||||||
|
'mail_location' => "maildir:${maildir_path}/${maildir_var}/Maildir",
|
||||||
|
'login_trusted_networks' => '10.0.0.0/8 127.0.0.0/8 [::1]/128',
|
||||||
|
'disable_plaintext_auth' => 'no',
|
||||||
|
'auth_mechanisms' => 'cram-md5 plain login',
|
||||||
|
'ssl' => 'required',
|
||||||
|
'ssl_cert' => $tls_cert_file,
|
||||||
|
'ssl_key' => $tls_key_file,
|
||||||
|
'ssl_ca' => $tls_ca_file,
|
||||||
|
'ssl_min_protocol' => 'TLSv1.2',
|
||||||
|
'ssl_cipher_list' => join([
|
||||||
|
'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES',
|
||||||
|
'ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS'
|
||||||
|
], ':'),
|
||||||
|
'ssl_prefer_server_ciphers' => 'yes',
|
||||||
|
},
|
||||||
|
sections => [
|
||||||
|
{
|
||||||
|
name => 'passdb',
|
||||||
|
values => {
|
||||||
|
'driver' => 'passwd-file',
|
||||||
|
'args' => 'scheme=CRAM-MD5 username_format=%u /etc/dovecot/users',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name => 'userdb',
|
||||||
|
values => {
|
||||||
|
'driver' => 'static',
|
||||||
|
'args' => "uid=vmail gid=vmail home=${maildir_path}/${maildir_var}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# # Postfix smtp-auth
|
||||||
|
# unix_listener /var/spool/postfix/private/auth {
|
||||||
|
# mode = 0666
|
||||||
|
# user = postfix
|
||||||
|
# group = postfix
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
|
# Configure dovecot
|
||||||
|
class { 'dovecot':
|
||||||
|
main_config => $main_config,
|
||||||
|
include_sysdefault => false,
|
||||||
|
require => [User['vmail'], Group['vmail'], File[$maildir_path]],
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -47,15 +47,24 @@ class profiles::postfix::gateway (
|
|||||||
'permit_mynetworks',
|
'permit_mynetworks',
|
||||||
'reject_unauth_destination',
|
'reject_unauth_destination',
|
||||||
],
|
],
|
||||||
Hash[String, String] $smtp_tls_policy_maps = {},
|
Hash[Stdlib::Fqdn, String] $smtp_tls_policy_maps = {},
|
||||||
Hash[String, String] $sender_canonical_maps = {},
|
Hash[String, String] $sender_canonical_maps = {},
|
||||||
Hash[String, String] $sender_access_maps = {},
|
Hash[Stdlib::Email, String] $sender_access_maps = {},
|
||||||
Hash[String, String] $relay_recipients_maps = {},
|
Hash[String, String] $relay_recipients_maps = {},
|
||||||
Hash[String, String] $relay_domains_maps = {},
|
Hash[Stdlib::Fqdn, String] $relay_domains_maps = {},
|
||||||
Hash[String, String] $recipient_canonical_maps = {},
|
Hash[String, String] $recipient_canonical_maps = {},
|
||||||
Hash[String, String] $recipient_access_maps = {},
|
Hash[Stdlib::Email, String] $recipient_access_maps = {},
|
||||||
Hash[String, String] $postscreen_access_maps = {},
|
Hash[Variant[Stdlib::IP::Address, Stdlib::IP::Address::CIDR], String] $postscreen_access_maps = {},
|
||||||
Hash[String, String] $helo_access_maps = {},
|
Hash[String, String] $helo_access_maps = {},
|
||||||
|
Hash[Stdlib::Email, String] $virtual_mailbox_maps = {},
|
||||||
|
Hash[Variant[Stdlib::Email, Pattern[/^@.+$/]], Stdlib::Email] $virtual_alias_maps = {},
|
||||||
|
# Dovecot integration
|
||||||
|
Boolean $enable_dovecot = false,
|
||||||
|
Array[Stdlib::Fqdn] $virtual_mailbox_domains = [],
|
||||||
|
String $virtual_uid_maps = 'static:5000',
|
||||||
|
String $virtual_gid_maps = 'static:5000',
|
||||||
|
Stdlib::Absolutepath $virtual_mailbox_base = '/var/vmail',
|
||||||
|
String $virtual_transport = 'dovecot',
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$alias_maps_string = join($alias_maps, ', ')
|
$alias_maps_string = join($alias_maps, ', ')
|
||||||
@ -281,6 +290,7 @@ class profiles::postfix::gateway (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Postfix maps (all using templates now)
|
# Postfix maps (all using templates now)
|
||||||
$postfix_maps = {
|
$postfix_maps = {
|
||||||
'postscreen_access' => {
|
'postscreen_access' => {
|
||||||
@ -333,6 +343,39 @@ class profiles::postfix::gateway (
|
|||||||
'type' => 'hash',
|
'type' => 'hash',
|
||||||
'content' => template('profiles/postfix/gateway/smtp_tls_policy_maps.erb')
|
'content' => template('profiles/postfix/gateway/smtp_tls_policy_maps.erb')
|
||||||
},
|
},
|
||||||
|
'virtual_mailbox_maps' => {
|
||||||
|
'ensure' => 'present',
|
||||||
|
'type' => 'hash',
|
||||||
|
'content' => template('profiles/postfix/gateway/virtual_mailbox_maps.erb')
|
||||||
|
},
|
||||||
|
'virtual_alias_maps' => {
|
||||||
|
'ensure' => 'present',
|
||||||
|
'type' => 'hash',
|
||||||
|
'content' => template('profiles/postfix/gateway/virtual_alias_maps.erb')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if $enable_dovecot {
|
||||||
|
postfix::config {
|
||||||
|
'virtual_mailbox_domains': value => join($virtual_mailbox_domains, ', ');
|
||||||
|
'virtual_mailbox_maps': value => 'hash:/etc/postfix/virtual_mailbox_maps';
|
||||||
|
'virtual_alias_maps': value => 'hash:/etc/postfix/virtual_alias_maps';
|
||||||
|
'virtual_uid_maps': value => $virtual_uid_maps;
|
||||||
|
'virtual_gid_maps': value => $virtual_gid_maps;
|
||||||
|
'virtual_mailbox_base': value => $virtual_mailbox_base;
|
||||||
|
'virtual_transport': value => $virtual_transport;
|
||||||
|
'home_mailbox': value => "${virtual_mailbox_base}/%d/%n/Maildir";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
postfix::config {
|
||||||
|
'virtual_mailbox_domains': ensure => 'absent';
|
||||||
|
'virtual_mailbox_maps': ensure => 'absent';
|
||||||
|
'virtual_uid_maps': ensure => 'absent';
|
||||||
|
'virtual_gid_maps': ensure => 'absent';
|
||||||
|
'virtual_mailbox_base': ensure => 'absent';
|
||||||
|
'virtual_transport': ensure => 'absent';
|
||||||
|
'home_mailbox': ensure => 'absent';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Merge base configs with postscreen configs
|
# Merge base configs with postscreen configs
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED
|
||||||
|
#
|
||||||
|
# Defines virtual alias mappings
|
||||||
|
# Maps email addresses or patterns to target addresses
|
||||||
|
# Format: alias@foo.net real@corp.foo.net
|
||||||
|
|
||||||
|
<% @virtual_alias_maps.each do |source, target| -%>
|
||||||
|
<%= source %> <%= target %>
|
||||||
|
<% end -%>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
# FILE MANAGED BY PUPPET, CHANGES WILL BE REPLACED
|
||||||
|
#
|
||||||
|
# Defines virtual mailbox mappings for dovecot delivery
|
||||||
|
# Maps email addresses to maildir paths
|
||||||
|
# Format: user@domain maildir/path/
|
||||||
|
|
||||||
|
<% @virtual_mailbox_maps.each do |email, path| -%>
|
||||||
|
<%= email %> <%= path %>
|
||||||
|
<% end -%>
|
||||||
@ -6,5 +6,7 @@ class roles::infra::mail::backend {
|
|||||||
}else{
|
}else{
|
||||||
include profiles::defaults
|
include profiles::defaults
|
||||||
include profiles::base
|
include profiles::base
|
||||||
|
include profiles::dovecot::server
|
||||||
|
include profiles::postfix::gateway
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user