--- /dev/null
+STD_USER=wk
---
-
+# Ansible playbook to prepare the system for a standarized server
- hosts: all
vars:
hostname: "{{ inventory_hostname | regex_search('[0-9a-zA-Z_]+')}}"
tasks:
- name: Prepare /media/trg directory
- file: path=/media/trg state=directory
+ ansible.builtin.file: path=/media/trg state=directory
- name: Prepare /media/tmp directory
- file: path=/media/trg state=directory
+ ansible.builtin.file: path=/media/trg state=directory
- name: Prepare /media/fs.cave directory
- file: path=/media/fs.cave state=directory
+ ansible.builtin.file: path=/media/fs.cave state=directory
- name: Prepare /media/fs.sys directory
- file: path=/media/fs.sys state=directory
+ ansible.builtin.file: path=/media/fs.sys state=directory
- name: Prepare /usr/local/bin directory
- file: path=/usr/local/bin state=directory
+ ansible.builtin.file: path=/usr/local/bin state=directory
- name: Prepare /usr/local/bin/local directory
- file: path=/usr/local/bin/local state=directory
+ ansible.builtin.file: path=/usr/local/bin/local state=directory
- name: Prepare /usr/share/pyrshell directory
- file: path=/usr/share/pyrshell state=directory
+ ansible.builtin.file: path=/usr/share/pyrshell state=directory
- name: Symbolic link to local directory
- file: src=/usr/local/bin/local dest=/usr/local/bin/{{hostname}} state=link
+ ansible.builtin.file: src=/usr/local/bin/local dest=/usr/local/bin/{{hostname}} state=link
- name: Unpack a tar into /usr/local/bin/local
unarchive: src=../resources/needed.tgz dest=/usr/local/bin
- name: Symbolic link to /p
- file: src=/usr/local/bin/std.profile dest=/p state=link
+ ansible.builtin.file: src=/usr/local/bin/std.profile dest=/p state=link
- name: Unpack a tar into /usr/share/pyrshell
unarchive: src=../resources/rsh.tgz dest=/usr/share/pyrshell
- name: Create user bupsrv
- user: name=bupsrv state=present uid=201
+ ansible.builtin.user: name=bupsrv state=present uid=201
- name: Create user bupsupply
- user: name=bupsupply state=present uid=202
+ ansible.builtin.user: name=bupsupply state=present uid=202
- name: Create ssh directory for bupsupply
- file: path=/home/bupsupply/.ssh state=directory group=bupsupply owner=bupsupply mode=0700
+ ansible.builtin.file: path=/home/bupsupply/.ssh state=directory group=bupsupply owner=bupsupply mode=0700
- name: Create authorized_keys for bupsupply
- file: path=/home/bupsupply/.ssh/authorized_keys state=touch group=bupsupply owner=bupsupply mode=0600
+ ansible.builtin.file: path=/home/bupsupply/.ssh/authorized_keys state=touch group=bupsupply owner=bupsupply mode=0600
- name: Create user bupwiki
- user: name=bupwiki state=present uid=203
+ ansible.builtin.user: name=bupwiki state=present uid=203
- name: Create user buptmp
- user: name=buptmp state=present uid=204
+ ansible.builtin.user: name=buptmp state=present uid=204
- name: Create ssh directory for buptmp
- file: path=/home/buptmp/.ssh state=directory group=buptmp owner=buptmp mode=0700
+ ansible.builtin.file: path=/home/buptmp/.ssh state=directory group=buptmp owner=buptmp mode=0700
- name: Create authorized_keys for buptmp
- file: path=/home/buptmp/.ssh/authorized_keys state=touch group=buptmp owner=buptmp mode=0600
+ ansible.builtin.file: path=/home/buptmp/.ssh/authorized_keys state=touch group=buptmp owner=buptmp mode=0600
- name: Create user extdata
- user: name=extdata state=present uid=211
+ ansible.builtin.user: name=extdata state=present uid=211
- name: Create user extcloud
- user: name=extcloud state=present uid=212
+ ansible.builtin.user: name=extcloud state=present uid=212
- name: Create user extbup
- user: name=extbup state=present uid=213
+ ansible.builtin.user: name=extbup state=present uid=213
- name: Create configuration directory
- file: path=/etc/config state=directory mode=0700
+ ansible.builtin.file: path=/etc/config state=directory mode=0700
- name: Create webapp.d
- file: path=/etc/config/webapps.d state=directory mode=0700
+ ansible.builtin.file: path=/etc/config/webapps.d state=directory mode=0700
- name: install standard packages
apt:
name: "{{ item }}"
hostname: "{{ inventory_hostname }}"
log_name: "{{ inventory_hostname | regex_search('[0-9a-zA-Z_]+') }}"
vars_files:
+ - ../var/common.yaml
- ../var/ssl-certificate.yaml
tasks:
- name: Install nginx
- apt:
+ ansible.builtin.apt:
name: nginx
state: latest
update_cache: yes
- name: Prepare letsencrypt home directory
- file: path=/home/www/letsencrypt/.well-known/acme-challenge state=directory
+ ansible.builtin.file: path=/srv/www/letsencrypt/.well-known/acme-challenge state=directory
- name: Add test file1
- copy: src=../templates/nginx/hi1.txt dest=/home/www/letsencrypt/.well-known/
+ ansible.builtin.copy: src=../templates.fix/nginx/hi1.txt dest=/srv/www/letsencrypt/.well-known/
- name: Add test file2
- copy: src=../templates/nginx/hi2.txt dest=/home/www/letsencrypt/.well-known/acme-challenge/hi2.txt
+ ansible.builtin.copy: src=../templates.fix/nginx/hi2.txt dest=/srv/www/letsencrypt/.well-known/acme-challenge/hi2.txt
- name: Prepare letsencrypt
- copy:
- src: ../templates/nginx/letsencrypt.conf
+ ansible.builtin.copy:
+ src: ../templates.fix/nginx/letsencrypt.conf
dest: /etc/nginx/snippets
- name: add HTTP-variables
- copy:
- src: ../templates/nginx/http.conf
+ ansible.builtin.copy:
+ src: ../templates.local/nginx/http.conf
dest: /etc/nginx/snippets
- name: create a www directory
- file: path=/home/www state=directory owner=root group=www-data
-
+ ansible.builtin.file: path={{ remote_www_directory }} state=directory owner=root group=www-data
- name: create the /srv/www link
- file: src=/home/www dest=/srv/www state=link
+ ansible.builtin.file: src={{ remote_www_directory }} dest=/srv/www state=link
- name: Ensure nginx is running
- systemd:
+ ansible.builtin.systemd:
name: nginx
state: started
enabled: yes
- name: create a test virtual hosts
- template:
- src: ../templates/nginx/test.site
+ ansible.builtin.template:
+ src: ../templates.fix/nginx/test.site
dest: /etc/nginx/sites-available/{{hostname}}
- name: activate by link in sites-enabled
- file:
+ ansible.builtin.file:
src: /etc/nginx/sites-available/{{hostname}}
dest: /etc/nginx/sites-enabled/{{hostname}}
state: link
- name: create a ssh-certificate
- command: openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/{{hostname}}.key -out /etc/ssl/certs/{{hostname}}.pem -subj "/C={{ssl_country}}/ST={{ssl_state}}/L={{ssl_locality}}/O={{ssl_organization}}/CN={{hostname}}"
+ ansible.builtin.command: openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/{{hostname}}.key -out /etc/ssl/certs/{{hostname}}.pem -subj "/C={{ssl_country}}/ST={{ssl_state}}/L={{ssl_locality}}/O={{ssl_organization}}/CN={{hostname}}"
args:
creates: /etc/ssl/private/{{hostname}}.key
- name: create a document root
- file: dest=/srv/www/{{hostname}} state=directory owner=www-data group=www-data
+ ansible.builtin.file: dest=/srv/www/{{hostname}} state=directory owner=www-data group=www-data
- name: create a test index.html
- template: src=../templates/nginx/index.html dest=/srv/www/{{hostname}}/index.html
+ template: src=../templates.fix/nginx/index.html dest=/srv/www/{{hostname}}/index.html
- name: create a test index.php
- copy: src=../templates/nginx/index.php dest=/srv/www/{{hostname}}/index.php
+ ansible.builtin.copy: src=../templates.fix/nginx/index.php dest=/srv/www/{{hostname}}/index.php
- name: Install mariadb
ansible.builtin.apt:
name:
- - mariadb-server
- - python3-mysqldb
+ - "mariadb-server"
+ - "python3-mysqldb"
state: latest
update_cache: yes
- name: Ensure mariadb is running
- ../var/php.yaml
pre_tasks:
- name:
- apt:
+ ansible.builtin.apt:
name: gpg
state: present
update_cache: true
- name: add packages.sury.org (Debian case)
block:
- name: add gpg repo key
- apt_key:
+ ansible.builtin.apt_key:
url: 'https://packages.sury.org/php/apt.gpg'
state: present
- name: add apt repo
- apt_repository:
+ ansible.builtin.apt_repository:
repo: 'deb https://packages.sury.org/php/ {{ ansible_distribution_release|lower }} main'
state: present
filename: php
- postfix
- mailutils
- name: build the main.cf
- copy:
- src: "../resources/postfix/{{ item }}"
+ ansible.builtin.copy:
+ src: "../templates.local/postfix/send_only/{{ item }}"
dest: "/etc/postfix/{{ item }}"
mode: 0640
owner: root
- restart postfix
- name: create alias
template:
- src: "../resources/postfix/aliases"
+ src: "../templates.local/postfix/aliases"
dest: "/etc/aliases"
mode: 0640
owner: root
- restart postfix
- name: create virtual alias
template:
- src: "../resources/postfix/virtual"
+ src: "../templates.local/postfix/virtual"
dest: "/etc/postfix/virtual"
mode: 0640
owner: root
group: root
+ when: postfix_mode == "email_forwarding"
notify:
- restart postfix
- name: create the mailname file
- copy:
+ ansible.builtin.copy:
content: |
- {{ postfix_domain }}
+ {{ postfix_host }}
dest: "/etc/mailname"
mode: 0644
owner: root
notify:
- restart postfix
- name: create a script to activate the virtual alias
- copy:
+ ansible.builtin.copy:
content: |
#! /bin/bash
postmap virtual
mode: 0700
owner: root
group: root
+ when: postfix_mode == "email_forwarding"
notify:
- postalias
- name: Ensure postfix is running
- name: postalias
shell: postalias /etc/aliases
- name: postmap
- shell: postalias /etc/postfix/virtual
+ shell: postmap /etc/postfix/virtual
--- /dev/null
+---
+# Installs the the spam reducing staff for postfix: SPF DKIM DMARYC
+# Needed facts (variables):
+# -
+# Needed role installation:
+- hosts: all
+ vars_files:
+ - ../var/common.yaml
+ - ../var/antispam.yaml
+ tasks:
+ - name: install the packages
+ ansible.builtin.package:
+ name: "{{ item }}"
+ state: present
+ with_items: [ postfix-policyd-spf-python, opendkim, opendkim-tools, opendmarc]
+ # ====== SPF ======
+ - name: Configure the SPF staff
+ ansible.builtin.include_tasks: ../tasks/t_spf_configuration.yaml
+ # ====== DKIM ======
+ - name: Configure the DKIM staff
+ ansible.builtin.include_tasks: ../tasks/t_dkim.yaml
+ # ====== DMARC ======
+ - name: Configure the DMARC staff
+ ansible.builtin.include_tasks: ../tasks/t_dmarc.yaml
+ handlers:
+ - name: restart opendkim
+ ansible.builtin.systemd:
+ name: opendkim
+ state: restarted
+ - name: restart opendmarc
+ ansible.builtin.systemd:
+ name: opendmarc
+ state: restarted
+ - name: restart postfix
+ ansible.builtin.systemd:
+ name: postfix
+ state: restarted
+
---
- name: Install and configure with letsencrypt
- hosts: all
+ hosts: localhost
become: yes
vars:
vars_files:
- ../var/webapps.yaml
tasks:
+ - name: Test regexpr
+ lineinfile:
+ dest: /tmp/wk.conf
+ regexp: '^{{ item }}\s*=\s*Fail'
+ line: "{{ item }} = False"
+ with_items: [x, y]
- name: Test Dateiänderung
- copy:
+ ansible.builtin.copy:
content: |
Line 1
Line 2
---
+# Create a new project directory structure for an Ansible project.
+# needed facts (variables) from the commandline:
- hosts: localhost
- become: yes
+ become: true
tasks:
+ - name: check if postfix_mode is defined
+ ansible.builtin.fail:
+ msg: "The 'postfix_mode' variable is not defined. -e postfix_mode=none|send_only|email_forwarding"
+ when: postfix_mode is not defined
- name: Check if project variable is defined
- fail:
+ ansible.builtin.fail:
msg: "The 'project' variable is not defined. -e project=your_project_name"
when: project is not defined
- name: Prepare base directory for {{ project }}
- file: path=../../{{ project }} state=directory
+ ansible.builtin.file: path=../../{{ project }} state=directory
- name: create sub directories for {{ project }}
- file: path=../../{{ project }}/{{ item }} state=directory
+ ansible.builtin.file: path=../../{{ project }}/{{ item }} state=directory
with_items: [playbooks, tasks, var, scripts, templates, resources, roles]
- name: create the links into the resources directory
- file:
- src: "../../ansknife/resources/{{ item }}"
- dest: "../resources/{{ item }}"
+ ansible.builtin.file:
+ src: ../../ansknife/resources/{{ item }}"
+ dest: "../../{{ project }}/resources/{{ item }}"
+ force: yes
state: link
with_items: [needed.tgz, rsh.tgz]
- name: create the nginx link into the templates directory
- file:
+ ansible.builtin.file:
src: "../../ansknife/templates/nginx"
- dest: "../templates/nginx"
- state: link
- - name: create the postfix link into the templates directory
- file:
- src: "../../ansknife/templates/postfix"
- dest: "../templates/postfix"
+ dest: "../../{{ project }}/templates/nginx"
+ force: yes
state: link
+ - name: create the postfix directory in the templates directory
+ ansible.builtin.file:
+ path: "../../{{ project }}/resources/postfix"
+ state: directory
+ - name: copy the postfix configuration files into the resources directory
+ ansible.builtin.template:
+ src: "../templates/postfix/{{ postfix_mode }}/{{ item }}"
+ dest: "../../{{ project }}/resources/postfix/{{ item }}"
+ when: postfix_mode != 'none'
+ with_items: [master.cf, main.cf]
- name: Prepare task facts
- set_fact:
+ ansible.builtin.set_fact:
src_dir: '../templates/var'
dest_dir: "../../{{ project }}/var"
pattern: "*.yaml"
- name: Copy var.templates
- import_tasks: ../tasks.templates/t_copy_wildcard.yaml
+ ansible.builtin.import_tasks: ../tasks.templates/t_copy_wildcard.yaml
- name: Prepare facts for links in playbooks
- set_fact:
+ ansible.builtin.set_fact:
src_dir: '../playbooks.templates'
src_relative: '../../ansknife/playbooks.templates'
dest_dir: "../../{{ project }}/playbooks"
- name: Create links in playbooks
import_tasks: ../tasks.templates/t_link_wildcard.yaml
- name: Prepare facts for links in tasks
- set_fact:
+ ansible.builtin.set_fact:
src_dir: '../tasks.templates'
src_relative: '../../ansknife/tasks.templates'
dest_dir: "../../{{ project }}/tasks"
pattern: "*.yaml"
- name: Create links in tasks
- import_tasks: ../tasks.templates/t_link_wildcard.yaml
+ ansible.builtin.import_tasks: ../tasks.templates/t_link_wildcard.yaml
- name: Prepare facts for links in scripts
set_fact:
src_dir: "../scripts.templates"
dest_dir: "../../{{ project }}/scripts"
pattern: "*"
- name: Create links in scripts
- import_tasks: ../tasks.templates/t_link_wildcard.yaml
+ ansible.builtin.import_tasks: ../tasks.templates/t_link_wildcard.yaml
- name: create a README file
copy:
dest: ../../{{ project }}/README.md
# Description
This project defines the software of the server
- name: create a CHANGELOG file
- copy:
+ ansible.builtin.copy:
dest: ../../{{ project }}/CHANGELOG.md
content: |
# V0.1.0
- Initial version
- name: create a the inventory (host definition)
- copy:
+ ansible.builtin.copy:
dest: ../../{{ project }}/inventory
content: |
[hosts]
ansible_user=ansadm
ansible_become=yes
- name: create a the ansible configuration file
- copy:
+ ansible.builtin.copy:
dest: ../../{{ project }}/ansible.cfg
content: |
[defaults]
#! /bin/bash
chown -R ansadm:ansadm *
chmod -R g+rw *
+if [ -d playbooks.templates ]; then
+ echo "protecting templates.local from changing"
+ chmod -R uog-w templates.local
+fi
+
--- /dev/null
+#! /usr/bin/python3
+import sys
+def main(args):
+ filename = args[0]
+ with open(filename, "r") as fp:
+ lines = fp.read().split('\n')
+ # 20250419._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
+ # "p=MIIBIjANBgkqh...QoSuyvjwoNEUNO"
+ # "dfsOuTKBzmchQ4Z...c2jwIDAQAB" ) ; ----- DKIM key 20250419 for f-r-e-i.de
+ info = lines[0].split('"')[1]
+ info += lines[1].split('"')[1]
+ info += lines[2].split('"')[1]
+ print(info)
+
+if __name__ == '__main__':
+ #main(["/tmp/example.txt"])
+ main(sys.argv[1:])
# - dest_dir: destination directory
# - pattern: wildcard pattern
- name: Copy files matching {{ pattern }} from {{ src_dir }} to {{dest_dir}}
- copy:
+ ansible.builtin.copy:
src: "{{ item }}"
dest: "{{ dest_dir }}"
with_fileglob:
--- /dev/null
+---
+# Configures DKIM
+# needed facts (variables):
+# dkim_domains: a list of domains handled by DKIM
+# dkim_opendkim_config_dir: normally /etc/opendkim
+# dkim_config_ansible.builtin.file: normally /etc/opendkim.conf
+# dkim_selector: normally the date yyyymmdd
+# dkim_user: the user running opendkim
+# dkim_group: the user group running opendkim
+# dkim_socket_port: port of the socket of opendkim
+
+
+- name: add user to group postfix
+ ansible.builtin.user:
+ name: '{{ dkim_user }}'
+ groups: postfix
+ append: yes
+- name: ensure existence of /var/spool/postfix/opendkim
+ ansible.builtin.file:
+ path: /var/spool/postfix/opendkim
+ state: directory
+ recurse: true
+ owner: "{{ dkim_user }}"
+ group: "{{ dkim_group }}"
+
+- name: opendkim directory present
+ ansible.builtin.file:
+ path: '{{ dkim_opendkim_config_dir }}/keys'
+ owner: "{{ dkim_user }}"
+ state: directory
+ group: "{{ dkim_group }}"
+ mode: 0750
+
+- name: opendkim trusted.hosts present
+ ansible.builtin.template:
+ src: ../templates.local/antispam/trusted.hosts
+ dest: '{{ dkim_opendkim_config_dir }}/trusted.hosts'
+ notify:
+ - restart opendkim
+
+- name: configure opendkim in {{ dkim_config_file }}
+ ansible.builtin.copy:
+ src: ../templates.local/antispam/opendkim.conf
+ dest: "{{ dkim_config_file }}"
+ notify:
+ - restart opendkim
+
+- name: installing tables
+ ansible.builtin.template:
+ src: "../templates.fix/antispam/{{ item }}"
+ dest: '{{ dkim_opendkim_config_dir }}/{{item}}'
+ notify:
+ - restart opendkim
+ with_items: [key.table, signing.table]
+
+- name: generate opendkim keys
+ ansible.builtin.include_tasks: "../tasks/t_dkim_keys.yaml"
+ loop: "{{ dkim_domains }}"
+ loop_control:
+ loop_var: dkim_domain
+
+- name: ensure opendkim is running
+ service:
+ name: opendkim
+ state: started
+ enabled: yes
+- name: display DNS staff and tests
+ ansible.builtin.include_tasks: "../tasks/t_dkim_dns.yaml"
+ loop: "{{ dkim_domains }}"
+ loop_control:
+ loop_var: dkim_domain
+
+
+...
--- /dev/null
+---
+# Show the DNS records to configure with dkim publik key
+# needed facts (variables):
+# dkim_domain: the domain to configure
+# dkim_opendkim_config_dir: normally /etc/opendkim
+# dkim_selector: normally the date yyyymmdd
+- name: store hostname and name of the public key file
+ ansible.builtin.set_fact:
+ hostname: "{{ inventory_hostname }}"
+ public_key: "{{ dkim_opendkim_config_dir }}/keys/{{ dkim_domain }}/{{ dkim_selector }}.txt"
+- name: fetch the remote key file to the (local) control host
+ fetch:
+ src: "{{ public_key }}"
+ dest: "/tmp"
+- name: start the local script to find out the related info
+ script: "../scripts/build_dkim_text.py /tmp/{{ hostname }}{{ public_key }}"
+ register: dns_text
+ delegate_to: localhost
+- name: display DKIM public key DNS record
+ debug:
+ msg:
+ - "#============================================="
+ - "zone: {{ dkim_selector }}._domainkey.{{ dkim_domain }}"
+ - "type: TXT"
+ - "content: {{ dns_text.stdout | regex_replace('\n', '')}}"
+ - "#============================================="
+ - "Test:"
+ - "host -t txt {{ dkim_selector }}._domainkey.{{ dkim_domain }}._domainkey"
+ - "opendkim-testkey -d {{ dkim_domain }} -s {{ dkim_selector }} -vvv"
+ - "#============================================="
+...
--- /dev/null
+---
+## DKIM: Generates a key for a given domain
+# dkim_domain: the domain to configure
+# dkim_opendkim_config_dir: normally /etc/opendkim
+# dkim_selector: normally the date yyyymmdd
+# dkim_user: the user running DKIM
+# dkim_group: the group running DKIM
+# dkim_rsa_keylen: the count of bits of the RSA key
+
+- name: creates domain's keys directory
+ file:
+ path: "{{ dkim_opendkim_config_dir }}/keys/{{ dkim_domain }}"
+ state: directory
+ recurse: true
+
+- name: ensure signing key is present
+ stat:
+ path: "{{ dkim_opendkim_config_dir }}/keys/{{ dkim_domain }}/{{ dkim_selector }}.private"
+ get_checksum: false
+ register: dkim_key
+
+- name: generate signing key
+ command: opendkim-genkey -b {{ dkim_rsa_keylen }} -s {{ dkim_selector }} -d {{ dkim_domain }} -D {{ dkim_opendkim_config_dir }}/keys/{{ dkim_domain }}
+ when: not dkim_key.stat.exists
+ notify:
+ - restart opendkim
+
+- name: ensure signing key owner
+ file:
+ path: "{{ dkim_opendkim_config_dir }}/keys/{{ dkim_domain }}/{{ dkim_selector }}.private"
+ owner: '{{ dkim_user }}'
+ group: '{{ dkim_group }}'
+
+...
--- /dev/null
+---
+# Configures DMARC
+# needed facts (variables):
+# dkim_domains: a list of domains handled by DKIM
+# dmarc_config_dir: normally /etc/opendmarc
+# dmarc_config_file: normally /etc/opendmarc.conf
+# dmarc_user: the user running opendmarc
+# dmarc_group: the user group running opendmarc
+
+- name: add user to group postfix
+ ansible.builtin.user:
+ name: '{{ dmarc_user }}'
+ groups: postfix
+ append: yes
+- name: ensure existence of /var/spool/postfix/opendmarc
+ file:
+ path: /var/spool/postfix/opendmarc
+ state: directory
+ recurse: true
+ owner: "{{ dmarc_user }}"
+ group: "{{ dmarc_group }}"
+ mode: "0750"
+- name: configure opendmarc in {{ dmarc_config_file }}
+ ansible.builtin.copy:
+ src: ../templates.local/antispam/opendmarc.conf
+ dest: "{{ dmarc_config_file }}"
+ notify:
+ - restart opendmarc
+- name: "create configuration directory {{ dmarc_config_dir }}"
+ ansible.builtin.file:
+ path: "{{ dmarc_config_dir }}"
+ state: directory
+ owner: "{{ dmarc_user }}"
+ group: "{{ dmarc_group }}"
+ mode: "0750"
+
+- name: create ignore.hosts
+ ansible.builtin.copy:
+ src: ../templates.local/antispam/ignore.hosts
+ dest: "{{ dmarc_config_dir }}/ignore.hosts"
+ notify:
+ - restart opendmarc
+- name: download suffix list
+ get_url:
+ url: https://publicsuffix.org/list/public_suffix_list.dat
+ dest: "{{ dmarc_config_dir }}"
+ owner: "{{ dmarc_user }}"
+ group: "{{ dmarc_group }}"
+- name: display DNS staff and tests
+ ansible.builtin.include_tasks: "../tasks/t_dmarc_dns.yaml"
+ loop: "{{ dkim_domains }}"
+ loop_control:
+ loop_var: dkim_domain
+
--- /dev/null
+---
+# Show the DNS records to configure DMARC
+# needed facts (variables):
+# dkim_domain: the domain to configure
+# dmarc_email_report: receipient email addres for reports
+- name: display DMARC public key DNS record
+ debug:
+ msg:
+ - "#============================================="
+ - "zone: _dmarc.{{ dkim_domain }}"
+ - "type: TXT"
+ - "content: v=DMARC1; p=reje; sp=reje; adkim; aspf; pct=1; rua=mailto:{{ dmarc_email_report }}; ruf=mailto:{{ dmarc_email_report }}; fo=1;"
+ - "#============================================="
+ - "Test:"
+ - "host -t txt _dmarc.{{ dkim_domain }}"
+ - "#============================================="
+...
# - pattern: wildcard pattern
- name: Link files matching {{ pattern }} from {{ src_dir }} to {{dest_dir}}
#command: ln -s {{ src_relative }}/{{ item | basename}} {{ dest_dir }}/{{ item | basename }}
- file:
+ ansible.builtin.file:
src: "{{ src_relative }}/{{ item | basename }}"
dest: "{{ dest_dir }}/{{ item | basename }}"
state: link
when: not force and site_config.stat.exists
- name: Create nginx site configuration of {{ domain }}
ansible.builtin.template:
- src: ../templates/nginx/site.php
+ src: ../templates.fix/nginx/site.php
dest: /etc/nginx/sites-available/{{ domain }}
owner: root
group: root
--- /dev/null
+---
+# Installs the SPF staff for postfix
+# needed facts (variables):
+# dkim_domains: the list of email domains
+- name: intro
+ debug:
+ msg: "domains: {{ dkim_domains }}"
+- name: Adapt policyd-spf.conf
+ lineinfile:
+ dest: /etc/postfix-policyd-spf-python/policyd-spf.conf
+ regexp: "^{{ item }}\\s*=\\s*Fail"
+ line: "{{ item }} = False"
+ notify:
+ - restart postfix
+ with_items: [ HELO_reject, Mail_From_reject]
+- name: Display DNS configuration
+ debug:
+ msg:
+ - "*************************************************************"
+ - "zone: {{ item }}"
+ - "type: TXT"
+ - "content: 'v=spf1 mx -all' deny other"
+ - "content: 'v=spf1 mx ~all' allow other"
+ - "*************************************************************"
+ with_items: "{{ dkim_domains }}"
+- name: Display test command
+ debug:
+ msg:
+ - "*************************************************************"
+ - "Test it with:"
+ - "host -t txt {{ item }}"
+ - "*************************************************************"
+ with_items: "{{ dkim_domains }}"
# - ssl_lifetime: the lifetime of the certificate in days
# - ssl_rsa_key_size: the size of the RSA key for the certificate
- name: create a ssh-certificate
- command: openssl req -x509 -nodes -days {{ssl_lifetime}} -newkey rsa:{{ssl_rsa_key_size}} -keyout /etc/ssl/private/{{domain}}.key -out /etc/ssl/certs/{{domain}}.pem -subj "/C={{ssl_country}}/ST={{ssl_state}}/L={{ssl_locality}}/O={{ssl_organization}}/CN={{domain}}"
+ ansible.builtin.command: openssl req -x509 -nodes -days {{ssl_lifetime}} -newkey rsa:{{ssl_rsa_key_size}} -keyout /etc/ssl/private/{{domain}}.key -out /etc/ssl/certs/{{domain}}.pem -subj "/C={{ssl_country}}/ST={{ssl_state}}/L={{ssl_locality}}/O={{ssl_organization}}/CN={{domain}}"
args:
creates: /etc/ssl/private/{{domain}}.key
# webapp_backup_directory: a local directory which will be syncronized with the web application
# webapps_list: the list defined in ../var/webapps.yaml
# fetch: true: the file will be fetched to the local machine
-- set_fact:
+- ansible.builtin.set_fact:
db_name: "{{ webapps_list | selectattr('webapp_name', 'equalto', webapp_name) | map(attribute='db_name') | first }}"
db_user: "{{ webapps_list | selectattr('webapp_name', 'equalto', webapp_name) | map(attribute='db_user') | first }}"
db_password: "{{ webapps_list | selectattr('webapp_name', 'equalto', webapp_name) | map(attribute='db_password') | first }}"
document_root: "{{ webapps_list | selectattr('webapp_name', 'equalto', webapp_name) | map(attribute='directory') | first }}"
target_file: "{{ document_root }}/db/{{ webapp_name }}.sql.gz"
- name: Dump the database {{ db_name }} into {{ document_root }}
- import_tasks: t_webapp_export.yaml
+ ansible.builtin.import_tasks: t_webapp_export.yaml
- name: Synchronize the web application {{ webapp_name }} with {{ webapp_backup_directory }}
ansible.posix.synchronize:
mode: push
# remote_webapps_directory: the access data will be stored there, e.g. /etc/ansknife/webapp.d
# local_webapps_directory: the access data will be stored there, e.g. ../webapp.d
- name: 'check if the webapp is already defined'
- stat:
+ ansible.builtin.stat:
path: "{{remote_webapps_directory}}/{{ webapp_name }}.yaml"
register: webapp
- name: 'stop if the webapp already defined'
- fail: msg="webapp {{ webapp_name }} is already defined"
+ ansible.builtin.fail: msg="webapp {{ webapp_name }} is already defined"
when: webapp.stat.exists
- name: 'stop on missing facts'
- fail: msg="missing facts! webapp_name, db_name, db_user, db_password. Use -e webapp_name=..., -e db_name=..., -e db_user=..., -e db_password=..."
+ ansible.builtin.fail: msg="missing facts! webapp_name, db_name, db_user, db_password. Use -e webapp_name=..., -e db_name=..., -e db_user=..., -e db_password=..."
when: webapp_name is not defined or db_name is not defined or db_user is not defined or db_password is not defined
- name: Create the database {{db_name}} and db user {{db_user}}
- import_tasks: ../tasks/t_mysql_create_db_and_user.yaml
+ ansible.builtin.import_tasks: ../tasks/t_mysql_create_db_and_user.yaml
- name: Store data in remote configuration file
- copy:
+ ansible.builtin.copy:
content: |
db_name={{ db_name }}
db_user={{ db_user }}
single_transaction: true
pipefail: "{{ compressed }}"
- name: Fetch the database dump {{ target_file }} to local machine
- fetch:
+ ansible.builtin.fetch:
src: "{{ remote_file }}"
dest: "{{ target_file }}"
flat: true
--- /dev/null
+{% for domain in dkim_domains %}
+{{ dkim_selector }}._domainkey.{{ domain }} {{ domain }}:{{ dkim_selector }}:/etc/opendkim/keys/{{ domain }}/{{ dkim_selector }}.private
+{% endfor %}
--- /dev/null
+{% for domain in dkim_domains %}
+*@{{ domain }} {{ dkim_selector }}._domainkey.{{ domain }}
+{% endfor %}
--- /dev/null
+<html>
+<body>
+<h1>Welcome to {{hostname}}!</h1>
+</body
+</html>
\ No newline at end of file
--- /dev/null
+<?php
+phpinfo();
\ No newline at end of file
--- /dev/null
+location ^~ /.well-known/acme-challenge/ {
+ default_type "text/plain";
+ root /srv/www/letsencrypt;
+}
+# Hide /acme-challenge subdirectory and return 404 on all requests.
+# It is somewhat more secure than letting Nginx return 403.
+# Ending slash is important!
+location = /.well-known/acme-challenge/ {
+ return 404;
+}
+
--- /dev/null
+server {
+ listen 80;
+ listen [::]:80;
+ server_name {{ domain }};
+ include snippets/letsencrypt.conf;
+ root /srv/www/{{ document_root }};
+ location / {
+ return 301 https://hero$request_uri; # enforce https
+ }
+ }
+
+server {
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ server_name {{ domain}};
+ access_log /var/log/nginx/a_{{ shortname }}.log;
+ error_log /var/log/nginx/e_{{ shortname }}.log;
+
+ #ssl_certificate /etc/letsencrypt/live/latest/fullchain.pem;
+ #ssl_certificate_key /etc/letsencrypt/live/latest/privkey.pem;
+ ssl_certificate /etc/ssl/certs/{{ domain }}.pem;
+ ssl_certificate_key /etc/ssl/private/{{ domain }}.key;
+
+ # Path to the root of your installation
+ root /srv/www/{{ document_root }};
+ autoindex off;
+ client_max_body_size 1m; # set max upload size
+ fastcgi_buffers 64 4K;
+
+ index index.html;
+
+ location = /robots.txt {
+ allow all;
+ log_not_found off;
+ access_log off;
+ }
+ location / {
+ allow all;
+ }
+ # Optional: set long EXPIRES header on static assets
+ location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
+ expires 30d;
+ # Optional: Don't log access to assets
+ access_log off;
+ }
+ location ~ ^(.+?\.php)(/.*)?$ {
+ try_files $1 = 404;
+
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$1;
+ fastcgi_param PATH_INFO $2;
+ fastcgi_param HTTPS on;
+ fastcgi_pass unix:/run/php/php{{ php_version }}-fpm.sock;
+ }
+}
+
--- /dev/null
+server {
+ listen 80;
+ listen [::]:80;
+ server_name {{hostname}} hamatoma.de;
+ include snippets/letsencrypt.conf;
+ server_name {{hostname}};
+ root /srv/www/{{hostname}};
+ location / {
+ return 301 https://{{hostname}}$request_uri; # enforce https
+ }
+ }
+
+server {
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ server_name {{hostname}};
+ access_log /var/log/nginx/a_{{log_name}}.log;
+ error_log /var/log/nginx/e_{{log_name}}.log;
+
+ #ssl_certificate /etc/letsencrypt/live/latest/fullchain.pem;
+ #ssl_certificate_key /etc/letsencrypt/live/latest/privkey.pem;
+ ssl_certificate /etc/ssl/certs/{{hostname}}.pem;
+ ssl_certificate_key /etc/ssl/private/{{hostname}}.key;
+
+ # Path to the root of your installation
+ root /home/www/{{hostname}};
+ autoindex off;
+ client_max_body_size 1m; # set max upload size
+ fastcgi_buffers 64 4K;
+
+ index index.html;
+
+ location = /robots.txt {
+ allow all;
+ log_not_found off;
+ access_log off;
+ }
+ location / {
+ allow all;
+ }
+ # Optional: set long EXPIRES header on static assets
+ location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
+ expires 30d;
+ # Optional: Don't log access to assets
+ access_log off;
+ }
+ location ~ ^(.+?\.php)(/.*)?$ {
+ try_files $1 = 404;
+
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$1;
+ fastcgi_param PATH_INFO $2;
+ fastcgi_param HTTPS on;
+ fastcgi_pass unix:/run/php/php8.3-fpm.sock;
+ }
+}
+
\ No newline at end of file
--- /dev/null
+Objective: This directory contains templates that can be used in all projects without modification.
+Therefore, the files should only be linked within the project, not copied.
--- /dev/null
+configuration_directory: /etc/ansknife
+remote_webapps_directory: "{{ configuration_directory }}/webapps.d"
+remote_domain: "{{ inventory_hostname | regex_replace('[0-9a-zA-Z_]+\.', '') }}
+local_webapps_directory: "../webapps"
+webmaster_email: "{{ inventory_hostname | regex_search('[0-9a-zA-Z_]+') }}@hamatoma.de"
+systemd_journal_system_max_use: 200M
+systemd_journal_system_max_file_size: 50M
+
--- /dev/null
+---
+# Creation of the central password file:
+# echo "top_secret_password" > resources/.vaults
+# Creation of the encrypted vault file:
+# ansible-vault encrypt_string --vault-password-file resources/.vault --name 'vault_dba_password' --stdin-name 'vault_dba_password' | tee var/vault_db.yaml
+# Find the password file: ANSIBLE_VAULT_PASSWORD_FILE=resources/.vault
+dba_name: dba
+dba_password: "{{ vault_dba_password }}"
\ No newline at end of file
--- /dev/null
+---
+dkim_domains: ["example.com"]
+dkim_opendkim_config_dir: /etc/opendkim
+dkim_config_file: /etc/opendkim.conf
+dkim_selector: "email"
+dkim_user: opendkim
+dkim_group: opendkim
+
--- /dev/null
+---
+# php.yaml:
+# Defines variables for the PHP role.
+# This file is used to set up the PHP environment and configuration.
+# needed variables: PHP_VERS
+
+php_packages:
+ - php{{PHP_VERS}}-common
+ - php{{PHP_VERS}}-curl
+ - php{{PHP_VERS}}-fpm
+ - php{{PHP_VERS}}-gd
+ - php{{PHP_VERS}}-igbinary
+ - php{{PHP_VERS}}-imagick
+ - php{{PHP_VERS}}-imap
+ - php{{PHP_VERS}}-intl
+ - php{{PHP_VERS}}-mbstring
+ - php{{PHP_VERS}}-memcached
+ - php{{PHP_VERS}}-msgpack
+ - php{{PHP_VERS}}-mysql
+ - php{{PHP_VERS}}-opcache
+ - php{{PHP_VERS}}-phpdbg
+ - php{{PHP_VERS}}-readline
+ - php{{PHP_VERS}}-redis
+ - php{{PHP_VERS}}-xdebug
+ - php{{PHP_VERS}}-xml
+ - php{{PHP_VERS}}-zip
+php_additional_packages:
+ - redis-server
+ - imagemagick
+
+php_ini_settings:
+ - { section: "DEFAULT", option: "memory_limit", value: "512M" }
+ - { section: "DEFAULT", option: "upload_max_filesize", value: "512M" }
+ - { section: "DEFAULT", option: "max_file_uploads", value: 100 }
+ - { section: "DEFAULT", option: "post_max_size", value: "512M" }
+ - { section: "DEFAULT", option: "max_execution_time", value: 600 }
+ - { section: "DEFAULT", option: "max_input_time", value: 600 }
+ - { section: "DEFAULT", option: "default_socket_timeout", value: 600 }
+ - { section: "Session", option: "session.save_handler", value: "redis" }
+ - { section: "Session", option: "session.save_path", value: "tcp://127.0.0.1:6379" }
+ - { section: "opcache", option: "opcache.enable", value: 1 }
+ - { section: "opcache", option: "opcache.memory_consumption", value: 512 }
+ - { section: "opcache", option: "opcache.interned_strings_buffer", value: 256 }
+
--- /dev/null
+---
+# "/C=DE/ST=NRW/L=Bochum/O=IT/CN={{hostname}}"
+ssl_country: DE
+ssl_state: Bavaria
+ssl_locality: Kempten
+ssl_organization: 'Gemeinwohl-Gesellschaft e.V.'
+ssl_lifetime: 365
+ssl_rsa_key_size: 2048
+
--- /dev/null
+vault_dba_password: TopSecret
\ No newline at end of file
--- /dev/null
+webapps_list:
+ - dummy
+ db_name: dbdummy5
+ db_user: dummy5
+ db_password: NeverKnown5
+ directory: /srv/www/myapp5.example.com
--- /dev/null
+# normally no need for changes
+UserID opendkim:opendkim
+UMask 002
+PidFile /var/run/opendkim/opendkim.pid
+SOCKET local:/var/spool/postfix/opendkim/opendkim.sock
+Mode sv
+Domain *
+#Selector mail
+Canonicalization relaxed/relaxed
+SignatureAlgorithm rsa-sha256
+OversignHeaders From
+AutoRestart yes
+AutoRestartRate 10/1h
+SigningTable refile:/etc/opendkim/signing.table
+KeyTable /etc/opendkim/key.table
+ExternalIgnoreList refile:/etc/opendkim/trusted.hosts
+InternalHosts refile:/etc/opendkim/trusted.hosts
+Syslog yes
+SyslogSuccess yes
+LogWhy yes
--- /dev/null
+127.0.0.1
+::1
+localhost
\ No newline at end of file
--- /dev/null
+client_max_body_size 512M;
+## Detect when HTTPS is used
+map $scheme $fastcgi_https {
+ default off;
+ https on;
+}
+fastcgi_read_timeout 3600s;
+fastcgi_request_buffering off;
+error_log /var/log/nginx/error.log;
--- /dev/null
+# ansible controlled: do not change manually on remote server!
+#
+postmaster: root
+devnull: /dev/null
+mailer-daemon: root
+webmaster: root
+www: root
+security: root
+root: root.nest1@hamatoma.de
--- /dev/null
+myorigin = /etc/mailname
+smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
+biff = no
+append_dot_mydomain = no
+#delay_warning_time = 4h
+readme_directory = no
+compatibility_level = 3.6
+
+
+smtpd_tls_cert_file=/etc/letsencrypt/live/{{ postfix_host }}/fullchain.pem
+smtpd_tls_key_file=/etc/letsencrypt/live/{{ postfix_host }}/privkey.pem
+#smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
+#smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
+smtpd_tls_security_level=may
+
+smtp_tls_CApath=/etc/ssl/certs
+smtp_tls_security_level=may
+smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
+
+smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
+myhostname = nest1.gemeinwohl-gesellschaft.de
+alias_maps = hash:/etc/aliases
+alias_database = hash:/etc/aliases
+myorigin = /etc/mailname
+mydestination = $myhostname, localhost.{{ postfix_domain }}, , localhost
+relayhost =
+mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
+mailbox_size_limit = 0
+recipient_delimiter = +
+inet_interfaces = all
+inet_protocols = all
--- /dev/null
+#
+# Postfix master process configuration file. For details on the format
+# of the file, see the master(5) manual page (command: "man 5 master" or
+# on-line: http://www.postfix.org/master.5.html).
+#
+# Do not forget to execute "postfix reload" after editing this file.
+#
+# ==========================================================================
+# service type private unpriv chroot wakeup maxproc command + args
+# (yes) (yes) (no) (never) (100)
+# ==========================================================================
+smtp inet n - y - - smtpd
+#smtp inet n - y - 1 postscreen
+#smtpd pass - - y - - smtpd
+#dnsblog unix - - y - 0 dnsblog
+#tlsproxy unix - - y - 0 tlsproxy
+# Choose one: enable submission for loopback clients only, or for any client.
+#127.0.0.1:submission inet n - y - - smtpd
+#submission inet n - y - - smtpd
+# -o syslog_name=postfix/submission
+# -o smtpd_tls_security_level=encrypt
+# -o smtpd_sasl_auth_enable=yes
+# -o smtpd_tls_auth_only=yes
+# -o smtpd_reject_unlisted_recipient=no
+# Instead of specifying complex smtpd_<xxx>_restrictions here,
+# specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
+# here, and specify mua_<xxx>_restrictions in main.cf (where
+# "<xxx>" is "client", "helo", "sender", "relay", or "recipient").
+# -o smtpd_client_restrictions=
+# -o smtpd_helo_restrictions=
+# -o smtpd_sender_restrictions=
+# -o smtpd_relay_restrictions=
+# -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
+# -o milter_macro_daemon_name=ORIGINATING
+# Choose one: enable submissions for loopback clients only, or for any client.
+#127.0.0.1:submissions inet n - y - - smtpd
+#submissions inet n - y - - smtpd
+# -o syslog_name=postfix/submissions
+# -o smtpd_tls_wrappermode=yes
+# -o smtpd_sasl_auth_enable=yes
+# -o smtpd_reject_unlisted_recipient=no
+# Instead of specifying complex smtpd_<xxx>_restrictions here,
+# specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
+# here, and specify mua_<xxx>_restrictions in main.cf (where
+# "<xxx>" is "client", "helo", "sender", "relay", or "recipient").
+# -o smtpd_client_restrictions=
+# -o smtpd_helo_restrictions=
+# -o smtpd_sender_restrictions=
+# -o smtpd_relay_restrictions=
+# -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
+# -o milter_macro_daemon_name=ORIGINATING
+#628 inet n - y - - qmqpd
+pickup unix n - y 60 1 pickup
+cleanup unix n - y - 0 cleanup
+qmgr unix n - n 300 1 qmgr
+#qmgr unix n - n 300 1 oqmgr
+tlsmgr unix - - y 1000? 1 tlsmgr
+rewrite unix - - y - - trivial-rewrite
+bounce unix - - y - 0 bounce
+defer unix - - y - 0 bounce
+trace unix - - y - 0 bounce
+verify unix - - y - 1 verify
+flush unix n - y 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - y - - smtp
+relay unix - - y - - smtp
+ -o syslog_name=postfix/$service_name
+# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
+showq unix n - y - - showq
+error unix - - y - - error
+retry unix - - y - - error
+discard unix - - y - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - y - - lmtp
+anvil unix - - y - 1 anvil
+scache unix - - y - 1 scache
+postlog unix-dgram n - n - 1 postlogd
+#
+# ====================================================================
+# Interfaces to non-Postfix software. Be sure to examine the manual
+# pages of the non-Postfix software to find out what options it wants.
+#
+# Many of the following services use the Postfix pipe(8) delivery
+# agent. See the pipe(8) man page for information about ${recipient}
+# and other message envelope options.
+# ====================================================================
+#
+# maildrop. See the Postfix MAILDROP_README file for details.
+# Also specify in main.cf: maildrop_destination_recipient_limit=1
+#
+maildrop unix - n n - - pipe
+ flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
+#
+# ====================================================================
+#
+# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
+#
+# Specify in cyrus.conf:
+# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
+#
+# Specify in main.cf one or more of the following:
+# mailbox_transport = lmtp:inet:localhost
+# virtual_transport = lmtp:inet:localhost
+#
+# ====================================================================
+#
+# Cyrus 2.1.5 (Amos Gouaux)
+# Also specify in main.cf: cyrus_destination_recipient_limit=1
+#
+#cyrus unix - n n - - pipe
+# flags=DRX user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
+#
+# ====================================================================
+# Old example of delivery via Cyrus.
+#
+#old-cyrus unix - n n - - pipe
+# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
+#
+# ====================================================================
+#
+# See the Postfix UUCP_README file for configuration details.
+#
+uucp unix - n n - - pipe
+ flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
+#
+# Other external delivery methods.
+#
+ifmail unix - n n - - pipe
+ flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
+bsmtp unix - n n - - pipe
+ flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
+scalemail-backend unix - n n - 2 pipe
+ flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
+mailman unix - n n - - pipe
+ flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
--- /dev/null
+myorigin = /etc/mailname
+smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
+biff = no
+append_dot_mydomain = no
+#delay_warning_time = 4h
+readme_directory = no
+compatibility_level = 3.6
+
+
+smtpd_tls_cert_file=/etc/letsencrypt/live/{{ postfix_host }}/fullchain.pem
+smtpd_tls_key_file=/etc/letsencrypt/live/{{ postfix_host }}/privkey.pem
+#smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
+#smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
+smtpd_tls_security_level=may
+
+smtp_tls_CApath=/etc/ssl/certs
+smtp_tls_security_level=may
+smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
+
+smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
+myhostname = nest1.gemeinwohl-gesellschaft.de
+alias_maps = hash:/etc/aliases
+alias_database = hash:/etc/aliases
+myorigin = /etc/mailname
+mydestination = $myhostname, localhost.{{ postfix_domain }}, , localhost
+relayhost =
+mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
+mailbox_size_limit = 0
+recipient_delimiter = +
+inet_interfaces = all
+inet_protocols = all
--- /dev/null
+#
+# Postfix master process configuration file. For details on the format
+# of the file, see the master(5) manual page (command: "man 5 master" or
+# on-line: http://www.postfix.org/master.5.html).
+#
+# Do not forget to execute "postfix reload" after editing this file.
+#
+# ==========================================================================
+# service type private unpriv chroot wakeup maxproc command + args
+# (yes) (yes) (no) (never) (100)
+# ==========================================================================
+smtp inet n - y - - smtpd
+#smtp inet n - y - 1 postscreen
+#smtpd pass - - y - - smtpd
+#dnsblog unix - - y - 0 dnsblog
+#tlsproxy unix - - y - 0 tlsproxy
+# Choose one: enable submission for loopback clients only, or for any client.
+#127.0.0.1:submission inet n - y - - smtpd
+#submission inet n - y - - smtpd
+# -o syslog_name=postfix/submission
+# -o smtpd_tls_security_level=encrypt
+# -o smtpd_sasl_auth_enable=yes
+# -o smtpd_tls_auth_only=yes
+# -o smtpd_reject_unlisted_recipient=no
+# Instead of specifying complex smtpd_<xxx>_restrictions here,
+# specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
+# here, and specify mua_<xxx>_restrictions in main.cf (where
+# "<xxx>" is "client", "helo", "sender", "relay", or "recipient").
+# -o smtpd_client_restrictions=
+# -o smtpd_helo_restrictions=
+# -o smtpd_sender_restrictions=
+# -o smtpd_relay_restrictions=
+# -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
+# -o milter_macro_daemon_name=ORIGINATING
+# Choose one: enable submissions for loopback clients only, or for any client.
+#127.0.0.1:submissions inet n - y - - smtpd
+#submissions inet n - y - - smtpd
+# -o syslog_name=postfix/submissions
+# -o smtpd_tls_wrappermode=yes
+# -o smtpd_sasl_auth_enable=yes
+# -o smtpd_reject_unlisted_recipient=no
+# Instead of specifying complex smtpd_<xxx>_restrictions here,
+# specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
+# here, and specify mua_<xxx>_restrictions in main.cf (where
+# "<xxx>" is "client", "helo", "sender", "relay", or "recipient").
+# -o smtpd_client_restrictions=
+# -o smtpd_helo_restrictions=
+# -o smtpd_sender_restrictions=
+# -o smtpd_relay_restrictions=
+# -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
+# -o milter_macro_daemon_name=ORIGINATING
+#628 inet n - y - - qmqpd
+pickup unix n - y 60 1 pickup
+cleanup unix n - y - 0 cleanup
+qmgr unix n - n 300 1 qmgr
+#qmgr unix n - n 300 1 oqmgr
+tlsmgr unix - - y 1000? 1 tlsmgr
+rewrite unix - - y - - trivial-rewrite
+bounce unix - - y - 0 bounce
+defer unix - - y - 0 bounce
+trace unix - - y - 0 bounce
+verify unix - - y - 1 verify
+flush unix n - y 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - y - - smtp
+relay unix - - y - - smtp
+ -o syslog_name=postfix/$service_name
+# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
+showq unix n - y - - showq
+error unix - - y - - error
+retry unix - - y - - error
+discard unix - - y - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - y - - lmtp
+anvil unix - - y - 1 anvil
+scache unix - - y - 1 scache
+postlog unix-dgram n - n - 1 postlogd
+#
+# ====================================================================
+# Interfaces to non-Postfix software. Be sure to examine the manual
+# pages of the non-Postfix software to find out what options it wants.
+#
+# Many of the following services use the Postfix pipe(8) delivery
+# agent. See the pipe(8) man page for information about ${recipient}
+# and other message envelope options.
+# ====================================================================
+#
+# maildrop. See the Postfix MAILDROP_README file for details.
+# Also specify in main.cf: maildrop_destination_recipient_limit=1
+#
+maildrop unix - n n - - pipe
+ flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
+#
+# ====================================================================
+#
+# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
+#
+# Specify in cyrus.conf:
+# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
+#
+# Specify in main.cf one or more of the following:
+# mailbox_transport = lmtp:inet:localhost
+# virtual_transport = lmtp:inet:localhost
+#
+# ====================================================================
+#
+# Cyrus 2.1.5 (Amos Gouaux)
+# Also specify in main.cf: cyrus_destination_recipient_limit=1
+#
+#cyrus unix - n n - - pipe
+# flags=DRX user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
+#
+# ====================================================================
+# Old example of delivery via Cyrus.
+#
+#old-cyrus unix - n n - - pipe
+# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
+#
+# ====================================================================
+#
+# See the Postfix UUCP_README file for configuration details.
+#
+uucp unix - n n - - pipe
+ flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
+#
+# Other external delivery methods.
+#
+ifmail unix - n n - - pipe
+ flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
+bsmtp unix - n n - - pipe
+ flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
+scalemail-backend unix - n n - 2 pipe
+ flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
+mailman unix - n n - - pipe
+ flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
--- /dev/null
+root {{ postfix_receipient_email }}
+webmaster {{ postfix_receipient_email }}
+#ada ada@miller.com
+#all@example.com jonny@miller.com ada@miller.com
+#@example.com info@miller.com
+
--- /dev/null
+Objective: This directory contains templates that are specific to the project and must be adapted for each project.
+Therefore, the files may only be copied into the project, not linked.
+++ /dev/null
-client_max_body_size 512M;
-## Detect when HTTPS is used
-map $scheme $fastcgi_https {
- default off;
- https on;
-}
-fastcgi_read_timeout 3600s;
-fastcgi_request_buffering off;
-error_log /var/log/nginx/error.log;
+++ /dev/null
-<html>
-<body>
-<h1>Welcome to {{hostname}}!</h1>
-</body
-</html>
\ No newline at end of file
+++ /dev/null
-<?php
-phpinfo();
\ No newline at end of file
+++ /dev/null
-location ^~ /.well-known/acme-challenge/ {
- default_type "text/plain";
- root /home/www/letsencrypt;
-}
-# Hide /acme-challenge subdirectory and return 404 on all requests.
-# It is somewhat more secure than letting Nginx return 403.
-# Ending slash is important!
-location = /.well-known/acme-challenge/ {
- return 404;
-}
-
+++ /dev/null
-server {
- listen 80;
- listen [::]:80;
- server_name {{ domain }};
- include snippets/letsencrypt.conf;
- root /srv/www/{{ document_root }};
- location / {
- return 301 https://hero$request_uri; # enforce https
- }
- }
-
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name {{ domain}};
- access_log /var/log/nginx/a_{{ shortname }}.log;
- error_log /var/log/nginx/e_{{ shortname }}.log;
-
- #ssl_certificate /etc/letsencrypt/live/latest/fullchain.pem;
- #ssl_certificate_key /etc/letsencrypt/live/latest/privkey.pem;
- ssl_certificate /etc/ssl/certs/{{ domain }}.pem;
- ssl_certificate_key /etc/ssl/private/{{ domain }}.key;
-
- # Path to the root of your installation
- root /srv/www/{{ document_root }};
- autoindex off;
- client_max_body_size 1m; # set max upload size
- fastcgi_buffers 64 4K;
-
- index index.html;
-
- location = /robots.txt {
- allow all;
- log_not_found off;
- access_log off;
- }
- location / {
- allow all;
- }
- # Optional: set long EXPIRES header on static assets
- location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
- expires 30d;
- # Optional: Don't log access to assets
- access_log off;
- }
- location ~ ^(.+?\.php)(/.*)?$ {
- try_files $1 = 404;
-
- include fastcgi_params;
- fastcgi_param SCRIPT_FILENAME $document_root$1;
- fastcgi_param PATH_INFO $2;
- fastcgi_param HTTPS on;
- fastcgi_pass unix:/run/php/php{{ php_version }}-fpm.sock;
- }
-}
-
+++ /dev/null
-server {
- listen 80;
- listen [::]:80;
- server_name {{hostname}} hamatoma.de;
- include snippets/letsencrypt.conf;
- server_name {{hostname}};
- root /srv/www/{{hostname}};
- location / {
- return 301 https://{{hostname}}$request_uri; # enforce https
- }
- }
-
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name {{hostname}};
- access_log /var/log/nginx/a_{{log_name}}.log;
- error_log /var/log/nginx/e_{{log_name}}.log;
-
- #ssl_certificate /etc/letsencrypt/live/latest/fullchain.pem;
- #ssl_certificate_key /etc/letsencrypt/live/latest/privkey.pem;
- ssl_certificate /etc/ssl/certs/{{hostname}}.pem;
- ssl_certificate_key /etc/ssl/private/{{hostname}}.key;
-
- # Path to the root of your installation
- root /home/www/{{hostname}};
- autoindex off;
- client_max_body_size 1m; # set max upload size
- fastcgi_buffers 64 4K;
-
- index index.html;
-
- location = /robots.txt {
- allow all;
- log_not_found off;
- access_log off;
- }
- location / {
- allow all;
- }
- # Optional: set long EXPIRES header on static assets
- location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
- expires 30d;
- # Optional: Don't log access to assets
- access_log off;
- }
- location ~ ^(.+?\.php)(/.*)?$ {
- try_files $1 = 404;
-
- include fastcgi_params;
- fastcgi_param SCRIPT_FILENAME $document_root$1;
- fastcgi_param PATH_INFO $2;
- fastcgi_param HTTPS on;
- fastcgi_pass unix:/run/php/php8.3-fpm.sock;
- }
-}
-
\ No newline at end of file
+++ /dev/null
-root {{ postfix_receipient_email }}
-webmaster {{ postfix_receipient_email }}
-#ada ada@miller.com
-#all@example.com jonny@miller.com ada@miller.com
-#@example.com info@miller.com
-
+++ /dev/null
-configuration_directory: /etc/ansknife
-remote_webapps_directory: "{{ configuration_directory }}/webapps.d"
-local_webapps_directory: "../webapps"
-webmaster_email: "{{ inventory_hostname | regex_search('[0-9a-zA-Z_]+') }}@hamatoma.de"
-systemd_journal_system_max_use: 200M
-systemd_journal_system_max_file_size: 50M
-
+++ /dev/null
----
-# Creation of the central password file:
-# echo "top_secret_password" > resources/.vaults
-# Creation of the encrypted vault file:
-# ansible-vault encrypt_string --vault-password-file resources/.vault --name 'vault_dba_password' --stdin-name 'vault_dba_password' | tee var/vault_db.yaml
-# Find the password file: ANSIBLE_VAULT_PASSWORD_FILE=resources/.vault
-dba_name: dba
-dba_password: "{{ vault_dba_password }}"
\ No newline at end of file
+++ /dev/null
----
-# php.yaml:
-# Defines variables for the PHP role.
-# This file is used to set up the PHP environment and configuration.
-# needed variables: PHP_VERS
-
-php_packages:
- - php{{PHP_VERS}}-common
- - php{{PHP_VERS}}-curl
- - php{{PHP_VERS}}-fpm
- - php{{PHP_VERS}}-gd
- - php{{PHP_VERS}}-igbinary
- - php{{PHP_VERS}}-imagick
- - php{{PHP_VERS}}-imap
- - php{{PHP_VERS}}-intl
- - php{{PHP_VERS}}-mbstring
- - php{{PHP_VERS}}-memcached
- - php{{PHP_VERS}}-msgpack
- - php{{PHP_VERS}}-mysql
- - php{{PHP_VERS}}-opcache
- - php{{PHP_VERS}}-phpdbg
- - php{{PHP_VERS}}-readline
- - php{{PHP_VERS}}-redis
- - php{{PHP_VERS}}-xdebug
- - php{{PHP_VERS}}-xml
- - php{{PHP_VERS}}-zip
-php_additional_packages:
- - redis-server
- - imagemagick
-
-php_ini_settings:
- - { section: "DEFAULT", option: "memory_limit", value: "512M" }
- - { section: "DEFAULT", option: "upload_max_filesize", value: "512M" }
- - { section: "DEFAULT", option: "max_file_uploads", value: 100 }
- - { section: "DEFAULT", option: "post_max_size", value: "512M" }
- - { section: "DEFAULT", option: "max_execution_time", value: 600 }
- - { section: "DEFAULT", option: "max_input_time", value: 600 }
- - { section: "DEFAULT", option: "default_socket_timeout", value: 600 }
- - { section: "Session", option: "session.save_handler", value: "redis" }
- - { section: "Session", option: "session.save_path", value: "tcp://127.0.0.1:6379" }
- - { section: "opcache", option: "opcache.enable", value: 1 }
- - { section: "opcache", option: "opcache.memory_consumption", value: 512 }
- - { section: "opcache", option: "opcache.interned_strings_buffer", value: 256 }
-
+++ /dev/null
-# postfix.yaml:
-# Defines variables for the postfix configuration.
-# Needed facts (variables):
-# - postfix_domain: The full qualified name of the postfix server.
-postfix_configuration:
- - alias_database: "hash:/etc/aliases"
- - alias_maps: "hash:/etc/aliases"
- - append_dot_mydomain: no
- - biff: no
- - compatibility_level: 2
- - inet_interfaces: all
- - inet_protocols: all
- - mailbox_size_limit: 0
- - mydestination: $myhostname, {{ postfix_domain }}, ,localhost
- - myhostname: "{{ postfix_domain }}"
- - mynetworks: 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
- - myorigin: /etc/mailname
- - readme_directory: no
- - recipient_delimiter: +
- - relayhost: ""
- - smtpd_banner: $myhostname ESMTP $mail_name (Debian/GNU)
- - smtpd_relay_restrictions: permit_mynetworks permit_sasl_authenticated defer_unauth_destination
- - smtpd_tls_cert_file: /etc/ssl/certs/ssl-cert-snakeoil.pem
- - smtpd_tls_key_file: /etc/ssl/private/ssl-cert-snakeoil.key
- - smtpd_tls_security_level: may
- - smtp_tls_CApath: /etc/ssl/certs
- - smtp_tls_security_level: may
- - smtp_tls_session_cache_database: btree:${data_directory}/smtp_scache
-postfix_recipient_email: jonny@example.com
+++ /dev/null
----
-# "/C=DE/ST=NRW/L=Bochum/O=IT/CN={{hostname}}"
-ssl_country: DE
-ssl_state: Bavaria
-ssl_locality: Kempten
-ssl_organization: 'Gemeinwohl-Gesellschaft e.V.'
-ssl_lifetime: 365
-ssl_rsa_key_size: 2048
-
+++ /dev/null
-vault_dba_password: TopSecret
\ No newline at end of file
+++ /dev/null
-webapps_list:
- - dummy
- db_name: dbdummy5
- db_user: dummy5
- db_password: NeverKnown5
- directory: /srv/www/myapp5.example.com