mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 11:03:59 +00:00
feat(certs): add acme.sh DNS-01 role and cert-manager playbook for LE
- New acme role: installs acme.sh, issues certs for myrddin/merlin/gandalf via DNS-01 (name.com API), installs cert files to /etc/ssl/certs/prole/, sets up renewal cron. rc=2 (already valid) treated as ok. - New playbooks/acme.yml: runs acme role on myrddin (issues all 3 host certs) - New playbooks/certmgr.yml: cert-manager and letsencrypt-prod ClusterIssuer (HTTP-01/Traefik) for external endpoints (db/svc/api.prole.org) - Add vault references for name.com API creds to group_vars/all/vars.yml - Add prole_ssl_src_dir and prole_ssl_files to myrddin/merlin/gandalf host_vars Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6f506a97b2
commit
86990af9c8
@ -28,6 +28,10 @@ ptr_records:
|
||||
|
||||
rsyslog_server: myrddin.prole.org
|
||||
|
||||
# name.com API credentials for acme.sh DNS-01 (values from vault)
|
||||
acme_namecom_username: "{{ vault_namecom_username }}"
|
||||
acme_namecom_token: "{{ vault_namecom_token }}"
|
||||
|
||||
# Prole management
|
||||
prole_home: "/opt/prole"
|
||||
prole_repo_url: "https://github.com/prole-org/prole.git"
|
||||
|
||||
@ -35,4 +35,9 @@ iscsi_targets:
|
||||
path: /synology/d005
|
||||
device: /dev/disk/by-path/ip-10.0.0.203:3260-iscsi-iqn.2000-01.com.synology:synology.Target-14.292d45194a1-lun-1-part1
|
||||
fstype: ext4
|
||||
opts: "_netdev,noatime,nofail"
|
||||
opts: "_netdev,noatime,nofail"
|
||||
|
||||
prole_ssl_src_dir: /etc/ssl/certs/prole
|
||||
prole_ssl_files:
|
||||
- gandalf.crt
|
||||
- gandalf.key
|
||||
@ -83,3 +83,8 @@ iscsi_targets:
|
||||
src: "UUID=45143352-142d-4e47-8508-9eb84c4c1f29"
|
||||
|
||||
iscsi_absent_mounts: []
|
||||
|
||||
prole_ssl_src_dir: /etc/ssl/certs/prole
|
||||
prole_ssl_files:
|
||||
- merlin.crt
|
||||
- merlin.key
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
prole_ssl_src_dir: /etc/ssl/certs/prole
|
||||
prole_ssl_files:
|
||||
- myrddin-registry.crt
|
||||
- myrddin-registry.key
|
||||
|
||||
iscsi_portal: 10.0.0.203
|
||||
|
||||
iscsi_targets:
|
||||
|
||||
6
infrastructure/playbooks/acme.yml
Normal file
6
infrastructure/playbooks/acme.yml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
- name: Issue and install internal host certs via acme.sh (DNS-01 / name.com)
|
||||
hosts: myrddin.prole.org
|
||||
become: true
|
||||
roles:
|
||||
- acme
|
||||
14
infrastructure/playbooks/certmgr.yml
Normal file
14
infrastructure/playbooks/certmgr.yml
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
# Ensures cert-manager is installed and the letsencrypt-prod ClusterIssuer
|
||||
# (HTTP-01 / Traefik) is configured in the k3s cluster.
|
||||
# The multi-SAN cert for db/svc/api/git.prole.org is issued automatically
|
||||
# by cert-manager once prole-svc-ingress.yaml is applied (annotation-driven).
|
||||
- name: Ensure cert-manager and letsencrypt-prod ClusterIssuer
|
||||
hosts: k3s_servers
|
||||
become: true
|
||||
tasks:
|
||||
- name: Install cert-manager
|
||||
ansible.builtin.include_tasks: "{{ playbook_dir }}/../roles/k3s/tasks/certmgr.yml"
|
||||
|
||||
- name: Configure ACME ClusterIssuer and service certificate
|
||||
ansible.builtin.include_tasks: "{{ playbook_dir }}/../roles/k3s/tasks/acme_cert.yml"
|
||||
27
infrastructure/roles/acme/defaults/main.yml
Normal file
27
infrastructure/roles/acme/defaults/main.yml
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
acme_install_dir: /opt/acme.sh
|
||||
acme_email: "admin@prole.org"
|
||||
acme_namecom_username: ""
|
||||
acme_namecom_token: ""
|
||||
|
||||
# Certs to issue and where to install them on the host.
|
||||
# src paths are relative to the acme.sh cert dir for each domain.
|
||||
acme_certs:
|
||||
- domain: myrddin.prole.org
|
||||
install:
|
||||
- src: fullchain.cer
|
||||
dest: /etc/ssl/certs/prole/myrddin-registry.crt
|
||||
- src: myrddin.prole.org.key
|
||||
dest: /etc/ssl/certs/prole/myrddin-registry.key
|
||||
- domain: merlin.prole.org
|
||||
install:
|
||||
- src: fullchain.cer
|
||||
dest: /etc/ssl/certs/prole/merlin.crt
|
||||
- src: merlin.prole.org.key
|
||||
dest: /etc/ssl/certs/prole/merlin.key
|
||||
- domain: gandalf.prole.org
|
||||
install:
|
||||
- src: fullchain.cer
|
||||
dest: /etc/ssl/certs/prole/gandalf.crt
|
||||
- src: gandalf.prole.org.key
|
||||
dest: /etc/ssl/certs/prole/gandalf.key
|
||||
5
infrastructure/roles/acme/handlers/main.yml
Normal file
5
infrastructure/roles/acme/handlers/main.yml
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
# Stub — extend when services consuming the certs need reloading (e.g. registry, nginx)
|
||||
- name: reload prole ssl consumers
|
||||
ansible.builtin.debug:
|
||||
msg: "Certs renewed — restart any services that consume /etc/ssl/certs/prole/ as needed."
|
||||
85
infrastructure/roles/acme/tasks/main.yml
Normal file
85
infrastructure/roles/acme/tasks/main.yml
Normal file
@ -0,0 +1,85 @@
|
||||
---
|
||||
- name: Ensure /etc/ssl/certs/prole exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/ssl/certs/prole
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0750"
|
||||
|
||||
- name: Ensure git is installed (required for acme.sh clone)
|
||||
ansible.builtin.apt:
|
||||
name: git
|
||||
state: present
|
||||
|
||||
- name: Check if acme.sh is already installed
|
||||
ansible.builtin.stat:
|
||||
path: "{{ acme_install_dir }}/acme.sh"
|
||||
register: acme_sh_stat
|
||||
|
||||
- name: Clone acme.sh
|
||||
ansible.builtin.git:
|
||||
repo: https://github.com/acmesh-official/acme.sh.git
|
||||
dest: /tmp/acme.sh-src
|
||||
depth: 1
|
||||
when: not acme_sh_stat.stat.exists
|
||||
|
||||
- name: Install acme.sh
|
||||
ansible.builtin.command: >-
|
||||
./acme.sh --install
|
||||
--home {{ acme_install_dir }}
|
||||
--accountemail {{ acme_email }}
|
||||
--nocron
|
||||
args:
|
||||
chdir: /tmp/acme.sh-src
|
||||
creates: "{{ acme_install_dir }}/acme.sh"
|
||||
when: not acme_sh_stat.stat.exists
|
||||
|
||||
- name: Set default CA to Let's Encrypt
|
||||
ansible.builtin.command: "{{ acme_install_dir }}/acme.sh --set-default-ca --server letsencrypt"
|
||||
changed_when: false
|
||||
|
||||
- name: Check existing cert status
|
||||
ansible.builtin.command: "{{ acme_install_dir }}/acme.sh --list"
|
||||
register: acme_list
|
||||
changed_when: false
|
||||
|
||||
- name: Issue certs via DNS-01 (name.com) — skip if already issued
|
||||
ansible.builtin.command: >-
|
||||
{{ acme_install_dir }}/acme.sh --issue
|
||||
--dns dns_namecom
|
||||
-d {{ item.domain }}
|
||||
--home {{ acme_install_dir }}
|
||||
environment:
|
||||
NAMECOM_Username: "{{ acme_namecom_username }}"
|
||||
NAMECOM_Token: "{{ acme_namecom_token }}"
|
||||
loop: "{{ acme_certs }}"
|
||||
register: acme_issue
|
||||
changed_when: "'Cert success' in acme_issue.stdout"
|
||||
# rc=2 means cert already exists and is not due for renewal — treat as ok
|
||||
failed_when: acme_issue.rc not in [0, 2]
|
||||
when: item.domain not in acme_list.stdout
|
||||
|
||||
- name: Install cert files to target paths
|
||||
ansible.builtin.command: >-
|
||||
{{ acme_install_dir }}/acme.sh --install-cert
|
||||
-d {{ item.domain }}
|
||||
--home {{ acme_install_dir }}
|
||||
--fullchain-file {{ (item.install | selectattr('src', 'equalto', 'fullchain.cer') | first).dest }}
|
||||
--key-file {{ (item.install | selectattr('src', 'match', '.*\\.key$') | first).dest }}
|
||||
loop: "{{ acme_certs }}"
|
||||
notify: reload prole ssl consumers
|
||||
|
||||
- name: Fix permissions on installed cert files
|
||||
ansible.builtin.file:
|
||||
path: "{{ file_item.dest }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "{{ '0600' if file_item.dest.endswith('.key') else '0644' }}"
|
||||
loop: "{{ acme_certs | map(attribute='install') | flatten }}"
|
||||
loop_control:
|
||||
loop_var: file_item
|
||||
|
||||
- name: Install acme.sh renewal cron
|
||||
ansible.builtin.command: "{{ acme_install_dir }}/acme.sh --install-cronjob"
|
||||
changed_when: false
|
||||
Loading…
Reference in New Issue
Block a user