commit 0ad709f59f01ba361b804d431e9524335376d210 Author: Aaron Johnson Date: Thu Mar 5 16:50:06 2026 -0600 Initial commit of whatever junk this is diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/group_vars/all.yml b/group_vars/all.yml new file mode 100644 index 0000000..0856c74 --- /dev/null +++ b/group_vars/all.yml @@ -0,0 +1,33 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +acme_user: acme +acme_home: /var/lib/acme +acme_sh_path: /var/lib/acme/.acme.sh/acme.sh + +apache_user: apache +# apache_group: apache + +cert_base_dir: /etc/pki/tls +cert_dir: "{{ cert_base_dir }}/{{ inventory_hostname }}" + +# Change if needed +apache_service: httpd diff --git a/inventory/hosts.yml b/inventory/hosts.yml new file mode 100644 index 0000000..6f10012 --- /dev/null +++ b/inventory/hosts.yml @@ -0,0 +1,54 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +all: + hosts: + keycloak.bart.bslnaj.net: + keycloak.lisa.bslnaj.net: + # keycloak.maggie.bslnaj.net: + # nextcloud.bart.bslnaj.net: + # nextcloud.lisa.bslnaj.net: + # nextcloud.maggie.bslnaj.net: + sharedplex.bart.bslnaj.net: + ourplex.bart.bslnaj.net: + plex.maggie.bslnaj.net: + +acme_hosts: + hosts: + # keycloak.bart.bslnaj.net: + # keycloak.lisa.bslnaj.net: + # keycloak.maggie.bslnaj.net: + # nextcloud.bart.bslnaj.net: + # nextcloud.lisa.bslnaj.net: + # nextcloud.maggie.bslnaj.net: + sharedplex.bart.bslnaj.net: + ourplex.bart.bslnaj.net: + plex.maggie.bslnaj.net: + +web_servers: + hosts: + keycloak.bart.bslnaj.net: + keycloak.lisa.bslnaj.net: + # keycloak.maggie.bslnaj.net: + # nextcloud.bart.bslnaj.net: + # nextcloud.lisa.bslnaj.net: + # nextcloud.maggie.bslnaj.net: + diff --git a/roles/acme/tasks/IssueCert.yml b/roles/acme/tasks/IssueCert.yml new file mode 100644 index 0000000..b65f1aa --- /dev/null +++ b/roles/acme/tasks/IssueCert.yml @@ -0,0 +1,49 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + + +- name: Issue certificate + shell: | + . {{ acme_home }}/godaddy.env + export ACME_DEFAULT_DNS_TIMEOUT=180 + export ACME_RETRY=10 + export ACME_SLEEP=15 + {{ acme_home }}/.acme.sh/acme.sh --server letsencrypt --issue --dns dns_gd -d {{ inventory_hostname }} + become_user: "{{ acme_user }}" + args: + creates: "{{ acme_home }}/.acme.sh/{{ inventory_hostname }}_ecc/fullchain.cer" + when: hostvars[inventory_hostname].gd_key is defined + +- name: Install renewal service + template: + src: acme-renew.service.j2 + dest: /etc/systemd/system/acme-renew.service + +- name: Install renewal timer + template: + src: acme-renew.timer.j2 + dest: /etc/systemd/system/acme-renew.timer + +- name: Enable renewal timer + systemd: + name: acme-renew.timer + enabled: yes + state: started diff --git a/roles/acme/tasks/acme.yml b/roles/acme/tasks/acme.yml new file mode 100644 index 0000000..583721a --- /dev/null +++ b/roles/acme/tasks/acme.yml @@ -0,0 +1,47 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + + +- name: Install acme.sh as acme user + become_user: "{{ acme_user }}" + shell: | + curl https://get.acme.sh | sh + args: + creates: "{{ acme_home }}/.acme.sh/acme.sh" + +- name: Check if GoDaddy env file exists on remote hosts + stat: + path: "{{ acme_home }}/godaddy.env" + register: godaddy_env_file + +- name: Create GoDaddy env file + copy: + dest: "{{ acme_home }}/godaddy.env" + content: | + export GD_Key={{ hostvars[inventory_hostname].gd_key }} + export GD_Secret={{ hostvars[inventory_hostname].gd_secret }} + owner: "{{ acme_user }}" + group: "{{ acme_user }}" + mode: "0400" + when: + - hostvars[inventory_hostname].gd_key is defined + - gd_env_stat.stat.exists is not defined or not gd_env_stat.stat.exists + diff --git a/roles/acme/tasks/main.yml b/roles/acme/tasks/main.yml new file mode 100644 index 0000000..21a1a34 --- /dev/null +++ b/roles/acme/tasks/main.yml @@ -0,0 +1,24 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +- import_tasks: users.yml +- import_tasks: acme.yml +- import_tasks: systemd.yml \ No newline at end of file diff --git a/roles/acme/tasks/systemd.yml b/roles/acme/tasks/systemd.yml new file mode 100644 index 0000000..2611246 --- /dev/null +++ b/roles/acme/tasks/systemd.yml @@ -0,0 +1,59 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Sunday, 21st December 2025 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + + +- name: Issue certificate + shell: | + source {{ acme_home }}/godaddy.env + export ACME_DEFAULT_DNS_TIMEOUT=180 + export ACME_RETRY=10 + export ACME_SLEEP=15 + {{ acme_sh_path }} --server letsencrypt --issue --dns dns_gd -d {{ inventory_hostname }} + become_user: "{{ acme_user }}" + args: + creates: "{{ acme_home }}/.acme.sh/{{ inventory_hostname }}_ecc/fullchain.cer" + +- name: Install certificate + become_user: "{{ acme_user }}" + shell: | + {{ acme_sh_path }} --install-cert \ + -d {{ inventory_hostname }} \ + --key-file {{ cert_dir }}/privkey.pem \ + --fullchain-file {{ cert_dir }}/fullchain.pem \ + --reloadcmd "chmod 640 {{ cert_dir }}/privkey.pem {{ cert_dir }}/fullchain.pem && sudo /bin/systemctl reload {{ apache_service }}" + args: + creates: "{{ cert_dir }}/fullchain.pem" + +- name: Install renewal service + template: + src: acme-renew.service.j2 + dest: /etc/systemd/system/acme-renew.service + +- name: Install renewal timer + template: + src: acme-renew.timer.j2 + dest: /etc/systemd/system/acme-renew.timer + +- name: Enable renewal timer + systemd: + name: acme-renew.timer + enabled: yes + state: started diff --git a/roles/acme/tasks/users.yml b/roles/acme/tasks/users.yml new file mode 100644 index 0000000..15ea448 --- /dev/null +++ b/roles/acme/tasks/users.yml @@ -0,0 +1,36 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +- name: Create acme system user + user: + name: "{{ acme_user }}" + home: "{{ acme_home }}" + shell: /sbin/nologin + system: yes + create_home: yes + +- name: Create certificate directory + file: + path: "{{ cert_dir }}" + state: directory + owner: "{{ acme_user }}" + group: "{{ apache_group | default(omit) }}" + mode: "2750" diff --git a/roles/acme/templates/acme-renew.service.j2 b/roles/acme/templates/acme-renew.service.j2 new file mode 100644 index 0000000..39303ac --- /dev/null +++ b/roles/acme/templates/acme-renew.service.j2 @@ -0,0 +1,28 @@ +/* + * Created Date: Sunday December 21st 2025 + * Author: Aaron Johnson aaron.johnson@akamai.com + * ----- + * Last Modified: Sunday, 21st December 2025 + * Modified By: the engineer formerly known as Aaron Johnson + * ----- + * Copyright (c) 2025 Contact Author for details + * ----- + * USAGE/DOCUMENTATION: + * + * ----- + * INSTALLATION + * + * ----- + * HISTORY: + * Date By Comments + * ---------- --- --------------------------------------------------------- + */ + +[Unit] +Description=ACME certificate renewal + +[Service] +User={{ acme_user }} +Group={{ acme_user }} +EnvironmentFile={{ acme_home }}/godaddy.env +ExecStart={{ acme_sh_path }} --renew --dns dns_gd diff --git a/roles/acme/templates/acme-renew.timer.j2 b/roles/acme/templates/acme-renew.timer.j2 new file mode 100644 index 0000000..0cfcc7f --- /dev/null +++ b/roles/acme/templates/acme-renew.timer.j2 @@ -0,0 +1,30 @@ +/* + * Created Date: Sunday December 21st 2025 + * Author: Aaron Johnson aaron.johnson@akamai.com + * ----- + * Last Modified: Sunday, 21st December 2025 + * Modified By: the engineer formerly known as Aaron Johnson + * ----- + * Copyright (c) 2025 Contact Author for details + * ----- + * USAGE/DOCUMENTATION: + * + * ----- + * INSTALLATION + * + * ----- + * HISTORY: + * Date By Comments + * ---------- --- --------------------------------------------------------- + */ + +[Unit] +Description=Daily ACME renewal check + +[Timer] +OnCalendar=daily +RandomizedDelaySec=1h +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/roles/apache/files/sudoers-acme-httpd b/roles/apache/files/sudoers-acme-httpd new file mode 100644 index 0000000..25ba68a --- /dev/null +++ b/roles/apache/files/sudoers-acme-httpd @@ -0,0 +1,2 @@ +Defaults:acme secure_path=/bin:/usr/bin +acme ALL=(root) NOPASSWD: /bin/systemctl reload httpd diff --git a/roles/apache/tasks/apache.yml b/roles/apache/tasks/apache.yml new file mode 100644 index 0000000..94580d5 --- /dev/null +++ b/roles/apache/tasks/apache.yml @@ -0,0 +1,42 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Sunday, 21st December 2025 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +- name: Allow acme user to reload apache without password + copy: + dest: /etc/sudoers.d/acme-apache + content: | + {{ acme_user }} ALL=NOPASSWD: /bin/systemctl reload {{ apache_service }} + mode: "0440" + owner: root + group: root + +- name: Allow Apache to read cert directory (SELinux) + command: semanage fcontext -a -t httpd_config_t "{{ cert_dir }}(/.*)?" + args: + creates: "/etc/selinux/targeted/contexts/files/file_contexts.local" + +# - name: Apply SELinux labels +# command: restorecon -Rv "{{ cert_dir }}" + +- name: Apply SELinux labels only if incorrect + command: restorecon -Rv "{{ cert_dir }}" + register: restorecon_result + changed_when: restorecon_result.stdout_lines | select("search", "Relabeled") | list | length > 0 diff --git a/roles/apache/tasks/installCert.yml b/roles/apache/tasks/installCert.yml new file mode 100644 index 0000000..2800d1a --- /dev/null +++ b/roles/apache/tasks/installCert.yml @@ -0,0 +1,32 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +- name: Install certificate + become_user: "{{ acme_user }}" + shell: | + {{ acme_sh_path }} --install-cert \ + -d {{ inventory_hostname }} \ + --key-file {{ cert_dir }}/privkey.pem \ + --fullchain-file {{ cert_dir }}/fullchain.pem \ + --reloadcmd "chmod 640 {{ cert_dir }}/privkey.pem {{ cert_dir }}/fullchain.pem && sudo /bin/systemctl reload {{ apache_service }}" + args: + creates: "{{ cert_dir }}/fullchain.pem" + diff --git a/roles/apache/tasks/main.yml b/roles/apache/tasks/main.yml new file mode 100644 index 0000000..bdafe99 --- /dev/null +++ b/roles/apache/tasks/main.yml @@ -0,0 +1,23 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +- import_tasks: apache.yml +- import_tasks: installCert.yml diff --git a/roles/plex/tasks/installCert.yml b/roles/plex/tasks/installCert.yml new file mode 100644 index 0000000..dd8e3d4 --- /dev/null +++ b/roles/plex/tasks/installCert.yml @@ -0,0 +1,39 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +- name: Install certificate and generate PKCS#12 for Plex + become_user: "{{ acme_user }}" + shell: | + {{ acme_sh_path }} --install-cert \ + -d {{ inventory_hostname }} \ + --key-file {{ cert_dir }}/privkey.pem \ + --fullchain-file {{ cert_dir }}/fullchain.pem \ + --reloadcmd " + chmod 640 {{ cert_dir }}/privkey.pem {{ cert_dir }}/fullchain.pem && + openssl pkcs12 -export \ + -inkey {{ cert_dir }}/privkey.pem \ + -in {{ cert_dir }}/fullchain.pem \ + -out {{ cert_dir }}/{{ inventory_hostname }}.p12 \ + -password pass:{{ pkcs12_password | default('ChangeMe123!') }} && + sudo systemctl restart {{ plex_service | default('plex') }} + " + args: + creates: "{{ cert_dir }}/{{ inventory_hostname }}.p12" diff --git a/roles/plex/tasks/main.yml b/roles/plex/tasks/main.yml new file mode 100644 index 0000000..93c6cd9 --- /dev/null +++ b/roles/plex/tasks/main.yml @@ -0,0 +1,22 @@ +--- +################################################################################ +# Created Date: Sunday December 21st 2025 +# Author: Aaron Johnson aaron.johnson@akamai.com +# ----- +# Last Modified: Tuesday, 24th February 2026 +# Modified By: the engineer formerly known as Aaron Johnson +# ----- +# Copyright (c) 2025 Contact Author for details +# ----- +# USAGE/DOCUMENTATION: +# +# ----- +# INSTALLATION +# +# ----- +# HISTORY: +# Date By Comments +# ---------- --- --------------------------------------------------------- +################################################################################ + +- import_tasks: installCert.yml \ No newline at end of file diff --git a/site.yml b/site.yml new file mode 100644 index 0000000..108662d --- /dev/null +++ b/site.yml @@ -0,0 +1,90 @@ +--- +# ----------------------------- +# Play 1: Check remote env files +# ----------------------------- +- name: Check if GoDaddy env file exists on remote hosts + hosts: acme_hosts + gather_facts: false + tasks: + - name: Stat godaddy.env + stat: + path: "{{ acme_home }}/godaddy.env" + register: gd_env_stat + tags: acme + +# ----------------------------- +# Play 2: Fetch secrets from 1Password (control node) +# Only runs if any remote host is missing the env file +# ----------------------------- +- name: Fetch GoDaddy API credentials from 1Password if needed + hosts: acme_hosts + # connection: local + # delegate_to: localhost + run_once: true + gather_facts: false + vars: + op_account: my.1password.com + op_item_title: godaddy-api + tasks: + - name: Determine if fetch is needed + run_once: true + delegate_to: localhost + set_fact: + fetch_godaddy_creds: >- + {{ + groups['acme_hosts'] + | map('extract', hostvars) + | selectattr('gd_env_stat.stat.exists','equalto',false) + | list + | length > 0 + }} + + - name: Get GD_Key and GD_Secret from 1Password + run_once: true + delegate_to: localhost + command: op item get "{{ op_item_title }}" --account {{ op_account }} --fields username,credential --reveal + register: godaddy_creds_raw + changed_when: false + when: fetch_godaddy_creds + + - name: Split GD_Key and GD_Secret + run_once: true + # delegate_to: localhost + set_fact: + gd_key: "{{ godaddy_creds_raw.stdout.split(',')[0] }}" + gd_secret: "{{ godaddy_creds_raw.stdout.split(',')[1] }}" + when: fetch_godaddy_creds + + - name: Add GD_Key and GD_Secret to hostvars for remote hosts + run_once: true + # delegate_to: localhost + add_host: + name: "{{ item }}" + gd_key: "{{ gd_key }}" + gd_secret: "{{ gd_secret }}" + loop: "{{ groups['all'] }}" + when: fetch_godaddy_creds + tags: acme + +# ----------------------------- +# Play 2: Run role on remote hosts +# ----------------------------- +- name: ACME + Apache TLS bootstrap + hosts: all + become: true + roles: + - apache + +- name: ACME + hosts: all + become: true + roles: + - acme + tags: acme + +- name: plex + hosts: all + become: true + roles: + - plex + tags: plex \ No newline at end of file