aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron LI <aly@aaronly.me>2019-09-22 10:18:57 +0800
committerAaron LI <aly@aaronly.me>2019-09-22 10:22:21 +0800
commit64cd268f1cf113911bf4472fbb63efe53f6eb760 (patch)
treec8edd39007557e82fe1758867d8b0404314dd173
parent60c85c56f25e10b9819214507ebd496cc0fbb855 (diff)
downloadansible-dfly-vps-64cd268f1cf113911bf4472fbb63efe53f6eb760.tar.bz2
web: Use 'acme.sh' to issue and renew certificates
The 'acme-client' seems obsolete and is missing from DPorts.
-rw-r--r--group_vars/all/vars.yml2
-rw-r--r--roles/web/tasks/main.yml150
-rw-r--r--roles/web/tasks/nginx-gensites.yml2
-rw-r--r--roles/web/templates/acme/deploy.sh.j227
-rw-r--r--roles/web/templates/acme/issue.sh.j219
5 files changed, 125 insertions, 75 deletions
diff --git a/group_vars/all/vars.yml b/group_vars/all/vars.yml
index 8d09fc4..107aa41 100644
--- a/group_vars/all/vars.yml
+++ b/group_vars/all/vars.yml
@@ -15,7 +15,9 @@ pf:
max_conn_rate: 15/5 # 15 of connections per 5 seconds
web:
+ acme_home: /var/db/acme
acme_webroot: /home/www/acme
+ ssl_root: /usr/local/etc/ssl/acme
domains:
- name: liwt.net
diff --git a/roles/web/tasks/main.yml b/roles/web/tasks/main.yml
index 3841cb8..0bc6466 100644
--- a/roles/web/tasks/main.yml
+++ b/roles/web/tasks/main.yml
@@ -3,7 +3,7 @@
pkgng:
name:
- nginx
- - acme-client
+ - acme.sh
state: present
- name: (local) ssl/tls - check dhparam existence
@@ -75,103 +75,105 @@
/var/log/nginx/error.log 644 7 * @T00 Z /var/run/nginx.pid
tags: nginx
-- name: acme - copy scripts
- copy:
- src: "{{ item }}"
- dest: /usr/local/etc/acme/{{ item | basename }}
+- name: acme - create webroot directory
+ file:
+ path: "{{ web.acme_webroot }}/.well-known/acme-challenge"
+ state: directory
+ owner: acme
+ group: www
mode: 0755
- with_fileglob:
- - "acme/*.sh"
- tags: acme
-
-- name: acme - copy deployment scripts
- copy:
- src: acme/deploy.d/ # note the trailing '/'
- dest: /usr/local/etc/acme/deploy.d/
- tags: acme
-
-- name: (local) acme - check account private key existence
- become: false
- stat:
- path: "{{ playbook_dir }}/private/acme/privkey.pem"
- delegate_to: localhost
- register: stat_result
- tags: acme
-
-- name: (local) acme - generate account private key (4096 bit)
- become: false
- command: >
- openssl genrsa
- -out "{{ playbook_dir }}/private/acme/privkey.pem" 4096
- delegate_to: localhost
- when: not stat_result.stat.exists
+ recurse: true
tags: acme
-- name: acme - copy account private key
- copy:
- src: "{{ playbook_dir }}/private/acme/privkey.pem"
- dest: /usr/local/etc/acme/privkey.pem
- mode: 0400
+- name: acme.sh - touch log file
+ file:
+ path: /var/log/acme.sh.log
+ owner: acme
+ group: acme
+ mode: 0640
+ state: touch
tags: acme
-- name: acme - create domain private directory
- file:
- path: /usr/local/etc/ssl/acme/private/
- state: directory
- mode: 0700
+- name: acme.sh - set newsyslog to rotate log file
+ lineinfile:
+ path: /etc/newsyslog.conf
+ regexp: '^#?/var/log/acme.sh.log'
+ line: "/var/log/acme.sh.log acme:acme 640 90 * @T00 Z"
tags: acme
-# Credit: https://shasawas.wordpress.com/2016/05/23/how-to-loop-over-a-set-of-tasks-in-ansible/
-- block:
- - name: acme - generate and copy domain private keys
- include_tasks: acme-domainkey.yml
- vars:
- domain: "{{ item.name }}"
- with_items: "{{ domains }}"
+- name: acme.sh - generate issue script
+ template:
+ src: acme/issue.sh.j2
+ dest: "{{ web.acme_home }}/issue.sh"
+ mode: 0755
tags:
- acme
- acme-renew
-- name: acme - generate domains.txt
- template:
- src: domains.txt.j2
- dest: /usr/local/etc/acme/domains.txt
+- name: acme.sh - issue certificates
+ become: true
+ become_user: acme
+ command: sh "{{ web.acme_home }}/issue.sh"
tags:
- acme
- acme-renew
-- name: acme - create challenge directory
- file:
- path: /usr/local/www/acme/.well-known/acme-challenge
- state: directory
- group: www
- recurse: true
- tags: acme
-
-- name: nginx - force reload
- command: rcreload nginx
+- name: acme.sh - generate deploy script
+ template:
+ src: acme/deploy.sh.j2
+ dest: "{{ web.acme_home }}/deploy.sh"
+ mode: 0755
tags:
- acme
- acme-renew
-- name: acme - request domain certificates
- command: sh /usr/local/etc/acme/acme-client.sh -e
- notify: deploy-acme
+- name: acme.sh - deploy certificates
+ command: sh "{{ web.acme_home }}/deploy.sh"
tags:
- acme
- acme-renew
-- name: acme - setup periodic tasks for cert renewal
- blockinfile:
- path: /etc/periodic.conf
- marker: "# {mark} ANSIBLE MANAGED - acme"
- block: |
- # Auto renew certificates with acme-client
- weekly_acme_client_enable="YES"
- weekly_acme_client_renewscript="/usr/local/etc/acme/acme-client.sh"
- weekly_acme_client_deployscript="/usr/local/etc/acme/deploy.sh"
+- name: acme.sh - touch local deploy script
+ file:
+ path: "{{ web.acme_home }}/deploy.local.sh"
+ mode: 0755
+ state: touch
+ tags: acme
+
+- name: acme.sh - add nginx reload to deploy
+ lineinfile:
+ path: "{{ web.acme_home }}/deploy.local.sh"
+ line: "service nginx reload"
+ tags: acme
+
+- name: acme.sh - generate renew script
+ copy:
+ dest: "{{ web.acme_home }}/renew.sh"
+ mode: 0755
+ content: |
+ acme.sh --cron
+ sh {{ web.acme_home }}/deploy.sh
+ tags: acme
+
+- name: acme.sh - install cron job to renew (1)
+ cron:
+ user: acme
+ name: MAILTO
+ env: true
+ job: root
+ tags: acme
+
+- name: acme.sh - install cron job to renew (2)
+ cron:
+ user: acme
+ name: "acme.sh-renew"
+ special_time: monthly
+ job: "sh {{ web.acme_home }}/renew.sh"
+ tags: acme
- block:
- name: nginx - re-generate sites
include_tasks: nginx-gensites.yml
- tags: sites
+ tags:
+ - acme
+ - sites
diff --git a/roles/web/tasks/nginx-gensites.yml b/roles/web/tasks/nginx-gensites.yml
index 162a8f3..daea875 100644
--- a/roles/web/tasks/nginx-gensites.yml
+++ b/roles/web/tasks/nginx-gensites.yml
@@ -1,7 +1,7 @@
---
- name: domains - check certificate existence
stat:
- path: /usr/local/etc/ssl/acme/{{ item.name }}/fullchain.pem
+ path: "{{ web.ssl_root }}/{{ item.name }}/fullchain"
register: stat
with_items: "{{ domains }}"
diff --git a/roles/web/templates/acme/deploy.sh.j2 b/roles/web/templates/acme/deploy.sh.j2
new file mode 100644
index 0000000..141b112
--- /dev/null
+++ b/roles/web/templates/acme/deploy.sh.j2
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Deploy the issued certificates.
+#
+# Aaron LI
+# 2019-09-21
+#
+
+SSL_ROOT="{{ web.ssl_root }}"
+[ -d "${SSL_ROOT}" ] || mkdir -p -m 0700 ${SSL_ROOT}
+
+{% for domain in domains %}
+CERT_DIR="${SSL_ROOT}/{{ domain.name }}"
+[ -d "${CERT_DIR}" ] || mkdir -m 0700 ${CERT_DIR}
+acme.sh --install-cert --log /var/log/acme.sh.log \
+ --config-home {{ web.acme_home }}/.acme.sh \
+ --cert-home {{ web.acme_home }}/certs \
+ --domain {{ domain.name }} \
+ --key-file ${CERT_DIR}/key \
+ --cert-file ${CERT_DIR}/cert \
+ --fullchain-file ${CERT_DIR}/fullchain
+
+{% endfor %}
+
+echo "Reload relevant services ..."
+SCRIPT="{{ web.acme_home }}/deploy.local.sh"
+[ -f "${SCRIPT}" ] && sh ${SCRIPT} || exit 0
diff --git a/roles/web/templates/acme/issue.sh.j2 b/roles/web/templates/acme/issue.sh.j2
new file mode 100644
index 0000000..6e63fb4
--- /dev/null
+++ b/roles/web/templates/acme/issue.sh.j2
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Use 'acme.sh' to issue certificates.
+#
+# Aaron LI
+# 2019-09-21
+#
+
+{% for domain in domains %}
+acme.sh --issue --log /var/log/acme.sh.log \
+ --config-home {{ web.acme_home }}/.acme.sh \
+ --domain {{ domain.name }} \
+ {% for sub in domain.sub %}--domain {{ sub }}.{{ domain.name }} {% endfor %} \
+ --webroot {{ web.acme_webroot }} ||
+ echo "WARNING: exit with non-zero code: $?"
+
+{% endfor %}
+
+acme.sh --list