summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chaos-at-home/ch-http-proxy.yml17
-rw-r--r--chaos-at-home/ch-imap-proxy.yml11
-rw-r--r--chaos-at-home/ch-mimas.yml3
-rw-r--r--chaos-at-home/ch-pan.yml11
-rw-r--r--chaos-at-home/r3-0x10.yml3
-rw-r--r--dan/k8s-emc.yml3
-rw-r--r--dan/sk-testvm.yml115
-rw-r--r--inventory/host_vars/ch-mimas.yml2
-rw-r--r--inventory/host_vars/ele-coturn.yml9
-rw-r--r--inventory/host_vars/ele-jitsi.yml3
-rw-r--r--inventory/host_vars/ele-lt.yml1
-rw-r--r--inventory/host_vars/ele-media.yml1
-rw-r--r--inventory/host_vars/glt-coturn.yml10
-rw-r--r--inventory/host_vars/glt-meet1.yml2
-rw-r--r--inventory/host_vars/glt-meet2.yml2
-rw-r--r--inventory/host_vars/sk-cloudio/coturn.yml4
-rw-r--r--inventory/host_vars/sk-cloudio/vars.yml2
-rw-r--r--inventory/host_vars/sk-testvm.yml371
-rw-r--r--inventory/host_vars/sk-tomnext-nc.yml1
-rw-r--r--inventory/hosts.ini1
-rw-r--r--roles/apps/bluespice/tasks/main.yml3
-rw-r--r--roles/apps/collabora/code/tasks/main.yml12
-rw-r--r--roles/apps/collabora/code/tasks/nginx-vhost.yml17
-rw-r--r--roles/apps/collabora/code/templates/nginx-vhost.conf.j2153
-rw-r--r--roles/apps/coturn/defaults/main.yml5
-rw-r--r--roles/apps/coturn/tasks/main.yml59
-rw-r--r--roles/apps/coturn/templates/acmetool-reload.sh.j228
-rw-r--r--roles/apps/coturn/templates/nginx-vhost.conf.j227
-rw-r--r--roles/apps/etherpad-lite/tasks/main.yml13
-rw-r--r--roles/apps/etherpad-lite/tasks/nginx-vhost.yml16
-rw-r--r--roles/apps/etherpad-lite/templates/nginx-vhost.conf.j288
-rw-r--r--roles/apps/jitsi/meet/tasks/main.yml3
-rw-r--r--roles/apps/keycloak/tasks/main.yml3
-rw-r--r--roles/apps/mumble/defaults/main.yml3
-rw-r--r--roles/apps/mumble/tasks/main.yml49
-rw-r--r--roles/apps/mumble/templates/acmetool-reload.sh.j228
-rw-r--r--roles/apps/nextcloud/tasks/main.yml3
-rw-r--r--roles/apps/onlyoffice/tasks/main.yml3
-rw-r--r--roles/apps/pigallery2/tasks/main.yml3
-rw-r--r--roles/apps/wikijs/tasks/main.yml3
-rw-r--r--roles/elevate/liquidtruth/tasks/main.yml7
-rw-r--r--roles/elevate/media/tasks/nextcloud-app.yml3
-rw-r--r--roles/gitolite/base/defaults/main.yml2
-rw-r--r--roles/gitolite/http/tasks/main.yml51
-rw-r--r--roles/gitolite/http/templates/nginx-vhost.conf.j272
-rw-r--r--roles/monitoring/graphite/web/tasks/main.yml6
-rw-r--r--roles/monitoring/landingpage/defaults/main.yml8
-rw-r--r--roles/monitoring/landingpage/tasks/main.yml22
-rw-r--r--roles/monitoring/landingpage/templates/index.html.j26
-rw-r--r--roles/monitoring/prometheus/exporter/base/tasks/main.yml10
-rw-r--r--roles/nginx/vhost/defaults/main.yml33
-rw-r--r--roles/nginx/vhost/tasks/acme.yml44
-rw-r--r--roles/nginx/vhost/tasks/main.yml26
-rw-r--r--roles/nginx/vhost/templates/generic.conf.j298
-rw-r--r--roles/x509/acmetool/cert/defaults/main.yml2
-rw-r--r--roles/x509/acmetool/cert/finalize/defaults/main.yml5
-rw-r--r--roles/x509/acmetool/cert/finalize/handlers/main.yml (renamed from roles/x509/acmetool/cert/handlers/main.yml)1
-rw-r--r--roles/x509/acmetool/cert/finalize/tasks/main.yml (renamed from roles/x509/acmetool/cert/tasks/main.yml)2
-rw-r--r--roles/x509/acmetool/cert/meta/main.yml4
-rw-r--r--roles/x509/acmetool/cert/prepare/defaults/main.yml2
-rw-r--r--roles/x509/acmetool/cert/prepare/filter_plugins/acme_certs.py (renamed from roles/x509/acmetool/cert/filter_plugins/acme_certs.py)0
-rw-r--r--roles/x509/acmetool/cert/prepare/handlers/main.yml10
-rw-r--r--roles/x509/acmetool/cert/prepare/tasks/main.yml79
-rw-r--r--roles/x509/acmetool/cert/prepare/templates/reload.sh.j231
-rw-r--r--roles/x509/selfsigned/base/tasks/main.yml5
-rw-r--r--roles/x509/selfsigned/cert/finalize/tasks/main.yml2
-rw-r--r--roles/x509/selfsigned/cert/meta/main.yml4
-rw-r--r--roles/x509/selfsigned/cert/prepare/defaults/main.yml41
-rw-r--r--roles/x509/selfsigned/cert/prepare/handlers/main.yml6
-rw-r--r--roles/x509/selfsigned/cert/prepare/tasks/main.yml69
-rw-r--r--roles/x509/static/base/tasks/main.yml2
-rw-r--r--roles/x509/static/cert/finalize/tasks/main.yml2
-rw-r--r--roles/x509/static/cert/meta/main.yml4
-rw-r--r--roles/x509/static/cert/prepare/defaults/main.yml35
-rw-r--r--roles/x509/static/cert/prepare/handlers/main.yml6
-rw-r--r--roles/x509/static/cert/prepare/tasks/main.yml81
-rw-r--r--roles/x509/uacme/base/defaults/main.yml2
-rw-r--r--roles/x509/uacme/base/tasks/main.yml29
-rw-r--r--roles/x509/uacme/base/tasks/selfsigned.yml47
-rw-r--r--roles/x509/uacme/base/templates/uacme-reconcile.service.j218
-rw-r--r--roles/x509/uacme/base/templates/uacme-reconcile.sh.j232
-rw-r--r--roles/x509/uacme/base/templates/uacme-reconcile.timer.j210
-rw-r--r--roles/x509/uacme/cert/finalize/defaults/main.yml3
-rw-r--r--roles/x509/uacme/cert/finalize/tasks/main.yml5
-rw-r--r--roles/x509/uacme/cert/meta/main.yml4
-rw-r--r--roles/x509/uacme/cert/prepare/defaults/main.yml15
-rw-r--r--roles/x509/uacme/cert/prepare/handlers/main.yml10
-rw-r--r--roles/x509/uacme/cert/prepare/tasks/main.yml112
-rw-r--r--roles/x509/uacme/cert/prepare/templates/updated.sh.j233
-rw-r--r--spreadspace/glt-stream.yml3
-rw-r--r--spreadspace/sgg-icecast.yml6
91 files changed, 1653 insertions, 548 deletions
diff --git a/chaos-at-home/ch-http-proxy.yml b/chaos-at-home/ch-http-proxy.yml
index 0376fcd5..24fd6f92 100644
--- a/chaos-at-home/ch-http-proxy.yml
+++ b/chaos-at-home/ch-http-proxy.yml
@@ -6,6 +6,10 @@
- role: core/base
- role: core/sshd/base
- role: core/zsh
+
+- name: Payload Setup
+ hosts: ch-http-proxy
+ roles:
- role: apt-repo/spreadspace
- role: x509/acmetool/base
- role: nginx/base
@@ -43,7 +47,8 @@
default: yes
name: web
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- web.chaos-at-home.org
locations:
@@ -108,7 +113,8 @@
nginx_vhost:
name: passwd
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- passwd.chaos-at-home.org
locations:
@@ -175,7 +181,8 @@
nginx_vhost:
name: webmail
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- webmail.chaos-at-home.org
locations:
@@ -200,7 +207,8 @@
nginx_vhost:
name: webdav
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- webdav.chaos-at-home.org
locations:
@@ -224,7 +232,6 @@
vars:
nginx_vhost:
name: imap
- acme: no
content: |
server {
listen 80;
diff --git a/chaos-at-home/ch-imap-proxy.yml b/chaos-at-home/ch-imap-proxy.yml
index 936140bc..1c05f28b 100644
--- a/chaos-at-home/ch-imap-proxy.yml
+++ b/chaos-at-home/ch-imap-proxy.yml
@@ -6,10 +6,15 @@
- role: core/base
- role: core/sshd/base
- role: core/zsh
+
+- name: Payload Setup
+ hosts: ch-imap-proxy
+ roles:
- role: apt-repo/spreadspace
- role: x509/acmetool/base
- role: x509/acmetool/cert
- acmetool_cert_name: "imap.chaos-at-home.org"
+ acmetool_cert_hostnames:
+ - "imap.chaos-at-home.org"
acmetool_cert_config:
request:
challenge:
@@ -25,8 +30,8 @@
dest: /etc/stunnel/imap.conf
content: |
pid = /var/run/stunnel-imap.pid
- cert = /var/lib/acme/live/imap.chaos-at-home.org/fullchain
- key = /var/lib/acme/live/imap.chaos-at-home.org/privkey
+ cert = {{ x509_certificate_path_fullchain }}
+ key = {{ x509_certificate_path_key }}
[imap]
client = yes
diff --git a/chaos-at-home/ch-mimas.yml b/chaos-at-home/ch-mimas.yml
index 2743644c..fec7b0e5 100644
--- a/chaos-at-home/ch-mimas.yml
+++ b/chaos-at-home/ch-mimas.yml
@@ -44,7 +44,8 @@
nginx_vhost:
name: pub
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- pub.chaos-at-home.org
locations:
diff --git a/chaos-at-home/ch-pan.yml b/chaos-at-home/ch-pan.yml
index 56a4f30a..bccd9ca5 100644
--- a/chaos-at-home/ch-pan.yml
+++ b/chaos-at-home/ch-pan.yml
@@ -43,11 +43,12 @@
template: generic
hostnames:
- dyn.schaaas.at
- acme: yes
+ tls:
+ certificate_provider: acmetool
+ logs:
+ access: /var/log/nginx/dyn-schaaas_access.log
+ error: /var/log/nginx/dyn-schaaas_error.log
extra_directives: |
- access_log /var/log/nginx/dyn-schaaas_access.log;
- error_log /var/log/nginx/dyn-schaaas_error.log;
-
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
@@ -58,7 +59,7 @@
ssi on;
locations:
'= /raw':
- extra_directives: |
+ custom: |
types { }
default_type text/plain;
ssi_types text/plain;
diff --git a/chaos-at-home/r3-0x10.yml b/chaos-at-home/r3-0x10.yml
index c613f373..267bc596 100644
--- a/chaos-at-home/r3-0x10.yml
+++ b/chaos-at-home/r3-0x10.yml
@@ -33,7 +33,8 @@
default: yes
name: 0x10
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- 0x10.r3.at
- 0x10.realraum.at
diff --git a/dan/k8s-emc.yml b/dan/k8s-emc.yml
index 86fea6c5..b8358fee 100644
--- a/dan/k8s-emc.yml
+++ b/dan/k8s-emc.yml
@@ -16,7 +16,8 @@
roles:
- role: x509/acmetool/base
- role: x509/acmetool/cert
- acmetool_cert_name: "{{ host_name }}.{{ host_domain }}"
+ acmetool_cert_hostnames:
+ - "{{ host_name }}.{{ host_domain }}"
- role: storage/lvm/volume
lvm_volume:
vg: storage
diff --git a/dan/sk-testvm.yml b/dan/sk-testvm.yml
index e349a3c3..13a0b499 100644
--- a/dan/sk-testvm.yml
+++ b/dan/sk-testvm.yml
@@ -7,5 +7,118 @@
- role: core/sshd/base
- role: core/zsh
- role: core/ntp
- - role: x509/uacme/base
+
+- name: Payload Setup
+ hosts: sk-testvm
+ vars:
+ acme_client: uacme
+ # acme_client: acmetool
+ cert_provider: "{{ acme_client }}"
+ # cert_provider: static
+ # cert_provider: selfsigned
+ roles:
+ - role: apt-repo/spreadspace
+ - role: kubernetes/base
+ - role: kubernetes/standalone/base
+ - role: "x509/{{ cert_provider }}/base"
- role: nginx/base
+ - role: nginx/vhost
+ nginx_vhost:
+ default: yes
+ name: nosuchsite
+ template: generic
+ tls:
+ certificate_provider: "{{ cert_provider }}"
+ hsts: no
+ hostnames:
+ - testvm.elev8.at
+ locations:
+ '/':
+ root: /var/www/default
+ index: index.html
+ static_cert_config: "{{ static_cert_config__default }}"
+ selfsigned_cert_config: "{{ selfsigned_cert_config__default }}"
+ # - role: nginx/vhost
+ # nginx_vhost:
+ # name: test
+ # template: generic
+ # tls:
+ # certificate_provider: "{{ cert_provider }}"
+ # hsts: no
+ # hostnames:
+ # - test.spreadspace.org
+ # - test.spreadspace.com
+ # - test.spreadspace.net
+ # - test.spreadspace.systems
+ # locations:
+ # '/':
+ # root: /var/www/test
+ # index: index.html
+ # static_cert_config: "{{ static_cert_config__test }}"
+ # selfsigned_cert_config: "{{ selfsigned_cert_config__test }}"
+ # - role: apps/mumble
+ # mumble_version: v1.4.274-4
+ # mumble_instance: spreadspace
+ # mumble_hostnames:
+ # - test.spreadspace.org
+ # - test.spreadspace.com
+ # - test.spreadspace.net
+ # - test.spreadspace.systems
+ # mumble_superuser_password: "very-secret"
+ # mumble_config_options:
+ # bonjour: false
+ # sslCiphers: "ECDHE+AESGCM:DHE+AESGCM:ECDHE+AES256:DHE+AES256:ECDHE+AES128:DHE+AES128:!RSA:!ADH:!AECDH:!MD5"
+ # welcometext: "Welcome to the spreadspace Mumble Test-Server"
+ # rememberchannel: true
+ # mumble_tls:
+ # certificate_provider: "{{ cert_provider }}"
+ - role: apps/coturn
+ coturn_version: 4.6.2-r4
+ coturn_realm: spreadspace
+ coturn_hostnames:
+ - test.spreadspace.org
+ - test.spreadspace.com
+ - test.spreadspace.net
+ - test.spreadspace.systems
+ coturn_auth_secret: "somewhat-secret"
+ coturn_tls:
+ certificate_provider: "{{ cert_provider }}"
+ post_tasks:
+ - name: make sure document root directories exist
+ loop:
+ - test
+ - default
+ file:
+ path: "/var/www/{{ item }}"
+ state: directory
+
+ - name: install index.html for default server
+ copy:
+ dest: /var/www/default/index.html
+ content: |
+ <html>
+ <head>
+ <title>No Such Site</title>
+ </head>
+ <body style="font-family: Helvetica, Arial, Sans-Serif; color: white; background: black;">
+ <div style="text-align: center; margin-top: 4em; margin-left:auto; margin-right:auto;">
+ <h2 style="">You have reached testvm.elev8.at, nothing to see here.</h2>
+ </div>
+ </body>
+ </html>
+
+
+ - name: install index.html for test server
+ copy:
+ dest: /var/www/test/index.html
+ content: |
+ <html>
+ <head>
+ <title>This is Test</title>
+ </head>
+ <body style="font-family: Helvetica, Arial, Sans-Serif; color: white; background: black;">
+ <div style="text-align: center; margin-top: 4em; margin-left:auto; margin-right:auto;">
+ <h2 style="">If you can read this the test was successful.</h2>
+ </div>
+ </body>
+ </html>
diff --git a/inventory/host_vars/ch-mimas.yml b/inventory/host_vars/ch-mimas.yml
index fc3e6aae..710e4961 100644
--- a/inventory/host_vars/ch-mimas.yml
+++ b/inventory/host_vars/ch-mimas.yml
@@ -159,6 +159,8 @@ gitolite_instances:
- git.spreadspace.com
- git.spreadspace.net
- git.spreadspace.systems
+ tls:
+ certificate_provider: acmetool
enable_git_backend: yes
title: spreadspace
description: spreadspace GIT Repoistories
diff --git a/inventory/host_vars/ele-coturn.yml b/inventory/host_vars/ele-coturn.yml
index 28314433..ebfbe2aa 100644
--- a/inventory/host_vars/ele-coturn.yml
+++ b/inventory/host_vars/ele-coturn.yml
@@ -24,16 +24,18 @@ spreadspace_apt_repo_components:
- container
acme_directory_server: "{{ acme_directory_server_le_live_v2 }}"
+acme_client: acmetool
kubernetes_version: 1.27.3
kubernetes_cri_tools_pkg_version: 1.26.0-00
kubernetes_container_runtime: docker
kubernetes_standalone_max_pods: 100
+kubernetes_standalone_pod_cidr: 192.168.255.0/24
kubernetes_standalone_cni_variant: with-portmap
-coturn_version: 4.5.2-r2
+coturn_version: 4.6.2-r4
coturn_realm: elev8.at
coturn_hostnames:
- stun.elev8.at
@@ -43,6 +45,8 @@ coturn_auth_secret: "{{ vault_coturn_auth_secret }}"
coturn_listening_port: 3478
coturn_tls_listening_port: 443
coturn_install_nginx_vhost: no
+coturn_tls:
+ certificate_provider: "{{ acme_client }}"
mumble_version: v1.4.274-4
@@ -52,6 +56,9 @@ mumble_hostnames:
mumble_superuser_password: "{{ vault_mumble_superuser_password }}"
+mumble_tls:
+ certificate_provider: "{{ acme_client }}"
+
mumble_config_options:
bonjour: false
sslCiphers: "ECDHE+AESGCM:DHE+AESGCM:ECDHE+AES256:DHE+AES256:ECDHE+AES128:DHE+AES128:!RSA:!ADH:!AECDH:!MD5"
diff --git a/inventory/host_vars/ele-jitsi.yml b/inventory/host_vars/ele-jitsi.yml
index c7520247..e23dc2c9 100644
--- a/inventory/host_vars/ele-jitsi.yml
+++ b/inventory/host_vars/ele-jitsi.yml
@@ -29,6 +29,7 @@ ssh_users_root:
- datacop
acme_directory_server: "{{ acme_directory_server_le_live_v2 }}"
+acme_client: acmetool
kubernetes_version: 1.27.3
@@ -81,6 +82,8 @@ mumble_version: v1.4.274-4
mumble_instance: elev8.at
mumble_hostnames:
- mumble.elev8.at
+mumble_tls:
+ certificate_provider: "{{ acme_client }}"
mumble_superuser_password: "{{ vault_mumble_superuser_password }}"
diff --git a/inventory/host_vars/ele-lt.yml b/inventory/host_vars/ele-lt.yml
index a53141e0..6389db1d 100644
--- a/inventory/host_vars/ele-lt.yml
+++ b/inventory/host_vars/ele-lt.yml
@@ -29,6 +29,7 @@ liquidtruth_mongodb_app_password: "{{ vault_liquidtruth_mongodb_app_password }}"
acme_directory_server: "{{ acme_directory_server_le_live_v2 }}"
+acme_client: acmetool
liquidtruth_hostnames:
# - liquidtruth.at
diff --git a/inventory/host_vars/ele-media.yml b/inventory/host_vars/ele-media.yml
index e17947ff..a82ca897 100644
--- a/inventory/host_vars/ele-media.yml
+++ b/inventory/host_vars/ele-media.yml
@@ -112,6 +112,7 @@ wireguard_gateway_tunnels:
acme_directory_server: "{{ acme_directory_server_le_live_v2 }}"
+acme_client: acmetool
elevate_media_share_storage:
diff --git a/inventory/host_vars/glt-coturn.yml b/inventory/host_vars/glt-coturn.yml
index 7dbcca04..4a84c31f 100644
--- a/inventory/host_vars/glt-coturn.yml
+++ b/inventory/host_vars/glt-coturn.yml
@@ -17,14 +17,18 @@ kubelet_storage:
spreadspace_apt_repo_components:
- container
+acme_client: acmetool
+
+
kubernetes_version: 1.27.3
kubernetes_cri_tools_pkg_version: 1.26.0-00
kubernetes_container_runtime: docker
kubernetes_standalone_max_pods: 100
+kubernetes_standalone_pod_cidr: 192.168.255.0/24
kubernetes_standalone_cni_variant: with-portmap
-coturn_version: 4.5.2-r2
+coturn_version: 4.6.2-r4
coturn_realm: linuxtage.at
coturn_hostnames:
- cdn13.linuxtage.at
@@ -33,12 +37,16 @@ coturn_auth_secret: "{{ vault_coturn_auth_secret }}"
coturn_listening_port: 3478
coturn_tls_listening_port: 443
coturn_install_nginx_vhost: no
+coturn_tls:
+ certificate_provider: "{{ acme_client }}"
mumble_version: v1.4.274-4
mumble_instance: linuxtage.at
mumble_hostnames:
- mumble.linuxtage.at
+mumble_tls:
+ certificate_provider: "{{ acme_client }}"
mumble_superuser_password: "{{ vault_mumble_superuser_password }}"
diff --git a/inventory/host_vars/glt-meet1.yml b/inventory/host_vars/glt-meet1.yml
index 6ce86abf..d5ec9b5f 100644
--- a/inventory/host_vars/glt-meet1.yml
+++ b/inventory/host_vars/glt-meet1.yml
@@ -17,6 +17,8 @@ kubelet_storage:
spreadspace_apt_repo_components:
- container
+acme_client: acmetool
+
kubernetes_version: 1.27.3
kubernetes_cri_tools_pkg_version: 1.26.0-00
diff --git a/inventory/host_vars/glt-meet2.yml b/inventory/host_vars/glt-meet2.yml
index c9093da3..0a757e2d 100644
--- a/inventory/host_vars/glt-meet2.yml
+++ b/inventory/host_vars/glt-meet2.yml
@@ -17,6 +17,8 @@ kubelet_storage:
spreadspace_apt_repo_components:
- container
+acme_client: acmetool
+
kubernetes_version: 1.27.3
kubernetes_cri_tools_pkg_version: 1.26.0-00
diff --git a/inventory/host_vars/sk-cloudio/coturn.yml b/inventory/host_vars/sk-cloudio/coturn.yml
index 8a9eccd7..1ab00b49 100644
--- a/inventory/host_vars/sk-cloudio/coturn.yml
+++ b/inventory/host_vars/sk-cloudio/coturn.yml
@@ -1,11 +1,13 @@
---
coturn_base_path: /srv/storage/coturn
-coturn_version: 4.5.2-r8
+coturn_version: 4.6.2-r4
coturn_realm: elevate.at
coturn_hostnames:
- stun.elevate.at
- turn.elevate.at
+coturn_tls:
+ certificate_provider: "{{ acme_client }}"
coturn_max_bps: 1048576 ## 8Mbit/s
coturn_bps_capacity: 13107200 ## 100Mbit/s
diff --git a/inventory/host_vars/sk-cloudio/vars.yml b/inventory/host_vars/sk-cloudio/vars.yml
index 69f68e88..80772c5c 100644
--- a/inventory/host_vars/sk-cloudio/vars.yml
+++ b/inventory/host_vars/sk-cloudio/vars.yml
@@ -74,6 +74,7 @@ kubernetes_version: 1.27.3
kubernetes_cri_tools_pkg_version: 1.26.0-00
kubernetes_container_runtime: docker
kubernetes_standalone_max_pods: 100
+kubernetes_standalone_pod_cidr: 192.168.255.0/24
kubernetes_standalone_cni_variant: with-portmap
kubernetes_standalone_local_services_tcp:
@@ -89,3 +90,4 @@ postfix_base_inet_protocols:
acme_directory_server: "{{ acme_directory_server_le_live_v2 }}"
+acme_client: acmetool
diff --git a/inventory/host_vars/sk-testvm.yml b/inventory/host_vars/sk-testvm.yml
index 98f45441..a09d8de5 100644
--- a/inventory/host_vars/sk-testvm.yml
+++ b/inventory/host_vars/sk-testvm.yml
@@ -37,3 +37,374 @@ external_ip: "{{ network.primary.overlay }}"
#
# https://owncloud.org/news/upgrading-owncloud-on-debian-stable-to-official-packages/
#
+
+spreadspace_apt_repo_components:
+ - container
+
+docker_storage:
+ type: lvm
+ vg: "{{ host_name }}"
+ lv: docker
+ size: 2G
+ fs: ext4
+
+kubelet_storage:
+ type: lvm
+ vg: "{{ host_name }}"
+ lv: kubelet
+ size: 1G
+ fs: ext4
+
+kubernetes_version: 1.27.4
+kubernetes_cri_tools_pkg_version: 1.26.0-00
+kubernetes_container_runtime: docker
+kubernetes_standalone_max_pods: 100
+kubernetes_standalone_pod_cidr: 192.168.255.0/24
+kubernetes_standalone_cni_variant: with-portmap
+
+
+nginx_server_names_hash_bucket_size: 64
+
+
+static_cert_config__default:
+ key:
+ content: |
+ -----BEGIN RSA PRIVATE KEY-----
+ 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
+ -----END RSA PRIVATE KEY-----
+ cert:
+ content: |
+ -----BEGIN CERTIFICATE-----
+ MIIGGzCCBQOgAwIBAgITAPqTv2Ggom9ksX9aLTLweB6M0DANBgkqhkiG9w0BAQsF
+ ADBZMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXKFNUQUdJTkcpIExldCdzIEVuY3J5
+ cHQxKDAmBgNVBAMTHyhTVEFHSU5HKSBBcnRpZmljaWFsIEFwcmljb3QgUjMwHhcN
+ MjMwODA5MTA1MzAwWhcNMjMxMTA3MTA1MjU5WjAaMRgwFgYDVQQDEw90ZXN0dm0u
+ ZWxldjguYXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChRMRfIFJm
+ FhZCzTDHp8s7plb7gMGnz5Qk4bOcmfG5TrweFJyY+gMdcT0M/i4+rzqzZ4PeMJli
+ hQ7690RM5omurq8gDdYQB601Ca/oj0J+FaGvJv1AYNQU+2NOKUbYYMD6PmhLt30d
+ gt+kO4n71vLUj2tIimzzn3nx3VNu6+m3AvlEUHgEE52Gw1owpOxyxVR3dKjNnHjD
+ AMymMuM2KDtUqWeoxV6yc0O5CO0UxlkGN5eDUN/dPRFealJE0gJH8tPe8OfMWR/S
+ EU5pRI+gRfA3G/id6kivzZ3Uh2p51PFzhE9hy6LmUxtifAKKD82CUfoDAEkHEYWM
+ gZ8ZwG56agawqe7tmlNuzFDio23e+CwMMaxwnqh3VESnbthJ18AK0ybxLCflkB7H
+ Xw7ByJt4VWrrp9tWmrSIH6w2d7Oh/p6XTrBMXUx7HYFjsiQqkl4K4cLBP330qrrn
+ bVSSDU52DEu602GVsnAtbwt/pdgZoLJ3L9AzxaI9JRMu9GCPfX/dFA5UD/DvP6ag
+ DIk7X/9MFHmxbIoT+Bk1RbgCb74vX4vupDqRNWmFbx/z0UiAMctTaE52/swo38Zf
+ u4cJXF6xMqBT8MunvD2I2NR5RoPjqwt58oH4yzgqm+8ZuvEtHbWsPG4yq5ntUsbv
+ /QI1WewL96uCAeJRM+N11E/ZzPftxNZsnQIDAQABo4ICGTCCAhUwDgYDVR0PAQH/
+ BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8E
+ AjAAMB0GA1UdDgQWBBQ+nXoERS+3lz/+LksWdhlIRdBRZzAfBgNVHSMEGDAWgBTe
+ cnpI3zHDplDfn4Uj31c3S10uZTBdBggrBgEFBQcBAQRRME8wJQYIKwYBBQUHMAGG
+ GWh0dHA6Ly9zdGctcjMuby5sZW5jci5vcmcwJgYIKwYBBQUHMAKGGmh0dHA6Ly9z
+ dGctcjMuaS5sZW5jci5vcmcvMBoGA1UdEQQTMBGCD3Rlc3R2bS5lbGV2OC5hdDAT
+ BgNVHSAEDDAKMAgGBmeBDAECATCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB1ALDM
+ g+Wl+X1rr3wJzChJBIcqx+iLEyxjULfG/SbhbGx3AAABidoknl8AAAQDAEYwRAIg
+ WtCJ8ld4R1f2KNpuMFrOjvjp08Tz4OFvZ0+HPHxcPfECIFoVZ4ZYsgg7Z+gUsP+N
+ auCUo3gnonymPzdyl8Mlg2WgAHcA7audHd2Dc5Wf9SqI5Gu0vMPEzE12imDM/042
+ LX+41mgAAAGJ2iSgVwAABAMASDBGAiEA6vwwJZROjqHlG6PAI3PBTgQvsPf1XDVn
+ HdTRg3lVfxQCIQDiyPNyJVAQJcjDYxRJZchP2GIs3pHbmY2qC8TrzpTA/DANBgkq
+ hkiG9w0BAQsFAAOCAQEArmQ+hx5+72piX+y27K+pFzWvYAJ9VjYULj+Un3N+Ta2U
+ y7nL89b0Hpy9/FlZz2joG10/1TQGC11M6Nq0fWmK5BTf0MPEkVLG3ChkhPZeHsWa
+ ok18WiHjy5jjgF4uPbAnSorYmR77ANnuKM1RNpF/xkPb1wQDvF7TmtEdfeMbLGM0
+ 2Pa7cnrwEiq5dC2oyC+D2Qkfvr4Z1t28WepDHGG66VPes7puuL3XMZnor+8SGtCp
+ WfMrrIShXDSQcssxoD9XG6SM15lSCPHjKDT9lhellwvrbGOwKcX+PVJNZW9jGU7D
+ f/PRJpM9pJiz8KqUoVA0o3Sri6DPS6OEH7JPYXszqw==
+ -----END CERTIFICATE-----
+ chain:
+ content: |
+ -----BEGIN CERTIFICATE-----
+ MIIFWzCCA0OgAwIBAgIQTfQrldHumzpMLrM7jRBd1jANBgkqhkiG9w0BAQsFADBm
+ MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
+ aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
+ ZWFyIFgxMB4XDTIwMDkwNDAwMDAwMFoXDTI1MDkxNTE2MDAwMFowWTELMAkGA1UE
+ BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSgwJgYDVQQD
+ Ex8oU1RBR0lORykgQXJ0aWZpY2lhbCBBcHJpY290IFIzMIIBIjANBgkqhkiG9w0B
+ AQEFAAOCAQ8AMIIBCgKCAQEAu6TR8+74b46mOE1FUwBrvxzEYLck3iasmKrcQkb+
+ gy/z9Jy7QNIAl0B9pVKp4YU76JwxF5DOZZhi7vK7SbCkK6FbHlyU5BiDYIxbbfvO
+ L/jVGqdsSjNaJQTg3C3XrJja/HA4WCFEMVoT2wDZm8ABC1N+IQe7Q6FEqc8NwmTS
+ nmmRQm4TQvr06DP+zgFK/MNubxWWDSbSKKTH5im5j2fZfg+j/tM1bGaczFWw8/lS
+ nukyn5J2L+NJYnclzkXoh9nMFnyPmVbfyDPOc4Y25aTzVoeBKXa/cZ5MM+WddjdL
+ biWvm19f1sYn1aRaAIrkppv7kkn83vcth8XCG39qC2ZvaQIDAQABo4IBEDCCAQww
+ DgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAS
+ BgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTecnpI3zHDplDfn4Uj31c3S10u
+ ZTAfBgNVHSMEGDAWgBS182Xy/rAKkh/7PH3zRKCsYyXDFDA2BggrBgEFBQcBAQQq
+ MCgwJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdGcteDEuaS5sZW5jci5vcmcvMCsGA1Ud
+ HwQkMCIwIKAeoByGGmh0dHA6Ly9zdGcteDEuYy5sZW5jci5vcmcvMCIGA1UdIAQb
+ MBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCN
+ DLam9yN0EFxxn/3p+ruWO6n/9goCAM5PT6cC6fkjMs4uas6UGXJjr5j7PoTQf3C1
+ vuxiIGRJC6qxV7yc6U0X+w0Mj85sHI5DnQVWN5+D1er7mp13JJA0xbAbHa3Rlczn
+ y2Q82XKui8WHuWra0gb2KLpfboYj1Ghgkhr3gau83pC/WQ8HfkwcvSwhIYqTqxoZ
+ Uq8HIf3M82qS9aKOZE0CEmSyR1zZqQxJUT7emOUapkUN9poJ9zGc+FgRZvdro0XB
+ yphWXDaqMYph0DxW/10ig5j4xmmNDjCRmqIKsKoWA52wBTKKXK1na2ty/lW5dhtA
+ xkz5rVZFd4sgS4J0O+zm6d5GRkWsNJ4knotGXl8vtS3X40KXeb3A5+/3p0qaD215
+ Xq8oSNORfB2oI1kQuyEAJ5xvPTdfwRlyRG3lFYodrRg6poUBD/8fNTXMtzydpRgy
+ zUQZh/18F6B/iW6cbiRN9r2Hkh05Om+q0/6w0DdZe+8YrNpfhSObr/1eVZbKGMIY
+ qKmyZbBNu5ysENIK5MPc14mUeKmFjpN840VR5zunoU52lqpLDua/qIM8idk86xGW
+ xx2ml43DO/Ya/tVZVok0mO0TUjzJIfPqyvr455IsIut4RlCR9Iq0EDTve2/ZwCuG
+ hSjpTUFGSiQrR2JK2Evp+o6AETUkBCO1aw0PpQBPDQ==
+ -----END CERTIFICATE-----
+ -----BEGIN CERTIFICATE-----
+ MIIFVDCCBDygAwIBAgIRAO1dW8lt+99NPs1qSY3Rs8cwDQYJKoZIhvcNAQELBQAw
+ cTELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1
+ cml0eSBSZXNlYXJjaCBHcm91cDEtMCsGA1UEAxMkKFNUQUdJTkcpIERvY3RvcmVk
+ IER1cmlhbiBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQw
+ M1owZjELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBT
+ ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEiMCAGA1UEAxMZKFNUQUdJTkcpIFByZXRl
+ bmQgUGVhciBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALbagEdD
+ Ta1QgGBWSYkyMhscZXENOBaVRTMX1hceJENgsL0Ma49D3MilI4KS38mtkmdF6cPW
+ nL++fgehT0FbRHZgjOEr8UAN4jH6omjrbTD++VZneTsMVaGamQmDdFl5g1gYaigk
+ kmx8OiCO68a4QXg4wSyn6iDipKP8utsE+x1E28SA75HOYqpdrk4HGxuULvlr03wZ
+ GTIf/oRt2/c+dYmDoaJhge+GOrLAEQByO7+8+vzOwpNAPEx6LW+crEEZ7eBXih6V
+ P19sTGy3yfqK5tPtTdXXCOQMKAp+gCj/VByhmIr+0iNDC540gtvV303WpcbwnkkL
+ YC0Ft2cYUyHtkstOfRcRO+K2cZozoSwVPyB8/J9RpcRK3jgnX9lujfwA/pAbP0J2
+ UPQFxmWFRQnFjaq6rkqbNEBgLy+kFL1NEsRbvFbKrRi5bYy2lNms2NJPZvdNQbT/
+ 2dBZKmJqxHkxCuOQFjhJQNeO+Njm1Z1iATS/3rts2yZlqXKsxQUzN6vNbD8KnXRM
+ EeOXUYvbV4lqfCf8mS14WEbSiMy87GB5S9ucSV1XUrlTG5UGcMSZOBcEUpisRPEm
+ QWUOTWIoDQ5FOia/GI+Ki523r2ruEmbmG37EBSBXdxIdndqrjy+QVAmCebyDx9eV
+ EGOIpn26bW5LKerumJxa/CFBaKi4bRvmdJRLAgMBAAGjgfEwge4wDgYDVR0PAQH/
+ BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLXzZfL+sAqSH/s8ffNE
+ oKxjJcMUMB8GA1UdIwQYMBaAFAhX2onHolN5DE/d4JCPdLriJ3NEMDgGCCsGAQUF
+ BwEBBCwwKjAoBggrBgEFBQcwAoYcaHR0cDovL3N0Zy1kc3QzLmkubGVuY3Iub3Jn
+ LzAtBgNVHR8EJjAkMCKgIKAehhxodHRwOi8vc3RnLWRzdDMuYy5sZW5jci5vcmcv
+ MCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEB
+ CwUAA4IBAQB7tR8B0eIQSS6MhP5kuvGth+dN02DsIhr0yJtk2ehIcPIqSxRRmHGl
+ 4u2c3QlvEpeRDp2w7eQdRTlI/WnNhY4JOofpMf2zwABgBWtAu0VooQcZZTpQruig
+ F/z6xYkBk3UHkjeqxzMN3d1EqGusxJoqgdTouZ5X5QTTIee9nQ3LEhWnRSXDx7Y0
+ ttR1BGfcdqHopO4IBqAhbkKRjF5zj7OD8cG35omywUbZtOJnftiI0nFcRaxbXo0v
+ oDfLD0S6+AC2R3tKpqjkNX6/91hrRFglUakyMcZU/xleqbv6+Lr3YD8PsBTub6lI
+ oZ2lS38fL18Aon458fbc0BPHtenfhKj5
+ -----END CERTIFICATE-----
+
+selfsigned_cert_config__default:
+ cert:
+ organization_name: "elev8"
+ organizational_unit_name: "ansible"
+ key_usage:
+ - digitalSignature
+ - keyAgreement
+ key_usage_critical: yes
+ extended_key_usage:
+ - serverAuth
+ extended_key_usage_critical: yes
+ create_subject_key_identifier: yes
+ not_after: +1000w
+
+
+static_cert_config__test:
+ key:
+ content: |
+ -----BEGIN RSA PRIVATE KEY-----
+ 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
+ -----END RSA PRIVATE KEY-----
+ cert:
+ content: |
+ -----BEGIN CERTIFICATE-----
+ MIIGaTCCBVGgAwIBAgITAPqbPyeH5GyeBBoPgHbVWlDC3TANBgkqhkiG9w0BAQsF
+ ADBZMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXKFNUQUdJTkcpIExldCdzIEVuY3J5
+ cHQxKDAmBgNVBAMTHyhTVEFHSU5HKSBBcnRpZmljaWFsIEFwcmljb3QgUjMwHhcN
+ MjMwODA5MTA1MzI3WhcNMjMxMTA3MTA1MzI2WjAfMR0wGwYDVQQDExR0ZXN0LnNw
+ cmVhZHNwYWNlLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL9h
+ y+Pe0DFWDV+/9P/nfvhfb6rQUUvBOab8nzoi9q/ShoKrdS9uSqT2DZC38L9YmzIj
+ KJS0Q/Pe1McjXfN0x3O4OAQ8BFX+RCmHhL6RdUV1IdgUEcivD7xenBvrabHxOd53
+ y0fpjA0JMcmuQhpbRBUWOnguiXzxOdeKGUc5weoImzr9LProYFZe4pYrGSQLUpUE
+ VrhAwarKdLhqFXq2JAHFyHQKUj0KKOw4Cr0fxLMW83wZWjqSkL3vTiF53Q1olNeP
+ 7sbeSaLiE7s8ZGUW3xmkZzZ6f6SNdPB6XZ2FBiuQmCB6HlEwv2JtrNDKTQX94fUp
+ 5snVD7x00lI1ubnlLDGNkaEZTv6D+1cOmNwsGoPKJige9DQeO8rxlttppeqOxS1m
+ LPY6YyagacH6mx5O8o9j/ZHtF5saFYEC+QPj2aLAlAd9ikOzlFgU+Yep580sF55G
+ MmVCs/HDAi2Lx2+TFsliwY9Hwcp/VzSAcwIvyMGfbXaiiithVlvybFV9nKx2qpCP
+ Ons/g8Yuoq3ElGrcudCXiLVd6PdhaMTIlXJJ0fcmeHk0tT9EbyiZ4ALmee4wb5nN
+ FRrA1nS/KaI6VTaWdTX161bZryicRxDDtAfHVZCp1L+56WlM5OhWw05wWclD307d
+ 8qLIs3UHssjmlzhnfCBXSDdS89bYj0MBS4uHjMzHAgMBAAGjggJiMIICXjAOBgNV
+ HQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1Ud
+ EwEB/wQCMAAwHQYDVR0OBBYEFDy0lODy9HEp1M4FdG/YUjBBnQ0IMB8GA1UdIwQY
+ MBaAFN5yekjfMcOmUN+fhSPfVzdLXS5lMF0GCCsGAQUFBwEBBFEwTzAlBggrBgEF
+ BQcwAYYZaHR0cDovL3N0Zy1yMy5vLmxlbmNyLm9yZzAmBggrBgEFBQcwAoYaaHR0
+ cDovL3N0Zy1yMy5pLmxlbmNyLm9yZy8wZQYDVR0RBF4wXIIUdGVzdC5zcHJlYWRz
+ cGFjZS5jb22CFHRlc3Quc3ByZWFkc3BhY2UubmV0ghR0ZXN0LnNwcmVhZHNwYWNl
+ Lm9yZ4IYdGVzdC5zcHJlYWRzcGFjZS5zeXN0ZW1zMBMGA1UdIAQMMAowCAYGZ4EM
+ AQIBMIIBAgYKKwYBBAHWeQIEAgSB8wSB8ADuAHUA7audHd2Dc5Wf9SqI5Gu0vMPE
+ zE12imDM/042LX+41mgAAAGJ2iUJgAAABAMARjBEAiB2GccK+Wwc6m2JIsJ4PbrC
+ Y+UXnoi9v0VPzir4bVYMGwIgIonr7RaEhjJ8QiEfkcBc0j6k0AzM3Ee9raoNKx4l
+ rKcAdQCwzIPlpfl9a698CcwoSQSHKsfoixMsY1C3xv0m4WxsdwAAAYnaJQtyAAAE
+ AwBGMEQCIHPBuvYBtUfsYU6WTMoa1IuCD2TeTGbCySEW/ZHlYtkEAiBzTQNkThq8
+ tpregOqi7ypchg9JFS/JzMfjjuDlBnFndjANBgkqhkiG9w0BAQsFAAOCAQEAlG32
+ KRc6Ln3AwhodYdDB9+SC8/vouCzaRTcgPVWYX/dZuXCvsWCGQ9bi9/VAWRgR0IuF
+ yibvGQ7dgL8cTDzfVvXdNa52VlgIxJ8Zag7CPSSHrmoOwH7j00t6mZveujmHpg4o
+ mtaiC3NHAXJopkNJjJYNKUSLYO8xULhaHrkbA8m9khdlTesraMQQyv80H/ohE3J2
+ qWKB/qO2EpmlbolIVbFWJPvo6oynn4ELrVJBDbWLMoDqGq8suIIeWbSZvkoqm9O2
+ AYroae5qP5GjB47gceH2SmQwqP69GKJimJhGhO3WDE/9PGSCUQB5vUGuK/wNmYrj
+ VWVPzMLHuAhSryY9Fw==
+ -----END CERTIFICATE-----
+ chain:
+ content: |
+ -----BEGIN CERTIFICATE-----
+ MIIFWzCCA0OgAwIBAgIQTfQrldHumzpMLrM7jRBd1jANBgkqhkiG9w0BAQsFADBm
+ MQswCQYDVQQGEwJVUzEzMDEGA1UEChMqKFNUQUdJTkcpIEludGVybmV0IFNlY3Vy
+ aXR5IFJlc2VhcmNoIEdyb3VwMSIwIAYDVQQDExkoU1RBR0lORykgUHJldGVuZCBQ
+ ZWFyIFgxMB4XDTIwMDkwNDAwMDAwMFoXDTI1MDkxNTE2MDAwMFowWTELMAkGA1UE
+ BhMCVVMxIDAeBgNVBAoTFyhTVEFHSU5HKSBMZXQncyBFbmNyeXB0MSgwJgYDVQQD
+ Ex8oU1RBR0lORykgQXJ0aWZpY2lhbCBBcHJpY290IFIzMIIBIjANBgkqhkiG9w0B
+ AQEFAAOCAQ8AMIIBCgKCAQEAu6TR8+74b46mOE1FUwBrvxzEYLck3iasmKrcQkb+
+ gy/z9Jy7QNIAl0B9pVKp4YU76JwxF5DOZZhi7vK7SbCkK6FbHlyU5BiDYIxbbfvO
+ L/jVGqdsSjNaJQTg3C3XrJja/HA4WCFEMVoT2wDZm8ABC1N+IQe7Q6FEqc8NwmTS
+ nmmRQm4TQvr06DP+zgFK/MNubxWWDSbSKKTH5im5j2fZfg+j/tM1bGaczFWw8/lS
+ nukyn5J2L+NJYnclzkXoh9nMFnyPmVbfyDPOc4Y25aTzVoeBKXa/cZ5MM+WddjdL
+ biWvm19f1sYn1aRaAIrkppv7kkn83vcth8XCG39qC2ZvaQIDAQABo4IBEDCCAQww
+ DgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAS
+ BgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTecnpI3zHDplDfn4Uj31c3S10u
+ ZTAfBgNVHSMEGDAWgBS182Xy/rAKkh/7PH3zRKCsYyXDFDA2BggrBgEFBQcBAQQq
+ MCgwJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdGcteDEuaS5sZW5jci5vcmcvMCsGA1Ud
+ HwQkMCIwIKAeoByGGmh0dHA6Ly9zdGcteDEuYy5sZW5jci5vcmcvMCIGA1UdIAQb
+ MBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCN
+ DLam9yN0EFxxn/3p+ruWO6n/9goCAM5PT6cC6fkjMs4uas6UGXJjr5j7PoTQf3C1
+ vuxiIGRJC6qxV7yc6U0X+w0Mj85sHI5DnQVWN5+D1er7mp13JJA0xbAbHa3Rlczn
+ y2Q82XKui8WHuWra0gb2KLpfboYj1Ghgkhr3gau83pC/WQ8HfkwcvSwhIYqTqxoZ
+ Uq8HIf3M82qS9aKOZE0CEmSyR1zZqQxJUT7emOUapkUN9poJ9zGc+FgRZvdro0XB
+ yphWXDaqMYph0DxW/10ig5j4xmmNDjCRmqIKsKoWA52wBTKKXK1na2ty/lW5dhtA
+ xkz5rVZFd4sgS4J0O+zm6d5GRkWsNJ4knotGXl8vtS3X40KXeb3A5+/3p0qaD215
+ Xq8oSNORfB2oI1kQuyEAJ5xvPTdfwRlyRG3lFYodrRg6poUBD/8fNTXMtzydpRgy
+ zUQZh/18F6B/iW6cbiRN9r2Hkh05Om+q0/6w0DdZe+8YrNpfhSObr/1eVZbKGMIY
+ qKmyZbBNu5ysENIK5MPc14mUeKmFjpN840VR5zunoU52lqpLDua/qIM8idk86xGW
+ xx2ml43DO/Ya/tVZVok0mO0TUjzJIfPqyvr455IsIut4RlCR9Iq0EDTve2/ZwCuG
+ hSjpTUFGSiQrR2JK2Evp+o6AETUkBCO1aw0PpQBPDQ==
+ -----END CERTIFICATE-----
+ -----BEGIN CERTIFICATE-----
+ MIIFVDCCBDygAwIBAgIRAO1dW8lt+99NPs1qSY3Rs8cwDQYJKoZIhvcNAQELBQAw
+ cTELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBTZWN1
+ cml0eSBSZXNlYXJjaCBHcm91cDEtMCsGA1UEAxMkKFNUQUdJTkcpIERvY3RvcmVk
+ IER1cmlhbiBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQw
+ M1owZjELMAkGA1UEBhMCVVMxMzAxBgNVBAoTKihTVEFHSU5HKSBJbnRlcm5ldCBT
+ ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEiMCAGA1UEAxMZKFNUQUdJTkcpIFByZXRl
+ bmQgUGVhciBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALbagEdD
+ Ta1QgGBWSYkyMhscZXENOBaVRTMX1hceJENgsL0Ma49D3MilI4KS38mtkmdF6cPW
+ nL++fgehT0FbRHZgjOEr8UAN4jH6omjrbTD++VZneTsMVaGamQmDdFl5g1gYaigk
+ kmx8OiCO68a4QXg4wSyn6iDipKP8utsE+x1E28SA75HOYqpdrk4HGxuULvlr03wZ
+ GTIf/oRt2/c+dYmDoaJhge+GOrLAEQByO7+8+vzOwpNAPEx6LW+crEEZ7eBXih6V
+ P19sTGy3yfqK5tPtTdXXCOQMKAp+gCj/VByhmIr+0iNDC540gtvV303WpcbwnkkL
+ YC0Ft2cYUyHtkstOfRcRO+K2cZozoSwVPyB8/J9RpcRK3jgnX9lujfwA/pAbP0J2
+ UPQFxmWFRQnFjaq6rkqbNEBgLy+kFL1NEsRbvFbKrRi5bYy2lNms2NJPZvdNQbT/
+ 2dBZKmJqxHkxCuOQFjhJQNeO+Njm1Z1iATS/3rts2yZlqXKsxQUzN6vNbD8KnXRM
+ EeOXUYvbV4lqfCf8mS14WEbSiMy87GB5S9ucSV1XUrlTG5UGcMSZOBcEUpisRPEm
+ QWUOTWIoDQ5FOia/GI+Ki523r2ruEmbmG37EBSBXdxIdndqrjy+QVAmCebyDx9eV
+ EGOIpn26bW5LKerumJxa/CFBaKi4bRvmdJRLAgMBAAGjgfEwge4wDgYDVR0PAQH/
+ BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLXzZfL+sAqSH/s8ffNE
+ oKxjJcMUMB8GA1UdIwQYMBaAFAhX2onHolN5DE/d4JCPdLriJ3NEMDgGCCsGAQUF
+ BwEBBCwwKjAoBggrBgEFBQcwAoYcaHR0cDovL3N0Zy1kc3QzLmkubGVuY3Iub3Jn
+ LzAtBgNVHR8EJjAkMCKgIKAehhxodHRwOi8vc3RnLWRzdDMuYy5sZW5jci5vcmcv
+ MCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQBgt8TAQEBMA0GCSqGSIb3DQEB
+ CwUAA4IBAQB7tR8B0eIQSS6MhP5kuvGth+dN02DsIhr0yJtk2ehIcPIqSxRRmHGl
+ 4u2c3QlvEpeRDp2w7eQdRTlI/WnNhY4JOofpMf2zwABgBWtAu0VooQcZZTpQruig
+ F/z6xYkBk3UHkjeqxzMN3d1EqGusxJoqgdTouZ5X5QTTIee9nQ3LEhWnRSXDx7Y0
+ ttR1BGfcdqHopO4IBqAhbkKRjF5zj7OD8cG35omywUbZtOJnftiI0nFcRaxbXo0v
+ oDfLD0S6+AC2R3tKpqjkNX6/91hrRFglUakyMcZU/xleqbv6+Lr3YD8PsBTub6lI
+ oZ2lS38fL18Aon458fbc0BPHtenfhKj5
+ -----END CERTIFICATE-----
+
+selfsigned_cert_config__test:
+ cert:
+ organization_name: "spreadspace"
+ organizational_unit_name: "ansible"
+ key_usage:
+ - digitalSignature
+ - keyAgreement
+ key_usage_critical: yes
+ extended_key_usage:
+ - serverAuth
+ extended_key_usage_critical: yes
+ create_subject_key_identifier: yes
+ not_after: +100w
diff --git a/inventory/host_vars/sk-tomnext-nc.yml b/inventory/host_vars/sk-tomnext-nc.yml
index 47447048..f8af167f 100644
--- a/inventory/host_vars/sk-tomnext-nc.yml
+++ b/inventory/host_vars/sk-tomnext-nc.yml
@@ -105,6 +105,7 @@ postfix_base_mynetworks:
acme_directory_server: "{{ acme_directory_server_le_live_v2 }}"
+acme_client: acmetool
nginx_server_names_hash_bucket_size: 64
diff --git a/inventory/hosts.ini b/inventory/hosts.ini
index e58673ce..6b8622db 100644
--- a/inventory/hosts.ini
+++ b/inventory/hosts.ini
@@ -611,6 +611,7 @@ glt-telesto
glt-tsdatacop
glt-thetys
sgg-icecast
+sk-testvm
[kubernetes:children]
kubernetes-cluster
diff --git a/roles/apps/bluespice/tasks/main.yml b/roles/apps/bluespice/tasks/main.yml
index 899d1e1d..49ef2418 100644
--- a/roles/apps/bluespice/tasks/main.yml
+++ b/roles/apps/bluespice/tasks/main.yml
@@ -49,7 +49,8 @@
nginx_vhost:
name: "bluespice-{{ item.key }}"
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames:
- "{{ item.value.hostname }}"
locations:
diff --git a/roles/apps/collabora/code/tasks/main.yml b/roles/apps/collabora/code/tasks/main.yml
index db28bb65..84efec5c 100644
--- a/roles/apps/collabora/code/tasks/main.yml
+++ b/roles/apps/collabora/code/tasks/main.yml
@@ -45,16 +45,8 @@
include_role:
name: kubernetes/standalone/pod
-- name: configure nginx vhost
+- name: install nginx vhost config
loop: "{{ collabora_code_instances | dict2items }}"
loop_control:
label: "{{ item.key }}"
- vars:
- nginx_vhost:
- name: "collabora-code-{{ item.key }}"
- content: "{{ lookup('template', 'nginx-vhost.conf.j2') }}"
- acme: true
- hostnames:
- - "{{ item.value.hostname }}"
- include_role:
- name: nginx/vhost
+ include_tasks: nginx-vhost.yml
diff --git a/roles/apps/collabora/code/tasks/nginx-vhost.yml b/roles/apps/collabora/code/tasks/nginx-vhost.yml
new file mode 100644
index 00000000..afd8f1e0
--- /dev/null
+++ b/roles/apps/collabora/code/tasks/nginx-vhost.yml
@@ -0,0 +1,17 @@
+---
+- name: render nginx-vhost custom config
+ set_fact:
+ collabora_code_nginx_vhost_custom: "{{ lookup('template', 'nginx-vhost.conf.j2') }}"
+
+- name: configure nginx vhost
+ vars:
+ nginx_vhost:
+ name: "collabora-code-{{ item.key }}"
+ template: generic
+ tls:
+ certificate_provider: "{{ acme_client }}"
+ hostnames:
+ - "{{ item.value.hostname }}"
+ custom: "{{ collabora_code_nginx_vhost_custom }}"
+ include_role:
+ name: nginx/vhost
diff --git a/roles/apps/collabora/code/templates/nginx-vhost.conf.j2 b/roles/apps/collabora/code/templates/nginx-vhost.conf.j2
index d56d77a0..67502e20 100644
--- a/roles/apps/collabora/code/templates/nginx-vhost.conf.j2
+++ b/roles/apps/collabora/code/templates/nginx-vhost.conf.j2
@@ -1,124 +1,99 @@
-server {
- listen 80;
- listen [::]:80;
- server_name {{ item.value.hostname }};
+client_max_body_size 128M;
- include snippets/acmetool.conf;
-
- location / {
- return 301 https://$host$request_uri;
- }
-}
-
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name {{ item.value.hostname }};
-
- include snippets/acmetool.conf;
- include snippets/tls.conf;
- ssl_certificate /var/lib/acme/live/{{ item.value.hostname }}/fullchain;
- ssl_certificate_key /var/lib/acme/live/{{ item.value.hostname }}/privkey;
- include snippets/hsts.conf;
-
-
- client_max_body_size 128M;
-
- # static files
+# static files
{% if item.value.version | collabora_code_loolvcool %}
- location ^~ /loleaflet {
+location ^~ /loleaflet {
{% else %}
- location ^~ /browser {
+location ^~ /browser {
{% endif %}
- include snippets/proxy-nobuff.conf;
- include snippets/proxy-forward-headers.conf;
+ include snippets/proxy-nobuff.conf;
+ include snippets/proxy-forward-headers.conf;
- proxy_set_header Host $http_host;
- proxy_pass http://127.0.0.1:{{ item.value.port }};
+ proxy_set_header Host $http_host;
+ proxy_pass http://127.0.0.1:{{ item.value.port }};
- proxy_redirect http://$host/ https://$host/;
- proxy_redirect http://$host:9980/ https://$host/;
- }
+ proxy_redirect http://$host/ https://$host/;
+ proxy_redirect http://$host:9980/ https://$host/;
+}
- # WOPI discovery URL
- location ^~ /hosting/discovery {
- include snippets/proxy-nobuff.conf;
- include snippets/proxy-forward-headers.conf;
+# WOPI discovery URL
+location ^~ /hosting/discovery {
+ include snippets/proxy-nobuff.conf;
+ include snippets/proxy-forward-headers.conf;
- proxy_set_header Host $http_host;
- proxy_pass http://127.0.0.1:{{ item.value.port }};
+ proxy_set_header Host $http_host;
+ proxy_pass http://127.0.0.1:{{ item.value.port }};
- proxy_redirect http://$host/ https://$host/;
- proxy_redirect http://$host:9980/ https://$host/;
- }
+ proxy_redirect http://$host/ https://$host/;
+ proxy_redirect http://$host:9980/ https://$host/;
+}
- # Capabilities
- location ^~ /hosting/capabilities {
- include snippets/proxy-nobuff.conf;
- include snippets/proxy-forward-headers.conf;
+# Capabilities
+location ^~ /hosting/capabilities {
+ include snippets/proxy-nobuff.conf;
+ include snippets/proxy-forward-headers.conf;
- proxy_set_header Host $http_host;
- proxy_pass http://127.0.0.1:{{ item.value.port }};
+ proxy_set_header Host $http_host;
+ proxy_pass http://127.0.0.1:{{ item.value.port }};
- proxy_redirect http://$host/ https://$host/;
- proxy_redirect http://$host:9980/ https://$host/;
- }
+ proxy_redirect http://$host/ https://$host/;
+ proxy_redirect http://$host:9980/ https://$host/;
+}
- # main websocket
+# main websocket
{% if item.value.version | collabora_code_loolvcool %}
- location ~ ^/lool/(.*)/ws$ {
+location ~ ^/lool/(.*)/ws$ {
{% else %}
- location ~ ^/cool/(.*)/ws$ {
+location ~ ^/cool/(.*)/ws$ {
{% endif %}
- include snippets/proxy-nobuff.conf;
- include snippets/proxy-forward-headers.conf;
+ include snippets/proxy-nobuff.conf;
+ include snippets/proxy-forward-headers.conf;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
- proxy_read_timeout 36000s;
+ proxy_read_timeout 36000s;
- proxy_set_header Host $http_host;
- proxy_pass http://127.0.0.1:{{ item.value.port }};
+ proxy_set_header Host $http_host;
+ proxy_pass http://127.0.0.1:{{ item.value.port }};
- proxy_redirect http://$host/ https://$host/;
- proxy_redirect http://$host:9980/ https://$host/;
- }
+ proxy_redirect http://$host/ https://$host/;
+ proxy_redirect http://$host:9980/ https://$host/;
+}
- # download, presentation and image upload
+# download, presentation and image upload
{% if item.value.version | collabora_code_loolvcool %}
- location ~ ^/lool {
+location ~ ^/lool {
{% else %}
- location ~ ^/(c|l)ool {
+location ~ ^/(c|l)ool {
{% endif %}
- include snippets/proxy-nobuff.conf;
- include snippets/proxy-forward-headers.conf;
+ include snippets/proxy-nobuff.conf;
+ include snippets/proxy-forward-headers.conf;
- proxy_set_header Host $http_host;
- proxy_pass http://127.0.0.1:{{ item.value.port }};
+ proxy_set_header Host $http_host;
+ proxy_pass http://127.0.0.1:{{ item.value.port }};
- proxy_redirect http://$host/ https://$host/;
- proxy_redirect http://$host:9980/ https://$host/;
- }
+ proxy_redirect http://$host/ https://$host/;
+ proxy_redirect http://$host:9980/ https://$host/;
+}
- # Admin Console websocket
+# Admin Console websocket
{% if item.value.version | collabora_code_loolvcool %}
- location ^~ /lool/adminws {
+location ^~ /lool/adminws {
{% else %}
- location ^~ /cool/adminws {
+location ^~ /cool/adminws {
{% endif %}
- include snippets/proxy-nobuff.conf;
- include snippets/proxy-forward-headers.conf;
+ include snippets/proxy-nobuff.conf;
+ include snippets/proxy-forward-headers.conf;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
- proxy_read_timeout 36000s;
+ proxy_read_timeout 36000s;
- proxy_set_header Host $http_host;
- proxy_pass http://127.0.0.1:{{ item.value.port }};
+ proxy_set_header Host $http_host;
+ proxy_pass http://127.0.0.1:{{ item.value.port }};
- proxy_redirect http://$host/ https://$host/;
- proxy_redirect http://$host:9980/ https://$host/;
- }
+ proxy_redirect http://$host/ https://$host/;
+ proxy_redirect http://$host:9980/ https://$host/;
}
diff --git a/roles/apps/coturn/defaults/main.yml b/roles/apps/coturn/defaults/main.yml
index 842e7f05..760a6499 100644
--- a/roles/apps/coturn/defaults/main.yml
+++ b/roles/apps/coturn/defaults/main.yml
@@ -3,7 +3,7 @@ coturn_uid: 930
coturn_gid: 930
coturn_base_path: /srv/coturn
-# coturn_version: 4.5.2-r2
+# coturn_version: 4.6.2-r4
# coturn_realm: example.com
# coturn_hostnames:
# - stun.example.com
@@ -17,6 +17,9 @@ coturn_threads: 0
coturn_dhparam_size: 2048
+# coturn_tls:
+# certificate_provider: ...
+
coturn_listening_port: 3478
coturn_tls_listening_port: 5349
diff --git a/roles/apps/coturn/tasks/main.yml b/roles/apps/coturn/tasks/main.yml
index 42ccd2b3..4e5adbd5 100644
--- a/roles/apps/coturn/tasks/main.yml
+++ b/roles/apps/coturn/tasks/main.yml
@@ -39,43 +39,52 @@
group: coturn
mode: 0644
-- name: install acmetool hook script
- template:
- src: acmetool-reload.sh.j2
- dest: "/etc/acme/hooks/coturn-{{ coturn_realm }}"
- mode: 0755
-
-- name: install acmetool systemd unit snippet
- copy:
- dest: "/etc/systemd/system/acmetool.service.d/coturn-{{ coturn_realm }}.conf"
- content: |
- [Service]
- ReadWritePaths={{ coturn_base_path }}/{{ coturn_realm }}/config/ssl
- register: coturn_acmetool_snippet
-
-- name: reload systemd
- when: coturn_acmetool_snippet is changed
- systemd:
- daemon_reload: yes
+- name: compute certificate renewal config
+ set_fact:
+ coturn_certificate_renewal:
+ install:
+ - dest: "{{ coturn_base_path }}/{{ coturn_realm }}/config/ssl/cert.pem"
+ src:
+ - fullchain
+ owner: root
+ group: coturn
+ mode: "0644"
+ - dest: "{{ coturn_base_path }}/{{ coturn_realm }}/config/ssl/privkey.pem"
+ src:
+ - key
+ owner: root
+ group: coturn
+ mode: "0640"
+ reload: |
+ pod_id=$(crictl pods -q --state ready --name "^coturn-{{ coturn_realm }}-{{ ansible_nodename }}$")
+ [ -n "$pod_id" ] || exit 42
+ container_id=$(crictl ps -q --name '^coturn$' -p "$pod_id")
+ [ -n "$container_id" ] || exit 42
+ crictl stop "$container_id"
- name: configure nginx vhost
when: coturn_install_nginx_vhost
vars:
nginx_vhost:
name: "coturn-{{ coturn_realm }}"
- content: "{{ lookup('template', 'nginx-vhost.conf.j2') }}"
- acme: true
+ template: generic
+ tls: "{{ coturn_tls }}"
hostnames: "{{ coturn_hostnames }}"
+ locations:
+ '/':
+ return: "404"
+ x509_certificate_renewal: "{{ coturn_certificate_renewal }}"
include_role:
name: nginx/vhost
-- name: get certificate using acmetool
+- name: generate/install/fetch TLS certificate
when: not coturn_install_nginx_vhost
- import_role:
- name: x509/acmetool/cert
vars:
- acmetool_cert_name: "coturn-{{ coturn_realm }}"
- acmetool_cert_hostnames: "{{ coturn_hostnames }}"
+ x509_certificate_name: "coturn-{{ coturn_realm }}"
+ x509_certificate_hostnames: "{{ coturn_hostnames }}"
+ x509_certificate_renewal: "{{ coturn_certificate_renewal }}"
+ include_role:
+ name: "x509/{{ coturn_tls.certificate_provider }}/cert"
- name: install pod manifest
vars:
diff --git a/roles/apps/coturn/templates/acmetool-reload.sh.j2 b/roles/apps/coturn/templates/acmetool-reload.sh.j2
deleted file mode 100644
index 08530583..00000000
--- a/roles/apps/coturn/templates/acmetool-reload.sh.j2
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-set -e
-EVENT_NAME="$1"
-[ "$EVENT_NAME" = "live-updated" ] || exit 42
-
-MAIN_HOSTNAME="{{ coturn_hostnames[0] }}"
-SSL_D="{{ coturn_base_path }}/{{ coturn_realm }}/config/ssl"
-
-while read name; do
- certdir="$ACME_STATE_DIR/live/$name"
- if [ -z "$name" -o ! -e "$certdir" ]; then
- continue
- fi
- if [ "$name" != "$MAIN_HOSTNAME" ]; then
- continue
- fi
-
- install -m 0644 -o root -g coturn "$certdir/fullchain" "$SSL_D/cert.pem"
- install -m 0640 -o root -g coturn "$certdir/privkey" "$SSL_D/privkey.pem"
-
- pod_id=$(crictl pods -q --state ready --name "^coturn-{{ coturn_realm }}-{{ ansible_nodename }}$")
- [ -n "$pod_id" ] || exit 42
- container_id=$(crictl ps -q --name '^coturn$' -p "$pod_id")
- [ -n "$container_id" ] || exit 42
- crictl stop "$container_id"
-
- break
-done
diff --git a/roles/apps/coturn/templates/nginx-vhost.conf.j2 b/roles/apps/coturn/templates/nginx-vhost.conf.j2
deleted file mode 100644
index 0639fbe1..00000000
--- a/roles/apps/coturn/templates/nginx-vhost.conf.j2
+++ /dev/null
@@ -1,27 +0,0 @@
-server {
- listen 80;
- listen [::]:80;
- server_name {{ coturn_hostnames | join(' ') }};
-
- include snippets/acmetool.conf;
-
- location / {
- return 301 https://$host$request_uri;
- }
-}
-
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name {{ coturn_hostnames | join(' ') }};
-
- include snippets/acmetool.conf;
- include snippets/tls.conf;
- ssl_certificate /var/lib/acme/live/{{ coturn_hostnames[0] }}/fullchain;
- ssl_certificate_key /var/lib/acme/live/{{ coturn_hostnames[0] }}/privkey;
- include snippets/hsts.conf;
-
- location / {
- return 404;
- }
-}
diff --git a/roles/apps/etherpad-lite/tasks/main.yml b/roles/apps/etherpad-lite/tasks/main.yml
index 072a6c09..a3b167a8 100644
--- a/roles/apps/etherpad-lite/tasks/main.yml
+++ b/roles/apps/etherpad-lite/tasks/main.yml
@@ -108,13 +108,8 @@
include_role:
name: kubernetes/standalone/pod
-- name: configure nginx vhost
+- name: install nginx vhost config
loop: "{{ etherpad_lite_instances | dict2items }}"
- vars:
- nginx_vhost:
- name: "etherpad-lite-{{ item.key }}"
- content: "{{ lookup('template', 'nginx-vhost.conf.j2') }}"
- acme: true
- hostnames: "{{ item.value.hostnames }}"
- include_role:
- name: nginx/vhost
+ loop_control:
+ label: "{{ item.key }}"
+ include_tasks: nginx-vhost.yml
diff --git a/roles/apps/etherpad-lite/tasks/nginx-vhost.yml b/roles/apps/etherpad-lite/tasks/nginx-vhost.yml
new file mode 100644
index 00000000..91c8b54d
--- /dev/null
+++ b/roles/apps/etherpad-lite/tasks/nginx-vhost.yml
@@ -0,0 +1,16 @@
+---
+- name: render nginx-vhost custom config
+ set_fact:
+ etherpad_lite_nginx_vhost_custom: "{{ lookup('template', 'nginx-vhost.conf.j2') }}"
+
+- name: configure nginx vhost
+ vars:
+ nginx_vhost:
+ name: "etherpad-lite-{{ item.key }}"
+ template: generic
+ tls:
+ certificate_provider: "{{ acme_client }}"
+ hostnames: "{{ item.value.hostnames }}"
+ custom: "{{ etherpad_lite_nginx_vhost_custom }}"
+ include_role:
+ name: nginx/vhost
diff --git a/roles/apps/etherpad-lite/templates/nginx-vhost.conf.j2 b/roles/apps/etherpad-lite/templates/nginx-vhost.conf.j2
index b59701fc..209a81c0 100644
--- a/roles/apps/etherpad-lite/templates/nginx-vhost.conf.j2
+++ b/roles/apps/etherpad-lite/templates/nginx-vhost.conf.j2
@@ -1,57 +1,33 @@
-server {
- listen 80;
- listen [::]:80;
- server_name {{ item.value.hostnames | join(' ') }};
-
- include snippets/acmetool.conf;
-
- location / {
- return 301 https://$host$request_uri;
- }
-}
-
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name {{ item.value.hostnames | join(' ') }};
-
- include snippets/acmetool.conf;
- include snippets/tls.conf;
- ssl_certificate /var/lib/acme/live/{{ item.value.hostnames[0] }}/fullchain;
- ssl_certificate_key /var/lib/acme/live/{{ item.value.hostnames[0] }}/privkey;
- include snippets/hsts.conf;
-
- location / {
- rewrite ^/$ / break;
- rewrite ^/locales/(.*) /locales/$1 break;
- rewrite ^/locales.json /locales.json break;
- rewrite ^/admin(.*) /admin$1 break;
- rewrite ^/p/(.*) /p/$1 break;
- rewrite ^/static/(.*) /static/$1 break;
- rewrite ^/pluginfw/(.*) /pluginfw/$1 break;
- rewrite ^/javascripts/(.*) /javascripts/$1 break;
- rewrite ^/socket.io/(.*) /socket.io/$1 break;
- rewrite ^/ep/(.*) /ep/$1 break;
- rewrite ^/minified/(.*) /minified/$1 break;
- rewrite ^/api/(.*) /api/$1 break;
- rewrite ^/ro/(.*) /ro/$1 break;
- rewrite ^/error/(.*) /error/$1 break;
- rewrite ^/jserror(.*) /jserror$1 break;
- rewrite ^/redirect(.*) /redirect$1 break;
- rewrite /favicon.ico /favicon.ico break;
- rewrite /robots.txt /robots.txt break;
- rewrite /(.*) /p/$1;
-
- include snippets/proxy-nobuff.conf;
-
- proxy_set_header Host $host;
- include snippets/proxy-forward-headers.conf;
- proxy_pass_header Server;
-
- # for websockets
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection $connection_upgrade;
-
- proxy_pass http://127.0.0.1:{{ item.value.port }};
- }
+location / {
+ rewrite ^/$ / break;
+ rewrite ^/locales/(.*) /locales/$1 break;
+ rewrite ^/locales.json /locales.json break;
+ rewrite ^/admin(.*) /admin$1 break;
+ rewrite ^/p/(.*) /p/$1 break;
+ rewrite ^/static/(.*) /static/$1 break;
+ rewrite ^/pluginfw/(.*) /pluginfw/$1 break;
+ rewrite ^/javascripts/(.*) /javascripts/$1 break;
+ rewrite ^/socket.io/(.*) /socket.io/$1 break;
+ rewrite ^/ep/(.*) /ep/$1 break;
+ rewrite ^/minified/(.*) /minified/$1 break;
+ rewrite ^/api/(.*) /api/$1 break;
+ rewrite ^/ro/(.*) /ro/$1 break;
+ rewrite ^/error/(.*) /error/$1 break;
+ rewrite ^/jserror(.*) /jserror$1 break;
+ rewrite ^/redirect(.*) /redirect$1 break;
+ rewrite /favicon.ico /favicon.ico break;
+ rewrite /robots.txt /robots.txt break;
+ rewrite /(.*) /p/$1;
+
+ include snippets/proxy-nobuff.conf;
+
+ proxy_set_header Host $host;
+ include snippets/proxy-forward-headers.conf;
+ proxy_pass_header Server;
+
+ # for websockets
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+
+ proxy_pass http://127.0.0.1:{{ item.value.port }};
}
diff --git a/roles/apps/jitsi/meet/tasks/main.yml b/roles/apps/jitsi/meet/tasks/main.yml
index eff8232b..1d55fc78 100644
--- a/roles/apps/jitsi/meet/tasks/main.yml
+++ b/roles/apps/jitsi/meet/tasks/main.yml
@@ -151,7 +151,8 @@
nginx_vhost:
name: "jitsi-meet-{{ jitsi_meet_inst_name }}"
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames:
- "{{ jitsi_meet_hostname }}"
locations: "{{ nginx_vhost_locations_base | combine(nginx_vhost_locations_streamui) }}"
diff --git a/roles/apps/keycloak/tasks/main.yml b/roles/apps/keycloak/tasks/main.yml
index 68806458..c3e93666 100644
--- a/roles/apps/keycloak/tasks/main.yml
+++ b/roles/apps/keycloak/tasks/main.yml
@@ -96,7 +96,8 @@
nginx_vhost:
name: "keycloak-{{ item.key }}"
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames:
- "{{ item.value.hostname }}"
locations:
diff --git a/roles/apps/mumble/defaults/main.yml b/roles/apps/mumble/defaults/main.yml
index 627af125..c9cd9db3 100644
--- a/roles/apps/mumble/defaults/main.yml
+++ b/roles/apps/mumble/defaults/main.yml
@@ -14,6 +14,9 @@ mumble_dhparam_size: 2048
mumble_timezone: "Europe/Vienna"
+# mumble_tls:
+# certificate_provider: ...
+
mumble_config_options:
bonjour: false
sslCiphers: "ECDHE+AESGCM:DHE+AESGCM:ECDHE+AES256:DHE+AES256:ECDHE+AES128:DHE+AES128:!RSA:!ADH:!AECDH:!MD5"
diff --git a/roles/apps/mumble/tasks/main.yml b/roles/apps/mumble/tasks/main.yml
index 33331dca..5b380725 100644
--- a/roles/apps/mumble/tasks/main.yml
+++ b/roles/apps/mumble/tasks/main.yml
@@ -27,31 +27,32 @@
group: mumble
mode: 0644
-- name: install acmetool hook script
- template:
- src: acmetool-reload.sh.j2
- dest: "/etc/acme/hooks/mumble-{{ mumble_instance }}"
- mode: 0755
-
-- name: install acmetool systemd unit snippet
- copy:
- dest: "/etc/systemd/system/acmetool.service.d/mumble-{{ mumble_instance }}.conf"
- content: |
- [Service]
- ReadWritePaths={{ mumble_base_path }}/{{ mumble_instance }}/ssl
- register: mumble_acmetool_snippet
-
-- name: reload systemd
- when: mumble_acmetool_snippet is changed
- systemd:
- daemon_reload: yes
-
-- name: get certificate using acmetool
- import_role:
- name: x509/acmetool/cert
+- name: generate/install/fetch TLS certificate
vars:
- acmetool_cert_name: "mumble-{{ mumble_instance }}"
- acmetool_cert_hostnames: "{{ mumble_hostnames }}"
+ x509_certificate_name: "mumble-{{ mumble_instance }}"
+ x509_certificate_hostnames: "{{ mumble_hostnames }}"
+ x509_certificate_renewal:
+ install:
+ - dest: "{{ mumble_base_path }}/{{ mumble_instance }}/ssl/cert.pem"
+ src:
+ - fullchain
+ owner: root
+ group: mumble
+ mode: "0644"
+ - dest: "{{ mumble_base_path }}/{{ mumble_instance }}/ssl/privkey.pem"
+ src:
+ - key
+ owner: root
+ group: mumble
+ mode: "0640"
+ reload: |
+ pod_id=$(crictl pods -q --state ready --name "^mumble-{{ mumble_instance }}-{{ ansible_nodename }}$")
+ [ -n "$pod_id" ] || exit 42
+ container_id=$(crictl ps -q --name '^mumble$' -p "$pod_id")
+ [ -n "$container_id" ] || exit 42
+ crictl exec "$container_id" kill -USR1 1
+ include_role:
+ name: "x509/{{ mumble_tls.certificate_provider }}/cert"
- name: create mumble data directory
file:
diff --git a/roles/apps/mumble/templates/acmetool-reload.sh.j2 b/roles/apps/mumble/templates/acmetool-reload.sh.j2
deleted file mode 100644
index fd9f01ba..00000000
--- a/roles/apps/mumble/templates/acmetool-reload.sh.j2
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-set -e
-EVENT_NAME="$1"
-[ "$EVENT_NAME" = "live-updated" ] || exit 42
-
-MAIN_HOSTNAME="{{ mumble_hostnames[0] }}"
-SSL_D="{{ mumble_base_path }}/{{ mumble_instance }}/ssl"
-
-while read name; do
- certdir="$ACME_STATE_DIR/live/$name"
- if [ -z "$name" -o ! -e "$certdir" ]; then
- continue
- fi
- if [ "$name" != "$MAIN_HOSTNAME" ]; then
- continue
- fi
-
- install -m 0644 -o root -g mumble "$certdir/fullchain" "$SSL_D/cert.pem"
- install -m 0640 -o root -g mumble "$certdir/privkey" "$SSL_D/privkey.pem"
-
- pod_id=$(crictl pods -q --state ready --name "^mumble-{{ mumble_instance }}-{{ ansible_nodename }}$")
- [ -n "$pod_id" ] || exit 42
- container_id=$(crictl ps -q --name '^mumble$' -p "$pod_id")
- [ -n "$container_id" ] || exit 42
- crictl exec "$container_id" kill -USR1 1
-
- break
-done
diff --git a/roles/apps/nextcloud/tasks/main.yml b/roles/apps/nextcloud/tasks/main.yml
index 29ab9c39..c9a9061c 100644
--- a/roles/apps/nextcloud/tasks/main.yml
+++ b/roles/apps/nextcloud/tasks/main.yml
@@ -160,7 +160,8 @@
nginx_vhost:
name: "nextcloud-{{ item.key }}"
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames: "{{ item.value.hostnames }}"
locations:
'/':
diff --git a/roles/apps/onlyoffice/tasks/main.yml b/roles/apps/onlyoffice/tasks/main.yml
index 957d8afe..960e811b 100644
--- a/roles/apps/onlyoffice/tasks/main.yml
+++ b/roles/apps/onlyoffice/tasks/main.yml
@@ -140,7 +140,8 @@
nginx_vhost:
name: "onlyoffice-{{ item.key }}"
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames:
- "{{ item.value.hostname }}"
locations:
diff --git a/roles/apps/pigallery2/tasks/main.yml b/roles/apps/pigallery2/tasks/main.yml
index b8b0166d..2a758da1 100644
--- a/roles/apps/pigallery2/tasks/main.yml
+++ b/roles/apps/pigallery2/tasks/main.yml
@@ -67,7 +67,8 @@
nginx_vhost:
name: "pigallery2-{{ item.key }}"
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames:
- "{{ item.value.hostname }}"
locations:
diff --git a/roles/apps/wikijs/tasks/main.yml b/roles/apps/wikijs/tasks/main.yml
index e2b03d24..10b0aa54 100644
--- a/roles/apps/wikijs/tasks/main.yml
+++ b/roles/apps/wikijs/tasks/main.yml
@@ -73,7 +73,8 @@
nginx_vhost:
name: "wikijs-{{ item.key }}"
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames:
- "{{ item.value.hostname }}"
locations:
diff --git a/roles/elevate/liquidtruth/tasks/main.yml b/roles/elevate/liquidtruth/tasks/main.yml
index 837d2fd0..9f1ef3ad 100644
--- a/roles/elevate/liquidtruth/tasks/main.yml
+++ b/roles/elevate/liquidtruth/tasks/main.yml
@@ -12,17 +12,18 @@
import_tasks: nodejs.yml
- name: configure nginx vhost
- import_role:
- name: nginx/vhost
vars:
nginx_vhost:
name: liquidtruth
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames: "{{ liquidtruth_hostnames }}"
locations:
'/':
proxy_pass: "http://127.0.0.1:8080"
+ include_role:
+ name: nginx/vhost
- name: create app user
user:
diff --git a/roles/elevate/media/tasks/nextcloud-app.yml b/roles/elevate/media/tasks/nextcloud-app.yml
index 2e533ec6..42a351e4 100644
--- a/roles/elevate/media/tasks/nextcloud-app.yml
+++ b/roles/elevate/media/tasks/nextcloud-app.yml
@@ -102,7 +102,8 @@
nginx_vhost:
name: "nextcloud-{{ elevate_media_nextcloud_instance_name }}"
template: generic
- acme: true
+ tls:
+ certificate_provider: "{{ acme_client }}"
hostnames: "{{ elevate_media_nextcloud_instance.hostnames }}"
locations:
'/':
diff --git a/roles/gitolite/base/defaults/main.yml b/roles/gitolite/base/defaults/main.yml
index 1c5962cc..3c2e8fa3 100644
--- a/roles/gitolite/base/defaults/main.yml
+++ b/roles/gitolite/base/defaults/main.yml
@@ -15,3 +15,5 @@ gitolite_base_path: /srv/git
# title: cgit root title
# description: this will be shown by cgit below the title
# logo: path/to/logo/file/on/ansible/controller.png
+# tls:
+# certificate_provider: "{{ acme_client }}"
diff --git a/roles/gitolite/http/tasks/main.yml b/roles/gitolite/http/tasks/main.yml
index a3055902..ee5b226c 100644
--- a/roles/gitolite/http/tasks/main.yml
+++ b/roles/gitolite/http/tasks/main.yml
@@ -50,12 +50,59 @@
src: "{{ gitolite_instances[gitolite_instance].http.logo }}"
dest: "/usr/local/share/cgit/{{ gitolite_instance }}.png"
+ - name: compute nginx location directive for logo
+ set_fact:
+ nginx_locations_logo:
+ '= /logo.png':
+ alias: "/usr/local/share/cgit/{{ gitolite_instance }}.png"
+
+- name: compute nginx locations directives
+ set_fact:
+ nginx_locations_base:
+ '= /':
+ return: "303 /cgit/"
+ '/cgit-css/':
+ alias: "/usr/share/cgit/"
+ nginx_locations_main:
+ '/cgit/':
+ custom: |-
+ include fastcgi_params;
+ fastcgi_split_path_info ^(/cgit)(.*)$;
+
+ fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ fastcgi_param QUERY_STRING $args;
+ fastcgi_param HTTP_HOST $server_name;
+ fastcgi_param CGIT_CONFIG {{ gitolite_base_path }}/{{ gitolite_instance }}/cgitrc;
+
+ fastcgi_pass unix:/run/fcgiwrap/gitolite-{{ gitolite_instance }}.sock;
+
+- name: compute nginx location directive for git_backend
+ when: "'enable_git_backend' in gitolite_instances[gitolite_instance].http and gitolite_instances[gitolite_instance].http.enable_git_backend"
+ set_fact:
+ nginx_locations_git_backend:
+ '~ ^.*/git-receive-pack$':
+ return: "403"
+ '~ ^.*/(HEAD|info/refs|objects/(info/.*|[0-9a-f]+/[0-9a-f]+|pack/pack-[0-9a-f]+.(pack|idx))|git-upload-pack)$':
+ custom: |-
+ include fastcgi_params;
+
+ fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
+ fastcgi_param PATH_INFO $uri;
+ fastcgi_param GIT_PROJECT_ROOT {{ gitolite_base_path }}/{{ gitolite_instance }}/repositories;
+
+ fastcgi_pass unix:/run/fcgiwrap/gitolite-{{ gitolite_instance }}.sock;
+
- name: install nginx vhost
vars:
nginx_vhost:
name: "gitolite-{{ gitolite_instance }}"
- acme: true
+ template: generic
+ tls: "{{ gitolite_instances[gitolite_instance].http.tls }}"
hostnames: "{{ gitolite_instances[gitolite_instance].http.hostnames }}"
- content: "{{ lookup('template', 'nginx-vhost.conf.j2') }}"
+ logs:
+ access: "/var/log/nginx/git-{{ gitolite_instance }}_access.log"
+ error: "/var/log/nginx/git-{{ gitolite_instance }}_error.log"
+ locations: "{{ nginx_locations_base | combine(nginx_locations_logo | default({})) | combine(nginx_locations_main) | combine(nginx_locations_git_backend | default({})) }}"
include_role:
name: nginx/vhost
diff --git a/roles/gitolite/http/templates/nginx-vhost.conf.j2 b/roles/gitolite/http/templates/nginx-vhost.conf.j2
deleted file mode 100644
index add7a719..00000000
--- a/roles/gitolite/http/templates/nginx-vhost.conf.j2
+++ /dev/null
@@ -1,72 +0,0 @@
- server {
- listen 80;
- listen [::]:80;
- server_name {{ gitolite_instances[gitolite_instance].http.hostnames | join(' ') }};
-
- access_log /var/log/nginx/git-{{ gitolite_instance }}_access.log;
- error_log /var/log/nginx/git-{{ gitolite_instance }}_error.log;
-
- include snippets/acmetool.conf;
-
- location / {
- return 301 https://$host$request_uri;
- }
-}
-
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name {{ gitolite_instances[gitolite_instance].http.hostnames | join(' ') }};
-
- access_log /var/log/nginx/git-{{ gitolite_instance }}_access.log;
- error_log /var/log/nginx/git-{{ gitolite_instance }}_error.log;
-
- include snippets/acmetool.conf;
- include snippets/tls.conf;
- ssl_certificate /var/lib/acme/live/{{ gitolite_instances[gitolite_instance].http.hostnames[0] }}/fullchain;
- ssl_certificate_key /var/lib/acme/live/{{ gitolite_instances[gitolite_instance].http.hostnames[0] }}/privkey;
- include snippets/hsts.conf;
-
- location = / {
- return 303 /cgit/;
- }
-
- location /cgit-css/ {
- alias /usr/share/cgit/;
- }
-{% if 'logo' in gitolite_instances[gitolite_instance].http %}
-
- location = /logo.png {
- alias /usr/local/share/cgit/{{ gitolite_instance }}.png;
- }
-{% endif %}
-
- location /cgit/ {
- include fastcgi_params;
- fastcgi_split_path_info ^(/cgit)(.*)$;
-
- fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
- fastcgi_param PATH_INFO $fastcgi_path_info;
- fastcgi_param QUERY_STRING $args;
- fastcgi_param HTTP_HOST $server_name;
- fastcgi_param CGIT_CONFIG {{ gitolite_base_path }}/{{ gitolite_instance }}/cgitrc;
-
- fastcgi_pass unix:/run/fcgiwrap/gitolite-{{ gitolite_instance }}.sock;
- }
-{% if 'enable_git_backend' in gitolite_instances[gitolite_instance].http and gitolite_instances[gitolite_instance].http.enable_git_backend %}
-
- location ~ ^.*/git-receive-pack$ {
- return 403;
- }
-
- location ~ ^.*/(HEAD|info/refs|objects/(info/.*|[0-9a-f]+/[0-9a-f]+|pack/pack-[0-9a-f]+.(pack|idx))|git-upload-pack)$ {
- include fastcgi_params;
-
- fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
- fastcgi_param PATH_INFO $uri;
- fastcgi_param GIT_PROJECT_ROOT {{ gitolite_base_path }}/{{ gitolite_instance }}/repositories;
-
- fastcgi_pass unix:/run/fcgiwrap/gitolite-{{ gitolite_instance }}.sock;
- }
-{% endif %}
-}
diff --git a/roles/monitoring/graphite/web/tasks/main.yml b/roles/monitoring/graphite/web/tasks/main.yml
index 7c796722..e450fac4 100644
--- a/roles/monitoring/graphite/web/tasks/main.yml
+++ b/roles/monitoring/graphite/web/tasks/main.yml
@@ -41,10 +41,14 @@
include_role:
name: uwsgi/app
+- name: render nginx-vhost config template
+ set_fact:
+ graphite_web_nginx_vhost_content: "{{ lookup('template', 'nginx-vhost.conf.j2') }}"
+
- name: install nginx vhost
vars:
nginx_vhost:
name: graphite
- content: "{{ lookup('template', 'nginx-vhost.conf.j2') }}"
+ content: "{{ graphite_web_nginx_vhost_content }}"
include_role:
name: nginx/vhost
diff --git a/roles/monitoring/landingpage/defaults/main.yml b/roles/monitoring/landingpage/defaults/main.yml
index ad2a3895..8cdaba86 100644
--- a/roles/monitoring/landingpage/defaults/main.yml
+++ b/roles/monitoring/landingpage/defaults/main.yml
@@ -2,6 +2,12 @@
# monitoring_landingpage_hostnames:
# - "mon.example.com"
-monitoring_landingpage_acme: no
+# monitoring_landingpage_tls:
+# certificate_provider: "{{ acme_client }}"
#monitoring_landingpage_title: "Example Monitoring Host"
+
+monitoring_landingpage_services:
+ - prometheus
+ - alertmanager
+ - grafana
diff --git a/roles/monitoring/landingpage/tasks/main.yml b/roles/monitoring/landingpage/tasks/main.yml
index 3158770b..85543294 100644
--- a/roles/monitoring/landingpage/tasks/main.yml
+++ b/roles/monitoring/landingpage/tasks/main.yml
@@ -9,21 +9,37 @@
src: index.html.j2
dest: "/var/www/landingpage/index.html"
-- name: configure nginx vhost
+- name: compute nginx vhost config
vars:
- nginx_vhost:
+ monitoring_landingpage_vhost_base:
name: landingpage
template: generic
hostnames: "{{ monitoring_landingpage_hostnames }}"
- acme: "{{ monitoring_landingpage_acme }}"
locations:
'/':
root: /var/www/landingpage
+ monitoring_landingpage_vhost_override__yaml: |
+ {% if monitoring_landingpage_tls is defined %}
+ tls: "{{ monitoring_landingpage_tls }}"
+ {% endif %}
+ locations:
+ {% if 'prometheus' in monitoring_landingpage_services %}
'/prometheus/':
proxy_pass: "http://{{ prometheus_server_web_listen_address | default('127.0.0.1:9090') }}"
+ {% endif %}
+ {% if 'alertmanager' in monitoring_landingpage_services %}
'/alertmanager/':
proxy_pass: "http://{{ prometheus_alertmanager_web_listen_address | default('127.0.0.1:9093') }}"
+ {% endif %}
+ {% if 'grafana' in monitoring_landingpage_services %}
'/grafana/':
proxy_pass: "http://{{ grafana_config_server.http_addr | default('localhost') }}:{{ grafana_config_server.http_port | default(3000) }}"
+ {% endif %}
+ set_fact:
+ monitoring_landingpage_vhost: "{{ monitoring_landingpage_vhost_base | combine(monitoring_landingpage_vhost_override__yaml | from_yaml, recursive=True) }}"
+
+- name: configure nginx vhost
+ vars:
+ nginx_vhost: "{{ monitoring_landingpage_vhost }}"
include_role:
name: nginx/vhost
diff --git a/roles/monitoring/landingpage/templates/index.html.j2 b/roles/monitoring/landingpage/templates/index.html.j2
index a340f1db..a9bb8aca 100644
--- a/roles/monitoring/landingpage/templates/index.html.j2
+++ b/roles/monitoring/landingpage/templates/index.html.j2
@@ -8,9 +8,15 @@
<div style="text-align:center; margin-left:auto; margin-right:auto;">
<h1>{{ monitoring_landingpage_title }}</h1>
<ul style="list-style-type: none;">
+{% if 'prometheus' in monitoring_landingpage_services %}
<li><a target='_blank' href='/prometheus/'>Prometheus</a></li>
+{% endif %}
+{% if 'alertmanager' in monitoring_landingpage_services %}
<li><a target='_blank' href='/alertmanager/'>Prometheus Alertmanager</a></li>
+{% endif %}
+{% if 'grafana' in monitoring_landingpage_services %}
<li><a target='_blank' href='/grafana/'>Grafana</a></li>
+{% endif %}
</ul>
</div>
</body>
diff --git a/roles/monitoring/prometheus/exporter/base/tasks/main.yml b/roles/monitoring/prometheus/exporter/base/tasks/main.yml
index c69c6e05..235b7241 100644
--- a/roles/monitoring/prometheus/exporter/base/tasks/main.yml
+++ b/roles/monitoring/prometheus/exporter/base/tasks/main.yml
@@ -21,10 +21,14 @@
- name: create TLS certificate and key
import_tasks: tls.yml
+- name: render nginx-vhost config template
+ set_fact:
+ prometheus_exporter_nginx_vhost_content: "{{ lookup('template', 'nginx-vhost.j2') }}"
+
- name: configure nginx vhost
- import_role:
- name: nginx/vhost
vars:
nginx_vhost:
name: prometheus-exporter
- content: "{{ lookup('template', 'nginx-vhost.j2') }}"
+ content: "{{ prometheus_exporter_nginx_vhost_content }}"
+ include_role:
+ name: nginx/vhost
diff --git a/roles/nginx/vhost/defaults/main.yml b/roles/nginx/vhost/defaults/main.yml
index b80a5442..0eb67b42 100644
--- a/roles/nginx/vhost/defaults/main.yml
+++ b/roles/nginx/vhost/defaults/main.yml
@@ -3,10 +3,14 @@
# default: yes
# name: example
# template: generic
-# acme: yes
+# tls:
+# certificate_provider: acmetool
# hostnames:
# - example.com
# - www.example.com
+# logs:
+# access: /var/log/nginx/example_access.log
+# error: /var/log/nginx/example_error.log
# extra_directives: |-
# add_header X-Example-Header "foo";
# locations:
@@ -26,7 +30,10 @@
# nginx_vhost:
# name: mixed-static-and-proxy
# template: generic
-# acme: yes
+# tls:
+# variant: legacy
+# hsts: false
+# certificate_provider: acmetool
# hostnames:
# - static.example.com
# extra_directives: |-
@@ -41,8 +48,30 @@
# add_header X-Example-Header "foo";
# '/subdir/':
# alias: /srv/www/foo
+# '/private/':
+# return: "403"
# '/foo/':
# proxy_pass: http://127.0.0.1:1234
+# '/custom/':
+# custom: |-
+# include fastcgi_params;
+# fastcgi_param SCRIPT_FILENAME /usr/lib/cgi/foo
+# fastcgi_param PATH_INFO $uri;
+# fastcgi_pass unix:/run/fcgiwrap/foo.sock;
+
+# nginx_vhost:
+# name: example-custom
+# template: generic
+# tls:
+# variant: legacy
+# hsts: false
+# certificate_provider: acmetool
+# hostnames:
+# - static.example.com
+# custom: |-
+# location / {
+# foo "bar";
+# }
# nginx_vhost:
# name: other-example
diff --git a/roles/nginx/vhost/tasks/acme.yml b/roles/nginx/vhost/tasks/acme.yml
deleted file mode 100644
index 8a6cddb7..00000000
--- a/roles/nginx/vhost/tasks/acme.yml
+++ /dev/null
@@ -1,44 +0,0 @@
----
-- name: check if acme certs already exist
- loop: "{{ nginx_vhost.hostnames }}"
- loop_control:
- loop_var: acme_hostname
- stat:
- path: "/var/lib/acme/live/{{ acme_hostname }}"
- register: acme_cert_stat
-
-- name: set acmecert_missing_hostnames variable
- set_fact:
- acmecert_missing_hostnames: "{{ acme_cert_stat.results | acme_cert_nonexistent(nginx_vhost.hostnames) }}"
-
-- name: link nonexistent hostnames to self-signed interim cert
- when: acmecert_missing_hostnames | length > 0
- block:
- - name: get id of existing selfsigned interim certificate
- command: cat /var/lib/acme/.selfsigned-interim-cert
- changed_when: false
- check_mode: false
- register: selfsigned_interim_cert_id
-
- - name: set selfsigned_interim_cert_id variable
- set_fact:
- selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"
-
- - name: link to snakeoil cert for nonexistent hostnames
- loop: "{{ acmecert_missing_hostnames }}"
- loop_control:
- loop_var: acme_missing_hostname
- file:
- src: "../certs/{{ selfsigned_interim_cert_id }}"
- dest: "/var/lib/acme/live/{{ acme_missing_hostname }}"
- state: link
-
-- name: make sure nginx config has been (re)loaded
- meta: flush_handlers
-
-- name: get certificate using acmetool
- import_role:
- name: x509/acmetool/cert
- vars:
- acmetool_cert_name: "{{ nginx_vhost.name }}"
- acmetool_cert_hostnames: "{{ nginx_vhost.hostnames }}"
diff --git a/roles/nginx/vhost/tasks/main.yml b/roles/nginx/vhost/tasks/main.yml
index 1b5e3392..2c1f0f29 100644
--- a/roles/nginx/vhost/tasks/main.yml
+++ b/roles/nginx/vhost/tasks/main.yml
@@ -1,4 +1,15 @@
---
+- name: ensure certificate exists (fake it, until you make it)
+ when: "'tls' in nginx_vhost"
+ vars:
+ x509_certificate_name: "{{ nginx_vhost.name }}"
+ x509_certificate_hostnames: "{{ nginx_vhost.hostnames }}"
+ x509_certificate_reload_services:
+ - nginx
+ include_role:
+ name: "x509/{{ nginx_vhost.tls.certificate_provider }}/cert/prepare"
+ public: true
+
- name: install nginx configs from template
when: "'template' in nginx_vhost"
template:
@@ -23,5 +34,16 @@
notify: reload nginx
- name: generate acme certificate
- when: "'acme' in nginx_vhost and nginx_vhost.acme"
- include_tasks: acme.yml
+ when: "'tls' in nginx_vhost"
+ block:
+ - name: make sure nginx config has been (re)loaded
+ meta: flush_handlers
+
+ - name: actually request the certificate
+ vars:
+ x509_certificate_name: "{{ nginx_vhost.name }}"
+ x509_certificate_hostnames: "{{ nginx_vhost.hostnames }}"
+ x509_certificate_reload_services:
+ - nginx
+ include_role:
+ name: "x509/{{ nginx_vhost.tls.certificate_provider }}/cert/finalize"
diff --git a/roles/nginx/vhost/templates/generic.conf.j2 b/roles/nginx/vhost/templates/generic.conf.j2
index 08bf7a60..dae84a2f 100644
--- a/roles/nginx/vhost/templates/generic.conf.j2
+++ b/roles/nginx/vhost/templates/generic.conf.j2
@@ -3,9 +3,20 @@ server {
listen [::]:80{% if 'default' in nginx_vhost and nginx_vhost.default %} default_server{% endif %};
server_name {{ nginx_vhost.hostnames | join(' ') }};
-{% if 'acme' in nginx_vhost and nginx_vhost.acme %}
- include snippets/acmetool.conf;
+{% if 'logs' in nginx_vhost %}
+{% if 'access' in nginx_vhost.logs %}
+ access_log {{ nginx_vhost.logs.access }};
+{% endif %}
+{% if 'error' in nginx_vhost.logs %}
+ error_log {{ nginx_vhost.logs.error }};
+{% endif %}
+
+{% endif %}
+{% if 'tls' in nginx_vhost %}
+{% if nginx_vhost.tls.certificate_provider == 'acmetool' or nginx_vhost.tls.certificate_provider == 'uacme' %}
+ include snippets/{{ nginx_vhost.tls.certificate_provider }}.conf;
+{% endif %}
location / {
return 301 https://$host$request_uri;
}
@@ -16,20 +27,36 @@ server {
listen [::]:443 ssl http2{% if 'default' in nginx_vhost and nginx_vhost.default %} default_server{% endif %};
server_name {{ nginx_vhost.hostnames | join(' ') }};
- include snippets/acmetool.conf;
- include snippets/tls{% if 'tls_variant' in nginx_vhost %}-{{ nginx_vhost.tls_variant }}{% endif %}.conf;
- ssl_certificate /var/lib/acme/live/{{ nginx_vhost.hostnames[0] }}/fullchain;
- ssl_certificate_key /var/lib/acme/live/{{ nginx_vhost.hostnames[0] }}/privkey;
+{% if 'logs' in nginx_vhost %}
+{% if 'access' in nginx_vhost.logs %}
+ access_log {{ nginx_vhost.logs.access }};
+{% endif %}
+{% if 'error' in nginx_vhost.logs %}
+ error_log {{ nginx_vhost.logs.error }};
+{% endif %}
+
+{% endif %}
+{% if nginx_vhost.tls.certificate_provider == 'acmetool' or nginx_vhost.tls.certificate_provider == 'uacme' %}
+ include snippets/{{ nginx_vhost.tls.certificate_provider }}.conf;
+{% endif %}
+ include snippets/tls{% if 'variant' in nginx_vhost.tls %}-{{ nginx_vhost.tls.variant }}{% endif %}.conf;
+ ssl_certificate {{ x509_certificate_path_fullchain }};
+ ssl_certificate_key {{ x509_certificate_path_key }};
+{% if 'hsts' not in nginx_vhost.tls or nginx_vhost.tls.hsts %}
include snippets/hsts.conf;
+{% endif %}
{% endif %}
-{% if 'extra_directives' in nginx_vhost %}
- {{ nginx_vhost.extra_directives | indent(4) }}
+{% if 'custom' in nginx_vhost %}
+ {{ nginx_vhost.custom | trim | indent(4) }}
+{% else %}
+{% if 'extra_directives' in nginx_vhost %}
+ {{ nginx_vhost.extra_directives | trim | indent(4) }}
-{% endif %}
-{% for path, location in nginx_vhost.locations.items() %}
+{% endif %}
+{% for path, location in nginx_vhost.locations.items() %}
location {{ path }} {
-{% if 'proxy_pass' in location %}
+{% if 'proxy_pass' in location %}
include snippets/proxy-nobuff.conf;
proxy_set_header Host $host;
include snippets/proxy-forward-headers.conf;
@@ -39,36 +66,41 @@ server {
proxy_set_header Connection $connection_upgrade;
proxy_pass {{ location.proxy_pass }};
-{% if 'proxy_redirect' in location %}
-{% for entry in location.proxy_redirect %}
+{% if 'proxy_redirect' in location %}
+{% for entry in location.proxy_redirect %}
proxy_redirect {{ entry.redirect }} {{ entry.replacement }};
-{% endfor %}
-{% endif %}
-{% if 'proxy_ssl' in location %}
-{% for prop in (location.proxy_ssl | list | sort) %}
+{% endfor %}
+{% endif %}
+{% if 'proxy_ssl' in location %}
+{% for prop in (location.proxy_ssl | list | sort) %}
proxy_ssl_{{ prop }} {{ location.proxy_ssl[prop] }};
-{% endfor %}
-{% endif %}
-{% else %}
-{% if 'root' in location %}
+{% endfor %}
+{% endif %}
+{% elif 'return' in location %}
+ return {{ location.return }};
+{% elif 'custom' in location %}
+ {{ location.custom | trim | indent(8) }}
+{% else %}
+{% if 'root' in location %}
root {{ location.root }};
-{% elif 'alias' in location %}
+{% elif 'alias' in location %}
alias {{ location.alias }};
-{% endif %}
-{% if 'index' in location %}
+{% endif %}
+{% if 'index' in location %}
index {{ location.index }};
-{% endif %}
-{% if 'autoindex' in location %}
+{% endif %}
+{% if 'autoindex' in location %}
autoindex on;
-{% if 'format' in location.autoindex %}
+{% if 'format' in location.autoindex %}
autoindex_format {{ nginx_vhost.autoindex.format }};
-{% endif %}
+{% endif %}
+{% endif %}
{% endif %}
-{% endif %}
-{% if 'extra_directives' in location %}
+{% if 'extra_directives' in location %}
- {{ location.extra_directives | indent(8) }}
-{% endif %}
+ {{ location.extra_directives | trim | indent(8) }}
+{% endif %}
}
-{% endfor %}
+{% endfor %}
+{% endif %}
}
diff --git a/roles/x509/acmetool/cert/defaults/main.yml b/roles/x509/acmetool/cert/defaults/main.yml
deleted file mode 100644
index ab0afaa3..00000000
--- a/roles/x509/acmetool/cert/defaults/main.yml
+++ /dev/null
@@ -1,2 +0,0 @@
----
-acmetool_reconcile_disabled: false
diff --git a/roles/x509/acmetool/cert/finalize/defaults/main.yml b/roles/x509/acmetool/cert/finalize/defaults/main.yml
new file mode 100644
index 00000000..b9a80136
--- /dev/null
+++ b/roles/x509/acmetool/cert/finalize/defaults/main.yml
@@ -0,0 +1,5 @@
+---
+acmetool_cert_hostnames: "{{ x509_certificate_hostnames }}"
+acmetool_cert_name: "{{ x509_certificate_name | default(acmetool_cert_hostnames[0]) }}"
+
+acmetool_reconcile_disabled: false
diff --git a/roles/x509/acmetool/cert/handlers/main.yml b/roles/x509/acmetool/cert/finalize/handlers/main.yml
index a7fc43ed..02ffa598 100644
--- a/roles/x509/acmetool/cert/handlers/main.yml
+++ b/roles/x509/acmetool/cert/finalize/handlers/main.yml
@@ -2,5 +2,6 @@
- name: reconcile acmetool
when: not acmetool_reconcile_disabled
systemd:
+ daemon_reload: yes
name: acmetool.service
state: started
diff --git a/roles/x509/acmetool/cert/tasks/main.yml b/roles/x509/acmetool/cert/finalize/tasks/main.yml
index 09980dad..abb2d4cb 100644
--- a/roles/x509/acmetool/cert/tasks/main.yml
+++ b/roles/x509/acmetool/cert/finalize/tasks/main.yml
@@ -3,7 +3,7 @@
vars:
acmetool_cert_satisfy:
satisfy:
- names: "{{ acmetool_cert_hostnames | default([acmetool_cert_name]) }}"
+ names: "{{ acmetool_cert_hostnames }}"
copy:
content: "{{ acmetool_cert_config | default({}) | combine(acmetool_cert_satisfy) | to_nice_yaml }}"
dest: "/var/lib/acme/desired/{{ acmetool_cert_name }}"
diff --git a/roles/x509/acmetool/cert/meta/main.yml b/roles/x509/acmetool/cert/meta/main.yml
new file mode 100644
index 00000000..472f5a8c
--- /dev/null
+++ b/roles/x509/acmetool/cert/meta/main.yml
@@ -0,0 +1,4 @@
+---
+dependencies:
+ - role: x509/acmetool/cert/prepare
+ - role: x509/acmetool/cert/finalize
diff --git a/roles/x509/acmetool/cert/prepare/defaults/main.yml b/roles/x509/acmetool/cert/prepare/defaults/main.yml
new file mode 100644
index 00000000..d4eb7c86
--- /dev/null
+++ b/roles/x509/acmetool/cert/prepare/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+acmetool_cert_hostnames: "{{ x509_certificate_hostnames }}"
diff --git a/roles/x509/acmetool/cert/filter_plugins/acme_certs.py b/roles/x509/acmetool/cert/prepare/filter_plugins/acme_certs.py
index 179f71e9..179f71e9 100644
--- a/roles/x509/acmetool/cert/filter_plugins/acme_certs.py
+++ b/roles/x509/acmetool/cert/prepare/filter_plugins/acme_certs.py
diff --git a/roles/x509/acmetool/cert/prepare/handlers/main.yml b/roles/x509/acmetool/cert/prepare/handlers/main.yml
new file mode 100644
index 00000000..330bcd11
--- /dev/null
+++ b/roles/x509/acmetool/cert/prepare/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+- name: reload systemd
+ systemd:
+ daemon_reload: yes
+
+- name: reload services for x509 certificates
+ loop: "{{ x509_certificate_reload_services | default([]) }}"
+ service:
+ name: "{{ item }}"
+ state: reloaded
diff --git a/roles/x509/acmetool/cert/prepare/tasks/main.yml b/roles/x509/acmetool/cert/prepare/tasks/main.yml
new file mode 100644
index 00000000..2db332b8
--- /dev/null
+++ b/roles/x509/acmetool/cert/prepare/tasks/main.yml
@@ -0,0 +1,79 @@
+---
+- name: check if acme certs already exist
+ loop: "{{ acmetool_cert_hostnames }}"
+ loop_control:
+ loop_var: acme_hostname
+ stat:
+ path: "/var/lib/acme/live/{{ acme_hostname }}"
+ register: acme_cert_stat
+
+- name: set acmecert_missing_hostnames variable
+ set_fact:
+ acmecert_missing_hostnames: "{{ acme_cert_stat.results | acme_cert_nonexistent(acmetool_cert_hostnames) }}"
+
+- name: link nonexistent hostnames to self-signed interim cert
+ when: acmecert_missing_hostnames | length > 0
+ block:
+ - name: get id of existing selfsigned interim certificate
+ command: cat /var/lib/acme/.selfsigned-interim-cert
+ changed_when: false
+ check_mode: false
+ register: selfsigned_interim_cert_id
+
+ - name: set selfsigned_interim_cert_id variable
+ set_fact:
+ selfsigned_interim_cert_id: "{{ selfsigned_interim_cert_id.stdout }}"
+
+ - name: link to snakeoil cert for nonexistent hostnames
+ loop: "{{ acmecert_missing_hostnames }}"
+ loop_control:
+ loop_var: acme_missing_hostname
+ file:
+ src: "../certs/{{ selfsigned_interim_cert_id }}"
+ dest: "/var/lib/acme/live/{{ acme_missing_hostname }}"
+ state: link
+ notify: reload services for x509 certificates
+
+- name: export paths to certificate files
+ set_fact:
+ x509_certificate_path_key: "/var/lib/acme/live/{{ acmetool_cert_hostnames[0] }}/privkey"
+ x509_certificate_path_cert: "/var/lib/acme/live/{{ acmetool_cert_hostnames[0] }}/cert"
+ x509_certificate_path_chain: "/var/lib/acme/live/{{ acmetool_cert_hostnames[0] }}/chain"
+ x509_certificate_path_fullchain: "/var/lib/acme/live/{{ acmetool_cert_hostnames[0] }}/fullchain"
+
+- name: setup custom renewal script
+ when: x509_certificate_renewal is defined
+ block:
+ - name: install custom hook script
+ template:
+ src: reload.sh.j2
+ dest: "/etc/acme/hooks/{{ x509_certificate_name }}"
+ mode: 0755
+
+ - name: install acmetool systemd unit snippet
+ when: "'install' in x509_certificate_renewal"
+ copy:
+ dest: "/etc/systemd/system/acmetool.service.d/{{ x509_certificate_name }}.conf"
+ content: |
+ [Service]
+ {% for path in (x509_certificate_renewal.install | map(attribute='dest') | map('dirname') | unique | list) %}
+ ReadWritePaths={{ path }}
+ {% endfor %}
+ notify: reload systemd
+
+ - name: remove acmetool systemd unit snippet
+ when: "'install' not in x509_certificate_renewal"
+ file:
+ path: "/etc/systemd/system/acmetool.service.d/{{ x509_certificate_name }}.conf"
+ state: absent
+ notify: reload systemd
+
+- name: remove custom renewal script
+ when: x509_certificate_renewal is not defined
+ loop:
+ - "/etc/systemd/system/acmetool.service.d/{{ x509_certificate_name }}.conf"
+ - "/etc/acme/hooks/{{ x509_certificate_name }}"
+ file:
+ path: "{{ item }}"
+ state: absent
+ notify: reload systemd
diff --git a/roles/x509/acmetool/cert/prepare/templates/reload.sh.j2 b/roles/x509/acmetool/cert/prepare/templates/reload.sh.j2
new file mode 100644
index 00000000..f4b8259e
--- /dev/null
+++ b/roles/x509/acmetool/cert/prepare/templates/reload.sh.j2
@@ -0,0 +1,31 @@
+#!/bin/sh
+set -e
+EVENT_NAME="$1"
+[ "$EVENT_NAME" = "live-updated" ] || exit 42
+
+MAIN_HOSTNAME="{{ acmetool_cert_hostnames[0] }}"
+
+while read name; do
+ certdir="$ACME_STATE_DIR/live/$name"
+ if [ -z "$name" -o ! -e "$certdir" ]; then
+ continue
+ fi
+ if [ "$name" != "$MAIN_HOSTNAME" ]; then
+ continue
+ fi
+{% if 'install' in x509_certificate_renewal %}
+
+{% for file in x509_certificate_renewal.install %}
+ install{% if 'mode' in file %} -m {{ file.mode }}{% endif %}{% if 'owner' in file %} -o {{ file.owner }}{% endif %}{% if 'owner' in file %} -g {{ file.group }}{% endif %} /dev/null "{{ file.dest }}.new"
+{% for src in file.src %}
+ cat "{{ hostvars[inventory_hostname]['x509_certificate_path_' + src] }}" >> "{{ file.dest }}.new"
+ mv "{{ file.dest }}.new" "{{ file.dest }}"
+{% endfor %}
+{% endfor %}
+{% endif %}
+{% if 'reload' in x509_certificate_renewal %}
+
+ {{ x509_certificate_renewal.reload | trim | indent(2) }}
+{% endif %}
+ break
+done
diff --git a/roles/x509/selfsigned/base/tasks/main.yml b/roles/x509/selfsigned/base/tasks/main.yml
new file mode 100644
index 00000000..51397d67
--- /dev/null
+++ b/roles/x509/selfsigned/base/tasks/main.yml
@@ -0,0 +1,5 @@
+---
+- name: install needed packages
+ apt:
+ name: "{{ python_basename }}-openssl"
+ state: present
diff --git a/roles/x509/selfsigned/cert/finalize/tasks/main.yml b/roles/x509/selfsigned/cert/finalize/tasks/main.yml
new file mode 100644
index 00000000..c5b6cafe
--- /dev/null
+++ b/roles/x509/selfsigned/cert/finalize/tasks/main.yml
@@ -0,0 +1,2 @@
+---
+# nothing to do here
diff --git a/roles/x509/selfsigned/cert/meta/main.yml b/roles/x509/selfsigned/cert/meta/main.yml
new file mode 100644
index 00000000..c7a30d00
--- /dev/null
+++ b/roles/x509/selfsigned/cert/meta/main.yml
@@ -0,0 +1,4 @@
+---
+dependencies:
+ - role: x509/selfsigned/cert/prepare
+ - role: x509/selfsigned/cert/finalize
diff --git a/roles/x509/selfsigned/cert/prepare/defaults/main.yml b/roles/x509/selfsigned/cert/prepare/defaults/main.yml
new file mode 100644
index 00000000..53dc3b06
--- /dev/null
+++ b/roles/x509/selfsigned/cert/prepare/defaults/main.yml
@@ -0,0 +1,41 @@
+---
+selfsigned_cert_hostnames: "{{ x509_certificate_hostnames }}"
+selfsigned_cert_name: "{{ x509_certificate_name | default(selfsigned_cert_hostnames[0]) }}"
+
+selfsigned_cert_base_dir: "/etc/ssl"
+
+# selfsigned_cert_config:
+# path: "{{ selfsigned_cert_base_dir }}/{{ selfsigned_cert_name }}"
+# mode: "0750"
+# owner: root
+# group: www-data
+# key:
+# mode: "0640"
+# owner: root
+# group: www-data
+# type: RSA
+# size: 4096
+# cert:
+# mode: "0644"
+# owner: root
+# group: www-data
+# country_name: "AT"
+# locality_name: "Graz"
+# organization_name: "spreadspace"
+# organizational_unit_name: "ansible"
+# state_or_province_name: "Styria"
+# basic_constraints:
+# - "CA:TRUE"
+# - "pathLenConstraint:0"
+# basic_constraints_critical: no
+# key_usage:
+# - digitalSignature
+# - keyAgreement
+# key_usage_critical: yes
+# extended_key_usage:
+# - serverAuth
+# extended_key_usage_critical: yes
+# create_subject_key_identifier: yes
+# digest: SHA256
+# not_before: +0h
+# not_after: +520w
diff --git a/roles/x509/selfsigned/cert/prepare/handlers/main.yml b/roles/x509/selfsigned/cert/prepare/handlers/main.yml
new file mode 100644
index 00000000..b169d6ca
--- /dev/null
+++ b/roles/x509/selfsigned/cert/prepare/handlers/main.yml
@@ -0,0 +1,6 @@
+---
+- name: reload services for x509 certificates
+ loop: "{{ x509_certificate_reload_services | default([]) }}"
+ service:
+ name: "{{ item }}"
+ state: reloaded
diff --git a/roles/x509/selfsigned/cert/prepare/tasks/main.yml b/roles/x509/selfsigned/cert/prepare/tasks/main.yml
new file mode 100644
index 00000000..e7a47742
--- /dev/null
+++ b/roles/x509/selfsigned/cert/prepare/tasks/main.yml
@@ -0,0 +1,69 @@
+---
+- name: compute path to selfsigned certificate directory
+ set_fact:
+ selfsigned_cert_path: "{{ selfsigned_cert_config.path | default([selfsigned_cert_base_dir, selfsigned_cert_name] | path_join) }}"
+
+- name: create directory for selfsigned certificate
+ file:
+ path: "{{ selfsigned_cert_path }}"
+ state: directory
+ mode: "{{ selfsigned_cert_config.mode | default('0700') }}"
+ owner: "{{ selfsigned_cert_config.owner | default(omit) }}"
+ group: "{{ selfsigned_cert_config.group | default(omit) }}"
+ notify: reload services for x509 certificates
+
+- name: generate key for selfsigned certificate
+ openssl_privatekey:
+ path: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-key.pem"
+ mode: "{{ selfsigned_cert_config.key.mode | default('0600') }}"
+ owner: "{{ selfsigned_cert_config.key.owner | default(omit) }}"
+ group: "{{ selfsigned_cert_config.key.group | default(omit) }}"
+ type: "{{ selfsigned_cert_config.key.type | default(omit) }}"
+ size: "{{ selfsigned_cert_config.key.size | default(omit) }}"
+ notify: reload services for x509 certificates
+
+- name: generate csr for selfsigned certificate
+ community.crypto.openssl_csr:
+ path: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-csr.pem"
+ mode: "{{ selfsigned_cert_config.cert.mode | default('0644') }}"
+ owner: "{{ selfsigned_cert_config.cert.owner | default(omit) }}"
+ group: "{{ selfsigned_cert_config.cert.group | default(omit) }}"
+ privatekey_path: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-key.pem"
+ create_subject_key_identifier: "{{ selfsigned_cert_config.cert.create_subject_key_identifier | default(omit) }}"
+ digest: "{{ selfsigned_cert_config.cert.digest | default(omit) }}"
+ common_name: "{{ selfsigned_cert_name }}"
+ subject_alt_name: "{{ ['DNS:'] | product(selfsigned_cert_hostnames) | map('join') | list }}"
+ subject_alt_name_critical: yes
+ use_common_name_for_san: no
+ country_name: "{{ selfsigned_cert_config.cert.country_name | default(omit) }}"
+ locality_name: "{{ selfsigned_cert_config.cert.locality_name | default(omit) }}"
+ organization_name: "{{ selfsigned_cert_config.cert.organization_name | default(omit) }}"
+ organizational_unit_name: "{{ selfsigned_cert_config.cert.organizational_unit_name | default(omit) }}"
+ state_or_province_name: "{{ selfsigned_cert_config.cert.state_or_province_name | default(omit) }}"
+ basic_constraints: "{{ selfsigned_cert_config.cert.basic_constraints | default(omit) }}"
+ basic_constraints_critical: "{{ selfsigned_cert_config.cert.basic_constraints_critical | default(omit) }}"
+ key_usage: "{{ selfsigned_cert_config.cert.key_usage | default(omit) }}"
+ key_usage_critical: "{{ selfsigned_cert_config.cert.key_usage_critical | default(omit) }}"
+ extended_key_usage: "{{ selfsigned_cert_config.cert.extended_key_usage | default(omit) }}"
+ extended_key_usage_critical: "{{ selfsigned_cert_config.cert.extended_key_usage_critical | default(omit) }}"
+
+- name: generate selfsigned certificate
+ community.crypto.x509_certificate:
+ path: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-crt.pem"
+ mode: "{{ selfsigned_cert_config.cert.mode | default('0644') }}"
+ owner: "{{ selfsigned_cert_config.cert.owner | default(omit) }}"
+ group: "{{ selfsigned_cert_config.cert.group | default(omit) }}"
+ privatekey_path: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-key.pem"
+ csr_path: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-csr.pem"
+ provider: selfsigned
+ selfsigned_digest: "{{ selfsigned_cert_config.cert.digest | default(omit) }}"
+ selfsigned_not_before: "{{ selfsigned_cert_config.cert.not_before | default(omit) }}"
+ selfsigned_not_after: "{{ selfsigned_cert_config.cert.not_after | default(omit) }}"
+ notify: reload services for x509 certificates
+
+- name: export paths to certificate files
+ set_fact:
+ x509_certificate_path_key: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-key.pem"
+ x509_certificate_path_cert: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-crt.pem"
+ x509_certificate_path_chain: ""
+ x509_certificate_path_fullchain: "{{ selfsigned_cert_path }}/{{ selfsigned_cert_name }}-crt.pem"
diff --git a/roles/x509/static/base/tasks/main.yml b/roles/x509/static/base/tasks/main.yml
new file mode 100644
index 00000000..c5b6cafe
--- /dev/null
+++ b/roles/x509/static/base/tasks/main.yml
@@ -0,0 +1,2 @@
+---
+# nothing to do here
diff --git a/roles/x509/static/cert/finalize/tasks/main.yml b/roles/x509/static/cert/finalize/tasks/main.yml
new file mode 100644
index 00000000..c5b6cafe
--- /dev/null
+++ b/roles/x509/static/cert/finalize/tasks/main.yml
@@ -0,0 +1,2 @@
+---
+# nothing to do here
diff --git a/roles/x509/static/cert/meta/main.yml b/roles/x509/static/cert/meta/main.yml
new file mode 100644
index 00000000..c619208c
--- /dev/null
+++ b/roles/x509/static/cert/meta/main.yml
@@ -0,0 +1,4 @@
+---
+dependencies:
+ - role: x509/static/cert/prepare
+ - role: x509/static/cert/finalize
diff --git a/roles/x509/static/cert/prepare/defaults/main.yml b/roles/x509/static/cert/prepare/defaults/main.yml
new file mode 100644
index 00000000..d632a5de
--- /dev/null
+++ b/roles/x509/static/cert/prepare/defaults/main.yml
@@ -0,0 +1,35 @@
+---
+static_cert_hostnames: "{{ x509_certificate_hostnames }}"
+static_cert_name: "{{ x509_certificate_name | default(static_cert_hostnames[0]) }}"
+
+static_cert_base_dir: "/etc/ssl"
+
+# static_cert_config:
+# path: "{{ static_cert_base_dir }}/{{ static_cert_name }}"
+# mode: "0750"
+# owner: root
+# group: www-data
+# key:
+# mode: "0640"
+# owner: root
+# group: www-data
+# content: |
+# -----BEGIN RSA PRIVATE KEY-----
+# ...
+# -----END RSA PRIVATE KEY-----
+# cert:
+# mode: "0644"
+# owner: root
+# group: www-data
+# content: |
+# -----BEGIN CERTIFICATE-----
+# ...
+# -----END CERTIFICATE-----
+# chain:
+# mode: "0644"
+# owner: root
+# group: www-data
+# content: |
+# -----BEGIN CERTIFICATE-----
+# ...
+# -----END CERTIFICATE-----
diff --git a/roles/x509/static/cert/prepare/handlers/main.yml b/roles/x509/static/cert/prepare/handlers/main.yml
new file mode 100644
index 00000000..b169d6ca
--- /dev/null
+++ b/roles/x509/static/cert/prepare/handlers/main.yml
@@ -0,0 +1,6 @@
+---
+- name: reload services for x509 certificates
+ loop: "{{ x509_certificate_reload_services | default([]) }}"
+ service:
+ name: "{{ item }}"
+ state: reloaded
diff --git a/roles/x509/static/cert/prepare/tasks/main.yml b/roles/x509/static/cert/prepare/tasks/main.yml
new file mode 100644
index 00000000..03df7542
--- /dev/null
+++ b/roles/x509/static/cert/prepare/tasks/main.yml
@@ -0,0 +1,81 @@
+---
+- name: compute path to static certificate directory
+ set_fact:
+ static_cert_path: "{{ static_cert_config.path | default([static_cert_base_dir, static_cert_name] | path_join) }}"
+
+- name: create directory for static certificate
+ file:
+ path: "{{ static_cert_path }}"
+ state: directory
+ mode: "{{ static_cert_config.mode | default('0700') }}"
+ owner: "{{ static_cert_config.owner | default(omit) }}"
+ group: "{{ static_cert_config.group | default(omit) }}"
+ notify: reload services for x509 certificates
+
+- name: install key for static certificate
+ copy:
+ content: "{{ static_cert_config.key.content }}"
+ dest: "{{ static_cert_path }}/{{ static_cert_name }}-key.pem"
+ mode: "{{ static_cert_config.key.mode | default('0600') }}"
+ owner: "{{ static_cert_config.key.owner | default(omit) }}"
+ group: "{{ static_cert_config.key.group | default(omit) }}"
+ notify: reload services for x509 certificates
+
+- name: install static certificate
+ copy:
+ content: "{{ static_cert_config.cert.content }}"
+ dest: "{{ static_cert_path }}/{{ static_cert_name }}-crt.pem"
+ mode: "{{ static_cert_config.cert.mode | default('0644') }}"
+ owner: "{{ static_cert_config.cert.owner | default(omit) }}"
+ group: "{{ static_cert_config.cert.group | default(omit) }}"
+ notify: reload services for x509 certificates
+
+- name: export paths to basic certificate files
+ set_fact:
+ x509_certificate_path_key: "{{ static_cert_path }}/{{ static_cert_name }}-key.pem"
+ x509_certificate_path_fullchain: "{{ static_cert_path }}/{{ static_cert_name }}-crt.pem"
+ x509_certificate_path_cert: "{{ static_cert_path }}/{{ static_cert_name }}-crt.pem"
+
+- name: install chain and fullchain for static certificate
+ when: "'chain' in static_cert_config"
+ block:
+ - name: install chain for static certificate
+ copy:
+ content: "{{ static_cert_config.chain.content }}"
+ dest: "{{ static_cert_path }}/{{ static_cert_name }}-chain.pem"
+ mode: "{{ static_cert_config.chain.mode | default('0644') }}"
+ owner: "{{ static_cert_config.chain.owner | default(omit) }}"
+ group: "{{ static_cert_config.chain.group | default(omit) }}"
+ notify: reload services for x509 certificates
+
+ - name: install fullchain for static certificate
+ copy:
+ content: |
+ {{ static_cert_config.cert.content | trim }}
+ {{ static_cert_config.chain.content }}
+ dest: "{{ static_cert_path }}/{{ static_cert_name }}-fullchain.pem"
+ mode: "{{ static_cert_config.cert.mode | default('0644') }}"
+ owner: "{{ static_cert_config.cert.owner | default(omit) }}"
+ group: "{{ static_cert_config.cert.group | default(omit) }}"
+ notify: reload services for x509 certificates
+
+ - name: export paths to additional certificate files
+ set_fact:
+ x509_certificate_path_chain: "{{ static_cert_path }}/{{ static_cert_name }}-chain.pem"
+ x509_certificate_path_fullchain: "{{ static_cert_path }}/{{ static_cert_name }}-fullchain.pem"
+
+- name: make sure chain and fullchain files are removed
+ when: "'chain' not in static_cert_config"
+ block:
+ - name: remove chain/fullchain files
+ loop:
+ - chain
+ - fullchain
+ file:
+ path: "{{ static_cert_path }}/{{ static_cert_name }}-{{ item }}.pem"
+ state: absent
+ notify: reload services for x509 certificates
+
+ - name: make sure variable that points to the chain certificate file is unset
+ set_fact:
+ x509_certificate_path_chain: ""
diff --git a/roles/x509/uacme/base/defaults/main.yml b/roles/x509/uacme/base/defaults/main.yml
index 50ac8019..264bc2d9 100644
--- a/roles/x509/uacme/base/defaults/main.yml
+++ b/roles/x509/uacme/base/defaults/main.yml
@@ -4,3 +4,5 @@ uacme_directory_server: "{{ acme_directory_server }}"
### this defaults to '/var/run/acme/acme-challenge'
# uacme_challenge_webroot_path: "/path/to/acme-challenge"
+
+# uacme_eab: <keyid>:base64(<key>)
diff --git a/roles/x509/uacme/base/tasks/main.yml b/roles/x509/uacme/base/tasks/main.yml
index 3d1c8404..3473d541 100644
--- a/roles/x509/uacme/base/tasks/main.yml
+++ b/roles/x509/uacme/base/tasks/main.yml
@@ -7,7 +7,7 @@
state: present
- name: create acme account key
- command: "uacme -c /var/lib/uacme.d -a '{{ uacme_directory_server }}' -y new '{{ uacme_account_email }}'"
+ command: "uacme -c /var/lib/uacme.d -a '{{ uacme_directory_server }}' -y{% if uacme_eab is defined %} -e {{ uacme_eab }}{% endif %} new '{{ uacme_account_email }}'"
args:
creates: /var/lib/uacme.d/private/key.pem
@@ -44,7 +44,28 @@
alias {{ uacme_challenge_webroot_path | default('/var/run/acme/acme-challenge') }}/;
}
-- name: generate selfsigned interim certificate
- include_tasks: selfsigned.yml
+- name: install reconcile script
+ template:
+ src: uacme-reconcile.sh.j2
+ dest: /usr/local/bin/uacme-reconcile.sh
+ mode: 0755
-## TODO: add global automatic refresher?
+- name: install systemd unit for automatic refresh
+ loop:
+ - service
+ - timer
+ template:
+ src: "uacme-reconcile.{{ item }}.j2"
+ dest: "/etc/systemd/system/uacme-reconcile.{{ item }}"
+
+- name: create system unit snippet directory
+ file:
+ path: /etc/systemd/system/uacme-reconcile.service.d/
+ state: directory
+
+- name: make sure systemd timer for automatic refresh is enabled and started
+ systemd:
+ daemon_reload: yes
+ name: uacme-reconcile.timer
+ state: started
+ enabled: yes
diff --git a/roles/x509/uacme/base/tasks/selfsigned.yml b/roles/x509/uacme/base/tasks/selfsigned.yml
deleted file mode 100644
index fff77d42..00000000
--- a/roles/x509/uacme/base/tasks/selfsigned.yml
+++ /dev/null
@@ -1,47 +0,0 @@
----
-- name: create directories for selfsigned interim certificate
- loop:
- - path: private/.self-signed
- mode: "0700"
- - path: .self-signed
- mode: "0755"
- loop_control:
- label: "{{ item.path }}"
- file:
- path: "/var/lib/uacme.d/{{ item.path }}"
- state: directory
- mode: "{{ item.mode }}"
-
-- name: generate private key for selfsigned interim certificate
- openssl_privatekey:
- path: /var/lib/uacme.d/private/.self-signed/key.pem
- mode: 0600
-
-- name: generate csr for selfsigned interim certificate
- community.crypto.openssl_csr_pipe:
- privatekey_path: /var/lib/uacme.d/private/.self-signed/key.pem
- common_name: "{{ ansible_fqdn }}"
- register: selfsigned_interim_cert_req
- changed_when: false
-
-### this is needed because strftime filter in ansible is exceptionally stupid
-### see: https://github.com/ansible/ansible/issues/39835
-- name: get remote date-time 10s ago
- command: date -d '10 seconds ago' -u '+%Y%m%d%H%M%SZ'
- register: remote_datetime_10sago
- changed_when: false
-
-- name: get remote date-time now
- command: date -u '+%Y%m%d%H%M%SZ'
- register: remote_datetime_now
- changed_when: false
-
-- name: generate selfsigned interim certificate
- community.crypto.x509_certificate:
- path: /var/lib/uacme.d/.self-signed/cert.pem
- privatekey_path: /var/lib/uacme.d/private/.self-signed/key.pem
- csr_content: "{{ selfsigned_interim_cert_req.csr }}"
- provider: selfsigned
- ## make sure the certificate is not valid anymore to force uacme to create a new cert
- selfsigned_not_before: "{{ remote_datetime_10sago.stdout }}"
- selfsigned_not_after: "{{ remote_datetime_now.stdout }}"
diff --git a/roles/x509/uacme/base/templates/uacme-reconcile.service.j2 b/roles/x509/uacme/base/templates/uacme-reconcile.service.j2
new file mode 100644
index 00000000..c2fe917a
--- /dev/null
+++ b/roles/x509/uacme/base/templates/uacme-reconcile.service.j2
@@ -0,0 +1,18 @@
+[Unit]
+Description=Reconcile Let's Encrypt certificates using uacme
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/uacme-reconcile.sh
+TimeoutStartSec=5min
+CapabilityBoundingSet=CAP_CHOWN CAP_NET_BIND_SERVICE
+NoNewPrivileges=yes
+PrivateTmp=yes
+PrivateDevices=yes
+ProtectSystem=strict
+ReadWritePaths=/var/lib/uacme.d {{ uacme_challenge_webroot_path | default('/var/run/acme/acme-challenge') }}
+ProtectHome=yes
+ProtectKernelTunables=yes
+ProtectControlGroups=yes
+RestrictRealtime=yes
+RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
diff --git a/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2 b/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2
new file mode 100644
index 00000000..ea02841d
--- /dev/null
+++ b/roles/x509/uacme/base/templates/uacme-reconcile.sh.j2
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+declare -a csr_files
+if [ -n "$1" ]; then
+ csr_files+=("/var/lib/uacme.d/$1/$1.csr")
+else
+ readarray -d '' csr_files < <(find /var/lib/uacme.d -name "*.csr" -print0)
+fi
+
+export UACME_CHALLENGE_PATH="{{ uacme_challenge_webroot_path | default('/var/run/acme/acme-challenge') }}"
+
+failed=0
+for csr_file in "${csr_files[@]}"; do
+ id=$(basename -s .csr "$csr_file")
+ uacme -c /var/lib/uacme.d -a "{{ uacme_directory_server }}" -h /usr/share/uacme/uacme.sh -n issue "$csr_file"
+ case $? in
+ 0)
+ echo "$id successfully (re)issued."
+ if [ -x "/var/lib/uacme.d/$id/updated.sh" ]; then
+ /var/lib/uacme.d/$id/updated.sh
+ fi
+ ;;
+ 1)
+ echo "$id not updated."
+ ;;
+ *)
+ failed=1
+ ;;
+ esac
+done
+
+exit $failed
diff --git a/roles/x509/uacme/base/templates/uacme-reconcile.timer.j2 b/roles/x509/uacme/base/templates/uacme-reconcile.timer.j2
new file mode 100644
index 00000000..6d37a162
--- /dev/null
+++ b/roles/x509/uacme/base/templates/uacme-reconcile.timer.j2
@@ -0,0 +1,10 @@
+[Unit]
+Description=Reconcile Let's Encrypt certificates using uacme
+
+[Timer]
+OnCalendar=*-*-* 00,12:00:00
+RandomizedDelaySec=1h
+Persistent=yes
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/x509/uacme/cert/finalize/defaults/main.yml b/roles/x509/uacme/cert/finalize/defaults/main.yml
new file mode 100644
index 00000000..611dc6fc
--- /dev/null
+++ b/roles/x509/uacme/cert/finalize/defaults/main.yml
@@ -0,0 +1,3 @@
+---
+uacme_cert_hostnames: "{{ x509_certificate_hostnames }}"
+uacme_cert_name: "{{ x509_certificate_name | default(uacme_cert_hostnames[0]) }}"
diff --git a/roles/x509/uacme/cert/finalize/tasks/main.yml b/roles/x509/uacme/cert/finalize/tasks/main.yml
new file mode 100644
index 00000000..6578c418
--- /dev/null
+++ b/roles/x509/uacme/cert/finalize/tasks/main.yml
@@ -0,0 +1,5 @@
+---
+- name: running uacme issue command
+ command: "/usr/local/bin/uacme-reconcile.sh '{{ uacme_cert_name }}'"
+ register: uacme_reconcile
+ changed_when: "'not updated.' not in uacme_reconcile.stdout"
diff --git a/roles/x509/uacme/cert/meta/main.yml b/roles/x509/uacme/cert/meta/main.yml
new file mode 100644
index 00000000..5106342c
--- /dev/null
+++ b/roles/x509/uacme/cert/meta/main.yml
@@ -0,0 +1,4 @@
+---
+dependencies:
+ - role: x509/uacme/cert/prepare
+ - role: x509/uacme/cert/finalize
diff --git a/roles/x509/uacme/cert/prepare/defaults/main.yml b/roles/x509/uacme/cert/prepare/defaults/main.yml
new file mode 100644
index 00000000..b15c1e44
--- /dev/null
+++ b/roles/x509/uacme/cert/prepare/defaults/main.yml
@@ -0,0 +1,15 @@
+---
+uacme_cert_hostnames: "{{ x509_certificate_hostnames }}"
+uacme_cert_name: "{{ x509_certificate_name | default(uacme_cert_hostnames[0]) }}"
+
+# uacme_cert_config:
+# key:
+# mode: "0640"
+# owner: root
+# group: www-data
+# type: RSA
+# size: 4096
+# cert:
+# mode: "0644"
+# owner: root
+# group: www-data
diff --git a/roles/x509/uacme/cert/prepare/handlers/main.yml b/roles/x509/uacme/cert/prepare/handlers/main.yml
new file mode 100644
index 00000000..330bcd11
--- /dev/null
+++ b/roles/x509/uacme/cert/prepare/handlers/main.yml
@@ -0,0 +1,10 @@
+---
+- name: reload systemd
+ systemd:
+ daemon_reload: yes
+
+- name: reload services for x509 certificates
+ loop: "{{ x509_certificate_reload_services | default([]) }}"
+ service:
+ name: "{{ item }}"
+ state: reloaded
diff --git a/roles/x509/uacme/cert/prepare/tasks/main.yml b/roles/x509/uacme/cert/prepare/tasks/main.yml
new file mode 100644
index 00000000..a83651b3
--- /dev/null
+++ b/roles/x509/uacme/cert/prepare/tasks/main.yml
@@ -0,0 +1,112 @@
+---
+- name: create directory for uacme-controlled certificate
+ file:
+ path: "/var/lib/uacme.d/{{ uacme_cert_name }}"
+ state: directory
+
+- name: generate key for uacme-controlled certificate
+ openssl_privatekey:
+ path: "/var/lib/uacme.d/{{ uacme_cert_name }}/key.pem"
+ mode: "{{ uacme_cert_config.key.mode | default('0600') }}"
+ owner: "{{ uacme_cert_config.key.owner | default(omit) }}"
+ group: "{{ uacme_cert_config.key.group | default(omit) }}"
+ type: "{{ uacme_cert_config.key.type | default(omit) }}"
+ size: "{{ uacme_cert_config.key.size | default(omit) }}"
+ notify: reload services for x509 certificates
+
+- name: generate csr for uacme-controlled certificate
+ community.crypto.openssl_csr:
+ path: "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}.csr"
+ mode: "{{ uacme_cert_config.cert.mode | default('0644') }}"
+ owner: "{{ uacme_cert_config.cert.owner | default(omit) }}"
+ group: "{{ uacme_cert_config.cert.group | default(omit) }}"
+ privatekey_path: "/var/lib/uacme.d/{{ uacme_cert_name }}/key.pem"
+ common_name: "{{ uacme_cert_hostnames[0] }}"
+ subject_alt_name: "{{ ['DNS:'] | product(uacme_cert_hostnames) | map('join') | list }}"
+ subject_alt_name_critical: yes
+ use_common_name_for_san: no
+
+- name: test if uacme-controlled certificate already exists
+ stat:
+ path: "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem"
+ register: uacme_cert_file
+
+- name: generate selfsigned interim certificate
+ when: not uacme_cert_file.stat.exists
+ block:
+ ### this is needed because strftime filter in ansible is exceptionally stupid
+ ### see: https://github.com/ansible/ansible/issues/39835
+ - name: get remote date-time 10s ago
+ command: date -d '10 seconds ago' -u '+%Y%m%d%H%M%SZ'
+ register: remote_datetime_10sago
+ changed_when: false
+
+ - name: get remote date-time now
+ command: date -u '+%Y%m%d%H%M%SZ'
+ register: remote_datetime_now
+ changed_when: false
+
+ - name: generate selfsigned interim certificate
+ community.crypto.x509_certificate:
+ path: "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem"
+ mode: "{{ uacme_cert_config.cert.mode | default('0644') }}"
+ owner: "{{ uacme_cert_config.cert.owner | default(omit) }}"
+ group: "{{ uacme_cert_config.cert.group | default(omit) }}"
+ privatekey_path: "/var/lib/uacme.d/{{ uacme_cert_name }}/key.pem"
+ csr_path: "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}.csr"
+ provider: selfsigned
+ ## make sure the certificate is not valid anymore to force uacme to create a new cert
+ selfsigned_not_before: "{{ remote_datetime_10sago.stdout }}"
+ selfsigned_not_after: "{{ remote_datetime_now.stdout }}"
+ return_content: yes
+ register: uacme_cert_selfsigned
+ notify: reload services for x509 certificates
+
+ - name: make sure cert-only file exists
+ copy:
+ content: "{{ uacme_cert_selfsigned.certificate }}"
+ dest: "/var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem"
+ mode: "{{ uacme_cert_config.cert.mode | default('0644') }}"
+ owner: "{{ uacme_cert_config.cert.owner | default(omit) }}"
+ group: "{{ uacme_cert_config.cert.group | default(omit) }}"
+ notify: reload services for x509 certificates
+
+ - name: make sure the chain file exists
+ copy:
+ content: ""
+ dest: "/var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem"
+ mode: "{{ uacme_cert_config.cert.mode | default('0644') }}"
+ owner: "{{ uacme_cert_config.cert.owner | default(omit) }}"
+ group: "{{ uacme_cert_config.cert.group | default(omit) }}"
+ notify: reload services for x509 certificates
+
+- name: export paths to certificate files
+ set_fact:
+ x509_certificate_path_key: "/var/lib/uacme.d/{{ uacme_cert_name }}/key.pem"
+ x509_certificate_path_cert: "/var/lib/uacme.d/{{ uacme_cert_name }}/crt.pem"
+ x509_certificate_path_chain: "/var/lib/uacme.d/{{ uacme_cert_name }}/chain.pem"
+ x509_certificate_path_fullchain: "/var/lib/uacme.d/{{ uacme_cert_name }}/{{ uacme_cert_name }}-cert.pem"
+
+- name: install script to be called when new certificate is generated
+ template:
+ src: updated.sh.j2
+ dest: "/var/lib/uacme.d/{{ uacme_cert_name }}/updated.sh"
+ mode: 0755
+
+- name: install systemd unit snippet
+ when: "x509_certificate_renewal is defined and 'install' in x509_certificate_renewal"
+ copy:
+ dest: "/etc/systemd/system/uacme-reconcile.service.d/{{ x509_certificate_name }}.conf"
+ content: |
+ [Service]
+ {% for path in (x509_certificate_renewal.install | map(attribute='dest') | map('dirname') | unique | list) %}
+ ReadWritePaths={{ path }}
+ {% endfor %}
+ notify: reload systemd
+
+- name: remove systemd unit snippet
+ when: "x509_certificate_renewal is undefined or 'install' not in x509_certificate_renewal"
+ file:
+ path: "/etc/systemd/system/uacme-reconcile.service.d/{{ x509_certificate_name }}.conf"
+ state: absent
+ notify: reload systemd
diff --git a/roles/x509/uacme/cert/prepare/templates/updated.sh.j2 b/roles/x509/uacme/cert/prepare/templates/updated.sh.j2
new file mode 100644
index 00000000..275ca189
--- /dev/null
+++ b/roles/x509/uacme/cert/prepare/templates/updated.sh.j2
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+BASE_D="/var/lib/uacme.d/{{ uacme_cert_name }}"
+
+# split fullchain and fix permissions
+awk '{if(length($0) > 0) print} /-----END CERTIFICATE-----/ { exit }' "$BASE_D/{{ uacme_cert_name }}-cert.pem" > "$BASE_D/crt.pem"
+awk '(show==1) {if(length($0) > 0) print} /-----END CERTIFICATE-----/ { show=1 }' "$BASE_D/{{ uacme_cert_name }}-cert.pem" > "$BASE_D/chain.pem"
+chmod "{{ uacme_cert_config.cert.mode | default('0644') }}" $BASE_D/{{ uacme_cert_name }}-cert.pem $BASE_D/crt.pem $BASE_D/chain.pem
+{% if uacme_cert_config.cert.owner is defined %}
+chown "{{ uacme_cert_config.cert.owner }}" $BASE_D/{{ uacme_cert_name }}-cert.pem $BASE_D/crt.pem $BASE_D/chain.pem
+{% endif %}
+{% if uacme_cert_config.cert.group is defined %}
+chgrp "{{ uacme_cert_config.cert.group }}" $BASE_D/{{ uacme_cert_name }}-cert.pem $BASE_D/crt.pem $BASE_D/chain.pem
+{% endif %}
+{% if x509_certificate_renewal is defined and 'install' in x509_certificate_renewal %}
+{% for file in x509_certificate_renewal.install %}
+
+install{% if 'mode' in file %} -m {{ file.mode }}{% endif %}{% if 'owner' in file %} -o {{ file.owner }}{% endif %}{% if 'owner' in file %} -g {{ file.group }}{% endif %} /dev/null "{{ file.dest }}.new"
+{% for src in file.src %}
+cat "{{ hostvars[inventory_hostname]['x509_certificate_path_' + src] }}" >> "{{ file.dest }}.new"
+mv "{{ file.dest }}.new" "{{ file.dest }}"
+{% endfor %}
+{% endfor %}
+{% endif %}
+
+## reload services
+{% for service in (x509_certificate_reload_services | default([])) %}
+systemctl reload "{{ service }}.service"
+{% endfor %}
+{% if x509_certificate_renewal is defined and 'reload' in x509_certificate_renewal %}
+
+{{ x509_certificate_renewal.reload | trim }}
+{% endif %}
diff --git a/spreadspace/glt-stream.yml b/spreadspace/glt-stream.yml
index 145f8671..e355d126 100644
--- a/spreadspace/glt-stream.yml
+++ b/spreadspace/glt-stream.yml
@@ -29,7 +29,8 @@
default: yes
name: stream
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- stream.linuxtage.at
extra_directives: |-
diff --git a/spreadspace/sgg-icecast.yml b/spreadspace/sgg-icecast.yml
index bfe67bde..4c6d61c4 100644
--- a/spreadspace/sgg-icecast.yml
+++ b/spreadspace/sgg-icecast.yml
@@ -32,7 +32,8 @@
default: yes
name: radio
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- radiogloria.at
- www.radiogloria.at
@@ -48,7 +49,8 @@
nginx_vhost:
name: radio-stream
template: generic
- acme: yes
+ tls:
+ certificate_provider: acmetool
hostnames:
- live.radiogloria.at
locations: