From 0cd2735c82d44223c884a6d0b39e0e353bd487e0 Mon Sep 17 00:00:00 2001 From: Alan Orth Date: Mon, 27 Jun 2016 23:52:39 +0300 Subject: [PATCH] roles/nginx: Rework Let's Encrypt stuff Take an opinionated stance on HTTPS and assume that hosts are using HTTPS for all vhosts. This can either be via custom TLS cert/key pairs defined in the host's variables (could even be self-signed certificates on dev boxes) or via Let's Encrypt. --- roles/nginx/defaults/main.yml | 3 +++ roles/nginx/files/renew-letsencrypt.timer | 12 ++++++++++ roles/nginx/tasks/letsencrypt.yml | 22 +++++++++++++++++++ roles/nginx/tasks/vhosts.yml | 4 ++++ roles/nginx/templates/https.j2 | 20 ++++++----------- .../templates/renew-letsencrypt.service.j2 | 6 +++++ 6 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 roles/nginx/files/renew-letsencrypt.timer create mode 100644 roles/nginx/tasks/letsencrypt.yml create mode 100644 roles/nginx/templates/renew-letsencrypt.service.j2 diff --git a/roles/nginx/defaults/main.yml b/roles/nginx/defaults/main.yml index 205f0a5..bfa021f 100644 --- a/roles/nginx/defaults/main.yml +++ b/roles/nginx/defaults/main.yml @@ -19,6 +19,9 @@ nginx_ssl_protocols: 'TLSv1 TLSv1.1 TLSv1.2' # Directory root for Let's Encrypt certs letsencrypt_root: /etc/letsencrypt/live +# Location of Let's Encrypt's certbot script +letsencrypt_certbot_dest: /opt/certbot-auto + # stable is 1.10.x # mainline is 1.11.x nginx_version: mainline diff --git a/roles/nginx/files/renew-letsencrypt.timer b/roles/nginx/files/renew-letsencrypt.timer new file mode 100644 index 0000000..cdc4f36 --- /dev/null +++ b/roles/nginx/files/renew-letsencrypt.timer @@ -0,0 +1,12 @@ +[Unit] +Description=Daily renewal of Let's Encrypt's certificates + +[Timer] +# twice a day, at midnight and noon +OnCalendar=*-*-* 00,12:00:00 +# Add a random delay of 0–3600 seconds +RandomizedDelaySec=3600 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/roles/nginx/tasks/letsencrypt.yml b/roles/nginx/tasks/letsencrypt.yml new file mode 100644 index 0000000..1c7663c --- /dev/null +++ b/roles/nginx/tasks/letsencrypt.yml @@ -0,0 +1,22 @@ +--- + +- name: Copy systemd service to renew Let's Encrypt certs + template: src=renew-letsencrypt.service.j2 dest=/etc/systemd/system/renew-letsencrypt.service mode=0644 owner=root group=root + register: letsencrypt_service + +- name: Copy systemd timer to renew Let's Encrypt certs + copy: src=renew-letsencrypt.timer dest=/etc/systemd/system/renew-letsencrypt.timer mode=0644 owner=root group=root + register: letsencrypt_timer + +# need to reload to pick up service/timer changes +- name: Reload systemd daemon + command: /bin/systemctl daemon-reload + when: letsencrypt_service|changed or letsencrypt_timer|changed + +- name: Start and enable systemd timer to renew Let's Encrypt certs + service: name=renew-letsencrypt.timer state=started enabled=yes + +- name: Download certbot + get_url: dest={{ letsencrypt_certbot_dest }} url=https://dl.eff.org/certbot-auto mode=700 + +# vim: set ts=2 sw=2: diff --git a/roles/nginx/tasks/vhosts.yml b/roles/nginx/tasks/vhosts.yml index a7b4792..bb47737 100644 --- a/roles/nginx/tasks/vhosts.yml +++ b/roles/nginx/tasks/vhosts.yml @@ -32,4 +32,8 @@ with_items: "{{ nginx_vhosts }}" tags: wordpress +- include: letsencrypt.yml + when: use_letsencrypt == 'yes' + tags: letsencrypt + # vim: set ts=2 sw=2: diff --git a/roles/nginx/templates/https.j2 b/roles/nginx/templates/https.j2 index 7ebd461..2c19d5c 100644 --- a/roles/nginx/templates/https.j2 +++ b/roles/nginx/templates/https.j2 @@ -2,28 +2,22 @@ {% set domain_name = item.domain_name %} {# assume HSTS is off unless a vhost explicitly sets it to "yes" #} {% set enable_hsts = item.enable_hsts | default("no") %} -{# assume a vhost is not using Let's Encrypt unless it explicitly sets it to "yes" #} -{% set use_letsencrypt = item.use_letsencrypt | default("no") %} - {% if use_letsencrypt == "yes" %} - - # concatenated key + cert - # See: http://nginx.org/en/docs/http/configuring_https_servers.html - ssl_certificate {{ letsencrypt_root }}/{{ domain_name }}/fullchain.pem; - ssl_certificate_key {{ letsencrypt_root }}/{{ domain_name }}/privkey.pem; - - {% elif item.tls_certificate_path and item.tls_key_path %} + {# first, check if the current vhost has a custom cert (perhaps self-signed) #} + {% if item.tls_certificate_path and item.tls_key_path %} # concatenated key + cert # See: http://nginx.org/en/docs/http/configuring_https_servers.html ssl_certificate {{ item.tls_certificate_path }}; ssl_certificate_key {{ item.tls_key_path }}; + {# otherwise, assume host is using letsencrypt #} {% else %} - # "snakeoil" certificate (self signed!) - ssl_certificate /etc/ssl/certs/nginx-snakeoil.crt; - ssl_certificate_key /etc/ssl/private/nginx-snakeoil.key; + # concatenated key + cert + # See: http://nginx.org/en/docs/http/configuring_https_servers.html + ssl_certificate {{ letsencrypt_root }}/{{ domain_name }}/fullchain.pem; + ssl_certificate_key {{ letsencrypt_root }}/{{ domain_name }}/privkey.pem; {% endif %} diff --git a/roles/nginx/templates/renew-letsencrypt.service.j2 b/roles/nginx/templates/renew-letsencrypt.service.j2 new file mode 100644 index 0000000..e063ceb --- /dev/null +++ b/roles/nginx/templates/renew-letsencrypt.service.j2 @@ -0,0 +1,6 @@ +[Unit] +Description=Let's Encrypt renewal + +[Service] +Type=oneshot +ExecStart={{ letsencrypt_certbot_dest }} renew --standalone --pre-hook "/bin/systemctl stop nginx" --post-hook "/bin/systemctl start nginx"