first commit

This commit is contained in:
sujiba 2024-09-17 00:45:38 +02:00
commit cfe7db8716
8 changed files with 370 additions and 0 deletions

29
README.md Normal file
View file

@ -0,0 +1,29 @@
# acme.sh
Thanks to [gmk/ansible-role-acme_sh](https://codeberg.org/gmk/ansible-role-acme_sh)
Install acme.sh with ansible.
## Configuration
```
# netcup settings
netcup_user: ID
netcup_api_key: KEY
netcup_api_password: PASSWORD
# certificate settings
acmesh_email: hostmaster@example.com
acme_domains:
- domain: example.com
keylength: ec-384
reloadcmd: "sudo systemctl reload nginx.service"
dnssleep: 900
- domain: example.org
san:
- www.example.com
- host.example.com
keylength: 3072
staging: true
key_group: www-data
key_mode: "0640"
```

26
defaults/main.yml Normal file
View file

@ -0,0 +1,26 @@
---
# defaults file for acme.sh
# netcup settings
# netcup_user: ID
# netcup_api_key: KEY
# netcup_api_password: PASSWORD
# certificate settings
# Add wildcards as san
# tls_cert_path: /etc/ssl/acme
# acmesh_email: hostmaster@example.com
# acme_domains:
# - domain: example.com
# san:
# - "*.example.com"
# keylength: ec-384
# reloadcmd: "sudo systemctl reload nginx.service"
# dnssleep: 900
# - domain: example.org
# san:
# - www.example.com
# - host.example.com
# keylength: 3072
# staging: true
# key_group: www-data
# key_mode: "0640"

11
handlers/main.yml Normal file
View file

@ -0,0 +1,11 @@
---
# handlers file for acme.sh
- name: Reload systemd daemon
ansible.builtin.systemd:
daemon_reload: true
- name: Restart acme_sh systemd timer
ansible.builtin.systemd:
name: acme_sh.timer
scope: system
state: restarted

52
meta/main.yml Normal file
View file

@ -0,0 +1,52 @@
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.1
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
#
# Provide a list of supported platforms, and for each platform a list of versions.
# If you don't wish to enumerate all versions for a particular platform, use 'all'.
# To view available platforms and versions (or releases), visit:
# https://galaxy.ansible.com/api/v1/platforms/
#
# platforms:
# - name: Fedora
# versions:
# - all
# - 25
# - name: SomePlatform
# versions:
# - all
# - 1.0
# - 7
# - 99.99
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.

213
tasks/main.yml Normal file
View file

@ -0,0 +1,213 @@
---
# tasks file for acme.sh
- name: Create system acme group
become: true
ansible.builtin.group:
name: "{{ acme_group }}"
state: present
system: true
- name: Create system acme user
become: true
ansible.builtin.user:
name: "{{ acme_user }}"
group: "{{ acme_group }}"
home: "{{ acme_home }}"
shell: "{{ acme_shell }}"
state: present
system: true
create_home: true
skeleton: false
- name: Ensure directories exist
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
owner: "{{ acme_user }}"
group: "{{ acme_group }}"
loop:
- "{{ acme_home }}"
- "{{ acmesh_config_path }}"
- "{{ acmesh_install_path }}"
- "{{ acmesh_cert_path }}"
- name: Check acme.sh installation
ansible.builtin.stat:
path: "{{ acmesh_config_path }}/account.conf"
register: stat_account_conf
- name: Download and install acme.sh
when: not stat_account_conf.stat.exists
become: true
become_method: su
become_user: "{{ acme_user }}"
become_flags: '-s /bin/sh'
become_exe: "sudo su"
block:
- name: Create temporary directory for git repository
ansible.builtin.tempfile:
state: directory
prefix: acmesh_git_
register: acme_tmp_repo
changed_when: false
- name: Temporary clone acme.sh git repository
ansible.builtin.git:
dest: "{{ acme_tmp_repo.path }}"
clone: true
depth: 1
repo: "{{ acmesh_repository }}"
version: "{{ acmesh_version }}"
changed_when: false
- name: Make install script executable
ansible.builtin.file:
path: "{{ acme_tmp_repo.path }}/acme.sh"
mode: "0744"
owner: acme
group: acme
- name: Install acme.sh
ansible.builtin.command:
cmd: >
"{{ acme_tmp_repo.path }}/acme.sh"
--install
--home "{{ acmesh_install_path }}"
--config-home "{{ acmesh_config_path }}"
--cert-home "{{ acmesh_cert_path }}"
--accountemail "{{ acmesh_email | mandatory }}"
--nocron
chdir: "{{ acme_tmp_repo.path }}"
creates: "{{ acmesh_config_path }}/account.conf"
always:
- name: Delete temporary git clone
ansible.builtin.file:
path: "{{ acme_tmp_repo.path }}"
state: absent
changed_when: false
- name: "Set default CA [letsencrypt]"
ansible.builtin.lineinfile:
path: "{{ acmesh_config_path }}/account.conf"
regexp: '^DEFAULT_ACME_SERVER='
line: "DEFAULT_ACME_SERVER='https://acme-v02.api.letsencrypt.org/directory'"
- name: Create sudo config file
ansible.builtin.file:
path: "/etc/sudoers.d/60_user_{{ acme_user }}"
state: touch
mode: "0440"
owner: root
group: root
access_time: preserve
modification_time: preserve
- name: Configure sudo permissions
become: true
ansible.builtin.lineinfile:
path: "/etc/sudoers.d/60_user_{{ acme_user }}"
line: "{{ acme_user }} ALL=(ALL:ALL) NOPASSWD: /usr/bin/{{ item.reloadcmd | regex_replace('^sudo (.*)$', '\\1') }}"
state: present
validate: /usr/sbin/visudo -csf %s
loop: "{{ acme_domains }}"
when: acme_domains is defined
- name: Ensure directories exist
become: true
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
owner: "{{ acme_user }}"
group: "{{ acme_group }}"
loop:
- "{{ tls_cert_path }}"
- name: Issue and install certificate
when: acme_domains is defined
become: true
become_method: su
become_user: "{{ acme_user }}"
become_flags: '-s /bin/sh'
become_exe: "sudo su"
block:
- name: Issue certificate with Netcup
ansible.builtin.command:
cmd: >
"{{ acmesh_install_path }}/acme.sh"
--issue
--dns dns_netcup
-d "{{ item.domain }}"
{% if item.san is defined %}
{% for san in item.san %}
-d "{{ san }}"
{% endfor %}
{% endif %}
{% if item.keylength is defined %}
--keylength "{{ item.keylength }}"
{% endif %}
{% if item.staging is defined %}
--staging
{% endif %}
{% if item.dnssleep is defined %}
--dnssleep {{ item.dnssleep }}
{% endif %}
creates: "{{ acmesh_cert_path }}/{{ item.domain }}_ecc/{{ item.domain }}.cer"
environment:
LE_WORKING_DIR: "{{ acmesh_install_path }}"
LE_CONFIG_HOME: "{{ acmesh_config_path }}"
NC_CID: "{{ netcup_user | mandatory }}"
NC_Apikey: "{{ netcup_api_key | mandatory }}"
NC_Apipw: "{{ netcup_api_password | mandatory }}"
loop: "{{ acme_domains }}"
- name: Install certificates
ansible.builtin.command:
cmd: >
"{{ acmesh_install_path }}/acme.sh"
--installcert
-d "{{ item.domain }}"
{% if 'ec' in item.keylength %}
--ecc
{% endif %}
--cert-file "{{ tls_cert_path }}/{{ item.domain }}.crt"
--key-file "{{ tls_cert_path }}/{{ item.domain }}.key"
--ca-file "{{ tls_cert_path }}/{{ item.domain }}.ca"
--fullchain-file "{{ tls_cert_path }}/{{ item.domain }}.fullchain"
{% if item.reloadcmd is defined %}
--reloadcmd '{{ item.reloadcmd }}'
{% endif %}
creates: "{{ tls_cert_path }}/{{ item.domain }}.crt"
environment:
LE_WORKING_DIR: "{{ acmesh_install_path }}"
LE_CONFIG_HOME: "{{ acmesh_config_path }}"
loop: "{{ acme_domains }}"
- name: Install systemd service
ansible.builtin.template:
src: acme_sh.service.j2
dest: /etc/systemd/system/acme_sh.service
owner: root
group: root
mode: "0644"
notify: Reload systemd daemon
- name: Install systemd timer
ansible.builtin.template:
src: acme_sh.timer.j2
dest: /etc/systemd/system/acme_sh.timer
owner: root
group: root
mode: "0644"
notify:
- Reload systemd daemon
- Restart acme_sh systemd timer
- name: Enable systemd timer
ansible.builtin.systemd:
name: acme_sh.timer
enabled: true
scope: system
state: started

View file

@ -0,0 +1,14 @@
#jinja2: lstrip_blocks: True
# {{ ansible_managed }}
[Unit]
Description=Renew certificates using acme.sh
After=network-online.target
[Service]
Type=oneshot
ExecStart={{ acmesh_install_path }}/acme.sh --cron --home {{ acmesh_install_path }} --config-home {{ acmesh_config_path }}
User={{ acme_user }}
Group={{ acme_group }}
SuccessExitStatus=0 2

View file

@ -0,0 +1,13 @@
#jinja2: lstrip_blocks: True
# {{ ansible_managed }}
[Unit]
Description=Daily Renew certificates using acme.sh
[Timer]
OnCalendar=*-*-* 04:00
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target

12
vars/main.yml Normal file
View file

@ -0,0 +1,12 @@
---
acme_user: acme
acme_group: acme
acme_home: /opt/acme
acme_shell: /usr/sbin/nologin
acmesh_install_path: "{{ acme_home }}/acme.sh"
acmesh_config_path: "{{ acme_home }}/config"
acmesh_cert_path: "{{ acme_home }}/certs"
acmesh_repository: https://github.com/acmesh-official/acme.sh.git
acmesh_version: 3.0.7