From 044ee49795911f8da7a9df0c4ab816d8f98b47e1 Mon Sep 17 00:00:00 2001 From: transcaffeine Date: Thu, 25 Dec 2025 15:34:14 +0100 Subject: [PATCH] feat(caddy_site): add ansible role for configuring sites using caddy --- playbooks/caddy_reverse_proxy.yml | 24 ++++++++++++++++++++++++ roles/caddy_site/README.md | 7 +++++++ roles/caddy_site/defaults/main.yml | 13 +++++++++++++ roles/caddy_site/meta/main.yml | 11 +++++++++++ roles/caddy_site/tasks/main.yml | 26 ++++++++++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 playbooks/caddy_reverse_proxy.yml create mode 100644 roles/caddy_site/README.md create mode 100644 roles/caddy_site/defaults/main.yml create mode 100644 roles/caddy_site/meta/main.yml create mode 100644 roles/caddy_site/tasks/main.yml diff --git a/playbooks/caddy_reverse_proxy.yml b/playbooks/caddy_reverse_proxy.yml new file mode 100644 index 0000000..5431297 --- /dev/null +++ b/playbooks/caddy_reverse_proxy.yml @@ -0,0 +1,24 @@ +--- +- name: Ensure reverse proxy configuration is created + hosts: "{{ target_hosts }}" + become: "{{ target_become | default(false) }}" + gather_facts: "{{ target_gather_facts | default(false) }}" + roles: + - role: finallycoffee.base.caddy_site + vars: + caddy_site_cert_basepath: >-2 + {{ caddy_site_tls_store | default('/tls') }}/{{ caddy_site_name }}/certificates/{{ caddy_site_name }} + caddy_site_config: |+2 + https://{{ caddy_site_name }} { + tls {{ caddy_site_cert_basepath}}.crt {{ caddy_site_cert_basepath }}.key + header { + Strict-Transport-Security "max-age=31536000" + } + encode zstd gzip + reverse_proxy {{ caddy_reverse_proxy_backend_addr | mandatory }} { + {% if caddy_reverse_proxy_import_proxyheaders | default(true, true) -%} + import proxyheaders + {%- endif +%} + } + } + diff --git a/roles/caddy_site/README.md b/roles/caddy_site/README.md new file mode 100644 index 0000000..71a226d --- /dev/null +++ b/roles/caddy_site/README.md @@ -0,0 +1,7 @@ +# `finallycoffee.base.caddy_site` ansible role + +Provision a single site configuration in caddy. + +Set `caddy_site_name` as a unique +site identifier (needs to be a valid filename) and `caddy_site_config` +to contain the actual `Caddyfile` contents. diff --git a/roles/caddy_site/defaults/main.yml b/roles/caddy_site/defaults/main.yml new file mode 100644 index 0000000..3783533 --- /dev/null +++ b/roles/caddy_site/defaults/main.yml @@ -0,0 +1,13 @@ +--- +caddy_site_name: ~ +caddy_site_config: ~ +caddy_site_state: "present" + +caddy_site_configs: "/etc/caddy/sites.d" +caddy_site_config_dir: >-2 + {{ caddy_site_configs }}/{{ caddy_site_name }} +caddy_site_config_file: >-2 + {{ caddy_site_config_dir }}/Caddyfile + +caddy_site_owner: "caddy" +caddy_site_group: "caddy" diff --git a/roles/caddy_site/meta/main.yml b/roles/caddy_site/meta/main.yml new file mode 100644 index 0000000..28cca73 --- /dev/null +++ b/roles/caddy_site/meta/main.yml @@ -0,0 +1,11 @@ +--- +allow_duplicates: true +dependencies: [] +galaxy_info: + role_name: caddy_site + description: Deploy a sites' configuration in caddy + galaxy_tags: + - caddy + - zerossl + - http + - webserver diff --git a/roles/caddy_site/tasks/main.yml b/roles/caddy_site/tasks/main.yml new file mode 100644 index 0000000..9c289ca --- /dev/null +++ b/roles/caddy_site/tasks/main.yml @@ -0,0 +1,26 @@ +--- +- name: Fail if required variables are not populated + ansible.builtin.fail: + msg: "Either `caddy_site_name` or `caddy_site_config` is not provided" + when: >-2 + (caddy_site_name | ansible.builtin.type_debug == 'NoneType') + or + (caddy_site_config | ansible.builtin.type_debug == 'NoneType') + +- name: Ensure directory for caddy site config '{{ caddy_site_name }}' is {{ caddy_site_state }} + ansible.builtin.file: + path: "{{ caddy_site_config_dir }}" + state: >-2 + {{ (caddy_site_state == 'present') | ternary('directory', 'absent') }} + owner: "{{ caddy_site_owner }}" + group: "{{ caddy_site_group }}" + mode: "0750" + +- name: Ensure caddy site configuration is templated + ansible.builtin.copy: + dest: "{{ caddy_site_config_file }}" + content: "{{ caddy_site_config }}" + owner: "{{ caddy_site_owner }}" + group: "{{ caddy_site_group }}" + mode: "0640" + when: caddy_site_state == 'present'