diff --git a/filter_plugins/acmedns_to_lego.py b/filter_plugins/acmedns_to_lego.py new file mode 100644 index 0000000..76a24cd --- /dev/null +++ b/filter_plugins/acmedns_to_lego.py @@ -0,0 +1,18 @@ +class FilterModule(object): + def filters(self): + return { + 'acmedns_to_lego': self.acmedns_to_lego, + } + + def acmedns_to_lego(self, acmedns_registered): + result = {} + for (key, value) in acmedns_registered.items(): + result[key] = { + "fulldomain": value["subd"] + "." + value["host"], + "subdomain": value["subd"], + "username": value["user"], + "password": value["pass"], + "server_url": "https://" + value["host"] + } + + return result diff --git a/node002.yml b/node002.yml index 6d4ddc3..0a9cb22 100644 --- a/node002.yml +++ b/node002.yml @@ -6,6 +6,8 @@ tags: [always] - role: backup tags: [backup] + - role: lego + tags: [lego, certificates] - role: caddy tags: [caddy, reverse-proxy, webserver] vars: @@ -38,6 +40,8 @@ tags: [influxdb, sensors, monitoring] - role: jellyfin tags: [jellyfin, media] + - role: ntfy + tags: [ntfy, notifications, push] - role: reitanlage_oranienburg tags: [reitanlage-oranienburg, website] - role: synapse diff --git a/roles/lego/files/hook.sh b/roles/lego/files/hook.sh new file mode 100644 index 0000000..b060634 --- /dev/null +++ b/roles/lego/files/hook.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +cp -f "$LEGO_CERT_PATH" /certificates +cp -f "$LEGO_CERT_KEY_PATH" /certificates + +exit 33 # special exit code to signal that the certificate has been updated diff --git a/roles/lego/files/lego.sh b/roles/lego/files/lego.sh new file mode 100755 index 0000000..f6a4a04 --- /dev/null +++ b/roles/lego/files/lego.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env sh + +domain="$1" +action="${2:-renew}" + +docker compose run --rm app \ + --domains "$domain" \ + "$action" \ + "--$action-hook" "/config/hook.sh" + +if [ "$?" = "33" ] && [ -x "./lego.d/$domain" ]; +then + echo "Running hook for $domain" + "./lego.d/$domain" +fi diff --git a/roles/lego/files/lego@.timer b/roles/lego/files/lego@.timer new file mode 100644 index 0000000..284347f --- /dev/null +++ b/roles/lego/files/lego@.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Renew certificates + +[Timer] +Persistent=true +OnCalendar=*-*-* 01:15:00 +RandomizedDelaySec=2h + +[Install] +WantedBy=timers.target diff --git a/roles/lego/files/node002/db.serguzim.me b/roles/lego/files/node002/db.serguzim.me new file mode 100755 index 0000000..09602b9 --- /dev/null +++ b/roles/lego/files/node002/db.serguzim.me @@ -0,0 +1,16 @@ +#!/usr/bin/env sh + +domain="db.serguzim.me" + +docker compose run --rm app "$1" "$domain" + +_install() { + install --owner=postgres --group=postgres --mode=600 \ + "/opt/services/_certificates/$domain.$1" \ + "/var/lib/postgresql/server.$1" +} + +_install crt +_install key + +sudo -u postgres pg_ctl -D /var/lib/postgres/data/ reload diff --git a/roles/lego/files/node002/registry.serguzim.me b/roles/lego/files/node002/registry.serguzim.me new file mode 100755 index 0000000..09e444c --- /dev/null +++ b/roles/lego/files/node002/registry.serguzim.me @@ -0,0 +1,17 @@ +#!/usr/bin/env sh + +domain="registry.serguzim.me" + +docker compose run --rm app "$1" "$domain" + +_install() { + install --owner=root --group=root --mode=600 \ + "/opt/services/_certificates/$domain.$1" \ + "/opt/services/harbor/server.$1" +} + +_install crt +_install key + +export HARBOR_BUNDLE_DIR=/opt/services/harbor +$HARBOR_BUNDLE_DIR/data/install.sh diff --git a/roles/lego/tasks/config.yml b/roles/lego/tasks/config.yml new file mode 100644 index 0000000..266efcb --- /dev/null +++ b/roles/lego/tasks/config.yml @@ -0,0 +1,19 @@ +--- +- name: Set config path + ansible.builtin.set_fact: + config_path: "{{ (service_path, 'config') | path_join }}" +- name: Create config directory + ansible.builtin.file: + path: "{{ config_path }}" + state: directory + mode: "0755" +- name: Copy the acme-dns-accounts + ansible.builtin.template: + src: "json.j2" + dest: "{{ (config_path, 'acme-dns-accounts.json') | path_join }}" + mode: "0644" +- name: Copy the hook script + ansible.builtin.copy: + src: "hook.sh" + dest: "{{ (config_path, 'hook.sh') | path_join }}" + mode: "0755" diff --git a/roles/lego/tasks/lego.d.yml b/roles/lego/tasks/lego.d.yml new file mode 100644 index 0000000..04acb4b --- /dev/null +++ b/roles/lego/tasks/lego.d.yml @@ -0,0 +1,16 @@ +--- +- name: Set lego.d path + ansible.builtin.set_fact: + lego_d_path: "{{ (service_path, 'lego.d') | path_join }}" +- name: Create lego.d directory + ansible.builtin.file: + path: "{{ lego_d_path }}" + state: directory + mode: "0755" +- name: Copy the additional lego scripts + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ lego_d_path }}" + mode: "0755" + with_fileglob: + - "{{ ansible_facts.hostname }}/*" diff --git a/roles/lego/tasks/main.yml b/roles/lego/tasks/main.yml new file mode 100644 index 0000000..3dc6de1 --- /dev/null +++ b/roles/lego/tasks/main.yml @@ -0,0 +1,35 @@ +--- +- name: Set common facts + ansible.builtin.import_tasks: tasks/set-default-facts.yml + +- name: Deploy {{ svc.name }} + vars: + svc: "{{ lego_svc }}" + env: "{{ lego_env }}" + json: "{{ vault_acmedns_registered | acmedns_to_lego }}" + compose: "{{ lego_compose }}" + block: + - name: Import prepare tasks for common service + ansible.builtin.import_tasks: tasks/prepare-common-service.yml + + - name: Create _certificates directory + ansible.builtin.file: + path: "{{ certificates_path }}" + state: directory + mode: "0755" + + - name: Import tasks specific to the config directory + ansible.builtin.import_tasks: config.yml + - name: Import tasks specific to lego.d + ansible.builtin.import_tasks: lego.d.yml + - name: Import tasks specific to systemd + ansible.builtin.import_tasks: systemd.yml + + - name: Copy the run script + ansible.builtin.copy: + src: "lego.sh" + dest: "{{ (service_path, 'lego.sh') | path_join }}" + mode: "0755" + + - name: Import tasks create a service.env file + ansible.builtin.import_tasks: tasks/steps/template-service-env.yml diff --git a/roles/lego/tasks/systemd.yml b/roles/lego/tasks/systemd.yml new file mode 100644 index 0000000..21e99bf --- /dev/null +++ b/roles/lego/tasks/systemd.yml @@ -0,0 +1,23 @@ +--- +- name: Copy the system service + ansible.builtin.template: + src: lego@.service.j2 + dest: /etc/systemd/system/lego@.service + mode: "0644" + become: true +- name: Copy the system timer + ansible.builtin.copy: + src: lego@.timer + dest: /etc/systemd/system/lego@.timer + mode: "0644" + become: true +- name: Enable the system timer for {{ item }} + ansible.builtin.systemd_service: + name: lego@{{ item }}.timer + state: started + enabled: true + daemon_reload: true + loop: + - db.serguzim.me + - registry.serguzim.me + become: true diff --git a/roles/lego/templates/lego@.service.j2 b/roles/lego/templates/lego@.service.j2 new file mode 100644 index 0000000..4b310f2 --- /dev/null +++ b/roles/lego/templates/lego@.service.j2 @@ -0,0 +1,4 @@ +[Service] +Type=oneshot +ExecStart={{ service_path }}/lego.sh %i +WorkingDirectory={{ service_path }} diff --git a/roles/lego/vars/main.yml b/roles/lego/vars/main.yml new file mode 100644 index 0000000..460fb79 --- /dev/null +++ b/roles/lego/vars/main.yml @@ -0,0 +1,31 @@ +--- +lego_svc: + name: lego + +lego_env: + ACME_DNS_API_BASE: https://{{ acme_dns.host }} + ACME_DNS_STORAGE_PATH: /config/acme-dns-accounts.json + + LEGO_EMAIL: "{{ admin_email }}" + LEGO_PATH: /data + +lego_compose: + watchtower: false + network: false + image: goacme/lego + volumes: + - ./config:/config:ro + - "{{ certificates_path }}:/certificates" + - data:/data + file: + services: + app: + restart: never + network_mode: "host" + entrypoint: + - /lego + - --accept-tos + - --email={{ admin_email }} + - --dns=acme-dns + volumes: + data: diff --git a/roles/ntfy/tasks/main.yml b/roles/ntfy/tasks/main.yml new file mode 100644 index 0000000..4026612 --- /dev/null +++ b/roles/ntfy/tasks/main.yml @@ -0,0 +1,12 @@ +--- +- name: Set common facts + ansible.builtin.import_tasks: tasks/set-default-facts.yml + +- name: Deploy {{ svc.name }} + vars: + svc: "{{ ntfy_svc }}" + compose: "{{ ntfy_compose }}" + env: "{{ ntfy_env }}" + block: + - name: Import tasks to deploy common service + ansible.builtin.import_tasks: tasks/deploy-common-service.yml diff --git a/roles/ntfy/vars/main.yml b/roles/ntfy/vars/main.yml new file mode 100644 index 0000000..b881fe4 --- /dev/null +++ b/roles/ntfy/vars/main.yml @@ -0,0 +1,55 @@ +--- +ntfy_svc: + name: ntfy + domain: push.serguzim.me + port: 80 + +ntfy_env: + TZ: "{{ timezone }}" + + NTFY_BASE_URL: "https://{{ ntfy_svc.domain }}" + + NTFY_CACHE_FILE: /var/cache/ntfy/cache.db + NTFY_CACHE_DURATION: "12h" + + NTFY_BEHIND_PROXY: true + + NTFY_AUTH_FILE: /var/lib/ntfy/user.db + NTFY_AUTH_DEFAULT_ACCESS: "deny-all" + + NTFY_ATTACHMENT_CACHE_DIR: "/var/cache/ntfy/attachments" + NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT: "5G" + NTFY_ATTACHMENT_FILE_SIZE_LIMIT: "15M" + NTFY_ATTACHMENT_EXPIRY_DURATION: "3h" + + NTFY_KEEPALIVE_INTERVAL: "45s" + NTFY_MANAGER_INTERVAL: "60m" + + NTFY_ENABLE_SIGNUP: false + NTFY_ENABLE_LOGIN: true + NTFY_ENABLE_RESERVATIONS: true + + NTFY_GLOBAL_TOPIC_LIMIT: 15000 + + NTFY_VISITOR_SUBSCRIPTION_LIMIT: 30 + NTFY_VISITOR_REQUEST_LIMIT_BURST: 60 + NTFY_VISITOR_REQUEST_LIMIT_REPLENISH: "5s" + NTFY_VISITOR_ATTACHMENT_TOTAL_SIZE_LIMIT: "100M" + NTFY_VISITOR_ATTACHMENT_DAILY_BANDWIDTH_LIMIT: "500M" + + NTFY_ENABLE_METRICS: true + +ntfy_compose: + watchtower: true + image: binwiederhier/ntfy + volumes: + - cache:/var/cache/ntfy + - data:/var/lib/ntfy + file: + services: + app: + command: + - serve + volumes: + cache: + data: diff --git a/roles/telegraf/templates/telegraf.conf.j2 b/roles/telegraf/templates/telegraf.conf.j2 index 9b4c404..654b933 100644 --- a/roles/telegraf/templates/telegraf.conf.j2 +++ b/roles/telegraf/templates/telegraf.conf.j2 @@ -18,12 +18,19 @@ [[inputs.prometheus]] urls = [ - {%- for url in svc.prometheus.urls -%} + {%- for url in svc.prometheus_unprotected.urls -%} "{{ url }}", {%- endfor -%} ] - bearer_token_string = "{{ svc.prometheus.bearer_token }}" +[[inputs.prometheus]] + urls = [ + {%- for url in svc.prometheus_protected.urls -%} + "{{ url }}", + {%- endfor -%} + ] + + bearer_token_string = "{{ svc.prometheus_protected.bearer_token }}" [[inputs.postgresql]] address = "postgres://{{ svc.postgresql.user }}:{{ svc.postgresql.pass }}@{{ svc.postgresql.host }}:{{ svc.postgresql.port }}/{{ svc.postgresql.database }}?sslmode=verify-full" diff --git a/roles/telegraf/vars/main.yml b/roles/telegraf/vars/main.yml index 887c8b7..a110aa0 100644 --- a/roles/telegraf/vars/main.yml +++ b/roles/telegraf/vars/main.yml @@ -6,12 +6,15 @@ telegraf_svc: token: "{{ vault_telegraf.influxdb_token }}" organization: serguzim.net bucket: metrics - prometheus: + prometheus_unprotected: + urls: + - https://matrix.msrg.cc/_synapse/metrics + - https://push.serguzim.me/metrics + - https://tick.serguzim.me/metrics + prometheus_protected: urls: - https://ci.serguzim.me/metrics - https://git.serguzim.me/metrics - - https://matrix.msrg.cc/_synapse/metrics - - https://tick.serguzim.me/metrics bearer_token: "{{ vault_metrics_token }}" postgresql: user: "{{ vault_telegraf.db.user }}"