From 41c60409e5a91a9edf206a40282bee55db01767e Mon Sep 17 00:00:00 2001 From: Lennard Brinkhaus Date: Sun, 11 Dec 2022 00:36:54 +0100 Subject: [PATCH] initial commit --- .editorconfig | 19 +++++++++++ .gitignore | 20 +++++++++++ README.md | 26 +++++++++++++++ ansible.cfg | 2 ++ defaults/main.yml | 29 ++++++++++++++++ handlers/main.yml | 11 ++++++ meta/main.yml | 34 +++++++++++++++++++ tasks/create_user.yml | 14 ++++++++ tasks/install.yml | 68 ++++++++++++++++++++++++++++++++++++++ tasks/install_systemd.yml | 11 ++++++ tasks/main.yml | 45 +++++++++++++++++++++++++ templates/Caddyfile.j2 | 27 +++++++++++++++ templates/caddy.service.j2 | 39 ++++++++++++++++++++++ tests/inventory | 1 + tests/test.yml | 14 ++++++++ vars/debian.yml | 2 ++ vars/main.yml | 10 ++++++ 17 files changed, 372 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 README.md create mode 100644 ansible.cfg create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 tasks/create_user.yml create mode 100644 tasks/install.yml create mode 100644 tasks/install_systemd.yml create mode 100644 tasks/main.yml create mode 100644 templates/Caddyfile.j2 create mode 100644 templates/caddy.service.j2 create mode 100644 tests/inventory create mode 100644 tests/test.yml create mode 100644 vars/debian.yml create mode 100644 vars/main.yml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ab9fdb4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Defaults for all editor files +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +# Files with a smaller indent +[*.yml] +indent_size = 2 + +# Jinja2 template files +[*.j2] +end_of_line = lf \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5b396ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +local-configure.yml +.vagrant/ +docs/_build/ +roles/plone.plone_server +roles/jnv.unattended-upgrades +roles/tersmitten.fail2ban +roles/ANXS.hostname +roles/ANXS.apt +._* +bin/ +lib/ +include/ +local/ +tests.out +*.retry +*.log +vbox_host.cfg +.DS_Store +*.py[co] +.idea/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..32b63c1 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +Caddy Role +========= + +A role to install and manage caddy + +## Config +### General + +* `caddy_version_check`: Check if installed version != `caddy_version` before initiating binary download (true/false) +* `caddy_version`: The Caddy-Version you want to install +* `caddy_user`: UNIX user used by Caddy (default: caddy) +* `caddy_group`: UNIX group used by Caddy (default: caddy) +* `caddy_home`: Base directory to work (default: /var/lib/caddy) +* `caddy_dl_url`: The URL, the compiled caddy-binary will be downloaded from +* `caddy_dl_url_checksum`: The URL, the checksums will be installed from + +### Caddyfile + +* `caddy_caddyfile.global.debug`: Enabled the Debug mode and set the log level to DEBUG (true/false) +* `caddy_caddyfile.global.http`: HTTP Port from Caddy (default: 80) +* `caddy_caddyfile.global.https`: HTTPS Port from Caddy (default: 443) +* `caddy_caddyfile.global.acme.issuer`: Set the global ACME Issuer (acme/zerossl) +* `caddy_caddyfile.global.acme.token`: Set the token for the global issuer. Required if issuer is `zerossl` +* `caddy_caddyfile.global.acme.email`: The email-address used while generating https certificates +* `caddy_caddyfile.global.acme.dns.provider`: The Provider used if you want to use dns-challenge. (Example: cloudflare) +* `caddy_caddyfile.global.acme.dns.token`: The Provider-Token used if you want to use dns-challenge diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..17c134e --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +roles_path: ./../ diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..47561b8 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,29 @@ +--- +caddy_version_check: true +caddy_version: "2.6.2" +caddy_dl_url: "https://github.com/caddyserver/caddy/releases/download/v{{ caddy_version }}/caddy_{{ caddy_version }}_linux_{{ caddy_arch }}" +caddy_dl_url_checksum: "https://github.com/caddyserver/caddy/releases/download/v{{ caddy_version }}/caddy_{{ caddy_version }}_checksums.txt" + +caddy_user: "caddy" +caddy_group: "caddy" +caddy_home: "/var/lib/caddy" + +caddy_caddyfile: + global: + debug: true + http: 80 + https: 443 + acme: + issuer: "" + token: "" + email: "" + dns: + provider: "" + token: "" + + domains: + - domain: localhost + reverse_proxy: + targets: + - "localhost:3000" + lb_policy: "least_conn" diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..6dc9014 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,11 @@ +--- +- name: "Restart caddy" + ansible.builtin.service: + name: caddy + state: restarted + when: ansible_service_mgr == "systemd" + +- name: "Reload systemd" + ansible.builtin.systemd: + daemon_reload: true + when: ansible_service_mgr == "systemd" diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..38f84c8 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,34 @@ +galaxy_info: + author: Lennard Brinkhaus + description: Install and manage a Caddy instance + company: DragSE + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + min_ansible_version: 2.1 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + platforms: + - name: Debian + versions: + - all + - name: Ubuntu + versions: + - all + + galaxy_tags: + - caddy + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. diff --git a/tasks/create_user.yml b/tasks/create_user.yml new file mode 100644 index 0000000..f50b9ae --- /dev/null +++ b/tasks/create_user.yml @@ -0,0 +1,14 @@ +--- +- name: "Create Caddy Group" + group: + name: "{{ caddy_group }}" + system: true + state: "present" + +- name: "Create Caddy user" + ansible.builtin.user: + name: "{{ caddy_user }}" + comment: "Caddy user" + home: "{{ caddy_home }}" + shell: "/bin/false" + system: true diff --git a/tasks/install.yml b/tasks/install.yml new file mode 100644 index 0000000..bd2802b --- /dev/null +++ b/tasks/install.yml @@ -0,0 +1,68 @@ +--- +- block: + - name: Update apt cache + apt: + cache_valid_time: 3600 + update_cache: true + register: _pre_update_apt_cache + until: _pre_update_apt_cache is succeeded + when: + - ansible_pkg_mgr == "apt" + + - name: Install dependencies + package: + name: "{{ caddy_dependencies }}" + state: present + register: _install_dep_packages + until: _install_dep_packages is succeeded + retries: 5 + delay: 2 +- block: + - name: Download caddy archive + get_url: + url: "{{ caddy_dl_url }}.tar.gz" + dest: "/tmp/caddy-{{ caddy_version }}-linux-{{ caddy_arch }}.tar.gz" + register: _download_archive + until: _download_archive is succeeded + retries: 5 + delay: 2 + + - name: Download caddy checksum.txt + get_url: + url: "{{ caddy_dl_url_checksum }}" + dest: "/tmp/caddy_{{ caddy_version }}_checksums.txt" + register: _download_checksums_txt + until: _download_checksums_txt is succeeded + retries: 5 + delay: 2 + + - name: Download caddy checksum.txt.pem + get_url: + url: "{{ caddy_dl_url_checksum }}.pem" + dest: "/tmp/caddy_{{ caddy_version }}_checksums.txt.pem" + register: _download_checksums_txt_pem + until: _download_checksums_txt_pem is succeeded + retries: 5 + delay: 2 + + - name: Download caddy checksum.txt.sig + get_url: + url: "{{ caddy_dl_url_checksum }}.sig" + dest: "/tmp/caddy_{{ caddy_version }}_checksums.txt.sig" + register: _download_checksums_txt_sig + until: _download_checksums_txt_pem is succeeded + retries: 5 + delay: 2 + +# TODO verify checksum with cosign (need to be installed (dependency)) + + - name: Unpack caddy binary + unarchive: + remote_src: yes + src: "/tmp/caddy-{{ caddy_version }}-linux-{{ caddy_arch }}.tar.gz" + dest: "/usr/local/bin" + mode: 0755 + owner: root + group: root + notify: "Restart caddy" + when: (not caddy_version_check|bool) or (caddy_active_version.stdout != caddy_version) diff --git a/tasks/install_systemd.yml b/tasks/install_systemd.yml new file mode 100644 index 0000000..6a11541 --- /dev/null +++ b/tasks/install_systemd.yml @@ -0,0 +1,11 @@ +--- +- name: "Setup systemd service" + ansible.builtin.template: + src: caddy.service.j2 + dest: /lib/systemd/system/caddy.service + owner: root + group: root + mode: 0644 + notify: + - "Reload systemd" + - "Restart caddy" diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..d55b6e2 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,45 @@ +--- +- name: Gather variables for each operating system + include_vars: "{{ ansible_distribution | lower }}.yml" + +- name: "Check caddy version" + ansible.builtin.shell: "set -eo pipefail; caddy version | cut -d' ' -f 1 | cut -d'v' -f 2" + args: + executable: /bin/bash + register: caddy_active_version + changed_when: false + failed_when: false + when: caddy_version_check|bool + +- include_tasks: "create_user.yml" + +- include_tasks: "install.yml" + +- include_tasks: install_systemd.yml + when: ansible_service_mgr == "systemd" + +- name: "Create config and data directory" + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: "{{ caddy_user }}" + group: "{{ caddy_group }}" + mode: '0755' + with_items: + - "/etc/caddy" + +- name: "Configure caddy" + ansible.builtin.template: + src: Caddyfile.j2 + dest: /etc/caddy/Caddyfile + owner: "{{ caddy_user }}" + group: "{{ caddy_group }}" + mode: 0600 + notify: "Restart caddy" + +- name: "Service caddy" + ansible.builtin.service: + name: caddy + state: started + enabled: true + when: ansible_service_mgr == "systemd" diff --git a/templates/Caddyfile.j2 b/templates/Caddyfile.j2 new file mode 100644 index 0000000..77fcf0f --- /dev/null +++ b/templates/Caddyfile.j2 @@ -0,0 +1,27 @@ +{ +{% if caddy_caddyfile.global.debug | default(false) %} + debug +{% endif %} + http_port {{ caddy_caddyfile.global.http | default('80') }} + https_port {{ caddy_caddyfile.global.https | default('443') }} + storage file_system {{ caddy_home }} +{% if caddy_caddyfile.global.acme.dns.provider is defined %} + acme_dns: {{ caddy_caddyfile.global.acme.dns.provider }} {{ caddy_caddyfile.global.acme.dns.token | default('') }} +{% endif %} +{% if caddy_caddyfile.global.acme.issuer is defined %} + cert_issuer: {{ caddy_caddyfile.global.acme.issuer }} {{ caddy_caddyfile.global.acme.token | default('') }} +{% endif %} +{% if caddy_caddyfile.global.acme.email is defined %} + email: {{ caddy_caddyfile.global.acme.email }} +{% endif %} + admin off +} +{% for domain in caddy_caddyfile.domains %} +{{ domain.domain }} { +{% if domain.reverse_proxy %} + reverse_proxy {{ domain.reverse_proxy.targets | join(" ") }} { + lb_policy {{ domain.reverse_proxy.lb_policy }} + } +{% endif %} +} +{% endfor %} diff --git a/templates/caddy.service.j2 b/templates/caddy.service.j2 new file mode 100644 index 0000000..38c58d0 --- /dev/null +++ b/templates/caddy.service.j2 @@ -0,0 +1,39 @@ +# Example from https://github.com/caddyserver/dist/blob/master/init/caddy.service +# caddy.service +# +# For using Caddy with a config file. +# +# Make sure the ExecStart and ExecReload commands are correct +# for your installation. +# +# See https://caddyserver.com/docs/install for instructions. +# +# WARNING: This service does not use the --resume flag, so if you +# use the API to make changes, they will be overwritten by the +# Caddyfile next time the service is restarted. If you intend to +# use Caddy's API to configure it, add the --resume flag to the +# `caddy run` command or use the caddy-api.service file instead. + +[Unit] +Description=Caddy +Documentation=https://caddyserver.com/docs/ +After=network.target +After=network-online.target +Requires=network-online.target + +[Service] +Type=notify +User=caddy +Group=caddy +ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile +ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --force +TimeoutStopSec=5s +LimitNOFILE=1048576 +LimitNPROC=512 +PrivateDevices=yes +PrivateTmp=true +ProtectSystem=full +AmbientCapabilities=CAP_NET_BIND_SERVICE + +[Install] +WantedBy=multi-user.target diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..ac96836 --- /dev/null +++ b/tests/inventory @@ -0,0 +1 @@ +192.168.1.142 diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..35d5016 --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,14 @@ +--- +- hosts: all + remote_user: root + roles: + - role-caddy + vars: + caddy_caddyfile: + global: + domains: + - domain: 192.168.1.142 + reverse_proxy: + targets: + - "localhost:3000" + lb_policy: "least_conn" diff --git a/vars/debian.yml b/vars/debian.yml new file mode 100644 index 0000000..a99502a --- /dev/null +++ b/vars/debian.yml @@ -0,0 +1,2 @@ +--- +caddy_dependencies: [] diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..f729d04 --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,10 @@ +--- +caddy_go_arch_map: + i386: '386' + x86_64: 'amd64' + aarch64: 'arm64' + armv7l: 'arm-6' + armv6l: 'arm-6' + armv5l: 'arm-5' + +caddy_arch: "{{ caddy_go_arch_map[ansible_architecture] | default(ansible_architecture) }}"