rewrite lego role

This commit is contained in:
Oli
2025-06-05 22:53:10 +00:00
parent 62fabb2277
commit 230feb9b0c
12 changed files with 247 additions and 71 deletions

View File

@@ -0,0 +1,14 @@
---
# lego_certificate_domains:
# - cn: "dns.ows.cx"
# sans: [*.dns.ows.cx]
# lego_certificate_destination:
# path: /etc/nginx/certs
# owner: root
# group: nginx
# lego_services_reload:
# name: nginx
# # OR
# command: /usr/sbin/nginx -s reload

View File

@@ -1,14 +1,21 @@
--- ---
- name: Get latest lego version - name: Get latest lego version
github_release: become: false
user: go-acme
repo: lego
action: latest_release
token: "{{ vault_github_token }}"
delegate_to: localhost delegate_to: localhost
run_once: true run_once: true
register: lego_version when: lego_version is undefined
block:
- name: Get latest version from Github
github_release: # needs Python Module github3.py
user: go-acme
repo: lego
action: latest_release
token: "{{ vault_github_token }}"
register: lego_github_version
- name: "{{ lego_github_version }}"
set_fact:
lego_version: "{{ lego_github_version.tag }}"
- name: Set architecture alias - name: Set architecture alias
set_fact: set_fact:
@@ -20,10 +27,10 @@
architecture_alias: "arm64" # noqa: var-naming[no-role-prefix] architecture_alias: "arm64" # noqa: var-naming[no-role-prefix]
when: ansible_architecture == "aarch64" when: ansible_architecture == "aarch64"
- name: "Download lego from GitHub ({{ lego_version.tag }})" - name: "Download lego from GitHub"
get_url: get_url:
url: "https://github.com/go-acme/lego/releases/download/\ url: "https://github.com/go-acme/lego/releases/download/\
{{ lego_version.tag }}/lego_{{ lego_version.tag }}\ {{ lego_version }}/lego_{{ lego_version }}\
_linux_{{ architecture_alias }}.tar.gz" _linux_{{ architecture_alias }}.tar.gz"
dest: "/var/tmp/lego.tar.gz" dest: "/var/tmp/lego.tar.gz"
mode: "0644" mode: "0644"
@@ -48,22 +55,44 @@
mode: "0755" mode: "0755"
state: directory state: directory
- name: Copy ACME renew-hook script
template:
src: "renew-hook.sh.j2"
dest: "{{ lego_config_dir }}/renew-hook.sh"
mode: "0750"
vars:
lego_cert_dir: "{{ lego_config_dir }}/certificates"
- name: Register lego and create cert - name: Register lego and create cert
command: | shell: >
{{ lego_install_dir }}/lego --accept-tos {{ lego_install_dir }}/lego --accept-tos
{% for dns in certificate_domains %} --domains="{{ item.cn }}"
--domains="{{ dns }}" {% if item.sans is defined and item.sans %}
{% endfor %} {% for san in item.sans %}--domains="{{ san }}" {% endfor %}
{{ lego_cli_params | join(' ') }} {% endif %}
run {{ lego_cli_params | join(' ') }}
run &&
{{ lego_config_dir }}/renew-hook.sh '{{ item.cn }}'
args: args:
creates: "/var/lib/lego/accounts" creates: "{{ lego_certificate_destination.path | default(lego_config_dir + '/certificates') }}/{{ item.cn }}.crt"
environment: '{ "{{ lego_provider|upper }}_API_KEY": "{{ vault_ionos_token_dns }}" }' environment: '{ "{{ lego_provider|upper }}_API_KEY": "{{ vault_ionos_token_dns }}" }'
loop: "{{ lego_certificate_domains }}"
loop_control:
label: "{{ item.cn }}"
- name: Copy lego systemd service - name: Copy lego systemd service
template: template:
src: "{{ item }}.j2" src: "lego.{{ item.1 }}.j2"
dest: "/etc/systemd/system/{{ item }}" dest: "/etc/systemd/system/lego_{{ item.0.cn }}.{{ item.1 }}"
mode: "0644" mode: "0644"
loop: [lego.service, lego.timer] loop: "{{ lego_certificate_domains | product(['service', 'timer']) | list }}"
notify: [Restart lego_service, Restart lego_timer] loop_control:
label: "lego_{{ item.0.cn }}.{{ item.1 }}"
- name: Start lego_timer
systemd:
daemon_reload: true
enabled: true
name: "lego_{{ item.cn }}.timer"
state: started
loop: "{{ lego_certificate_domains }}"

View File

@@ -1,19 +1,31 @@
## Managed by Ansible ## ## Managed by Ansible ##
[Unit] [Unit]
Description=Run lego renew Description=Renew Lets Encrypt certificate for {{ item.0.cn }}
After=network-online.target After=network-online.target
[Service] [Service]
Type=oneshot Type=oneshot
{% if lego_provider == "ionos" %}
Environment={{ lego_provider|upper }}_API_KEY={{ vault_ionos_token_dns }} Environment={{ lego_provider|upper }}_API_KEY={{ vault_ionos_token_dns }}
{% endif %}
ExecStart={{ lego_install_dir }}/lego \ ExecStart={{ lego_install_dir }}/lego \
{% for dns in certificate_domains %} --domains="{{ item.0.cn }}" \
--domains="{{ dns }}" \ {% if item.0.sans is defined and item.0.sans %}
{% endfor %} {% for san in item.0.sans %}
{{ lego_cli_params|join(' ') }} \ --domains="{{ san }}" \
renew {% endfor %}
{% endif %}
{{ lego_cli_params | join(' ') }} \
renew \
--renew-hook="{{ lego_config_dir }}/renew-hook.sh {{ item.0.cn }}"
User=root User=root
# Restart if renewal fails, but not too quickly
RestartSec=12h
Restart=on-failure
StartLimitInterval=72h
StartLimitBurst=3
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

View File

@@ -1,11 +1,11 @@
## Managed by Ansible ## ## Managed by Ansible ##
[Unit] [Unit]
Description=Start lego renew Description=Timer for Lets Encrypt certificate renewal of {{ item.0.cn }}
[Timer] [Timer]
Persistent=true Persistent=true
OnCalendar=Mon 04:00:00 OnCalendar=Mon 03:00:00
RandomizedDelaySec=1h RandomizedDelaySec=1h
[Install] [Install]

View File

@@ -0,0 +1,134 @@
#!/usr/bin/bash
## Managed by Ansible ##
# Variables set by Ansible
cert_src_path="{{ lego_cert_dir }}"
# Certificate destination variables (if defined)
cert_dest_path="{{ lego_certificate_destination.path | default('') }}"
cert_owner="{{ lego_certificate_destination.owner | default('') }}"
cert_group="{{ lego_certificate_destination.group | default('') }}"
# Service reload variables (if defined)
service_name="{{ lego_services_reload.name | default('') }}"
service_command="{{ lego_services_reload.command | default('') }}"
copy_certificate_files() {
local domain="$1"
local success=true
# Check if destination is defined
if [ -z "$cert_dest_path" ]; then
echo "No certificate destination defined, skipping copy"
return 0
fi
echo "Copying certificate files for $domain..."
echo "Copying to $cert_dest_path..."
# Create destination directory if it doesn't exist
mkdir -p "$cert_dest_path"
# Copy certificate files
cp "$cert_src_path/${domain}.crt" "$cert_dest_path/${domain}.crt" || success=false
cp "$cert_src_path/${domain}.key" "$cert_dest_path/${domain}.key" || success=false
# Copy issuer cert if it exists
if [ -f "$cert_src_path/${domain}.issuer.crt" ]; then
cp "$cert_src_path/${domain}.issuer.crt" "$cert_dest_path/${domain}.issuer.crt" || success=false
fi
# Set standard secure permissions
# 644 for certificates, 600 for keys
chmod 644 "$cert_dest_path/${domain}.crt" || success=false
chmod 600 "$cert_dest_path/${domain}.key" || success=false
# Set issuer cert permissions if it exists
if [ -f "$cert_dest_path/${domain}.issuer.crt" ]; then
chmod 644 "$cert_dest_path/${domain}.issuer.crt" || success=false
fi
# Set ownership if specified
if [ -n "$cert_owner" ] && [ -n "$cert_group" ]; then
if [ -f "$cert_dest_path/${domain}.issuer.crt" ]; then
chown "$cert_owner":"$cert_group" "$cert_dest_path/${domain}.crt" "$cert_dest_path/${domain}.key" "$cert_dest_path/${domain}.issuer.crt" || success=false
else
chown "$cert_owner":"$cert_group" "$cert_dest_path/${domain}.crt" "$cert_dest_path/${domain}.key" || success=false
fi
fi
if $success; then
echo "Certificate files copied successfully"
return 0
else
echo "Error copying certificate files"
return 1
fi
}
reload_service() {
local domain="$1"
local success=true
# Check if service reload is defined
if [ -z "$service_name" ] && [ -z "$service_command" ]; then
echo "No service reload defined, skipping reload"
return 0
fi
echo "Reloading service..."
if [ -n "$service_command" ]; then
echo "Running command: $service_command"
eval "$service_command" || success=false
elif [ -n "$service_name" ]; then
echo "Reloading $service_name..."
systemctl reload "$service_name" || systemctl restart "$service_name" || success=false
fi
if $success; then
echo "Service reloaded successfully"
return 0
else
echo "Error reloading service"
return 1
fi
}
# Check if domain is provided as parameter
if [ $# -lt 1 ]; then
echo "Error: Domain parameter is required"
echo "Usage: $0 <domain>"
exit 1
fi
# Get domain from parameter
domain="$1"
# Main execution
echo "Certificate renewal hook triggered for $domain"
# Call the functions
copy_certificate_files "$domain"
copy_result=$?
reload_service "$domain"
reload_result=$?
# Send webhook notification
message="$domain certificate was successfully renewed"
if [ -n "$cert_dest_path" ]; then
message="${message}, files copied"
fi
if [ -n "$service_name" ] || [ -n "$service_command" ]; then
message="${message}, and service reloaded"
fi
if [ $copy_result -eq 0 ] && [ $reload_result -eq 0 ]; then
echo "$message"
else
echo "$domain certificate was renewed but post-renewal tasks failed"
fi

View File

@@ -1,21 +1,17 @@
--- ---
# Lego
lego_install_dir: "/usr/local/bin" lego_install_dir: "/usr/local/bin"
lego_config_dir: "/var/lib/lego" lego_config_dir: "/var/lib/lego"
lego_provider: "ionos" lego_provider: "ionos"
lego_cert_mail: !vault | lego_cli_params:
- --path={{ lego_config_dir }}
- --email={{ vault_lego_cert_mail }}
- --dns={{ lego_provider }}
- --key-type=ec256
vault_lego_cert_mail: !vault |
$ANSIBLE_VAULT;1.2;AES256;dtsv-dev $ANSIBLE_VAULT;1.2;AES256;dtsv-dev
32353064653631636431646333633664363866666439306235303138306461313266343939346463 32353064653631636431646333633664363866666439306235303138306461313266343939346463
6565636462656666366133653638333433393730656362360a333363623561646436613530623662 6565636462656666366133653638333433393730656362360a333363623561646436613530623662
34623331313964316464653333646134353037333065373063346164623037663235316361646666 34623331313964316464653333646134353037333065373063346164623037663235316361646666
3466623937663061340a643863633034633665316364313065303166643363653366363063303261 3466623937663061340a643863633034633665316364313065303166643363653366363063303261
34316163616637633837333539626337356563616566346561333439646565373665 34316163616637633837333539626337356563616566346561333439646565373665
lego_cli_params:
- --path={{ lego_config_dir }}
- --email={{ lego_cert_mail }}
- --dns={{ lego_provider }}
- --key-type=ec384
# Certificates
certificate_domains:
- "twirling.de"
- "*.twirling.de"

View File

@@ -34,11 +34,14 @@
path: /etc/nginx/conf.d/default.conf path: /etc/nginx/conf.d/default.conf
state: absent state: absent
- name: Create global config folder - name: Create additional config folder
file: file:
path: "/etc/nginx/global" path: "/etc/nginx/{{ item }}"
mode: "0755" mode: "0755"
state: directory state: directory
loop:
- global
- snippets
- name: Copy Nginx SSL Config - name: Copy Nginx SSL Config
template: template:

View File

@@ -1,5 +1,14 @@
--- ---
dependencies: dependencies:
- role: lego
vars:
lego_certificate_domains:
- cn: "{{ webserver_domain }}"
sans: ["*.{{ webserver_domain }}"]
lego_certificate_destination:
path: "{{ webserver_nginx_cert_path }}"
lego_services_reload:
name: nginx
- role: rclone - role: rclone
- role: nginx - role: nginx
- role: nginx_exporter - role: nginx_exporter

View File

@@ -7,10 +7,10 @@
mode: "0644" mode: "0644"
loop: loop:
- {src: "nginx.conf.j2", dest: "/etc/nginx/nginx.conf"} - {src: "nginx.conf.j2", dest: "/etc/nginx/nginx.conf"}
- {src: "cert.conf.j2", dest: "/etc/nginx/global/cert.conf"} - {src: "cert.conf.j2", dest: "/etc/nginx/snippets/cert.conf"}
- {src: "header.conf.j2", dest: "/etc/nginx/global/header.conf"} - {src: "header.conf.j2", dest: "/etc/nginx/global/header.conf"}
- {src: "proxy.conf.j2", dest: "/etc/nginx/global/proxy.conf"} - {src: "proxy.conf.j2", dest: "/etc/nginx/global/proxy.conf"}
- {src: "php_optimization.j2", dest: "/etc/nginx/global/php_optimization"} - {src: "php_optimization.j2", dest: "/etc/nginx/snippets/php_optimization.conf"}
notify: Reload nginx notify: Reload nginx
- name: Copy virtual server configs - name: Copy virtual server configs
@@ -21,26 +21,6 @@
with_fileglob: "../templates/conf.d/*.j2" with_fileglob: "../templates/conf.d/*.j2"
notify: Reload nginx notify: Reload nginx
## Certificates
- name: Create Certificate directory
file:
path: "{{ webserver_nginx_cert_path }}"
state: directory
mode: "0755"
- name: "Copy SSL certificates for {{ webserver_domain }}"
copy:
remote_src: true
# make sure that ssl certs are available
src: "{{ lego_config_dir }}/certificates/{{ webserver_domain }}.{{ item }}"
dest: "{{ webserver_nginx_cert_path }}/{{ webserver_domain }}.{{ item }}"
owner: root
group: root
mode: "0600"
loop: [crt, key, issuer.crt]
notify: Reload nginx
- name: Create nginx.service.d directory - name: Create nginx.service.d directory
file: file:
path: /etc/systemd/system/nginx.service.d path: /etc/systemd/system/nginx.service.d

View File

@@ -28,7 +28,7 @@ server {
http2 on; http2 on;
server_name {{ nextcloud_domain_name }} www.{{ nextcloud_domain_name }}; server_name {{ nextcloud_domain_name }} www.{{ nextcloud_domain_name }};
include global/cert.conf; include snippets/cert.conf;
# Path to the root of your installation # Path to the root of your installation
root {{ nextcloud_dir }}; root {{ nextcloud_dir }};
@@ -83,7 +83,7 @@ server {
# only for Nextcloud like below: # only for Nextcloud like below:
include mime.types; include mime.types;
types { types {
text/javascript js mjs; text/javascript mjs;
application/wasm wasm; application/wasm wasm;
} }
@@ -141,7 +141,7 @@ server {
# to the URI, resulting in a HTTP 500 error response. # to the URI, resulting in a HTTP 500 error response.
location ~ \.php(?:$|/) { location ~ \.php(?:$|/) {
# Required for legacy support # Required for legacy support
rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;
fastcgi_split_path_info ^(.+?\.php)(/.*)$; fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info; set $path_info $fastcgi_path_info;
@@ -164,7 +164,7 @@ server {
} }
# Serve static files # Serve static files
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ { location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
try_files $uri /index.php$request_uri; try_files $uri /index.php$request_uri;
# HTTP response headers borrowed from Nextcloud `.htaccess` # HTTP response headers borrowed from Nextcloud `.htaccess`
add_header Cache-Control "public, max-age=15778463$asset_immutable"; add_header Cache-Control "public, max-age=15778463$asset_immutable";
@@ -177,7 +177,7 @@ server {
access_log off; # Optional: Don't log access to assets access_log off; # Optional: Don't log access to assets
} }
location ~ \.woff2?$ { location ~ \.(otf|woff2?)$ {
try_files $uri /index.php$request_uri; try_files $uri /index.php$request_uri;
expires 7d; # Cache-Control policy borrowed from `.htaccess` expires 7d; # Cache-Control policy borrowed from `.htaccess`
access_log off; # Optional: Don't log access to assets access_log off; # Optional: Don't log access to assets

View File

@@ -21,7 +21,7 @@ server {
quic_gso on; quic_gso on;
server_name {{ webserver_domain }} www.{{ webserver_domain }}; server_name {{ webserver_domain }} www.{{ webserver_domain }};
include global/cert.conf; include snippets/cert.conf;
include global/header.conf; include global/header.conf;
# Path to the root of your installation # Path to the root of your installation

View File

@@ -3,7 +3,6 @@
- name: Install Webserver - name: Install Webserver
hosts: WEB hosts: WEB
roles: roles:
- lego
- nextcloud - nextcloud
- wordpress - wordpress
become: true become: true