---
- 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