diff --git a/ansible/inventory/host_vars/kodi00.balsillie.house/certbot.yaml b/ansible/inventory/host_vars/kodi00.balsillie.house/certbot.yaml index 9c282a3..8782155 100644 --- a/ansible/inventory/host_vars/kodi00.balsillie.house/certbot.yaml +++ b/ansible/inventory/host_vars/kodi00.balsillie.house/certbot.yaml @@ -5,7 +5,7 @@ certbot_rfc2136_key_algorithm: 'hmac-sha256' certbot_webserver_type: 'nginx' # 'nginx' or 'apache' certbot_dns_plugin: 'rfc2136' certbot_email: "certbot.kodi00@balsillie.email" -certbot_acme_server: "https://acme-v02.api.letsencrypt.org/directory" +certbot_acme_server: "acme-v02.api.letsencrypt.org" certbot_domains: - kodi.balsillie.house \ No newline at end of file diff --git a/ansible/inventory/host_vars/kodi00.balsillie.house/nginx.yaml b/ansible/inventory/host_vars/kodi00.balsillie.house/nginx.yaml index f70e2c7..15e6bdf 100644 --- a/ansible/inventory/host_vars/kodi00.balsillie.house/nginx.yaml +++ b/ansible/inventory/host_vars/kodi00.balsillie.house/nginx.yaml @@ -1,13 +1,27 @@ nginx_sites: - name: tv.balsillie.house - upstream: 127.0.0.1:8080 + upstream: + host: 127.0.0.1 + port: 8080 - name: movies.balsillie.house - upstream: 127.0.0.1:8081 + upstream: + host: 127.0.0.1 + port: 8081 - name: index.balsillie.house - upstream: 127.0.0.1:8082 + upstream: + host: 127.0.0.1 + port: 8082 - name: torrent.balsillie.house - upstream: 127.0.0.1:9090 + upstream: + host: 127.0.0.1 + port: 9090 - name: jellyfin.balsillie.house - upstream: 127.0.0.1:8096 + upstream: + host: 127.0.0.1 + port: 8096 - name: kodi.balsillie.house - upstream: 127.0.0.1:8082 \ No newline at end of file + upstream: + host: 127.0.0.1 + port: 8082 + +nginx_user: "http" \ No newline at end of file diff --git a/ansible/playbooks/infra/kodi.yaml b/ansible/playbooks/infra/kodi.yaml index ad24596..55a8e91 100644 --- a/ansible/playbooks/infra/kodi.yaml +++ b/ansible/playbooks/infra/kodi.yaml @@ -4,7 +4,6 @@ gather_facts: true become: true roles: - - role: sshd - - role: ufw + # - role: sshd + # - role: ufw - role: nginx - - role: certbot diff --git a/ansible/roles/certbot/handlers/main.yaml b/ansible/roles/certbot/handlers/main.yaml new file mode 100644 index 0000000..0d580c1 --- /dev/null +++ b/ansible/roles/certbot/handlers/main.yaml @@ -0,0 +1,6 @@ +--- + +- name: Restart nginx + ansible.builtin.service: + name: nginx.service + state: restarted diff --git a/ansible/roles/certbot/tasks/main.yaml b/ansible/roles/certbot/tasks/main.yaml index 4504d94..1b1a404 100644 --- a/ansible/roles/certbot/tasks/main.yaml +++ b/ansible/roles/certbot/tasks/main.yaml @@ -17,7 +17,7 @@ state: present update_cache: true -- name: Template out the dns config file +- name: Template out the rfc2136 credentials file when: certbot_dns_plugin == 'rfc2136' ansible.builtin.template: src: "{{ certbot_dns_plugin }}.conf.j2" @@ -26,24 +26,30 @@ group: root mode: '0600' -- name: Register certbot account - ansible.builtin.command: - argv: - - "certbot register" - - "--agree-tos" - - "--email {{ certbot_email }}" - - "--no-eff-email" - creates: /etc/letsencrypt/accounts/acme-v02.api.letsencrypt.org/directory/{{ certbot_email }} +- name: Template out the certbot default config + ansible.builtin.template: + src: cli.ini.j2 + dest: /etc/letsencrypt/cli.ini + owner: root + group: root + mode: '0644' - name: Request and install certificates ansible.builtin.command: argv: - - "certbot --nginx run -n" - - "--dns-{{ certbot_dns_plugin }}" - - "--dns-{{ certbot_dns_plugin }}-credentials /etc/letsencrypt/{{ certbot_dns_plugin }}.conf" - - "-d {{ item }}" + - certbot + - certonly + - -n + - --dns-{{ certbot_dns_plugin }} + - --dns-{{ certbot_dns_plugin }}-credentials + - /etc/letsencrypt/{{ certbot_dns_plugin }}.conf + - --dns-rfc2136-propagation-seconds + - "{{ certbot_rfc2136_propagation_seconds | default(5) }}" + - -d + - "{{ item }}" creates: /etc/letsencrypt/live/{{ item }}/fullchain.pem loop: "{{ certbot_domains }}" + notify: "{{ certbot_notify }}" - name: Enable certbot renewal ansible.builtin.service: diff --git a/ansible/roles/certbot/templates/cli.ini.j2 b/ansible/roles/certbot/templates/cli.ini.j2 new file mode 100644 index 0000000..3234e3d --- /dev/null +++ b/ansible/roles/certbot/templates/cli.ini.j2 @@ -0,0 +1,3 @@ +rsa-key-size = 4096 +email = {{ certbot_email }} +agree-tos = true \ No newline at end of file diff --git a/ansible/roles/certbot/templates/rfc2136.conf.j2 b/ansible/roles/certbot/templates/rfc2136.conf.j2 index 86fe7da..648d97f 100644 --- a/ansible/roles/certbot/templates/rfc2136.conf.j2 +++ b/ansible/roles/certbot/templates/rfc2136.conf.j2 @@ -1,4 +1,6 @@ dns_rfc2136_server = {{ certbot_rfc2136_server }} +dns_rfc2136_port = {{ certbot_rfc2136_port | default(53) }} dns_rfc2136_name = {{ certbot_rfc2136_key_name }} dns_rfc2136_secret = {{ certbot_rfc2136_key_secret }} -dns_rfc2136_algorithm = {{ certbot_rfc2136_key_algorithm }} \ No newline at end of file +dns_rfc2136_algorithm = {{ certbot_rfc2136_key_algorithm | upper }} +dns_rfc2136_sign_query = true diff --git a/ansible/roles/nginx/files/ssl.conf b/ansible/roles/nginx/files/ssl.conf new file mode 100644 index 0000000..11afa84 --- /dev/null +++ b/ansible/roles/nginx/files/ssl.conf @@ -0,0 +1,7 @@ +ssl_session_timeout 1d; +ssl_session_cache shared:MozSSL:1m; +ssl_session_tickets off; +ssl_dhparam ssl/dhparams.pem; +ssl_protocols TLSv1.2 TLSv1.3; +ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305; +ssl_prefer_server_ciphers off; \ No newline at end of file diff --git a/ansible/roles/nginx/handlers/main.yaml b/ansible/roles/nginx/handlers/main.yaml new file mode 100644 index 0000000..0d580c1 --- /dev/null +++ b/ansible/roles/nginx/handlers/main.yaml @@ -0,0 +1,6 @@ +--- + +- name: Restart nginx + ansible.builtin.service: + name: nginx.service + state: restarted diff --git a/ansible/roles/nginx/tasks/main.yaml b/ansible/roles/nginx/tasks/main.yaml index 1581428..93116c4 100644 --- a/ansible/roles/nginx/tasks/main.yaml +++ b/ansible/roles/nginx/tasks/main.yaml @@ -5,3 +5,96 @@ - nginx state: present update_cache: true + +- name: Create config dirs + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: root + group: root + mode: "0775" + loop: + - /etc/nginx/sites-available + - /etc/nginx/sites-enabled + - /etc/nginx/conf.d + - /etc/nginx/ssl + +- name: Copy the ssl configuration + ansible.builtin.copy: + src: ssl.conf + dest: /etc/nginx/ssl/ssl.conf + owner: root + group: root + mode: "0644" + notify: Restart nginx + +- name: Generate dhparams + ansible.builtin.command: + argv: + - openssl + - dhparam + - -dsaparam + - -outform + - PEM + - -out + - /etc/nginx/ssl/dhparams.pem + - 4096 + creates: /etc/nginx/ssl/dhparams.pem + notify: Restart nginx + +# - name: Generate dhparams (alternative) +# community.crypto.openssl_dhparam: +# group: root +# mode: "0644" +# owner: root +# path: /etc/nginx/ssl/dhparams.pem +# size: 4096 +# state: present + +- name: Set permissions on dhparams + ansible.builtin.file: + path: /etc/nginx/ssl/dhparams.pem + owner: root + group: root + mode: "0644" + notify: Restart nginx + +- name: Template out nginx base config + ansible.builtin.template: + src: nginx.conf.j2 + dest: /etc/nginx/nginx.conf + owner: root + group: root + mode: "0644" + notify: Restart nginx + +- name: Template out nginx site configs + ansible.builtin.template: + src: site.conf.j2 + dest: /etc/nginx/sites-available/{{ item.name }}.conf + owner: root + group: root + mode: "0644" + loop: "{{ nginx_sites }}" + notify: Restart nginx + +- name: Enable site configs + ansible.builtin.file: + path: /etc/nginx/sites-enabled/{{ item.name }}.conf + src: /etc/nginx/sites-available/{{ item.name }}.conf + state: link + loop: "{{ nginx_sites }}" + notify: Restart nginx + +- name: Run certbot role to install certificates + ansible.builtin.include_role: + name: certbot + vars: + certbot_domains: "{{ nginx_sites | map(attribute='name') }}" + certbot_notify: "Restart nginx" + +- name: Start and enable nginx + ansible.builtin.service: + name: nginx + state: started + enabled: true diff --git a/ansible/roles/nginx/templates/nginx.conf.j2 b/ansible/roles/nginx/templates/nginx.conf.j2 new file mode 100644 index 0000000..a852611 --- /dev/null +++ b/ansible/roles/nginx/templates/nginx.conf.j2 @@ -0,0 +1,48 @@ +user {{ nginx_user }}; +worker_processes auto; +worker_cpu_affinity auto; + +# include extra config +include /etc/nginx/conf.d/*.conf; + +events { + multi_accept on; + worker_connections 1024; +} + +http { + charset utf-8; + sendfile on; + tcp_nopush on; + tcp_nodelay on; + server_tokens off; + log_not_found off; + types_hash_max_size 4096; + client_max_body_size 16M; + + # MIME + include mime.types; + default_type application/octet-stream; + + # Include SSL config + include ssl/ssl.conf; + + server { + listen 80 default_server; + server_name "_"; + return 444; + } + + server { + listen 443 ssl http2 default_server; + server_name "_"; + ssl_reject_handshake on; + } + + # logging + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log warn; + + # include sites + include /etc/nginx/sites-enabled/*.conf; +} diff --git a/ansible/roles/nginx/templates/site.conf.j2 b/ansible/roles/nginx/templates/site.conf.j2 new file mode 100644 index 0000000..d697171 --- /dev/null +++ b/ansible/roles/nginx/templates/site.conf.j2 @@ -0,0 +1,17 @@ +server { + listen 80; + server_name {{ item.name }}; + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl http2; + server_name {{ item.name }}; + ssl_certificate /etc/letsencrypt/live/{{ item.name }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ item.name }}/privkey.pem; + location / { + proxy_pass http://{{ item.upstream.host }}:{{ item.upstream.port }}; + } +}