Initial commit

This commit is contained in:
Pijus Kamandulis
2024-05-25 23:11:17 +03:00
commit fcfd816548
11 changed files with 505 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
- name: Initial System Setup
hosts: mx1
remote_user: root
become: true
become_method: su
vars_files:
- vars.yml
tasks:
- name: Apply all available system patches
command: syspatch
register: syspatch
failed_when: syspatch.rc != 0 and syspatch.rc != 2
changed_when: syspatch.rc == 0
- name: Update package list and upgrade all packages
command: pkg_add -u
- name: Install essential packages
community.general.openbsd_pkg:
name:
- nano
- curl
- git
state: present
- name: Disable SSH password authentication
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: "^#?PasswordAuthentication"
line: "PasswordAuthentication no"
state: present
- name: Restart SSH service to apply changes
ansible.builtin.service:
name: sshd
state: restarted
- name: Add SSH public key to authorized_keys
ansible.posix.authorized_key:
user: root
key: "{{ ssh_public_key }}"

50
ansible/02-ssl.yml Normal file
View File

@@ -0,0 +1,50 @@
- name: SSL Setup
hosts: mx1
remote_user: root
vars_files:
- vars.yml
tasks:
- name: Create vhost directories
file:
path: "/var/www/vhosts/{{ item }}"
state: directory
owner: www
with_items: "{{ mx1_domains }}"
- name: Install httpd.conf
template:
src: "templates/httpd.conf"
dest: "/etc/httpd.conf"
- name: Enable and start httpd
service:
name: httpd
enabled: yes
state: started
- name: Install acme-client.conf
template:
src: "templates/acme-client.conf"
dest: "/etc/acme-client.conf"
- name: Initial acme-client run
command: "/usr/sbin/acme-client {{ item }}"
args:
creates: "/etc/ssl/{{ item }}.fullchain.pem"
with_items: "{{ mx1_domains }}"
notify:
- reload httpd
- name: Renew certificates via root crontab
cron:
name: "acme-client renew {{ item }}"
minute: "0"
job: "sleep $((RANDOM \\% 2048)) && acme-client {{ item }} && rcctl reload httpd"
user: root
with_items: "{{ mx1_domains }}"
handlers:
- name: reload httpd
service:
name: httpd
state: reloaded

120
ansible/03-mail.yml Normal file
View File

@@ -0,0 +1,120 @@
- name: OpenSMTPD Installation and Configuration
hosts: mx1
remote_user: root
vars_files:
- vars.yml
tasks:
- name: Install Packages
community.general.openbsd_pkg:
name:
- opensmtpd-filter-dkimsign
- dovecot
- dovecot-pigeonhole
- opensmtpd-extras
state: present
- name: Create the vmail group
group:
name: vmail
gid: 2000
- name: Create vmail user
user:
name: vmail
group: vmail
shell: /sbin/nologin
createhome: yes
home: /var/mail/vmail
uid: 2000
- name: Generate dkim keys
shell: |
KEYLEN=1024
DOMAIN={{ mx1_mail_domain }}
mkdir -p /etc/mail/dkim
if [ -f /etc/mail/dkim/$DOMAIN.key ]; then
echo "$DOMAIN.key already exists."
exit 0
fi
cd /etc/mail/dkim
(umask 337; openssl genrsa -out $DOMAIN.key $KEYLEN)
openssl rsa -in $DOMAIN.key -pubout -out $DOMAIN.pub
group info _dkimsign >/dev/null && chgrp _dkimsign $DOMAIN.key
echo "add the $DOMAIN.dns to the zone file"
echo "selector1._domainkey.$DOMAIN. 3600 IN TXT \"v=DKIM1; k=rsa; p=$(sed -e '1d' -e '$d' $DOMAIN.pub | tr -d '\n')\"" > ~/$DOMAIN.dns
- name: Configure OpenSMTPD smtpd.conf
template:
src: "templates/smtpd.conf"
dest: /etc/mail/smtpd.conf
notify:
- reload smtpd
- name: Enable and start OpenSMTPD service
service:
name: smtpd
enabled: yes
state: started
- name: Delete default dovecot configs
shell: |
if [ -f /etc/dovecot/conf.d/10-ssl.conf ]; then
cd /etc/dovecot/
rm -rf *
fi
- name: Install dovecot.conf
template:
src: "templates/dovecot.conf"
dest: "/etc/dovecot/dovecot.conf"
notify:
- reload dovecot
- name: Configure users
block:
- name: Remove existing
shell: |
echo "" > /etc/dovecot/users
chmod 640 /etc/dovecot/users
chown _smtpd:_dovecot /etc/dovecot/users
echo "" > /etc/mail/accounts
chmod 640 /etc/mail/accounts
chown _smtpd: /etc/mail/accounts
echo "" > /etc/mail/virtuals
chown _smtpd: /etc/mail/virtuals
- name: Add user accounts
loop: "{{ mail_users }}"
no_log: true
shell: |
DOVECOT_PASS=$(doveadm pw -p {{ item.password }})
SMTP_PASS=$(smtpctl encrypt {{ item.password }})
echo "{{ item.user }}:$DOVECOT_PASS::::" >> /etc/dovecot/users
echo "{{ item.user }}:$SMTP_PASS::::" >> /etc/mail/accounts
- name: Install dovecot.conf
template:
src: "templates/virtuals.conf"
dest: "/etc/mail/virtuals"
- name: Enable dovecot service
service:
name: dovecot
enabled: true
state: started
handlers:
- name: reload smtpd
service:
name: smtpd
state: restarted
- name: reload dovecot
service:
name: dovecot
state: reloaded

View File

@@ -0,0 +1,12 @@
authority letsencrypt {
api url "https://acme-v02.api.letsencrypt.org/directory"
account key "/etc/acme/letsencrypt-privkey.pem"
}
{% for domain in mx1_domains %}
domain "{{ domain }}" {
domain key "/etc/ssl/private/{{ domain }}.key"
domain full chain certificate "/etc/ssl/{{ domain }}.fullchain.pem"
sign with letsencrypt
}
{% endfor %}

View File

@@ -0,0 +1,127 @@
# Enable ssl
ssl = required
ssl_cert = < /etc/ssl/{{ mx1_mail_domain }}.fullchain.pem
ssl_key = < /etc/ssl/private/{{ mx1_mail_domain }}.key
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
disable_plaintext_auth = yes
# Define used protocols
protocols = lmtp imap sieve
service lmtp {
unix_listener lmtp {
user = vmail
group = vmail
}
}
service imap-login {
inet_listener imap {
port = 143
}
inet_listener imaps {
port = 993
}
}
# Setup users
passdb {
driver = passwd-file
args = scheme=ARGON2ID-CRYPT username_format=%u /etc/dovecot/users
}
userdb {
driver = passwd-file
args = username_format=%u /etc/dovecot/users
override_fields = uid=vmail gid=vmail home=/var/mail/vmail/%d/%n
}
# Setup mail location
mail_location = maildir:~/Maildir
# setup auth listener
service auth {
unix_listener auth-userdb {
mode = 0660
user = vmail
group = vmail
}
}
# change the authworker to run as non-root
service auth-worker {
user = $default_internal_user
}
# setup local delivery options
quota_full_tempfail = yes
protocol lda {
mail_plugins = $mail_plugins sieve
}
# setup some common mailboxes that are used by different clients to consistent destinations
namespace inbox {
inbox = yes
mailbox Spam {
special_use = \Junk
}
mailbox "Deleted Items" {
special_use = \Trash
}
}
# setup local delivery protocol
protocol lmtp {
mail_plugins = $mail_plugins sieve
}
# disable verify quota befor replying rcpt to
lmtp_rcpt_check_quota = no
# setup stats service
service stats {
unix_listener stats-writer {
user =
group = $default_internal_group
mode = 0660
}
}
# enable mail plugins
mail_plugins = $mail_plugins notify
# setup metrics
metric auth_success {
filter = event=auth_request_finished AND success=yes
}
metric auth_failures {
filter = event=auth_request_finished AND NOT success=yes
}
metric imap_command {
filter = event=imap_command_finished
group_by = cmd_name tagged_reply_state
}
metric smtp_command {
filter = event=smtp_server_command_finished
group_by = cmd_name status_code duration:exponential:1:5:10
}
metric mail_delivery {
filter = event=mail_delivery_finsihed
group_by = duration:exponential:1:5:10
}
# enable IMAP protocol
protocol imap {
mail_plugins = $mail_plugins imap_sieve
}
# setup sieve plugin options
# enable if there needs to be default sieve processing
#plugin {
# sieve_pipe_bin_dir = /usr/local/lib/dovecot/sieve
# sieve_before = /etc/dovecot/sieve/default.sieve
# sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
# sieve_plugins = sieve_imapsieve sieve_extprograms
#}

View File

@@ -0,0 +1,27 @@
server "{{ inventory_hostname }}" {
listen on * port 80
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
location * {
block return 302 "https://$HTTP_HOST$REQUEST_URI"
}
}
{% for vhost in mx1_domains %}
server "{{ vhost }}" {
listen on * tls port 443
tls {
certificate "/etc/ssl/{{ vhost }}.fullchain.pem"
key "/etc/ssl/private/{{ vhost }}.key"
}
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
location * {
root "/vhosts/{{ vhost }}"
}
}
{% endfor %}

View File

@@ -0,0 +1,23 @@
pki {{ mx1_mail_domain }} cert "/etc/ssl/{{ mx1_mail_domain }}.fullchain.pem"
pki {{ mx1_mail_domain }} key "/etc/ssl/private/{{ mx1_mail_domain }}.key"
table aliases file:/etc/mail/aliases
table users passwd:/etc/mail/accounts
table virtuals file:/etc/mail/virtuals
filter dkimsign_rsa proc-exec "filter-dkimsign -d {{ mx1_mail_domain }} -s selector1 \
-k /etc/mail/dkim/{{ mx1_mail_domain }}.key" user _dkimsign group _dkimsign
listen on socket filter dkimsign_rsa
listen on all tls pki {{ mx1_mail_domain }}
listen on all port submission tls-require pki {{ mx1_mail_domain }} auth <users> filter dkimsign_rsa
listen on all port smtps tls-require pki {{ mx1_mail_domain }} auth <users> filter dkimsign_rsa
action "local_mail" lmtp "/var/dovecot/lmtp" rcpt-to virtual <virtuals>
action "outbound" relay
{% for domain in mail_domains %}
match from any for domain {{ domain }} action "local_mail"
{% endfor %}
match from local for local action "local_mail"
match from local for any action "outbound"

View File

@@ -0,0 +1,8 @@
{% for user in mail_users %}
{{ user.user }}: vmail
{% if (user.virtuals is defined) and user.virtuals %}
{% for virtual in user.virtuals %}
{{ virtual }}: {{ user.user }}
{% endfor %}
{% endif %}
{% endfor %}