--- - name: Include public variables. include_vars: ../public/vars.yml - name: Include private variables. include_vars: ../private/vars.yml - name: Include members. include_vars: "{{ lookup('first_found', membership_rolls) }}" tags: accounts - name: Configure hostname. become: yes copy: content: "{{ domain_name }}\n" dest: "{{ item }}" loop: - /etc/hostname - /etc/mailname - name: Update hostname. become: yes command: hostname -F /etc/hostname when: domain_name != ansible_fqdn tags: actualizer - name: Add {{ ansible_user }} to system groups. become: yes user: name: "{{ ansible_user }}" append: yes groups: root,adm - name: Create monkey. become: yes user: name: monkey password: "!" - name: Authorize monkey@core. become: yes authorized_key: user: monkey key: "{{ lookup('file', '../Secret/ssh_monkey/id_ed25519.pub') }}" manage_dir: yes - name: Add {{ ansible_user }} to monkey group. become: yes user: name: "{{ ansible_user }}" append: yes groups: monkey - name: Install rsync. become: yes apt: pkg=rsync - name: Install basic software. become: yes apt: pkg=unattended-upgrades - name: Create user accounts. become: yes user: name: "{{ item }}" password: "{{ members[item].password_front }}" update_password: always home: /home/{{ item }} loop: "{{ usernames }}" when: members[item].status == 'current' tags: accounts - name: Disable former users. become: yes user: name: "{{ item }}" password: "!" loop: "{{ usernames }}" when: members[item].status != 'current' tags: accounts - name: Revoke former user authorized_keys. become: yes file: path: /home/{{ item }}/.ssh/authorized_keys state: absent loop: "{{ usernames }}" when: members[item].status != 'current' tags: accounts - name: Install server certificate/key. become: yes copy: src: "{{ item.src }}" dest: "{{ item.dest }}" mode: "{{ item.mode }}" force: no loop: - src: "../Secret/CA/pki/issued/{{ domain_name }}.crt" dest: "/etc/server.crt" mode: "u=r,g=r,o=r" - src: "../Secret/CA/pki/private/{{ domain_name }}.key" dest: "/etc/server.key" mode: "u=r,g=,o=" notify: - Restart Dovecot. - name: Install Postfix. become: yes apt: pkg=postfix - name: Configure Postfix. become: yes lineinfile: path: /etc/postfix/main.cf regexp: "^ *{{ item.p }} *=" line: "{{ item.p }} = {{ item.v }}" loop: - { p: smtpd_tls_cert_file, v: /etc/server.crt } - { p: smtpd_tls_key_file, v: /etc/server.key } - p: mynetworks v: >- {{ public_wg_net_cidr }} 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 - p: smtpd_recipient_restrictions v: >- permit_mynetworks reject_unauth_pipelining reject_unauth_destination reject_unknown_sender_domain - p: smtpd_relay_restrictions v: permit_mynetworks reject_unauth_destination - { p: message_size_limit, v: 104857600 } - { p: delay_warning_time, v: 1h } - { p: maximal_queue_lifetime, v: 4h } - { p: bounce_queue_lifetime, v: 4h } - { p: home_mailbox, v: Maildir/ } - p: smtp_header_checks v: regexp:/etc/postfix/header_checks.cf notify: Restart Postfix. - name: Install Postfix header_checks. become: yes copy: content: | /^Received:/ IGNORE /^User-Agent:/ IGNORE dest: /etc/postfix/header_checks.cf notify: Postmap header checks. - name: Start Postfix. become: yes systemd: service: postfix state: started tags: actualizer - name: Enable Postfix. become: yes systemd: service: postfix enabled: yes - name: Install institute email aliases. become: yes blockinfile: block: | abuse: root webmaster: root admin: root monkey: monkey@{{ front_wg_addr }} root: {{ ansible_user }} path: /etc/aliases marker: "# {mark} INSTITUTE MANAGED BLOCK" notify: New aliases. - name: Install OpenDKIM. become: yes apt: pkg=opendkim - name: Install DKIM private key. become: yes copy: src: "../Secret/opendkim/default.private" dest: "/etc/dkimkeys/default.private" owner: opendkim group: opendkim mode: u=rw,g=,o= - name: Add postfix to opendkim group. become: yes user: name: postfix append: yes groups: opendkim - name: Create opendkim/ in Postfix chroot. become: yes file: path: /var/spool/postfix/opendkim state: directory owner: opendkim group: opendkim - name: Configure OpenDKIM. become: yes lineinfile: path: /etc/opendkim.conf regexp: "^{{ item.name }}\t" line: "{{ item.name }}\t\t{{ item.value }}" loop: - { name: "Mode", value: "\ts" } - { name: "Domain", value: "\tbirchwood-abbey.net" } - { name: "Selector", value: "default" } - { name: "KeyFile", value: "\t/etc/dkimkeys/default.private" } - name: "Socket" value: "\tlocal:/var/spool/postfix/opendkim/opendkim.sock" - name: "InternalHosts" value: >- 127.0.0.1, {{ private_net_cidr }}, {{ public_wg_net_cidr }}, {{ campus_wg_net_cidr }} notify: Restart OpenDKIM. - name: Start OpenDKIM. become: yes systemd: service: opendkim state: started tags: actualizer - name: Enable OpenDKIM. become: yes systemd: service: opendkim enabled: yes - name: Configure Postfix for OpenDKIM. become: yes lineinfile: path: /etc/postfix/main.cf regexp: "^ *{{ item.p }} *=" line: "{{ item.p }} = {{ item.v }}" loop: - { p: "milter_default_action", v: "accept" } - { p: "milter_protocol", v: "6" } - { p: "smtpd_milters", v: "local:opendkim/opendkim.sock" } - { p: "non_smtpd_milters", v: '$smtpd_milters' } notify: Restart Postfix. - name: Install Dovecot IMAPd. become: yes apt: pkg=dovecot-imapd - name: Configure Dovecot 2.3 IMAPd. become: yes copy: content: | protocols = imap ssl = required ssl_cert = ansible_distribution_major_version|int ) notify: Restart Dovecot. - name: Configure Dovecot IMAPd. become: yes copy: content: | protocols = imap ssl = required ssl_server_cert_file = /etc/server.crt ssl_server_key_file = /etc/server.key service imap-login { inet_listener imap { port = 0 } } mail_driver = maildir mail_path = ~/Maildir mail_inbox_path = ~/Maildir dest: /etc/dovecot/local.conf when: - ansible_distribution == 'Debian' - 12 < ansible_distribution_major_version|int notify: Restart Dovecot. - name: Start Dovecot. become: yes systemd: service: dovecot state: started tags: actualizer - name: Enable Dovecot. become: yes systemd: service: dovecot enabled: yes - name: Install Apache2. become: yes apt: pkg=apache2 - name: Enable Apache2 modules. become: yes apache2_module: name: "{{ item }}" loop: [ ssl, userdir ] notify: Restart Apache2. - name: Create DocumentRoot. become: yes file: path: /home/www state: directory owner: monkey group: monkey - name: Configure web site. become: yes copy: content: | ServerName {{ domain_name }} ServerAdmin webmaster@{{ domain_name }} DocumentRoot /home/www Require all granted AllowOverride None UserDir /home/www-users Require all granted AllowOverride None ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined Redirect permanent / https://{{ domain_name }}/ SSLEngine on SSLCertificateFile /etc/server.crt SSLCertificateKeyFile /etc/server.key IncludeOptional \ /etc/apache2/sites-available/{{ domain_name }}-vhost.conf SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 SSLHonorCipherOrder on SSLCipherSuite {{ [ 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES256-GCM-SHA384', 'ECDHE-ECDSA-AES128-SHA', 'ECDHE-ECDSA-AES256-SHA', 'ECDHE-ECDSA-AES128-SHA256', 'ECDHE-ECDSA-AES256-SHA384', 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-RSA-AES128-SHA', 'ECDHE-RSA-AES256-SHA', 'ECDHE-RSA-AES128-SHA256', 'ECDHE-RSA-AES256-SHA384', 'DHE-RSA-AES128-GCM-SHA256', 'DHE-RSA-AES256-GCM-SHA384', 'DHE-RSA-AES128-SHA', 'DHE-RSA-AES256-SHA', 'DHE-RSA-AES128-SHA256', 'DHE-RSA-AES256-SHA256', '!aNULL', '!eNULL', '!LOW', '!3DES', '!MD5', '!EXP', '!PSK', '!SRP', '!DSS', '!RC4' ] |join(":") }} dest: /etc/apache2/sites-available/{{ domain_name }}.conf notify: Restart Apache2. - name: Enable web site. become: yes command: cmd: a2ensite -q {{ domain_name }} creates: /etc/apache2/sites-enabled/{{ domain_name }}.conf notify: Restart Apache2. - name: Start Apache2. become: yes systemd: service: apache2 state: started tags: actualizer - name: Enable Apache2. become: yes systemd: service: apache2 enabled: yes - name: Disable default vhosts. become: yes file: path: /etc/apache2/sites-enabled/{{ item }} state: absent loop: [ 000-default.conf, default-ssl.conf ] notify: Restart Apache2. - name: Disable other-vhosts-access-log option. become: yes file: path: /etc/apache2/conf-enabled/other-vhosts-access-log.conf state: absent notify: Restart Apache2. - name: Create UserDir. become: yes file: path: /home/www-users/ state: directory - name: Create UserDir links. become: yes file: path: /home/www-users/{{ item }} src: /home/{{ item }}/Public/HTML state: link force: yes follow: false loop: "{{ usernames }}" when: members[item].status == 'current' tags: accounts - name: Disable former UserDir links. become: yes file: path: /home/www-users/{{ item }} state: absent loop: "{{ usernames }}" when: members[item].status != 'current' tags: accounts - name: Enable IP forwarding. become: yes copy: content: "net.ipv4.ip_forward = 1\n" dest: /etc/sysctl.d/local.conf notify: Reload sysctl. - name: Install WireGuard™. become: yes apt: pkg=wireguard - name: Configure WireGuard™. become: yes vars: srcs: - ../private/front-wg0.conf - ../private/front-wg0-empty.conf copy: src: "{{ lookup('first_found', srcs) }}" dest: /etc/wireguard/wg0.conf mode: u=r,g=,o= owner: root group: root notify: Restart WireGuard™. tags: accounts - name: Start WireGuard™. become: yes systemd: service: wg-quick@wg0 state: started tags: actualizer - name: Enable WireGuard™. become: yes systemd: service: wg-quick@wg0 enabled: yes - name: Install Kamailio. become: yes apt: pkg=kamailio - name: Create Kamailio/Systemd configuration drop. become: yes file: path: /etc/systemd/system/kamailio.service.d state: directory - name: Create Kamailio dependence on WireGuard™ interface. become: yes copy: content: | [Unit] After=wg-quick@wg0.service Requires=sys-devices-virtual-net-wg0.device dest: /etc/systemd/system/kamailio.service.d/depend.conf notify: Reload Systemd. - name: Configure Kamailio. become: yes copy: content: | listen=udp:{{ front_wg_addr }}:5060 dest: /etc/kamailio/kamailio-local.cfg notify: Restart Kamailio. - name: Start Kamailio. become: yes systemd: service: kamailio state: started tags: actualizer - name: Enable Kamailio. become: yes systemd: service: kamailio enabled: yes