Compare commits
9 Commits
960d95a924
...
transcaffe
Author | SHA1 | Date | |
---|---|---|---|
6b513531a3
|
|||
967ebab4c1
|
|||
5f4fbd492c
|
|||
96f5da9bf6
|
|||
2aaa529585
|
|||
8941b9357a
|
|||
04b5837fd8
|
|||
4837172f64
|
|||
ab7cca0947
|
46
roles/lego/README.md
Normal file
46
roles/lego/README.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# `finallycoffee.base.lego` ansible role
|
||||||
|
|
||||||
|
This role can be used to retrieve ACME certificates on the target host. It uses `lego` for that, and with systemd template units provides an easy way to configure and monitor the status for each certificate.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- `systemd`
|
||||||
|
- write access to /tmp to unpack the lego release tarball during installation
|
||||||
|
- write access to /opt/lego (or whatever `lego_base_path` is set to) for configuration and certificate data
|
||||||
|
- `become` privileges of the `ansible_user` on the target
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Required configuration
|
||||||
|
|
||||||
|
- `lego_instance` - used for allowing multiple lego jobs to run with systemd template units. recommended to be set to the CN / first SAN of the certificate.
|
||||||
|
- `lego_cert_domains` - list of FQDNs to request a certificate for
|
||||||
|
- `lego_acme_account_email` - when using letsencrypt, a contact email is mandatory
|
||||||
|
|
||||||
|
### Proxies / Registries
|
||||||
|
|
||||||
|
The role ensure `lego` is downloaded from the github release page. If you are behind a proxy or use a registry like Nexus3, set `lego_release_archive_server`.
|
||||||
|
|
||||||
|
### ACME server
|
||||||
|
|
||||||
|
Per default, the Letsencrypt Staging ACME server is configured. Set `lego_acme_server_url` from `lego_letsencrypt_server_urls.{qa,prod}` or configure your own ACME v2 server directly.
|
||||||
|
|
||||||
|
### Certificate
|
||||||
|
|
||||||
|
To set for which domains to request a certificate for, set them as a list of SANs in `lego_cert_domains`. The default key type is EC256 and can be overridden using `lego_cert_key_type`.
|
||||||
|
|
||||||
|
Set the type of challenge in `lego_acme_challenge_type` (to either `http` or `dns`), and `lego_acme_challenge_provider` to, for example, `rfc2136` for DNS challenges using the DNSUPDATE mechanism. If your challenge needs additional data, set that in `lego_command_config` as a dictionary analog to `lego_base_command_config` (see [defaults](defaults/main.yml)).
|
||||||
|
|
||||||
|
## Trivia
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
By default, the lego distribution for `linux` on `amd64` is downloaded. If your target needs a different architecture or target OS, adjust this in `lego_os` and `lego_architecture`, cross-checking with the [lego GitHub release page](https://github.com/go-acme/lego/releases/tag/v4.17.4) for upstream availability.
|
||||||
|
|
||||||
|
### User management
|
||||||
|
|
||||||
|
The role will attempt to create user+group for each seperate lego instance for data isolation (i.e. to avoid leaking a TSIG key from one lego instance to other services). The user and group are of the form `acme-{{ lego_instance }}`. Beware that changing this in `lego_cert_{user,group}` also requires `lego_systemd_{user,group}` to be adjusted!
|
||||||
|
|
||||||
|
### Binding to ports < 1024 (HTTP-01 challenge)
|
||||||
|
|
||||||
|
Set `lego_binary_allow_net_bind_service: true` to allow the lego binary to bind to ports in the 'privileged' (< 1024) port range.
|
@ -1,10 +1,13 @@
|
|||||||
---
|
---
|
||||||
lego_user: "lego"
|
lego_user: "lego"
|
||||||
lego_version: "4.16.1"
|
lego_version: "4.17.4"
|
||||||
lego_instance: default
|
lego_instance: default
|
||||||
lego_base_path: "/opt/lego"
|
lego_base_path: "/opt/lego"
|
||||||
lego_cert_user: "acme-{{ lego_instance }}"
|
lego_cert_user: "acme-{{ lego_instance }}"
|
||||||
lego_cert_group: "{{ lego_cert_user }}"
|
lego_cert_group: "{{ lego_cert_user }}"
|
||||||
|
lego_cert_mode: "0640" # rw-r-----
|
||||||
|
lego_systemd_user: "acme-%i"
|
||||||
|
lego_systemd_group: "{{ lego_systemd_user }}"
|
||||||
lego_instance_base_path: "{{ lego_base_path }}/instances"
|
lego_instance_base_path: "{{ lego_base_path }}/instances"
|
||||||
lego_instance_path: "{{ lego_instance_base_path }}/{{ lego_instance }}"
|
lego_instance_path: "{{ lego_instance_base_path }}/{{ lego_instance }}"
|
||||||
|
|
||||||
@ -22,6 +25,7 @@ lego_acme_server_url: "{{ lego_letsencrypt_server_urls.qa }}"
|
|||||||
lego_base_environment:
|
lego_base_environment:
|
||||||
LEGO_CERT_USER: "{{ lego_cert_user }}"
|
LEGO_CERT_USER: "{{ lego_cert_user }}"
|
||||||
LEGO_CERT_GROUP: "{{ lego_cert_group }}"
|
LEGO_CERT_GROUP: "{{ lego_cert_group }}"
|
||||||
|
LEGO_CERT_MODE: "{{ lego_cert_mode }}"
|
||||||
LEGO_CERT_STORE_PATH: "{{ lego_instance_path }}"
|
LEGO_CERT_STORE_PATH: "{{ lego_instance_path }}"
|
||||||
LEGO_CERT_DAYS_TO_RENEW: "{{ lego_cert_days_to_renew }}"
|
LEGO_CERT_DAYS_TO_RENEW: "{{ lego_cert_days_to_renew }}"
|
||||||
LEGO_KEY_TYPE: "{{ lego_cert_key_type }}"
|
LEGO_KEY_TYPE: "{{ lego_cert_key_type }}"
|
||||||
@ -56,6 +60,7 @@ lego_systemd_timer_calendar: "*-*-* *:00/15:00"
|
|||||||
|
|
||||||
lego_architecture: "amd64"
|
lego_architecture: "amd64"
|
||||||
lego_os: "linux"
|
lego_os: "linux"
|
||||||
|
lego_binary_allow_net_bind_service: false
|
||||||
|
|
||||||
lego_release_archive_server: "https://github.com"
|
lego_release_archive_server: "https://github.com"
|
||||||
lego_release_archive_filename: >-
|
lego_release_archive_filename: >-
|
||||||
|
@ -1,10 +1,28 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
LEGO_BINARY=$(/usr/bin/env which lego)
|
LEGO_BINARY=$(/usr/bin/env which lego)
|
||||||
|
|
||||||
FILES_IN_DIR=$(find "$LEGO_CERT_STORE_PATH/certificates" | wc -l)
|
if [[ -n "$LEGO_HTTP_FALLBACK_PORT" ]]; then
|
||||||
if [[ $FILES_IN_DIR -gt 2 ]]; then
|
if ! nc_binary="$(type -p \"nc\")" || [[ -z $nc_binary ]]; then
|
||||||
$LEGO_BINARY $LEGO_COMMAND_ARGS renew --days=$LEGO_CERT_DAYS_TO_RENEW
|
echo "nc not found (in PATH), exiting"
|
||||||
else
|
exit 1
|
||||||
$LEGO_BINARY $LEGO_COMMAND_ARGS run
|
fi
|
||||||
|
nc -z 127.0.0.1 $LEGO_HTTP_PORT;
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
LEGO_HTTP_PORT=$LEGO_HTTP_FALLBACK_PORT
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
LEGO_COMMAND_ARGS_EXPANDED=$(bash -c "echo $LEGO_COMMAND_ARGS") # This is a bit icky
|
||||||
|
|
||||||
|
FILES_IN_DIR=$(find "$LEGO_CERT_STORE_PATH/certificates" -type f | wc -l)
|
||||||
|
if [[ $FILES_IN_DIR -gt 2 ]]; then
|
||||||
|
$LEGO_BINARY $LEGO_COMMAND_ARGS_EXPANDED renew --days=$LEGO_CERT_DAYS_TO_RENEW
|
||||||
|
else
|
||||||
|
$LEGO_BINARY $LEGO_COMMAND_ARGS_EXPANDED run
|
||||||
|
fi
|
||||||
|
|
||||||
|
find "$LEGO_CERT_STORE_PATH/certificates/" -type f | xargs -I{} -n 1 chmod "$LEGO_CERT_MODE" "{}"
|
||||||
|
find "$LEGO_CERT_STORE_PATH/certificates/" -type f | xargs -I{} -n 1 chown "${LEGO_CERT_USER}:${LEGO_CERT_GROUP}" "{}"
|
||||||
|
@ -63,6 +63,13 @@
|
|||||||
remote_src: true
|
remote_src: true
|
||||||
when: lego_binary_info.rc != 0
|
when: lego_binary_info.rc != 0
|
||||||
|
|
||||||
|
- name: Ensure lego is allowed to bind to ports < 1024
|
||||||
|
community.general.capabilities:
|
||||||
|
path: "/usr/local/bin/lego"
|
||||||
|
capability: "cap_net_bind_service+ep"
|
||||||
|
state: present
|
||||||
|
when: lego_binary_allow_net_bind_service
|
||||||
|
|
||||||
- name: Ensure intermediate data is gone
|
- name: Ensure intermediate data is gone
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
path: "{{ item }}"
|
path: "{{ item }}"
|
||||||
|
@ -4,9 +4,10 @@ Description=Run lego (letsencrypt client in go)
|
|||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
EnvironmentFile={{ lego_base_path }}/%i.conf
|
EnvironmentFile={{ lego_base_path }}/%i.conf
|
||||||
User=acme-%i
|
User={{ lego_systemd_user }}
|
||||||
Group=acme-%i
|
Group={{ lego_systemd_group }}
|
||||||
ExecStart={{ lego_base_path }}/run.sh
|
ExecStart={{ lego_base_path }}/run.sh
|
||||||
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=basic.target
|
WantedBy=basic.target
|
||||||
|
@ -30,7 +30,8 @@ minio_container_labels: {}
|
|||||||
minio_container_command:
|
minio_container_command:
|
||||||
- "server"
|
- "server"
|
||||||
- "{{ minio_container_data_path }}"
|
- "{{ minio_container_data_path }}"
|
||||||
- "--console-address \":{{ minio_container_listen_port_console }}\""
|
- "--console-address"
|
||||||
|
- ":{{ minio_container_listen_port_console }}"
|
||||||
minio_container_restart_policy: "unless-stopped"
|
minio_container_restart_policy: "unless-stopped"
|
||||||
minio_container_image_force_source: "{{ (minio_container_image_tag == 'latest')|bool }}"
|
minio_container_image_force_source: "{{ (minio_container_image_tag == 'latest')|bool }}"
|
||||||
|
|
||||||
|
@ -59,6 +59,18 @@
|
|||||||
throttle: 1
|
throttle: 1
|
||||||
become: true
|
become: true
|
||||||
|
|
||||||
|
- name: Ensure PowerDNS is restarted
|
||||||
|
community.docker.docker_container:
|
||||||
|
name: "{{ powerdns_tsig_key_container_name }}"
|
||||||
|
state: started
|
||||||
|
restart: true
|
||||||
|
when: >-
|
||||||
|
(powerdns_tsig_key_name ~ '. ' ~ powerdns_tsig_key_algo ~ '. ')
|
||||||
|
not in powerdns_tsig_key_powerdns_info.stdout
|
||||||
|
delegate_to: "{{ powerdns_tsig_key_hostname }}"
|
||||||
|
throttle: 1
|
||||||
|
become: true
|
||||||
|
|
||||||
- name: Extract TSIG key into variable
|
- name: Extract TSIG key into variable
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
powerdns_tsig_key_key: >-
|
powerdns_tsig_key_key: >-
|
||||||
|
Reference in New Issue
Block a user