diff --git a/roles/lego-nginx/files/lego.nginx.conf b/roles/lego-nginx/files/lego.nginx.conf new file mode 100644 index 0000000..69680dd --- /dev/null +++ b/roles/lego-nginx/files/lego.nginx.conf @@ -0,0 +1,3 @@ +location ^~ /.well-known/acme-challenge { + root /var/www/lego; +} diff --git a/roles/lego-nginx/handlers/main.yml b/roles/lego-nginx/handlers/main.yml new file mode 100644 index 0000000..71ffc65 --- /dev/null +++ b/roles/lego-nginx/handlers/main.yml @@ -0,0 +1,4 @@ +- name: reload nginx + service: + name: nginx + state: reloaded diff --git a/roles/lego-nginx/meta/main.yml b/roles/lego-nginx/meta/main.yml new file mode 100644 index 0000000..d55052e --- /dev/null +++ b/roles/lego-nginx/meta/main.yml @@ -0,0 +1,4 @@ +dependencies: +- role: lego + tags: + - lego diff --git a/roles/lego-nginx/tasks/cert.yml b/roles/lego-nginx/tasks/cert.yml new file mode 100644 index 0000000..84191eb --- /dev/null +++ b/roles/lego-nginx/tasks/cert.yml @@ -0,0 +1,50 @@ +# vim: set ft=yaml.jinja : +- name: ensure lego webroot exists + file: + path: /var/www/lego + owner: lego + group: lego + mode: u=rwx,go=rx + setype: httpd_sys_content_t + state: directory + tags: + - webroot + +- name: ensure lego is allowed to reload nginx + lineinfile: + dest: /etc/doas.conf + line: permit nopass lego cmd /usr/sbin/nginx args -s reload + tags: + - doas + +- name: ensure lego renew script exists + copy: + content: >+ + lego + --path /var/lib/lego + --accept-tos + {% if lego_acme_server %} + --server {{ lego_acme_server }} + {% endif %} + --http --http.webroot /var/www/lego + {% for domain in lego_domains %} + --domains {{ domain }} + {% endfor %} + --email {{ lego_acme_email }} + run + --run-hook 'doas /usr/sbin/nginx -s reload' + dest: /var/lib/lego/renew.sh + owner: lego + group: lego + mode: u=rwx,go=rx + tags: + - lego-renew + +- name: ensure server certificate exists + become: true + become_user: lego + command: /bin/sh /var/lib/lego/renew.sh + args: + creates: /var/lib/lego/certificates/{{ lego_domains[0] }}.json + tags: + - cert diff --git a/roles/lego-nginx/tasks/main.yml b/roles/lego-nginx/tasks/main.yml new file mode 100644 index 0000000..0deea15 --- /dev/null +++ b/roles/lego-nginx/tasks/main.yml @@ -0,0 +1,8 @@ +- import_tasks: nginx.yml + tags: + - nginx + - lego-nginx + +- import_tasks: cert.yml + tags: + - lego-nginx diff --git a/roles/lego-nginx/tasks/nginx.yml b/roles/lego-nginx/tasks/nginx.yml new file mode 100644 index 0000000..717134f --- /dev/null +++ b/roles/lego-nginx/tasks/nginx.yml @@ -0,0 +1,37 @@ +- name: ensure nginx is installed + package: + name: nginx + state: present + tags: + - install + +- name: ensure nginx is running + service: + name: nginx + state: started + tags: + - service + +- name: ensure nginx is configured for lego + copy: + src: lego.nginx.conf + dest: /etc/nginx/default.d/lego.conf + owner: root + group: root + mode: u=rw,go=r + notify: + - reload nginx + tags: + - nginx-config + +- name: ensure firewall allows http acme challenges + firewalld: + service: http + state: enabled + immediate: true + when: host_uses_firewalld|d(true) + tags: + - firewalld + +- name: flush handlers + meta: flush_handlers diff --git a/roles/lego/files/lego-renew.service b/roles/lego/files/lego-renew.service new file mode 100644 index 0000000..6a43b2a --- /dev/null +++ b/roles/lego/files/lego-renew.service @@ -0,0 +1,10 @@ +[Unit] +Description=Renew certificates with LEGO +Wants=network-online.target +After=network-online.target +After=httpd.service nginx.service + +[Service] +Type=oneshot +User=lego +ExecStart=/bin/sh /var/lib/lego/renew.sh diff --git a/roles/lego/files/lego-renew.timer b/roles/lego/files/lego-renew.timer new file mode 100644 index 0000000..27ee2dd --- /dev/null +++ b/roles/lego/files/lego-renew.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Periodically renew certificates with LEGO + +[Timer] +RandomizedDelaySec=15m +OnActiveSec=4h + +[Install] +WantedBy=timers.target diff --git a/roles/lego/meta/main.yml b/roles/lego/meta/main.yml new file mode 100644 index 0000000..e2827fe --- /dev/null +++ b/roles/lego/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: +- systemd-base diff --git a/roles/lego/tasks/main.yml b/roles/lego/tasks/main.yml new file mode 100644 index 0000000..af03206 --- /dev/null +++ b/roles/lego/tasks/main.yml @@ -0,0 +1,66 @@ +- name: load os-specific values + include_vars: '{{ item }}' + with_first_found: + - '{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml' + - '{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml' + - '{{ ansible_os_family }}-{{ ansible_distribution_major_version }}.yml' + - '{{ ansible_distribution }}.yml' + - '{{ ansible_os_family }}.yml' + - defaults.yml + tags: + - always + +- name: ensure lego is installed + package: + name: + - acl # required for `become_user: lego` + - '{{ lego_package }}' + state: present + tags: + - install + +- name: ensure lego group exists + group: + name: lego + system: true + tags: + - user + - group +- name: ensure lego user exists + user: + name: lego + group: lego + system: true + home: /var/lib/lego + createhome: true + shell: /bin/false + tags: + - user + +- name: ensure lego-renew systemd units are installed + copy: + src: '{{ item }}' + dest: /etc/systemd/system/ + owner: root + group: root + mode: u=rw,go=r + loop: + - lego-renew.service + - lego-renew.timer + notify: + - reload systemd + tags: + - systemd + +- name: ensure lego-renew systemd timer is enabled + systemd: + name: lego-renew.timer + enabled: true + tags: + - service +- name: ensure lego-renew systemd timer is running + systemd: + name: lego-renew.timer + state: started + tags: + - service diff --git a/roles/lego/vars/defaults.yml b/roles/lego/vars/defaults.yml new file mode 100644 index 0000000..0a92cd0 --- /dev/null +++ b/roles/lego/vars/defaults.yml @@ -0,0 +1 @@ +lego_package: golang-github-acme-lego