From 520a6781b905d350528d809d017591f657eb3f39 Mon Sep 17 00:00:00 2001 From: Raoul Date: Mon, 2 Nov 2020 04:51:35 +0100 Subject: [PATCH] Initial checkin --- defaults/main.yml | 19 +++ files/acmetool/enable_tls.sh | 16 +++ files/nginx/nginx.conf | 29 +++++ files/nginx/sites-available/default_http.j2 | 10 ++ files/nginx/sites-available/default_tls.j2 | 16 +++ .../http_plain_redirect.conf.j2 | 12 ++ files/nginx/snippets/acmetool.snippet.conf | 4 + .../nginx/snippets/tls_settings.snippet.conf | 6 + handlers/main.yml | 14 +++ tasks/acme.yml | 38 ++++++ tasks/default_site.yml | 57 +++++++++ tasks/installation.yml | 11 ++ tasks/main.yml | 51 ++++++++ tasks/nginx.yml | 77 +++++++++++++ tasks/single_site.yml | 109 ++++++++++++++++++ 15 files changed, 469 insertions(+) create mode 100644 defaults/main.yml create mode 100644 files/acmetool/enable_tls.sh create mode 100644 files/nginx/nginx.conf create mode 100644 files/nginx/sites-available/default_http.j2 create mode 100644 files/nginx/sites-available/default_tls.j2 create mode 100644 files/nginx/sites-available/http_plain_redirect.conf.j2 create mode 100644 files/nginx/snippets/acmetool.snippet.conf create mode 100644 files/nginx/snippets/tls_settings.snippet.conf create mode 100644 handlers/main.yml create mode 100644 tasks/acme.yml create mode 100644 tasks/default_site.yml create mode 100644 tasks/installation.yml create mode 100644 tasks/main.yml create mode 100644 tasks/nginx.yml create mode 100644 tasks/single_site.yml diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..8f7a222 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,19 @@ +--- + +nginx_sites: {} + +#nginx_sites: +# - name: 'example.org' +# altnames: +# - 'www.example.org' +# - 'ftp.example.org' +# robots: 'robots_allow_all.txt' Optional +# htaccess: 'htpasswd.example.org' Optional + + +snippet_files: + - 'acmetool.snippet.conf' + - 'tls_settings.snippet.conf' + + +#default_robots_file: 'robots_disallow_all.txt' diff --git a/files/acmetool/enable_tls.sh b/files/acmetool/enable_tls.sh new file mode 100644 index 0000000..c380af5 --- /dev/null +++ b/files/acmetool/enable_tls.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -euf -o pipefail + +IFS=$'\n' + +EVENT_NAME="$1" +[ "$EVENT_NAME" = "live-updated" ] || exit 42 + +while read -r host; do + if [[ -e "/etc/nginx/sites-available/${host}_tls" ]]; then + echo "Enabling tls site for ${host}" + ln -s -f "/etc/nginx/sites-available/${host}_tls" "/etc/nginx/sites-enabled/${host}_tls" + fi +done + +exit 0 diff --git a/files/nginx/nginx.conf b/files/nginx/nginx.conf new file mode 100644 index 0000000..fc49abc --- /dev/null +++ b/files/nginx/nginx.conf @@ -0,0 +1,29 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; +error_log /var/log/nginx/error.log; + +include /usr/share/nginx/modules/*.conf; + + +events { + worker_connections 1024; +} + + +http { + access_log /var/log/nginx/access.log; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + server_tokens off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} diff --git a/files/nginx/sites-available/default_http.j2 b/files/nginx/sites-available/default_http.j2 new file mode 100644 index 0000000..2299a02 --- /dev/null +++ b/files/nginx/sites-available/default_http.j2 @@ -0,0 +1,10 @@ +server { + listen 80 default_server; + listen [::]:80 default_server; + + include snippets/acmetool.snippet.conf; + + location ^~ / { + return 308 https://{{ inventory_hostname }}$request_uri; + } +} diff --git a/files/nginx/sites-available/default_tls.j2 b/files/nginx/sites-available/default_tls.j2 new file mode 100644 index 0000000..8416ff4 --- /dev/null +++ b/files/nginx/sites-available/default_tls.j2 @@ -0,0 +1,16 @@ +server { + listen 443 ssl http2 default_server; + listen [::]:443 ssl http2 default_server; + + include snippets/tls_settings.snippet.conf; + + ssl_certificate /var/lib/acme/live/{{ inventory_hostname }}/fullchain; + ssl_certificate_key /var/lib/acme/live/{{ inventory_hostname }}/privkey; + + access_log /var/log/nginx/log_{{ inventory_hostname }}.access.log; + error_log /var/log/nginx/log_{{ inventory_hostname }}.error.log; + + location ^~ / { + return 403; + } +} diff --git a/files/nginx/sites-available/http_plain_redirect.conf.j2 b/files/nginx/sites-available/http_plain_redirect.conf.j2 new file mode 100644 index 0000000..71eca6f --- /dev/null +++ b/files/nginx/sites-available/http_plain_redirect.conf.j2 @@ -0,0 +1,12 @@ +server { + listen 80; + listen [::]:80; + + server_name {{ site.name }}; + + include snippets/acmetool.snippet.conf; + + location ^~ / { + return 308 https://{{ site.name }}$request_uri; + } +} diff --git a/files/nginx/snippets/acmetool.snippet.conf b/files/nginx/snippets/acmetool.snippet.conf new file mode 100644 index 0000000..68dcc5c --- /dev/null +++ b/files/nginx/snippets/acmetool.snippet.conf @@ -0,0 +1,4 @@ +location /.well-known/acme-challenge/ { + alias /run/acme/acme-challenge/; + auth_basic "off"; +} diff --git a/files/nginx/snippets/tls_settings.snippet.conf b/files/nginx/snippets/tls_settings.snippet.conf new file mode 100644 index 0000000..23326fc --- /dev/null +++ b/files/nginx/snippets/tls_settings.snippet.conf @@ -0,0 +1,6 @@ +ssl_protocols TLSv1.2 TLSv1.3; +ssl_prefer_server_ciphers on; +#ssl_stapling on; +#ssl_stapling_verify on; +#resolver 8.8.8.8 8.8.4.4 valid=300s; +#resolver_timeout 3s; diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..70eedf4 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,14 @@ +--- + +- name: Restart nginx + systemd: + name: 'nginx.service' + daemon_reload: yes + state: restarted + + +- name: Reload nginx + systemd: + name: 'nginx.service' + daemon_reload: yes + state: reloaded diff --git a/tasks/acme.yml b/tasks/acme.yml new file mode 100644 index 0000000..b54700f --- /dev/null +++ b/tasks/acme.yml @@ -0,0 +1,38 @@ +--- + +- name: Copy shell script to enable tls sites + copy: + src: 'files/acmetool/enable_tls.sh' + dest: '/etc/acme/hooks/enable_tls.sh' + owner: root + group: root + mode: 'u=rx,g=r,o=' + tags: + - configuration + - acme + + +- name: Get certificate for default server + command: acmetool want '{{ inventory_hostname }}' + args: + creates: '/var/lib/acme/live/{{ inventory_hostname }}' + tags: + - configuration + - acme + - certificates + - operation + + +- name: Get certificates for all configured sites + #command: acmetool want '{{ site.name }}' '{{ site.altnames | default([]) | join(" ") }}' + command: acmetool want '{{ ([site.name] + (site.altnames | default([]) )) | join(" ") }}' + args: + creates: '/var/lib/acme/live/{{ site.name }}/' + with_items: '{{ nginx_sites }}' + loop_control: + loop_var: site + tags: + - configuration + - acme + - certificates + - operation diff --git a/tasks/default_site.yml b/tasks/default_site.yml new file mode 100644 index 0000000..ca60819 --- /dev/null +++ b/tasks/default_site.yml @@ -0,0 +1,57 @@ +--- + +- name: Create default site plain http configuration + template: + src: 'files/nginx/sites-available/default_http.j2' + dest: '/etc/nginx/sites-available/{{ inventory_hostname }}_http' + owner: root + group: root + mode: 'u=rw,g=r,o=r' + notify: + - Reload nginx + tags: + - configuration + - nginx + - sites + + +- name: Create default site tls https configuration + template: + src: 'files/nginx/sites-available/default_tls.j2' + dest: '/etc/nginx/sites-available/{{ inventory_hostname }}_tls' + owner: root + group: root + mode: 'u=rw,g=r,o=r' + notify: + - Reload nginx + tags: + - configuration + - nginx + - sites + + +- name: Enable default site plain http configuration + file: + src: '/etc/nginx/sites-available/{{ inventory_hostname }}_http' + dest: '/etc/nginx/sites-enabled/{{ inventory_hostname }}_http' + state: link + notify: + - Reload nginx + tags: + - configuration + - nginx + - sites + + +# Note: Done by acmetool after sucessfully obtaining a suitable certificate +#- name: Enable default site configuration +# file: +# src: '/etc/nginx/sites-available/{{ inventory_hostname }}_tls' +# dest: '/etc/nginx/sites-enabled/{{ inventory_hostname }}_tls' +# state: link +# notify: +# - Reload nginx +# tags: +# - configuration +# - nginx +# - sites diff --git a/tasks/installation.yml b/tasks/installation.yml new file mode 100644 index 0000000..642f240 --- /dev/null +++ b/tasks/installation.yml @@ -0,0 +1,11 @@ +--- + +- name: Install nginx + apt: + package: + - 'nginx' + state: latest + update_cache: yes + cache_valid_time: 43200 + tags: + - installation diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..ffa7d9a --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,51 @@ +--- + +- name: Install nginx + include_tasks: installation.yml + tags: + - repository + - installation + + +- name: Configure nginx + include_tasks: nginx.yml + tags: + - configuration + - nginx + - dhparam + + +- name: Start nginx webserver + service: + name: nginx + state: started + enabled: yes + tags: + - operation + - nginx + + +- name: Configure nginx default site + include_tasks: default_site.yml + tags: + - configuration + - nginx + - sites + + +- name: Configure nginx sites + include_tasks: single_site.yml + with_items: '{{ nginx_sites }}' + loop_control: + loop_var: site + tags: + - configuration + - nginx + - sites + + +- name: Configure acmetool and obtain certificates + include_tasks: acme.yml + tags: + - configuration + - acme diff --git a/tasks/nginx.yml b/tasks/nginx.yml new file mode 100644 index 0000000..b7e72dd --- /dev/null +++ b/tasks/nginx.yml @@ -0,0 +1,77 @@ +--- + +- name: Copy main nginx configuration file + copy: + src: 'nginx/nginx.conf' + dest: '/etc/nginx/' + owner: root + group: root + mode: 'u=rw,g=r,o=r' + notify: + - Reload nginx + tags: + - configuration + - nginx + + +#- name: Create strong dhparams +# openssl_dhparam: +# path: '/etc/nginx/dhparam.pem' +# size: 4096 +# notify: +# - Reload nginx +# tags: +# - configuration +# - nginx +# - dhparam + + +- name: Create 'sites-available' directory + file: + path: '/etc/nginx/sites-available' + state: directory + owner: root + group: root + mode: 'u=rwx,g=rx,o=rx' + tags: + - configuration + - nginx + + +- name: Create 'sites-enabled' directory + file: + path: '/etc/nginx/sites-enabled' + state: directory + owner: root + group: root + mode: 'u=rwx,g=rx,o=rx' + tags: + - configuration + - nginx + + +- name: Create 'snippets' directory + file: + path: '/etc/nginx/snippets' + state: directory + owner: root + group: root + mode: 'u=rwx,g=rx,o=rx' + tags: + - configuration + - nginx + + +- name: Copy nginx snippet files + copy: + src: 'files/nginx/snippets/{{ item }}' + dest: '/etc/nginx/snippets/{{ item }}' + owner: root + group: root + mode: 'u=rw,g=r,o=r' + with_items: '{{ snippet_files }}' + notify: + - Reload nginx + tags: + - configuration + - nginx diff --git a/tasks/single_site.yml b/tasks/single_site.yml new file mode 100644 index 0000000..844e780 --- /dev/null +++ b/tasks/single_site.yml @@ -0,0 +1,109 @@ +--- +# TODO: Implement site config template templates + + +- name: Create '{{ site.name }}' site plain http configuration + template: + src: 'files/nginx/sites-available/http_plain_redirect.conf.j2' + dest: '/etc/nginx/sites-available/{{ site.name }}_http' + owner: root + group: root + mode: 'u=rw,g=r,o=r' + #when: site.http_plain_template | default(True) + notify: + - Reload nginx + tags: + - configuration + - nginx + - sites + + +- name: Create '{{ site.name }}' site tls https configuration + template: + src: 'files/nginx/sites/{{ site.name }}_tls.conf' + dest: '/etc/nginx/sites-available/{{ site.name }}_tls' + owner: root + group: root + mode: 'u=rw,g=r,o=r' + #when: not site.redirect_target | default(True) + notify: + - Reload nginx + tags: + - configuration + - nginx + - sites + + +#- name: Create '{{ site.name }}' site tls parameter configuration +# template: +# src: 'files/nginx/snippets/tls_certificate.snippet.conf' +# dest: '/etc/nginx/snippets/tls_certificate_{{ site.name }}.snippet.conf' +# owner: root +# group: root +# mode: 'u=rw,g=r,o=r' +# notify: +# - Reload nginx +# tags: +# - configuration +# - nginx +# - sites + + +#- name: Create '{{ site.name }}' site logging configuration +# template: +# src: 'files/nginx/snippets/logging.snippet.conf' +# dest: '/etc/nginx/snippets/logging_{{ site.name }}.snippet.conf' +# owner: root +# group: root +# mode: 'u=rw,g=r,o=r' +# notify: +# - Reload nginx +# tags: +# - configuration +# - nginx +# - sites + + +#- name: Copy additional per site '{{ site.name }}' snippet files +# template: +# src: 'files/nginx/snippets/{{ item }}' +# dest: '/etc/nginx/snippets/{{ item }}' +# owner: root +# group: root +# mode: 'u=rw,g=r,o=r' +# with_items: '{{ site.snippets }}' +# when: site.snippets | default([]) +# notify: +# - Reload nginx +# tags: +# - configuration +# - nginx +# - sites + + +- name: Enable '{{ site.name }}' site plain http configuration + file: + src: '/etc/nginx/sites-available/{{ site.name }}_http' + dest: '/etc/nginx/sites-enabled/{{ site.name }}_http' + state: link + when: site.http_plain_template | default(True) + notify: + - Reload nginx + tags: + - configuration + - nginx + - sites + + +# Note: done by acmetool after sucessfully obtaining a suitable certificate +#- name: Enable '{{ site.name }}' site tls configuration +# file: +# src: '/etc/nginx/sites-available/{{ site.name }}_tls' +# dest: '/etc/nginx/sites-enabled/{{ site.name }}_tls' +# state: link +# notify: +# - Reload nginx +# tags: +# - configuration +# - nginx +# - sites