diff --git a/roles/caddy/README.md b/roles/caddy/README.md new file mode 100644 index 0000000..d8b03ef --- /dev/null +++ b/roles/caddy/README.md @@ -0,0 +1,37 @@ +caddy +======== + +Installs `caddy` as a systemd service. + +Requirements +------------ + +Role Variables +-------------- + +- `caddy_version`: default `2.11.3` +- `caddy_src_conf_path`: (required) location of the `Caddyfile` on the controller +- `caddy_dest_conf_path`: where to put the configuration file for the service default `/etc/caddy/Caddyfile` +- `caddy_limit_nofile`: default `1048576` + +Dependencies +------------ + +None + +Example Playbook +---------------- + +See: [converge.yml](molecule/default/converge.yml) + +License +------- + +MIT + +Author Information +------------------ + +Alexander Gorelyshev + +corvus-migratorius@proton.me diff --git a/roles/caddy/defaults/main.yml b/roles/caddy/defaults/main.yml new file mode 100644 index 0000000..fdc1407 --- /dev/null +++ b/roles/caddy/defaults/main.yml @@ -0,0 +1,4 @@ +--- +caddy_version: "2.11.3" +caddy_dest_conf_path: "/etc/caddy/Caddyfile" +caddy_limit_nofile: 1048576 diff --git a/roles/caddy/handlers/main.yml b/roles/caddy/handlers/main.yml new file mode 100644 index 0000000..113910d --- /dev/null +++ b/roles/caddy/handlers/main.yml @@ -0,0 +1,7 @@ +--- +- name: "Enable and restart the caddy daemon" + ansible.builtin.systemd: + name: caddy + state: restarted + enabled: true + daemon_reload: true diff --git a/roles/caddy/meta/main.yml b/roles/caddy/meta/main.yml new file mode 100644 index 0000000..6bf8e66 --- /dev/null +++ b/roles/caddy/meta/main.yml @@ -0,0 +1,19 @@ +--- +galaxy_info: + role_name: caddy + namespace: genlab + author: Alexander Gorelyshev + description: Deploy Caddy + + company: Genlab LLC + license: MIT + + min_ansible_version: "2.1" + + platforms: + - name: "Ubuntu" + versions: ["jammy", "noble"] + + galaxy_tags: [] + +dependencies: [] diff --git a/roles/caddy/molecule/default/converge.yml b/roles/caddy/molecule/default/converge.yml new file mode 100644 index 0000000..da41f83 --- /dev/null +++ b/roles/caddy/molecule/default/converge.yml @@ -0,0 +1,9 @@ +--- +- name: Converge + hosts: all + roles: + - role: genlab.common.caddy + caddy_src_conf_path: "files/Caddyfile" + caddy_dest_conf_path: "/etc/caddy/Caddyfile" + caddy_version: "2.11.3" + caddy_limit_nofile: 1048576 diff --git a/roles/caddy/molecule/default/files/Caddyfile b/roles/caddy/molecule/default/files/Caddyfile new file mode 100644 index 0000000..b1e0fd4 --- /dev/null +++ b/roles/caddy/molecule/default/files/Caddyfile @@ -0,0 +1,3 @@ +:8080 { + respond "caddy-ok" 200 +} diff --git a/roles/caddy/molecule/default/molecule.yml b/roles/caddy/molecule/default/molecule.yml new file mode 100644 index 0000000..943f66b --- /dev/null +++ b/roles/caddy/molecule/default/molecule.yml @@ -0,0 +1,24 @@ +--- +dependency: + name: galaxy +driver: + name: docker +platforms: + - name: ubuntu + image: geerlingguy/docker-ubuntu2404-ansible:latest + pre_build_image: true + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true +provisioner: + name: ansible + playbooks: + converge: converge.yml +verifier: + name: ansible +lint: | + set -e + yamllint . + ansible-lint . diff --git a/roles/caddy/molecule/default/verify.yml b/roles/caddy/molecule/default/verify.yml new file mode 100644 index 0000000..ed80302 --- /dev/null +++ b/roles/caddy/molecule/default/verify.yml @@ -0,0 +1,34 @@ +--- +- name: Verify + hosts: all + gather_facts: false + pre_tasks: + # https://github.com/ansible/molecule/issues/3587#issuecomment-1158650179 + - name: "Include default vars" + ansible.builtin.include_vars: + dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/" + extensions: ['yml'] + + tasks: + - name: "Wait for Caddy to start and listen on the configured port" + ansible.builtin.wait_for: + port: 8080 + delay: 2 + timeout: 10 + + # kics-scan ignore-block - kics doesn't like HTTP but on localhost it's not important + - name: "Get the Caddy daemon response" + retries: 3 + delay: 1 + register: caddy_response + ansible.builtin.uri: + url: "http://localhost:8080" + return_content: true + + - name: "Assert Caddy is responding corectly" + ansible.builtin.assert: + that: + - caddy_response.status == 200 + - "caddy_response.content == 'caddy-ok'" + success_msg: "OK: HTTP {{ caddy_response.status }}, '{{ caddy_response.content }}'" + fail_msg: "FAIL: HTTP {{ caddy_response.status }}, '{{ caddy_response.content }}'" diff --git a/roles/caddy/tasks/main.yml b/roles/caddy/tasks/main.yml new file mode 100644 index 0000000..74e39c4 --- /dev/null +++ b/roles/caddy/tasks/main.yml @@ -0,0 +1,89 @@ +--- +- name: "Install packages" + ansible.builtin.apt: + name: unzip + state: present + update_cache: true + cache_valid_time: 3600 + +- name: "Create the 'caddy' user" + ansible.builtin.user: + name: caddy + comment: "Caddy web server" + shell: /bin/nologin + home: /var/lib/caddy + state: present + system: true + +- name: "Install the requested caddy version" + block: + - name: "Check caddy version" + register: caddy_version_check + changed_when: false + ansible.builtin.command: + cmd: /usr/bin/caddy version + + - name: "Assert version correctness" + ansible.builtin.assert: + that: "caddy_version in caddy_version_check.stdout" + success_msg: "OK, expected caddy version already available: '{{ caddy_version }}'" + fail_msg: "Expected version '{{ caddy_version }}'; available is '{{ caddy_version_check.stdout }}'" + + rescue: + - name: "Create a temporary directory for caddy download" + ansible.builtin.file: + path: /tmp/caddy + state: directory + owner: root + group: root + mode: "0755" + + - name: "Download caddy" + notify: "Enable and restart the caddy daemon" + vars: + base_url: "github.com/caddyserver/caddy/releases/download" + ansible.builtin.unarchive: + src: "https://{{ base_url }}/v{{ caddy_version }}/caddy_{{ caddy_version }}_linux_amd64.tar.gz" + dest: /tmp/caddy + remote_src: true + + - name: "Rename and set permissions for the caddy binary" + ansible.builtin.copy: + src: "/tmp/caddy/caddy" + dest: "/usr/bin/caddy" + owner: root + group: root + mode: "0755" + remote_src: true + + - name: "Cleanup the downloaded file" + ansible.builtin.file: + path: "/tmp/caddy" + state: absent + + +- name: "Template the systemd unit file" + notify: "Enable and restart the caddy daemon" + ansible.builtin.template: + src: caddy.service.j2 + dest: /etc/systemd/system/caddy.service + owner: root + group: root + mode: "0644" + +- name: "Ensure '/etc/caddy' exists" + ansible.builtin.file: + path: /etc/caddy + state: directory + owner: caddy + group: caddy + mode: "0755" + +- name: "Template caddy config file" + notify: "Enable and restart the caddy daemon" + ansible.builtin.template: + src: "{{ caddy_src_conf_path }}" + dest: "{{ caddy_dest_conf_path }}" + owner: root + group: root + mode: "0644" diff --git a/roles/caddy/templates/caddy.service.j2 b/roles/caddy/templates/caddy.service.j2 new file mode 100644 index 0000000..fd95ea7 --- /dev/null +++ b/roles/caddy/templates/caddy.service.j2 @@ -0,0 +1,35 @@ +# 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 network-online.target +Requires=network-online.target + +[Service] +Type=notify +User=caddy +Group=caddy +ExecStart=/usr/bin/caddy run --environ --config {{ caddy_dest_conf_path }} +ExecReload=/usr/bin/caddy reload --config {{ caddy_dest_conf_path }} --force +TimeoutStopSec=5s +LimitNOFILE={{ caddy_limit_nofile }} +PrivateTmp=true +ProtectSystem=full +AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE + +[Install] +WantedBy=multi-user.target diff --git a/roles/caddy/vars/main.yml b/roles/caddy/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/caddy/vars/main.yml @@ -0,0 +1 @@ +---