Skip to content
Snippets Groups Projects
Commit d0297528 authored by Thomas Schneider's avatar Thomas Schneider
Browse files

Add role for lego ACME client

parent a444637d
Branches th/lego
No related tags found
1 merge request!50Draft: Add role for lego ACME client
Pipeline #5598 failed
---
lego_acme_server_base: acme-v02.api.letsencrypt.org
# lego_account_mail: root@example.org
# The following two variables are defaults for the respective entries in a
# `lego_certificates` entry.
lego_method:
type: http
subtype: webroot
lego_hooks:
services: {}
extra: {}
lego_global_args: []
# lego_certificates:
# # Default case, only one domain
# foo.example.org: {}
# bar.example.org:
# domains:
# # bar.example.org is already included
# - baz.example.org
# - qux.example.org
# account_mail: other@example.org
# method:
# type: dns
# subtype: rfc2136
# extra_args:
# - --foo
# - --bar baz
# extra_env:
# RFC2136_NAMESERVER: 127.0.0.1
# hooks:
# services:
# nginx.service: try-restart
# httpd.service: try-reload-or-restart
# extra:
# 10-install.sh: |
# #!/bin/sh
# set -e
# install -u foo -g foo -m 0644 "$LEGO_CERT_PATH" /etc/foo/cert.pem
# install -u foo -g foo -m 0600 "$LEGO_CERT_KEY_PATH" /etc/foo/key.pem
---
- name: Reload systemd
systemd:
daemon_reload: true
---
- name: Install instance config
template:
src: env-inst.j2
dest: /etc/lego/{{ item.key }}.env
owner: root
group: root
mode: "0600"
register: install_instance_config
- name: Create hooks directory
file:
path: /etc/lego/hooks/{{ item.key }}
state: directory
owner: root
group: root
mode: "0700"
- name: Install service hook
template:
src: 99-services.sh.j2
dest: /etc/lego/hooks/{{ item.key }}/99-services
owner: root
group: root
mode: "0700"
when: item.value.hooks.services != {}
- name: Install additional hooks
copy:
content: "{{ j.value }}"
dest: /etc/lego/hooks/{{ item.key }}/{{ j.key }}
owner: root
group: root
mode: "0700"
loop: "{{ item.value.hooks.extra | dict2items }}"
loop_control:
loop_var: j
# Yes, this should be a handler, but they cannot be as dynamic as we need it.
- name: Start lego
systemd:
name: lego-run@{{ item.key }}.service
state: started
when: install_instance_config.changed
- name: Enable renewal timer
systemd:
name: lego-renew@{{ item.key }}.timer
state: started
enabled: true
---
- name: Install lego
apt:
name: lego
- name: Create config and hooks directory
file:
path: "{{ item }}"
state: directory
owner: root
group: root
mode: "0700"
loop:
- /etc/lego
- /etc/lego/hooks
- name: Install systemd service files
template:
src: "{{ item }}.j2"
dest: /etc/systemd/system/{{ item }}
owner: root
group: root
mode: "0644"
loop:
- lego-run@.service
- lego-renew@.service
- lego-renew@.timer
notify:
- Reload systemd
- meta: flush_handlers
- name: Process individual certificate instances
loop: "{{ lego_certificates | dict2items }}"
loop_control:
label: "{{ item.key }}"
loop_var: _item
vars:
item: "{{ cert_skeleton | combine(_item, recursive=True) }}"
include_tasks: certificate.yml
#!/bin/sh
{% for svc, action in item.value.hooks.services.items() %}
set -- systemctl "{{ action }}" "{{ svc }}"
"$@"
ret=$?
if [ $ret -ne 0 ]; then
echo "(command was: $*)"
exit $ret
fi
{% endfor %}
{# -*- systemd -*- #}
{% macro execstart(typ) %}
ExecStart=/usr/bin/lego $LEGO_GLOBAL_ARGS $LEGO_ARGS \
--server https://${LEGO_ACME_SERVER_BASE}/directory \
--path $STATE_DIRECTORY \
--accept-tos \
{{ typ }} \
{% if typ == "renew" %}
--no-random-sleep \
{% endif %}
--{{ typ }}-hook='run-parts --report /etc/lego/hooks/%i/'
{% endmacro %}
{% macro systemd_boilerplate(typ) %}
[Unit]
Wants=network-online.target
After=network-online.target
[Service]
EnvironmentFile=/etc/lego/%i.env
StateDirectory=lego
StateDirectoryMode=0700
RuntimeDirectory=lego
Type=oneshot
{{ execstart(typ) }}
# PrivateDevices=yes
# NoNewPrivileges=yes
# ProtectHome=yes
TimeoutStartSec=5min
#CapabilityBoundingSet=CAP_CHOWN
# Empty = no capabilities at all
CapabilityBoundingSet=
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=yes
ProtectHostname=yes
ProtectClock=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
RestrictRealtime=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
LockPersonality=yes
SystemCallFilter=@system-service
SystemCallArchitectures=native
{% endmacro %}
{% if lego_global_args is iterable and not lego_global_args is string -%}
LEGO_GLOBAL_ARGS="{{ lego_global_args | join(' ') }}"
{% else %}
LEGO_GLOBAL_ARGS="{{ lego_global_args }}"
{% endif %}
LEGO_ACME_SERVER_BASE="{{ lego_acme_server_base }}"
LEGO_CERT_DOMAIN="{{ item.key }}"
LEGO_ARGS="\
--email {{ item.value.account_mail }} \
--{{ item.value.method.type }} \
{% if item.value.method.type == "http" and item.value.method.subtype == "webroot" %}
--http.webroot /run/lego \
{% endif %}
--domains {{ item.key }} \
{% for d in item.value.domains %}
--domains {{ d }} \
{% endfor %}
{% for i in item.value.extra_args %}
{{ i }} \
{% endfor %}
"
{% for k, v in item.value.extra_env.items() %}
{{ k }}="{{ v }}"
{% endfor %}
{# -*- systemd -*- #}
{% from "_macros.j2" import systemd_boilerplate -%}
[Unit]
Description=lego ACME client -- renewal for %i
{{ systemd_boilerplate("renew") }}
{# -*- systemd -*- #}
[Unit]
Description=lego ACME client -- renewal for %i timer
[Timer]
OnCalendar=weekly
RandomizedDelaySec=1d
Persistent=true
[Install]
WantedBy=timers.target
{# -*- systemd -*- #}
{% from "_macros.j2" import systemd_boilerplate -%}
[Unit]
Description=lego ACME client -- setup for %i
{{ systemd_boilerplate("run") }}
---
cert_skeleton:
value:
account_mail: "{{ lego_account_mail }}"
domains: []
method: "{{ lego_method }}"
extra_args: []
extra_env: {}
hooks: "{{ lego_hooks }}"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment