diff --git a/caddy/defaults/main.yml b/caddy/defaults/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..c6be69a869ae9b03da6823f7b0ae1adc6140d56d --- /dev/null +++ b/caddy/defaults/main.yml @@ -0,0 +1,39 @@ +--- + +# caddy_global: +# auto_https: false +# email: acme@example.org +# on_demand_tls: +# ask: http://localhost:9123/ask +# debug: "" # Special value-less option, use with empty string +# http_port: null # Omit, useful to override in more specific variables + +caddy_local_sites: {} +# example.org: +# root *: /var/www +# file_server: "" + +caddy_enabled_sites: [] +# - example.com # Config filled in by some other role + +caddy_local_config: {} +# cors: +# "(cors)": +# # Note the differences in quoting! The next line will not contain quotes +# # in the resulting Caddyfile, the one after that _will_ end up with +# # quotes! +# "@origin header Origin": "{args[0]}" +# header @origin Access-Control-Allow-Origin: '"{args[0]}"' +# header @origin Access-Control-Allow-Methods: >- +# "OPTIONS,HEAD,GET,POST,PUT,PATCH,DELETE" +# # Or just specify the contents verbatim: +# https-proxy: | +# (https-proxy) { +# reverse_proxy {args[:]} { +# transport http { +# tls +# } +# } +# } + +caddy_enabled_config: [] diff --git a/caddy/handlers/main.yml b/caddy/handlers/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..889b30b4691721c5fe9405f6ec9ad82de347e6f7 --- /dev/null +++ b/caddy/handlers/main.yml @@ -0,0 +1,6 @@ +--- + +- name: Reload Caddy + ansible.builtin.systemd: + name: caddy.service + state: reloaded diff --git a/caddy/tasks/main.yml b/caddy/tasks/main.yml new file mode 100644 index 0000000000000000000000000000000000000000..7c6108388c013883046ee93f294f4ce77e17ca50 --- /dev/null +++ b/caddy/tasks/main.yml @@ -0,0 +1,169 @@ +--- + +- name: Install Caddy + ansible.builtin.apt: + name: caddy + tags: + - caddy + +- name: Configure Caddy main configuration file + ansible.builtin.template: + src: Caddyfile.j2 + dest: /etc/caddy/Caddyfile + validate: caddy validate --adapter caddyfile --config %s + owner: root + group: root + mode: "0644" + notify: + - Reload Caddy + tags: + - caddy + - config + +- name: Create drop-in configuration directories + ansible.builtin.file: + path: /etc/caddy/{{ item }} + state: directory + owner: root + group: root + mode: "0755" + loop: + - conf-available + - sites-available + - conf-enabled + - sites-enabled + tags: + - caddy + +- name: Configure Caddy site drop-ins + ansible.builtin.template: + src: site.j2 + dest: /etc/caddy/sites-available/{{ item.key | urlencode }} + validate: caddy validate --adapter caddyfile --config %s + owner: root + group: root + mode: "0644" + loop: "{{ caddy_local_sites | dict2items }}" + vars: + site_name: "{{ item.key }}" + site_config: "{{ item.value }}" + notify: + - Reload Caddy + tags: + - caddy + - config + +- name: Configure Caddy config drop-ins + ansible.builtin.template: + src: conf.j2 + dest: /etc/caddy/conf-available/{{ item.key | urlencode }} + validate: caddy validate --adapter caddyfile --config %s + owner: root + group: root + mode: "0644" + loop: "{{ caddy_local_config | dict2items }}" + vars: + config: "{{ item.value }}" + notify: + - Reload Caddy + tags: + - caddy + - config + +- name: Link active sites + ansible.builtin.file: + path: /etc/caddy/sites-enabled/{{ item | urlencode }} + src: ../sites-available/{{ item | urlencode }} + state: link + loop: "{{ caddy_local_sites | list + caddy_enabled_sites }}" + notify: + - Reload Caddy + tags: + - caddy + - config + +- name: Link active config drop-ins + ansible.builtin.file: + path: /etc/caddy/conf-enabled/{{ item | urlencode }} + src: ../conf-available/{{ item | urlencode }} + state: link + loop: "{{ caddy_local_config | list + caddy_enabled_config }}" + notify: + - Reload Caddy + tags: + - caddy + - config + +- name: Get active sites + ansible.builtin.find: + path: /etc/caddy/sites-enabled + pattern: "*" + file_type: link + register: current_active_sites + tags: + - caddy + - config + +- name: Disable inactive sites + ansible.builtin.file: + path: /etc/caddy/sites-enabled/{{ item }} + state: absent + loop: >- + {{ current_active_sites.files + | map(attribute='path') + | map('basename') + | map('splitext') + | map('first') + | difference(wanted_active_sites) + }} + loop_control: + label: "{{ item }}" + vars: + wanted_active_sites: >- + {{ (caddy_local_sites | list + caddy_enabled_sites) + | map('urlencode') + }} + tags: + - caddy + - config + +- name: Get active configuration drop-ins + ansible.builtin.find: + path: /etc/caddy/conf-enabled + pattern: "*" + file_type: link + register: current_active_config + tags: + - caddy + - config + +- name: Disable inactive configuration drop-ins + ansible.builtin.file: + path: /etc/caddy/conf-enabled/{{ item }} + state: absent + loop: >- + {{ current_active_config.files + | map(attribute='path') + | map('basename') + | map('splitext') + | map('first') + | difference(wanted_active_config) + }} + loop_control: + label: "{{ item }}" + vars: + wanted_active_config: >- + {{ (caddy_local_config | list + caddy_enabled_config) + | map('urlencode') + }} + tags: + - caddy + - config + +- name: Enable and start Caddy + ansible.builtin.systemd: + name: caddy.service + state: started + enabled: true + tags: + - caddy diff --git a/caddy/templates/Caddyfile.j2 b/caddy/templates/Caddyfile.j2 new file mode 100644 index 0000000000000000000000000000000000000000..23d3f3ffea5aa0dac45909a6f0a361ff6c22844f --- /dev/null +++ b/caddy/templates/Caddyfile.j2 @@ -0,0 +1,9 @@ +{% from "_macros.j2" import option -%} +{ + {%- for k, v in caddy_global | items +%} + {{ option(k, v) | indent }} + {%- endfor +%} +} + +import conf-enabled/* +import sites-enabled/* diff --git a/caddy/templates/_macros.j2 b/caddy/templates/_macros.j2 new file mode 100644 index 0000000000000000000000000000000000000000..12ab970004661e97ae015035e37e94295fd4586c --- /dev/null +++ b/caddy/templates/_macros.j2 @@ -0,0 +1,13 @@ +{% macro option(key, value) -%} +{%- if value is mapping -%} +{{ key }} { + {%- for skey, svalue in value | items +%} + {{ option(skey, svalue) | indent }} + {%- endfor +%} +} +{%- elif value is boolean -%} +{{ key }} {{ "on" if value else "off" }} +{%- elif value is not none -%} +{{ key }} {{ value }} +{%- endif -%} +{%- endmacro -%} diff --git a/caddy/templates/conf.j2 b/caddy/templates/conf.j2 new file mode 100644 index 0000000000000000000000000000000000000000..744a06e84dd67d0577ee9df93beb22b1cc030c51 --- /dev/null +++ b/caddy/templates/conf.j2 @@ -0,0 +1,15 @@ +{% from "_macros.j2" import option -%} +{% if config is mapping -%} +{% for key, value in config | items -%} +{{ key }} { + {%- if value is string %} + {{ value | indent }} + {%- endif %} + {%- for subkey, subvalue in value | items +%} + {{ option(subkey, subvalue) | indent }} + {%- endfor +%} +} +{% endfor %} +{%- else -%} +{{ config }} +{%- endif %} diff --git a/caddy/templates/site.j2 b/caddy/templates/site.j2 new file mode 100644 index 0000000000000000000000000000000000000000..529c12b5b4c8e0fc0051c2fa4286b9126b829182 --- /dev/null +++ b/caddy/templates/site.j2 @@ -0,0 +1,6 @@ +{% from "_macros.j2" import option -%} +{{ site_name }} { + {%- for k, v in site_config | items +%} + {{ option(k, v) | indent }} + {%- endfor +%} +}