Update to trixie

This commit is contained in:
ibu ☉ radempa 2026-03-22 13:09:26 +01:00
parent 3686d35108
commit fbfb04717a
48 changed files with 914 additions and 2216 deletions

View file

@ -2,49 +2,50 @@
# we run freshclam (with daemons stopped) and then starting the daemons should work
# (avoiding 'clamav-daemon not started: "ConditionPathExistsGlob=/var/lib/clamav/daily.{c[vl]d,inc} was not met"')
- name: install clamav
apt:
- name: Install clamav
ansible.builtin.apt:
name: "{{ packages }}"
vars:
packages:
- clamav
- clamav-daemon
- clamav-freshclam
- clamav
- clamav-daemon
- clamav-freshclam
- name: stop clamav daemons
systemd:
- name: Stop clamav daemons
ansible.builtin.systemd:
name: "{{ item }}"
state: stopped
loop:
- clamav-freshclam
- clamav-daemon
- name: run freshclam
shell: freshclam
- name: Run freshclam
ansible.builtin.command: freshclam
register: out
changed_when: out.rc != 0
- name: start clamav daemons
systemd:
- name: Start clamav daemons
ansible.builtin.systemd:
name: "{{ item }}"
state: started
loop:
- clamav-daemon
- clamav-freshclam
- name: install clamav-unofficial-sigs, clamdscan
apt:
- name: Install clamdscan
ansible.builtin.apt:
name: "{{ packages }}"
vars:
packages:
- clamav-unofficial-sigs
- clamdscan
- clamdscan
- name: set clamav BytecodeSecurity to Paranoid
lineinfile:
- name: Set clamav BytecodeSecurity to Paranoid
ansible.builtin.lineinfile:
path: /etc/clamav/clamd.conf
regexp: '^BytecodeSecurity'
line: 'BytecodeSecurity Paranoid'
- name: restart clamav-daemon
systemd:
- name: Restart clamav-daemon
ansible.builtin.systemd:
name: clamav-daemon
state: restarted

View file

@ -1,173 +1,175 @@
- name: apt install python3-psycopg2
apt:
- name: Install package python3-psycopg2
ansible.builtin.apt:
name: python3-psycopg2
state: present
- name: database table domains
postgresql_table:
- name: Database table domains
community.postgresql.postgresql_table:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
name: domains
columns:
- id bigserial primary key
- name varchar(128) not null unique
- relay_transport text null
- id BIGSERIAL PRIMARY KEY
- name VARCHAR(128) NOT NULL UNIQUE
- relay_transport TEXT NULL
- name: database table users
postgresql_table:
- name: Database table users
community.postgresql.postgresql_table:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
name: users
columns:
- id BIGSERIAL PRIMARY KEY
- domain_id BIGINT references domains(id) on delete cascade
- username VARCHAR(128) NOT NULL
- realname VARCHAR(250) NOT NULL
- password VARCHAR(128) NOT NULL
- suspend_submission BOOL NOT NULL DEFAULT false
- suspend_imap_reason TEXT NULL
- quota_storage_bytes BIGINT NOT NULL DEFAULT {{ mailserver.dovecot.mailbox_max_bytes | default(100000000000) }}
- quota_inbox_messages INT NOT NULL DEFAULT {{ mailserver.dovecot.mailbox_max_messages | default(500000) }}
- unique(domain_id, username)
- id BIGSERIAL PRIMARY KEY
- domain_id BIGINT references domains(id) on delete cascade
- username VARCHAR(128) NOT NULL
- realname VARCHAR(250) NOT NULL
- password VARCHAR(128) NOT NULL
- suspend_submission BOOL NOT NULL DEFAULT false
- suspend_imap_reason TEXT NULL
- quota_storage_bytes BIGINT NOT NULL DEFAULT {{ mailserver.dovecot.mailbox_max_bytes | default(100000000000) }}
- quota_inbox_messages INT NOT NULL DEFAULT {{ mailserver.dovecot.mailbox_max_messages | default(500000) }}
- unique(domain_id, username)
- name: database index users__domain_username
postgresql_idx:
- name: Database index users__domain_username
community.postgresql.postgresql_idx:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
table: users
columns: domain_id, username
idxname: users__domain_username
- name: database table aliases
postgresql_table:
- name: Database table aliases
community.postgresql.postgresql_table:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
name: aliases
columns:
- id bigserial primary key
- alias_domain_id bigint references domains(id) on delete cascade
- alias varchar(250) not null
- forwardings varchar(250)[] not null
- t timestamp without time zone not null default now()
- comment text null
- unique(alias_domain_id, alias)
- id bigserial primary key
- alias_domain_id bigint references domains(id) on delete cascade
- alias varchar(250) not null
- forwardings varchar(250)[] not null
- t timestamp without time zone not null default now()
- comment text null
- unique(alias_domain_id, alias)
- name: database index aliases__alias
postgresql_idx:
- name: Database index aliases__alias
community.postgresql.postgresql_idx:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
table: aliases
columns: alias
idxname: aliases__alias
- name: database table shared_folders
postgresql_table:
- name: Database table shared_folders
community.postgresql.postgresql_table:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
name: shared_folders
columns:
- id bigserial primary key
- from_user varchar(128) not null
- to_user varchar(128) not null
- dummy char(1) DEFAULT '1'
- id bigserial primary key
- from_user varchar(128) not null
- to_user varchar(128) not null
- dummy char(1) DEFAULT '1'
- name: database index shared_folders__from_to
postgresql_idx:
- name: Database index shared_folders__from_to
community.postgresql.postgresql_idx:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
table: shared_folders
columns: from_user, to_user
idxname: shared_folders__from_to
unique: true
- name: database table shared_folders_anyone
postgresql_table:
- name: Database table shared_folders_anyone
community.postgresql.postgresql_table:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
name: shared_folders_anyone
columns:
- id bigserial primary key
- from_user varchar(128) not null
- dummy char(1) DEFAULT '1'
- id bigserial primary key
- from_user varchar(128) not null
- dummy char(1) DEFAULT '1'
- name: database index shared_folders_anyone__from
postgresql_idx:
- name: Database index shared_folders_anyone__from
community.postgresql.postgresql_idx:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
table: shared_folders_anyone
columns: from_user
idxname: shared_folders__from
unique: true
- name: database table mail_from
postgresql_table:
- name: Database table mail_from
community.postgresql.postgresql_table:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
name: mail_from
columns:
- id bigserial primary key
- t timestamp default now()
- original varchar(250) not null
- rewritten varchar(250) not null
- srs_id bigint
- id bigserial primary key
- t timestamp default now()
- original varchar(250) not null
- rewritten varchar(250) not null
- srs_id bigint
- name: database index mail_from__rewritten
postgresql_idx:
- name: Database index mail_from__rewritten
community.postgresql.postgresql_idx:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
table: mail_from
columns: rewritten
idxname: mail_from__rewritten
- name: database index mail_from__srs_id
postgresql_idx:
- name: Database index mail_from__srs_id
community.postgresql.postgresql_idx:
login_host: "{{ mailserver.postgresql.host }}"
port: "{{ mailserver.postgresql.port }}"
login_port: "{{ mailserver.postgresql.port }}"
login_user: "{{ mailserver.postgresql.username }}"
login_password: "{{ mailserver.postgresql.password }}"
db: "{{ mailserver.postgresql.dbname }}"
login_db: "{{ mailserver.postgresql.dbname }}"
ssl_mode: disable
table: mail_from
columns: srs_id

View file

@ -1,126 +1,87 @@
# here we assume that postfix.yml has run such that user 'mailstore' exists
- name: install dovecot packages
apt:
name: dovecot-imapd,dovecot-lmtpd,dovecot-pgsql,dovecot-managesieved,dovecot-lucene
# sieve scripts
- name: Install dovecot packages
ansible.builtin.apt:
name: dovecot-core,dovecot-flatcurve,dovecot-imapd,dovecot-lmtpd,dovecot-managesieved,dovecot-pgsql,dovecot-sieve
state: present
- name: install dovecot config files
template:
src: "dovecot/{{ item }}"
dest: "/etc/dovecot/conf.d/{{ item }}"
owner: root
group: root
mode: 0644
force: yes
loop:
- 10-auth.conf
- auth-sql.conf.ext
- 10-mail.conf
- 10-master.conf
- 10-ssl.conf
- 15-mailboxes.conf
- 20-lmtp.conf
- 20-imap.conf
- 90-sieve.conf
- 90-sieve-extprograms.conf
- 90-plugin.conf
- 90-acl.conf
- 90-quota.conf
- name: Remove inclusion of conf.d/*.conf from dovecot.conf
ansible.builtin.lineinfile:
path: /etc/dovecot/dovecot.conf
regexp: '^!include conf\.d/\*\.conf'
line: '#!include conf.d/*.conf'
- name: install more dovecot config files
template:
- name: Set dovecot_config_version to 2.4.1
ansible.builtin.lineinfile:
path: /etc/dovecot/dovecot.conf
regexp: '^dovecot_config_version = .*'
line: 'dovecot_config_version = 2.4.1'
- name: Set dovecot_storage_version to 2.4.1
ansible.builtin.lineinfile:
path: /etc/dovecot/dovecot.conf
regexp: '^dovecot_storage_version = .*'
line: 'dovecot_storage_version = 2.4.1'
- name: Install /etc/dovecot/local.conf
ansible.builtin.template:
src: "dovecot/{{ item }}"
dest: "/etc/dovecot/{{ item }}"
owner: root
group: dovecot
mode: 0640
force: yes
group: root
mode: "0600"
force: true
loop:
- dovecot.conf
- dovecot-sql.conf.ext
- dovecot-dict-sql.conf.ext
- local.conf
- name: directories /etc/dovecot/sieve_before /etc/dovecot/sieve_after
file:
path: "/etc/dovecot/{{ item }}"
- name: File quota-warning.sh
ansible.builtin.template:
src: dovecot/quota-warning.sh
dest: /usr/local/bin/quota-warning.sh
owner: root
group: root
mode: "0755"
force: true
- name: Directory /var/lib/dovecot/sieve
ansible.builtin.file:
path: "/var/lib/dovecot/sieve"
state: directory
owner: root
group: root
mode: 0755
loop:
- sieve_pipes
- sieve_filters
- sieve_execute
- sieve_before
- sieve_after
- name: file /etc/dovecot/sieve_after/spam-to-folder.sieve
template:
src: dovecot/spam-to-folder.sieve
dest: /etc/dovecot/sieve_after/spam-to-folder.sieve
owner: root
group: root
mode: 0644
force: yes
- name: files /etc/dovecot/sieve_pipes/*.sieve
template:
src: "dovecot/{{ item }}"
dest: "/etc/dovecot/sieve_pipes/{{ item }}"
owner: mailstore
group: mailstore
mode: 0600
force: yes
loop:
- learn-spam.sieve
- learn-ham.sieve
mode: "0755"
- name: files /etc/dovecot/sieve_pipes/*.sh
template:
src: "dovecot/{{ item }}"
dest: "/etc/dovecot/sieve_pipes/{{ item }}"
- name: Copy sieve files
ansible.builtin.copy:
src: dovecot/sieve
dest: /var/lib/dovecot/
owner: mailstore
group: mailstore
mode: 0700
force: yes
mode: "0600"
directory_mode: "0755"
- name: Directory permissions sieve pipes
ansible.builtin.file:
path: "/var/lib/dovecot/sieve/pipes"
owner: mailstore
group: mailstore
mode: "0777"
- name: Execution flag for spam training scripts
ansible.builtin.file:
path: "/var/lib/dovecot/sieve/pipes/{{ item }}"
owner: mailstore
group: mailstore
mode: "0700"
loop:
- rspamd-learn-spam.sh
- rspamd-learn-ham.sh
- name: README files
template:
src: "dovecot/README_{{ item }}"
dest: "/etc/dovecot/sieve_{{ item }}/README"
owner: mailstore
group: mailstore
mode: 0600
force: yes
loop:
- filters
- execute
- before
- after
- name: restart dovecot
systemd:
- name: Restart dovecot
ansible.builtin.systemd:
name: dovecot
state: restarted
- name: compile sieve files
shell: "/usr/bin/sievec /etc/dovecot/{{ item }}"
loop:
- "sieve_after/spam-to-folder.sieve"
- "sieve_pipes/learn-spam.sieve"
- "sieve_pipes/learn-ham.sieve"
- name: permissions of .svbin
file:
path: "/etc/dovecot/{{ item }}"
owner: mailstore
group: mailstore
mode: 0600
loop:
- "sieve_after/spam-to-folder.sieve"
- "sieve_pipes/learn-spam.svbin"
- "sieve_pipes/learn-ham.svbin"

View file

@ -1,6 +1,12 @@
- include: remove_other_mtas.yml
- include: database.yml
- include: postfix.yml
- include: dovecot.yml
- include: clamav.yml
- include: rspamd.yml
- name: Remove other MTAs
ansible.builtin.include_tasks: remove_other_mtas.yml
- name: Setup database tables and indexes
ansible.builtin.include_tasks: database.yml
- name: Setup postfix
ansible.builtin.include_tasks: postfix.yml
- name: Setup dovecot
ansible.builtin.include_tasks: dovecot.yml
- name: Setup clamav
ansible.builtin.include_tasks: clamav.yml
- name: Setup rspamd
ansible.builtin.include_tasks: rspamd.yml

View file

@ -1,70 +1,76 @@
- name: install postfix packages
apt:
- name: Install postfix packages
ansible.builtin.apt:
name: postfix,postfix-pgsql,postfix-doc
state: present
update_cache: yes
install_recommends: no
update_cache: true
install_recommends: false
- name: divert /etc/postfix/main.cf
shell: dpkg-divert --add --rename --divert /etc/postfix/main.cf.orig /etc/postfix/main.cf
- name: Divert /etc/postfix/main.cf
community.general.dpkg_divert:
path: /etc/postfix/main.cf
divert: /etc/postfix/main.cf.orig
rename: true
- name: divert /etc/postfix/master.cf
shell: dpkg-divert --add --rename --divert /etc/postfix/master.cf.orig /etc/postfix/master.cf
- name: Divert /etc/postfix/master.cf
community.general.dpkg_divert:
path: /etc/postfix/master.cf
divert: /etc/postfix/master.cf.orig
rename: true
- name: group 'mailstore'
group:
- name: Group 'mailstore'
ansible.builtin.group:
name: mailstore
state: present
system: yes
system: true
gid: 5000
- name: user 'mailstore'
user:
- name: User 'mailstore'
ansible.builtin.user:
name: mailstore
group: mailstore
state: present
shell: /usr/sbin/nologin
system: yes
system: true
uid: 5000
create_home: no
create_home: false
home: /srv/mailstore
password: '!'
password_lock: yes
password_lock: true
comment: created by ansible
- name: directories /srv/mailstore /srv/mailstore/role_specific
file:
- name: Directories /srv/mailstore /srv/mailstore/role_specific
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: mailstore
group: mailstore
mode: 0755
mode: "0755"
loop:
- /srv/mailstore
- /srv/mailstore/role_specific
- /srv/mailstore/role_specific/roles
- name: postfix configuration files
template:
- name: Postfix configuration files
ansible.builtin.template:
src: "postfix/{{ item }}"
dest: "/etc/postfix/{{ item }}"
owner: root
group: root
mode: 0644
mode: "0644"
force: "{{ mailserver.postfix.overwrite_config }}"
loop:
- main.cf
- master.cf
- header_checks
- name: postfix database queries
template:
- name: Postfix database queries
ansible.builtin.template:
src: "postfix/{{ item }}"
dest: "/etc/postfix/{{ item }}"
owner: root
group: root
mode: 0600
force: yes
mode: "0600"
force: true
loop:
- domains.cf
- mailboxes.cf
@ -76,7 +82,7 @@
- sender_canonical_maps.cf
- recipient_canonical_maps.cf
- name: restart postfix
systemd:
- name: Restart postfix
ansible.builtin.systemd:
name: postfix
state: restarted

View file

@ -1,10 +1,13 @@
- name: find all installed versions of mail-transport-agent except postfix
shell: aptitude search '~i~Pmail-transport-agent' | sed -e 's/^...\(.*\)/\1/' | awk '{ print $1 }' | grep -v postfix || /bin/true
- name: Find all installed versions of mail-transport-agent except postfix
ansible.builtin.shell:
cmd: set -o pipefail && aptitude search '~i~Pmail-transport-agent' | sed -e 's/^...\(.*\)/\1/' | awk '{ print $1 }' | grep -v postfix || /bin/true
executable: /bin/bash
register: mtas
changed_when: false
- name: purge MTAs other than postfix
apt:
- name: Purge MTAs other than postfix
ansible.builtin.apt:
name: "{{ item }}"
state: absent
purge: yes
loop: "{{ mtas.stdout_lines|list }}"
purge: true
loop: "{{ mtas.stdout_lines | list }}"

View file

@ -1,52 +1,52 @@
- name: apt install rspamd
apt:
- name: Install package rspamd
ansible.builtin.apt:
name: rspamd
state: present
# postfix integration
- name: postfix setting milter_mail_macros
lineinfile:
- name: Postfix setting milter_mail_macros
ansible.builtin.lineinfile:
path: /etc/postfix/main.cf
regexp: '^milter_mail_macros='
line: 'milter_mail_macros=i {mail_addr} {client_addr} {client_name} {auth_authen}'
insertafter: '^# rspamd'
- name: postfix setting milter_protocol
lineinfile:
- name: Postfix setting milter_protocol
ansible.builtin.lineinfile:
path: /etc/postfix/main.cf
regexp: '^milter_protocol='
line: 'milter_protocol=6'
insertafter: '^# rspamd'
- name: postfix setting non_smtpd_milters
lineinfile:
- name: Postfix setting non_smtpd_milters
ansible.builtin.lineinfile:
path: /etc/postfix/main.cf
regexp: '^non_smtpd_milters='
line: 'non_smtpd_milters=inet:127.0.0.1:11332'
insertafter: '^# rspamd'
- name: postfix setting smtpd_milters
lineinfile:
- name: Postfix setting smtpd_milters
ansible.builtin.lineinfile:
path: /etc/postfix/main.cf
regexp: '^smtpd_milters='
line: 'smtpd_milters=inet:127.0.0.1:11332'
insertafter: '^# rspamd'
- name: restart postfix
systemd:
- name: Restart postfix
ansible.builtin.systemd:
name: postfix
state: restarted
# rspamd configuration
- name: rspamd configure extended_spam_headers true
template:
- name: Rspamd configure extended_spam_headers true
ansible.builtin.template:
src: "rspamd/{{ item }}"
dest: "/etc/rspamd/override.d/{{ item }}"
owner: root
group: root
mode: 0644
mode: "0644"
loop:
- milter_headers.conf
- classifier-bayes.conf
@ -54,28 +54,28 @@
# install dkim
- name: mkdir /var/lib/rspamd/dkim
file:
- name: Mkdir /var/lib/rspamd/dkim
ansible.builtin.file:
path: /var/lib/rspamd/dkim
state: directory
owner: _rspamd
group: _rspamd
mode: '0755'
mode: "0755"
- name: rspamd config dkim_signing.conf and arc.conf
template:
- name: Rspamd config dkim_signing.conf and arc.conf
ansible.builtin.template:
src: "rspamd/{{ item }}"
dest: "/etc/rspamd/local.d/{{ item }}"
owner: root
group: root
mode: 0644
mode: "0644"
loop:
- dkim_signing.conf
- arc.conf
# restart rspamd
- name: restart rspamd
systemd:
- name: Restart rspamd
ansible.builtin.systemd:
name: rspamd
state: restarted