Initial Commit
Some checks failed
Ansible Linter / ansible-lint (push) Failing after 18s
Lint Markdown files / markdown-lint (push) Successful in 5s

This commit is contained in:
2026-03-02 18:48:41 +01:00
commit e62397b06f
40 changed files with 1147 additions and 0 deletions

4
.ansible-lint Normal file
View File

@@ -0,0 +1,4 @@
---
exclude_paths:
- .gitea/

12
.editorconfig Normal file
View File

@@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false

View File

@@ -0,0 +1,20 @@
name: Ansible Linter
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
jobs:
ansible-lint:
runs-on:
- ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
- name: Run ansible-lint
uses: ansible/ansible-lint@v26.2.0
with:
args: "--config-file .ansible-lint"
setup_python: "true"

View File

@@ -0,0 +1,18 @@
name: Lint Markdown files
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
jobs:
markdown-lint:
runs-on:
- ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
- uses: DavidAnson/markdownlint-cli2-action@v21.0.0
with:
globs: '**/*.md'

View File

@@ -0,0 +1,22 @@
name: Release Ansible Role
on:
push:
tags:
- '**'
workflow_dispatch: {}
jobs:
release:
name: Release Ansible Role
runs-on: ubuntu-latest
steps:
- name: Install Ansible Galaxy
run: |
apt update --yes
apt install --yes ansible
- env:
ANSIBLE_GALAXY_TOKEN: ${{ secrets.ANSIBLE_GALAXY_TOKEN }}
name: Update Ansible Role in Ansible Galaxy
run: |
ansible-galaxy role import --token=${ANSIBLE_GALAXY_TOKEN} volker-raschek ${GITHUB_REPOSITORY#*/}

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.ansible

137
.markdownlint.yaml Normal file
View File

@@ -0,0 +1,137 @@
# markdownlint YAML configuration
# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml
# Default state for all rules
default: true
# Path to configuration file to extend
extends: null
# MD003/heading-style/header-style - Heading style
MD003:
# Heading style
style: "atx"
# MD004/ul-style - Unordered list style
MD004:
style: "dash"
# MD007/ul-indent - Unordered list indentation
MD007:
# Spaces for indent
indent: 2
# Whether to indent the first level of the list
start_indented: false
# MD009/no-trailing-spaces - Trailing spaces
MD009:
# Spaces for line break
br_spaces: 2
# Allow spaces for empty lines in list items
list_item_empty_lines: false
# Include unnecessary breaks
strict: false
# MD010/no-hard-tabs - Hard tabs
MD010:
# Include code blocks
code_blocks: true
# MD012/no-multiple-blanks - Multiple consecutive blank lines
MD012:
# Consecutive blank lines
maximum: 1
# MD013/line-length - Line length
MD013:
# Number of characters
line_length: 120
# Number of characters for headings
heading_line_length: 120
# Number of characters for code blocks
code_block_line_length: 120
# Include code blocks
code_blocks: false
# Include tables
tables: false
# Include headings
headings: true
# Strict length checking
strict: false
# Stern length checking
stern: false
# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines
MD022:
# Blank lines above heading
lines_above: 1
# Blank lines below heading
lines_below: 1
# MD025/single-title/single-h1 - Multiple top-level headings in the same document
MD025:
# Heading level
level: 1
# RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]"
# MD026/no-trailing-punctuation - Trailing punctuation in heading
MD026:
# Punctuation characters
punctuation: ".,;:!。,;:!"
# MD029/ol-prefix - Ordered list item prefix
MD029:
# List style
style: "one_or_ordered"
# MD030/list-marker-space - Spaces after list markers
MD030:
# Spaces for single-line unordered list items
ul_single: 1
# Spaces for single-line ordered list items
ol_single: 1
# Spaces for multi-line unordered list items
ul_multi: 1
# Spaces for multi-line ordered list items
ol_multi: 1
# MD033/no-inline-html - Inline HTML
MD033:
# Allowed elements
allowed_elements: []
# MD035/hr-style - Horizontal rule style
MD035:
# Horizontal rule style
style: "---"
# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading
MD036:
# Punctuation characters
punctuation: ".,;:!?。,;:!?"
# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading
MD041:
# Heading level
level: 1
# RegExp for matching title in front matter
front_matter_title: "^\\s*title\\s*[:=]"
# MD044/proper-names - Proper names should have the correct capitalization
MD044:
# List of proper names
names:
- gitea
# Include code blocks
code_blocks: false
# MD046/code-block-style - Code block style
MD046:
# Block style
style: "fenced"
# MD048/code-fence-style - Code fence style
MD048:
# Code fence syle
style: "backtick"

14
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,14 @@
{
"ansible.python.interpreterPath": "/bin/python",
"files.associations": {
"**/.gitea/**/*.yml": "yaml",
"**/.gitea/**/*.yaml": "yaml",
"docker-compose*.yml": "dockercompose",
"*.yml": "ansible",
"*.yaml": "ansible",
".yamllint": "yaml",
".yamllint.yml": "yaml",
".yamllint.yaml": "yaml"
},
"rewrap.wrappingColumn": 120
}

19
.yamllint.yaml Normal file
View File

@@ -0,0 +1,19 @@
---
#
# Documentation:
# https://yamllint.readthedocs.io/en/stable/
#
rules:
brackets:
forbid: false
min-spaces-inside: 0
max-spaces-inside: 2
min-spaces-inside-empty: 0
max-spaces-inside-empty: 0
indentation:
spaces: 2
indent-sequences: false
line-length:
max: 360

20
LICENSE Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2022 Markus Pesch
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.

62
README.md Normal file
View File

@@ -0,0 +1,62 @@
# volker-raschek.rspamd
![Ansible Role](https://img.shields.io/ansible/role/d/volker-raschek/rspamd)
The ansible role `volker-raschek.rspamd` install rspamd - a spam milter. For example for Arch Linux, Fedora and Ubuntu.
Furthermore, rspamd can be integration in some MTA's like postfix.
## Examples
The following configuration enables DKIM signature validation and redis as backend. Furthermore, it configures custom
DNS servers for DNS queries.
```yaml
## @param rspamd_dkim_enabled Create `dkim_sining.conf`.
## @param rspamd_dkim_domains DKIM Domain configuration.
rspamd_dkim_enabled: true
rspamd_dkim_domains:
- name: my.example.local
selector: "2020"
## @section DNS
## @param List of DNS servers used for DNS lookups.
rspamd_dns_servers:
- 8.8.4.4
- 8.8.8.8
## @section Redis
## https://docs.rspamd.com/configuration/redis/#available-redis-options
## @param rspamd_redis_database Number of redis database.
## @param rspamd_redis_password Password to connect to redis.
## @param rspamd_redis_username Username to connect to redis.
## @param rspamd_redis_servers List of upstream redis server for read and write requests.
## @param rspamd_redis_timeout Timeout in seconds to get reply from redis. For example `0.5s`, `1min`.
## @param rspamd_redis_disabled_modules List of disabled modules.
rspamd_redis_enabled: true
rspamd_redis_database: "0"
rspamd_redis_password: "my-password"
rspamd_redis_username: "my-username"
rspamd_redis_servers:
- "127.0.0.1"
rspamd_redis_timeout: "5s"
rspamd_redis_disabled_modules:
- "ratelimit"
```
## Further ansible roles
This ansible role is used in combination with other ansible roles of `volker-raschek`. You can search for the other
ansible roles via the following command.
```bash
$ ansible-galaxy role search --author "volker-raschek"
Found roles matching your search:
Name Description
---- -----------
volker-raschek.bind9 Role to install and configure bind9 on different distributions
volker-raschek.dhcpd Role to install and configure dhcpd on different distributions
volker-raschek.renovate Role to configure renovate as container image
...
```

101
defaults/main.yaml Normal file
View File

@@ -0,0 +1,101 @@
---
## @section ACLs
## @param rspamd_acl_allowlist_from Allow emails by sender.
## @param rspamd_acl_allowlist_ips Allow emails by ip addresses.
## @param rspamd_acl_blocklist_from Reject emails by sender.
## @param rspamd_acl_blocklist_ips Reject emails by ip addresses.
rspamd_acl_allowlist_from: []
# - from: "max.mustermann@example.local"
# - from: "*@example.local"
rspamd_acl_allowlist_ips: []
# - ip: "10.11.12.13"
rspamd_acl_blocklist_from: []
# - from: "max.mustermann@example.local"
# - from: "*@example.local"
rspamd_acl_blocklist_ips: []
# - ip: "10.11.12.13"
## @section DKIM Singing configuration
## @param rspamd_dkim_enabled Create `dkim_sining.conf`.
## @param rspamd_dkim_allow_username_mismatch Enable DKIM signing for alias sender addresses.
## @param rspamd_dkim_directory Directory of the DKIM keys.
## @param rspamd_dkim_domains DKIM Domain configuration.
rspamd_dkim_enabled: false
rspamd_dkim_allow_username_mismatch: false
rspamd_dkim_dir: "/var/lib/rspamd/dkim"
rspamd_dkim_domains: []
# - name: example.local
# selector: "2020"
## @section DNS
## @param List of DNS servers used for DNS lookups.
rspamd_dns_servers: []
# - 8.8.4.4
# - 8.8.8.8
## @section Logging configuration
## https://docs.rspamd.com/configuration/logging/
## @param rspamd_logging_enabled Create `logging.inc.conf`.
## @param rspamd_logging_filename Path to log file for logging. Require logging_type `file`.
## @param rspamd_logging_level Log level. Allowed values: `error`, `warning`, `notice`, `info`, `silent` and `debug`.
## @param rspamd_logging_type Log type. Allowed values: `console`, `file` and `syslog`.
rspamd_logging_enabled: true
rspamd_logging_filename: ""
rspamd_logging_level: "info"
rspamd_logging_type: "syslog"
## @section Redis
## https://docs.rspamd.com/configuration/redis/#available-redis-options
## @param rspamd_redis_enabled Create `redis.conf`.
## @param rspamd_redis_database Number of redis database.
## @param rspamd_redis_password Password to connect to redis.
## @param rspamd_redis_username Username to connect to redis.
## @param rspamd_redis_servers List of upstream redis server for read and write requests.
## @param rspamd_redis_read_servers List of redis servers for read requests. Usually redis replication instances.
## @param rspamd_redis_timeout Timeout in seconds to get reply from redis. For example `0.5s`, `1min`.
## @param rspamd_redis_write_servers List of redis servers for write requests. Usually redis primary instances.
## @param rspamd_redis_disabled_modules List of disabled modules.
rspamd_redis_enabled: false
rspamd_redis_database: "0"
rspamd_redis_password: ""
rspamd_redis_username: ""
rspamd_redis_servers: []
# - "redis.example.local"
rspamd_redis_read_servers: []
# - "replica-0.redis.example.local"
# - "replica-1.redis.example.local"
rspamd_redis_timeout: "5s"
rspamd_redis_write_servers: []
# - "primary-0.redis.example.local"
# - "primary-1.redis.example.local"
rspamd_redis_disabled_modules: []
# - "ratelimit"
## @section Worker Controller
## https://docs.rspamd.com/workers/#common-worker-options
## @param rspamd_worker_controller_enabled Create `worker-controller.conf`.
## @param rspamd_worker_controller_read_password Password required for read-only commands.
## @param rspamd_worker_controller_read_password Password required for write (privileged) commands.
## @param rspamd_worker_controller_secure_ips List of secure IP-Addresses for password-less access. If using a reverse proxy with X-Forwarded-For, include both proxy and client IPs.
## @param rspamd_worker_controller_ssl_cert Path to PEM certificate file (required when using ssl bind sockets).
## @param rspamd_worker_controller_ssl_key Path to PEM private key file (required when using ssl bind sockets).
rspamd_worker_controller_enabled: false
rspamd_worker_controller_bind_socket: "localhost:11334"
rspamd_worker_controller_read_password: ""
rspamd_worker_controller_write_password: ""
rspamd_worker_controller_secure_ips:
- "localhost"
rspamd_worker_controller_ssl_cert: ""
rspamd_worker_controller_ssl_key: ""
## @section Drop-In directories
## @param rspamd_local_d_dir Drop-In directory to customize rspamd configurations.
## @param rspamd_modules_d_dir Drop-In directory to customize rspamd modules.
## @param rspamd_override_d_dir Drop-In directory to customize rspamd plugins.
## @param rspamd_plugins_d_dir Drop-In directory to override rspamd configurations.
rspamd_local_d_dir: "/etc/rspamd/local.d"
rspamd_modules_d_dir: "/etc/rspamd/modules.d"
rspamd_override_d_dir: "/etc/rspamd/override.d"
rspamd_plugins_d_dir: "/etc/rspamd/plugins.d"

11
handlers/main.yaml Normal file
View File

@@ -0,0 +1,11 @@
---
- name: Restart rspamd
ansible.builtin.systemd:
name: rspamd
state: restarted
- name: Restart nginx
ansible.builtin.systemd:
name: nginx
state: restarted

176
meta/argument_specs.yaml Normal file
View File

@@ -0,0 +1,176 @@
---
argument_specs:
main:
short_description: "Role to install and configure rspamd mail filter"
description:
- "This role configures rspamd with support for DKIM signing, Redis integration, logging, ACLs, and worker controller settings."
author: "Markus Pesch"
options:
# ACLs
rspamd_acl_allowlist_from:
description: "Allow emails by sender."
type: list
elements: dict
default: []
rspamd_acl_allowlist_ips:
description: "Allow emails by IP addresses."
type: list
elements: dict
default: []
rspamd_acl_blocklist_from:
description: "Reject emails by sender."
type: list
elements: dict
default: []
rspamd_acl_blocklist_ips:
description: "Reject emails by IP addresses."
type: list
elements: dict
default: []
# DKIM Signing
rspamd_dkim_enabled:
description: "Create dkim_signing.conf."
type: bool
default: false
rspamd_dkim_allow_username_mismatch:
description: "Enable DKIM signing for alias sender addresses."
type: bool
default: false
rspamd_dkim_dir:
description: "Directory of the DKIM keys."
type: str
default: "/var/lib/rspamd/dkim"
rspamd_dkim_domains:
description: "DKIM Domain configuration."
type: list
elements: dict
default: []
# DNS
rspamd_dns_servers:
description: "List of DNS servers used for DNS lookups."
type: list
elements: str
default: []
# Logging
rspamd_logging_enabled:
description: "Create logging.inc.conf."
type: bool
default: true
rspamd_logging_filename:
description: "Path to log file for logging. Requires logging_type 'file'."
type: str
default: ""
rspamd_logging_level:
description: "Log level."
type: str
default: "info"
choices:
- error
- warning
- notice
- info
- silent
- debug
rspamd_logging_type:
description: "Log type."
type: str
default: "syslog"
choices:
- console
- file
- syslog
# Redis
rspamd_redis_enabled:
description: "Create redis.conf."
type: bool
default: false
rspamd_redis_database:
description: "Number of redis database."
type: str
default: "0"
rspamd_redis_password:
description: "Password to connect to redis."
type: str
default: ""
rspamd_redis_username:
description: "Username to connect to redis."
type: str
default: ""
rspamd_redis_servers:
description: "List of upstream redis servers for read and write requests."
type: list
elements: str
default: []
rspamd_redis_read_servers:
description: "List of redis servers for read requests. Usually redis replication instances."
type: list
elements: str
default: []
rspamd_redis_timeout:
description: "Timeout in seconds to get reply from redis. For example '0.5s', '1min'."
type: str
default: "5s"
rspamd_redis_write_servers:
description: "List of redis servers for write requests. Usually redis primary instances."
type: list
elements: str
default: []
rspamd_redis_disabled_modules:
description: "List of disabled modules."
type: list
elements: str
default: []
# Worker Controller
rspamd_worker_controller_enabled:
description: "Create worker-controller.conf."
type: bool
default: false
rspamd_worker_controller_bind_socket:
description: "Bind socket for worker controller."
type: str
default: "localhost:11334"
rspamd_worker_controller_read_password:
description: "Password required for read-only commands."
type: str
default: ""
rspamd_worker_controller_write_password:
description: "Password required for write (privileged) commands."
type: str
default: ""
rspamd_worker_controller_secure_ips:
description: "List of secure IP addresses for password-less access. If using a reverse proxy with X-Forwarded-For, include both proxy and client IPs."
type: list
elements: str
default:
- localhost
rspamd_worker_controller_ssl_cert:
description: "Path to PEM certificate file (required when using ssl bind sockets)."
type: str
default: ""
rspamd_worker_controller_ssl_key:
description: "Path to PEM private key file (required when using ssl bind sockets)."
type: str
default: ""
# Drop-In directories
rspamd_local_d_dir:
description: "Drop-In directory to customize rspamd configurations."
type: str
default: "/etc/rspamd/local.d"
rspamd_modules_d_dir:
description: "Drop-In directory to customize rspamd modules."
type: str
default: "/etc/rspamd/modules.d"
rspamd_override_d_dir:
description: "Drop-In directory to override rspamd configurations."
type: str
default: "/etc/rspamd/override.d"
rspamd_plugins_d_dir:
description: "Drop-In directory to customize rspamd plugins."
type: str
default: "/etc/rspamd/plugins.d"

28
meta/main.yaml Normal file
View File

@@ -0,0 +1,28 @@
dependencies: []
galaxy_info:
author: "Markus Pesch"
company: "Cryptic Systems"
description: "Role to install and configure rspamd mail filter"
galaxy_tags:
- rspamd
- mail
- spam
- filter
- email
license: "MIT"
min_ansible_version: "2.9"
namespace: volker-raschek
platforms:
- name: ArchLinux
versions:
- all
- name: EL
versions:
- all
- name: Fedora
versions:
- all
- name: Ubuntu
versions:
- all
role_name: "rspamd"

9
renovate.json Normal file
View File

@@ -0,0 +1,9 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>volker.raschek/renovate-config:default#master",
"local>volker.raschek/renovate-config:container#master",
"local>volker.raschek/renovate-config:actions#master",
"local>volker.raschek/renovate-config:regexp#master"
]
}

48
tasks/dkim_create.yaml Normal file
View File

@@ -0,0 +1,48 @@
---
- name: "Create directory for dkim keys"
ansible.builtin.file:
path: "{{ rspamd_dkim_dir }}"
owner: "root"
group: "root"
mode: "0755"
state: "directory"
- name: "Generate dkim keys"
ansible.builtin.command:
cmd: "bash -c \"rspamadm dkim_keygen -b 2048 -s {{ item.selector }} -k {{ rspamd_dkim_dir }}/{{ item.name }}.{{ item.selector }}.key > {{ rspamd_dkim_dir }}/{{ item.name }}.{{ item.selector }}.txt\""
creates: "{{ rspamd_dkim_dir }}/{{ item.name }}.{{ item.selector }}.txt"
with_items: "{{ rspamd_dkim_domains }}"
notify: Restart rspamd
- name: "Change ownership for dkim key files"
ansible.builtin.file:
path: "{{ rspamd_dkim_dir }}/{{ item.name }}.{{ item.selector }}.txt"
owner: "{{ rspamd_unix_user }}"
group: "{{ rspamd_unix_group }}"
mode: "0440"
with_items: "{{ rspamd_dkim_domains }}"
- name: "Change ownership for dkim dns record files"
ansible.builtin.file:
path: "{{ rspamd_dkim_dir }}/{{ item.name }}.{{ item.selector }}.key"
owner: "{{ rspamd_unix_user }}"
group: "{{ rspamd_unix_group }}"
mode: "0440"
with_items: "{{ rspamd_dkim_domains }}"
- name: "Create dkim_signing.conf"
ansible.builtin.template:
src: etc/rspamd/local.d/dkim_signing.conf.j2
dest: "{{ rspamd_local_d_dir }}/dkim_signing.conf"
owner: "root"
group: "root"
mode: "0644"
- name: Link ARC module to same DKIM configuration
ansible.builtin.file:
src: "{{ rspamd_local_d_dir }}/dkim_signing.conf"
dest: "{{ rspamd_local_d_dir }}/arc.conf"
owner: "root"
group: "root"
state: link

11
tasks/dkim_delete.yaml Normal file
View File

@@ -0,0 +1,11 @@
---
- name: "Delete directory for dkim keys"
ansible.builtin.file:
path: "{{ rspamd_dkim_dir }}"
state: "absent"
- name: "Delete dkim_signing.conf"
ansible.builtin.file:
path: "{{ rspamd_local_d_dir }}/dkim_signing.conf"
state: "absent"

View File

@@ -0,0 +1,9 @@
---
- name: "Create logging.inc"
ansible.builtin.template:
src: etc/rspamd/local.d/logging.inc.j2
dest: "{{ rspamd_local_d_dir }}/logging.inc"
owner: "root"
group: "root"
mode: "0644"

View File

@@ -0,0 +1,6 @@
---
- name: "Delete logging.inc"
ansible.builtin.file:
path: "{{ rspamd_local_d_dir }}/logging.inc"
state: "absent"

121
tasks/main.yaml Normal file
View File

@@ -0,0 +1,121 @@
---
- name: Include OS-specific variables
tags: [ letsencrypt-hooks ]
ansible.builtin.include_vars: "{{ lookup('first_found', params) }}"
vars:
params:
files:
- "{{ ansible_facts['distribution'] }}_{{ ansible_facts['architecture'] }}.yaml"
- "{{ ansible_facts['distribution'] }}.yaml"
- "{{ ansible_facts['os_family'] }}_{{ ansible_facts['architecture'] }}.yaml"
- "{{ ansible_facts['os_family'] }}.yaml"
- main.yaml
paths:
- vars
- name: Install rspamd
ansible.builtin.package:
name: rspamd
state: "present"
- name: Create directory for custom rspamd configurations
ansible.builtin.file:
path: "{{ item }}"
owner: "root"
group: "root"
mode: "0755"
state: directory
with_items:
- "{{ rspamd_local_d_dir }}"
- "{{ rspamd_modules_d_dir }}"
- "{{ rspamd_override_d_dir }}"
- "{{ rspamd_plugins_d_dir }}"
- name: Manage dkim configuration
notify:
- Restart rspamd
block:
- name: Create dkim configuration
when: rspamd_dkim_enabled
ansible.builtin.include_tasks: dkim_create.yaml
- name: Delete dkim configuration
when: not rspamd_dkim_enabled
ansible.builtin.include_tasks: dkim_delete.yaml
- name: Manage logging configuration
notify:
- Restart rspamd
block:
- name: Create logging configuration
when: rspamd_logging_enabled
ansible.builtin.include_tasks: logging_create.yaml
- name: Delete logging configuration
when: not rspamd_logging_enabled
ansible.builtin.include_tasks: logging_delete.yaml
- name: Manage multimaps
ansible.builtin.include_tasks: multimaps.yaml
- name: Manage redis configuration
notify:
- Restart rspamd
block:
- name: Create redis configuration
when: rspamd_redis_enabled
ansible.builtin.include_tasks: redis_create.yaml
- name: Delete redis configuration
when: not rspamd_redis_enabled
ansible.builtin.include_tasks: redis_delete.yaml
- name: Manage worker controller
notify:
- Restart rspamd
block:
- name: Create worker controller configuration
when: rspamd_worker_controller_enabled
ansible.builtin.include_tasks: worker_controller_create.yaml
- name: Delete worker controller configuration
when: not rspamd_worker_controller_enabled
ansible.builtin.include_tasks: worker_controller_delete.yaml
- name: Template local.d files
vars:
selector_name: "{{ rspamd_dkim_selector_name | default('2020') }}"
ansible.builtin.template:
src: "{{ item }}.j2"
dest: "{{ rspamd_local_d_dir }}/{{ item | basename }}"
owner: "root"
group: "root"
mode: "0644"
with_items:
- etc/rspamd/local.d/classifier-bayes.conf
- etc/rspamd/local.d/milter_headers.conf
- etc/rspamd/local.d/options.inc
notify:
- Restart rspamd
- name: Template override.d files
ansible.builtin.template:
src: "{{ item }}.j2"
dest: "{{ rspamd_override_d_dir }}/{{ item | basename }}"
owner: "root"
group: "root"
mode: "0644"
with_items:
- etc/rspamd/override.d/classifier-bayes.conf
notify:
- Restart rspamd
- name: Test rspamd configuration
ansible.builtin.command:
cmd: rspamadm configtest --strict --config /etc/rspamd/rspamd.conf
register: _rspamd_rspamadm_configtest
changed_when: false
failed_when: _rspamd_rspamadm_configtest.rc > 0
- name: Start and enable rspamd
ansible.builtin.systemd:
name: rspamd
state: started
enabled: true

73
tasks/multimaps.yaml Normal file
View File

@@ -0,0 +1,73 @@
---
- name: "Create multimap.conf"
ansible.builtin.template:
src: etc/rspamd/local.d/multimap.conf.j2
dest: "{{ rspamd_local_d_dir }}/multimap.conf"
owner: "root"
group: "root"
mode: "0644"
- name: "Manage sender based allowlist"
block:
- name: "Create sender based allowlist"
when: rspamd_acl_allowlist_from | length > 0
ansible.builtin.template:
src: etc/rspamd/local.d/allowlist_from.map.j2
dest: "{{ rspamd_local_d_dir }}/allowlist_from.map"
owner: "root"
group: "root"
mode: "0644"
- name: "Delete sender based allowlist"
when: rspamd_acl_allowlist_from | length == 0
ansible.builtin.file:
path: "{{ rspamd_local_d_dir }}/allowlist_from.map"
state: "absent"
- name: "Manage ip based allowlist"
block:
- name: "Create ip based allowlist"
when: rspamd_acl_allowlist_ips | length > 0
ansible.builtin.template:
src: etc/rspamd/local.d/allowlist_ips.map.j2
dest: "{{ rspamd_local_d_dir }}/allowlist_ips.map"
owner: "root"
group: "root"
mode: "0644"
- name: "Delete ip based allowlist"
when: rspamd_acl_allowlist_ips | length == 0
ansible.builtin.file:
path: "{{ rspamd_local_d_dir }}/allowlist_ips.map"
state: "absent"
- name: "Manage sender based blocklist"
block:
- name: "Create sender based blocklist"
when: rspamd_acl_blocklist_from | length > 0
ansible.builtin.template:
src: etc/rspamd/local.d/blocklist_from.map.j2
dest: "{{ rspamd_local_d_dir }}/blocklist_from.map"
owner: "root"
group: "root"
mode: "0644"
- name: "Delete sender based blocklist"
when: rspamd_acl_blocklist_from | length == 0
ansible.builtin.file:
path: "{{ rspamd_local_d_dir }}/blocklist_from.map"
state: "absent"
- name: "Manage ip based blocklist"
block:
- name: "Create ip based blocklist"
when: rspamd_acl_blocklist_ips | length > 0
ansible.builtin.template:
src: etc/rspamd/local.d/blocklist_ips.map.j2
dest: "{{ rspamd_local_d_dir }}/blocklist_ips.map"
owner: "root"
group: "root"
mode: "0644"
- name: "Delete ip based blocklist"
when: rspamd_acl_blocklist_ips | length == 0
ansible.builtin.file:
path: "{{ rspamd_local_d_dir }}/blocklist_ips.map"
state: "absent"

9
tasks/redis_create.yaml Normal file
View File

@@ -0,0 +1,9 @@
---
- name: "Create redis.conf"
ansible.builtin.template:
src: etc/rspamd/local.d/redis.conf.j2
dest: "{{ rspamd_local_d_dir }}/redis.conf"
owner: "root"
group: "root"
mode: "0644"

6
tasks/redis_delete.yaml Normal file
View File

@@ -0,0 +1,6 @@
---
- name: "Delete redis.conf"
ansible.builtin.file:
path: "{{ rspamd_local_d_dir }}/redis.conf"
state: "absent"

View File

@@ -0,0 +1,23 @@
---
- name: Generate salted read password
when: rspamd_worker_controller_read_password | length > 0
ansible.builtin.command:
cmd: "rspamadm pw --password {{ rspamd_worker_controller_read_password }}"
changed_when: false
register: rspamd_worker_controller_read_password_salted
- name: Generate salted write password
when: rspamd_worker_controller_write_password | length > 0
ansible.builtin.command:
cmd: "rspamadm pw --password {{ rspamd_worker_controller_write_password }}"
changed_when: false
register: rspamd_worker_controller_write_password_salted
- name: "Create worker-controller.inc"
ansible.builtin.template:
src: etc/rspamd/local.d/worker-controller.inc.j2
dest: "{{ rspamd_local_d_dir }}/worker-controller.inc"
owner: "root"
group: "root"
mode: "0644"

View File

@@ -0,0 +1,6 @@
---
- name: "Delete worker-controller.inc"
ansible.builtin.file:
path: "{{ rspamd_local_d_dir }}/worker-controller.inc"
state: "absent"

View File

@@ -0,0 +1,6 @@
#
# {{ ansible_managed }}
#
{% for item in rspamd_acl_allowlist_from %}
{{ item.from }}
{% endfor %}

View File

@@ -0,0 +1,6 @@
#
# {{ ansible_managed }}
#
{% for item in rspamd_acl_allowlist_ips %}
{{ item.ip }}
{% endfor %}

View File

@@ -0,0 +1,6 @@
#
# {{ ansible_managed }}
#
{% for item in rspamd_acl_blocklist_from %}
{{ item.from }}
{% endfor %}

View File

@@ -0,0 +1,6 @@
#
# {{ ansible_managed }}
#
{% for item in rspamd_acl_blocklist_ips %}
{{ item.ip }}
{% endfor %}

View File

@@ -0,0 +1,5 @@
#
# {{ ansible_managed }}
#
backend = "redis";

View File

@@ -0,0 +1,23 @@
#
# {{ ansible_managed }}
#
#
# Documentation: https://rspamd.com/doc/modules/dkim_signing.html#configuration
#
# Default DKIM Keys
# selector = "";
# path = "";
allow_username_mismatch = {{ rspamd_dkim_allow_username_mismatch | lower }};
# Domain specific settings
domain {
{% for dkim_domain in rspamd_dkim_domains %}
{{ dkim_domain.name }} {
path = "{{ rspamd_dkim_dir }}/{{ dkim_domain.name }}.{{ dkim_domain.selector }}.key";
selector = "{{ dkim_domain.selector }}";
}
{% endfor %}
}

View File

@@ -0,0 +1,9 @@
#
# {{ ansible_managed }}
#
{% if rspamd_logging_type == "file" and rspamd_logging_filename | length > 0 %}
filename = "{{ rspamd_logging_filename }}";
{% endif %}
level = "{{ rspamd_logging_level }}";
type = "{{ rspamd_logging_type}}";

View File

@@ -0,0 +1,13 @@
#
# {{ ansible_managed }}
#
authenticated_headers = [
"authentication-results",
];
use = [
"x-spamd-bar",
"x-spam-level",
"authentication-results",
];

View File

@@ -0,0 +1,39 @@
#
# {{ ansible_managed }}
#
{% if rspamd_acl_blocklist_from | length > 0 %}
BLACKLIST_FROM {
type = "from";
map = "$CONFDIR/local.d/blocklist_from.map";
description = "Local from blocklist";
action = "reject";
}
{% endif %}
{% if rspamd_acl_blocklist_ips | length > 0 %}
BLACKLIST_IP {
type = "ip";
map = "$CONFDIR/local.d/blocklist_ips.map";
description = "Local ip blocklist";
action = "reject";
}
{% endif %}
{% if rspamd_acl_allowlist_from | length > 0 %}
WHITELIST_FROM {
type = "from";
map = "$CONFDIR/local.d/allowlist_from.map";
description = "Local from allowlist";
action = "accept";
}
{% endif %}
{% if rspamd_acl_allowlist_ips | length > 0 %}
WHITELIST_IP {
type = "ip";
map = "$CONFDIR/local.d/allowlist_ips.map";
description = "Local ip allowlist";
action = "accept";
}
{% endif %}

View File

@@ -0,0 +1,10 @@
#
# {{ ansible_managed }}
#
{% if rspamd_dns_server is defined and rspamd_dns_servers | length > 0 %}
dns {
nameserver = "{{ rspamd_dns_server }}";
}
{% endif %}
enable_test_patterns = true;

View File

@@ -0,0 +1,27 @@
#jinja2: lstrip_blocks: True, trim_blocks: True
#
# {{ ansible_managed }}
#
db = {{ rspamd_redis_database }};
{% if rspamd_redis_disabled_modules | length > 0 %}
disabled_modules = [
{% for item in rspamd_redis_disabled_modules %}
"{{ item }}",
{% endfor %}
];
{% endif %}
{% if rspamd_redis_password | length > 0 %}
password = "{{ rspamd_redis_password }}";
{% endif %}
{% if rspamd_redis_username| length > 0 %}
username = "{{ rspamd_redis_username }}";
{% endif %}
servers = "{{ rspamd_redis_servers | join(',') }}";
{% if rspamd_redis_read_servers | length > 0 %}
read_servers = "{{ rspamd_redis_read_servers | join(',') }}";
{% endif %}
{% if rspamd_redis_write_servers | length > 0 %}
write_servers = "{{ rspamd_redis_write_servers | join(',') }}";
{% endif %}
timeout = {{ rspamd_redis_timeout }};

View File

@@ -0,0 +1,22 @@
#
# {{ ansible_managed }}
#
{% if rspamd_worker_controller_bind_socket | length > 0 %}
bind_socket = "{{ rspamd_worker_controller_bind_socket }}";
{% endif %}
{% if rspamd_worker_controller_write_password_salted.stdout is defined and rspamd_worker_controller_write_password_salted.stdout | length > 0 %}
enable_password = "{{ rspamd_worker_controller_write_password_salted.stdout }}";
{% endif %}
{% if rspamd_worker_controller_read_password_salted.stdout is defined and rspamd_worker_controller_read_password_salted.stdout | length > 0 %}
password = "{{ rspamd_worker_controller_read_password_salted.stdout }}";
{% endif %}
{% if rspamd_worker_controller_secure_ips | length > 0 %}
secure_ip = "{{ rspamd_worker_controller_secure_ips | join(',') }}";
{% endif %}
{% if rspamd_worker_controller_ssl_cert | length > 0 %}
ssl_cert = "{{ rspamd_worker_controller_ssl_cert }}";
{% endif %}
{% if rspamd_worker_controller_ssl_key | length > 0 %}
ssl_key = "{{ rspamd_worker_controller_ssl_key }}";
{% endif %}

View File

@@ -0,0 +1,5 @@
#
# {{ ansible_managed }}
#
autolearn = true;

4
vars/Archlinux.yaml Normal file
View File

@@ -0,0 +1,4 @@
---
rspamd_unix_user: rspamd
rspamd_unix_group: rspamd