Browse Source

add caddy role

les 3 years ago
parent
commit
c9456f3e1f

+ 33 - 0
roles/caddy/defaults/main.yml

@@ -0,0 +1,33 @@
+---
+# defaults file for caddy-ansible
+caddy_user: www-data
+caddy_home: /home/caddy
+caddy_packages: []
+caddy_update: true
+caddy_bin_dir: /usr/local/bin
+caddy_conf_dir: /etc/caddy
+caddy_github_token: ""
+caddy_log_dir: /var/log/caddy
+caddy_log_file: stdout
+caddy_certs_dir: /etc/ssl/caddy
+caddy_http2_enabled: "true"
+# additional cli args to pass to caddy
+caddy_additional_args: ""
+caddy_systemd_network_dependency: true
+caddy_systemd_capabilities_enabled: false
+caddy_systemd_capabilities: "CAP_NET_BIND_SERVICE"
+caddy_systemd_restart: "on-failure"   # always, on-success, on-failure, on-abnormal, on-abort, on-watchdog
+caddy_systemd_restart_startlimitinterval: "86400"
+caddy_systemd_restart_startlimitburst: "5"
+caddy_systemd_private_tmp: "true"
+caddy_systemd_private_devices: "true"
+# Disable this because the git module writes to ~/.ssh
+caddy_systemd_protect_home: "false"
+caddy_systemd_protect_system: "full"
+caddy_systemd_nproc_limit: 0
+caddy_setcap: true
+caddy_config: |
+  http://localhost:2020
+  respond "Hello, world!"
+caddy_environment_variables: {}
+caddy_os: linux

+ 12 - 0
roles/caddy/handlers/main.yml

@@ -0,0 +1,12 @@
+---
+
+- name: Restart caddy
+  systemd:
+    daemon_reload: true
+    name: caddy
+    state: restarted
+
+- name: Reload caddy
+  systemd:
+    name: caddy
+    state: reloaded

+ 21 - 0
roles/caddy/tasks/github-extract.yml

@@ -0,0 +1,21 @@
+---
+- name: Extract Caddy
+  unarchive:
+    src: "{{ caddy_home }}/caddy.tar.gz"
+    dest: "{{ caddy_home }}"
+    copy: false
+    mode: 0644
+    owner: "{{ caddy_user }}"
+    group: "{{ caddy_user_details.group }}"
+  when: caddy_binary_cache.changed
+  tags: skip_ansible_lint
+
+- name: Extract Caddy
+  unarchive:
+    src: "{{ caddy_home }}/caddy.tar.gz"
+    dest: "{{ caddy_home }}"
+    creates: "{{ caddy_home }}/caddy"
+    copy: false
+    mode: 0644
+    owner: "{{ caddy_user }}"
+    group: "{{ caddy_user_details.group }}"

+ 20 - 0
roles/caddy/tasks/github-url.yml

@@ -0,0 +1,20 @@
+---
+- name: Get latest Caddy release details
+  uri:
+    url: https://api.github.com/repos/mholt/caddy/releases/latest
+    return_content: true
+    headers: '{{ caddy_github_headers }}'
+  register: latest_caddy_release
+
+- name: Set Caddy tag
+  set_fact:
+    caddy_tag: "{{ (latest_caddy_release.content | from_json).get('tag_name') }}"
+
+- name: Set Caddy version
+  set_fact:
+    caddy_version: "{{ caddy_tag | regex_replace('^v', '') }}"
+
+- name: Set Caddy url
+  set_fact:
+    caddy_url: "https://github.com/caddyserver/caddy/releases/download/\
+                {{ caddy_tag }}/caddy_{{ caddy_version }}_{{ caddy_os }}_{{ go_arch }}.tar.gz"

+ 134 - 0
roles/caddy/tasks/main.yml

@@ -0,0 +1,134 @@
+---
+- include: preflight.yml
+- include: packages-{{ ansible_pkg_mgr }}.yml
+
+- name: Create Caddy user
+  user:
+    name: "{{ caddy_user }}"
+    system: true
+    createhome: true
+    home: "{{ caddy_home }}"
+  register: caddy_user_details
+
+- name: Build headers to use when making requests to github
+  set_fact:
+    caddy_github_headers: "{{ caddy_github_headers | combine({'Authorization': 'token ' + caddy_github_token}) }}"
+  when: caddy_github_token | length > 0
+
+- name: Get all Caddy releases
+  get_url:
+    url: https://api.github.com/repos/mholt/caddy/git/refs/tags
+    dest: "{{ caddy_home }}/releases.txt"
+    force: true
+    headers: '{{ caddy_github_headers }}'
+    owner: "{{ caddy_user }}"
+    group: "{{ caddy_user_details.group }}"
+  retries: 3
+  delay: 2
+  when: caddy_update
+  register: caddy_releases_cache
+
+- name: Set Caddy features
+  copy:
+    content: "{{ ','.join(caddy_packages) }}"
+    dest: "{{ caddy_home }}/features.txt"
+    mode: 0640
+    owner: "{{ caddy_user }}"
+    group: "{{ caddy_user_details.group }}"
+  when: caddy_update
+  register: caddy_features_cache
+
+- include: github-url.yml
+  when: caddy_use_github
+
+- name: Download Caddy
+  get_url:
+    url: "{{ caddy_url }}"
+    dest: "{{ caddy_home }}/{{ 'caddy.tar.gz' if caddy_use_github else 'caddy' }}"
+    force: true
+    timeout: 300
+    mode: 0644
+    owner: "{{ caddy_user }}"
+    group: "{{ caddy_user_details.group }}"
+  retries: 3
+  delay: 2
+  when: caddy_releases_cache.changed or caddy_features_cache.changed
+  register: caddy_binary_cache
+  tags: skip_ansible_lint
+
+- name: Download Caddy
+  get_url:
+    url: "{{ caddy_url }}"
+    dest: "{{ caddy_home }}/{{ 'caddy.tar.gz' if caddy_use_github else 'caddy' }}"
+    timeout: 300
+    mode: 0644
+    owner: "{{ caddy_user }}"
+    group: "{{ caddy_user_details.group }}"
+  retries: 3
+  delay: 2
+  register: caddy_download
+  tags: skip_ansible_lint
+
+- include: github-extract.yml
+  when: caddy_use_github
+
+- name: Copy Caddy Binary
+  copy:
+    src: "{{ caddy_home }}/caddy"
+    dest: "{{ caddy_bin }}"
+    mode: 0755
+    remote_src: true
+  notify:
+    - Restart caddy
+
+- name: Create directories
+  file:
+    path: "{{ item }}"
+    state: directory
+    owner: "{{ caddy_user }}"
+    mode: 0770
+  with_items:
+    - "{{ caddy_conf_dir }}"
+    - "{{ caddy_certs_dir }}"
+
+- name: Create log directory
+  file:
+    path: "{{ caddy_log_dir }}"
+    state: directory
+    owner: "{{ caddy_user }}"
+    mode: 0775
+
+- name: Create Caddyfile
+  copy:
+    content: "{{ caddy_config }}"
+    dest: "{{ caddy_conf_dir }}/Caddyfile"
+    owner: "{{ caddy_user }}"
+    mode: 0640
+  notify:
+    - Reload caddy
+
+- name: Template systemd service
+  template:
+    src: caddy.service
+    dest: /etc/systemd/system/caddy.service
+    owner: root
+    group: root
+    mode: 0644
+  notify:
+    - Restart caddy
+
+- name: Set capability on the binary file to be able to bind to TCP port <1024
+  capabilities:
+    path: "{{ caddy_bin }}"
+    capability: cap_net_bind_service+eip
+    state: present
+  when: caddy_setcap
+
+- name: Ensue caddy service is up-to-date before starting it
+  meta: flush_handlers
+
+- name: Start Caddy service
+  systemd:
+    name: caddy
+    state: started
+    enabled: true

+ 18 - 0
roles/caddy/tasks/packages-apt.yml

@@ -0,0 +1,18 @@
+---
+
+- name: Update cache
+  apt:
+    update_cache: true
+    cache_valid_time: 43200   # 12 hours
+
+# This is required because it provides the /bin/kill binary used in the service file
+- name: Install procps
+  apt:
+    name: procps
+    state: present
+
+- name: Install libcap
+  apt:
+    name: libcap2-bin
+    state: present
+  when: caddy_setcap

+ 1 - 0
roles/caddy/tasks/packages-dnf.yml

@@ -0,0 +1 @@
+---

+ 1 - 0
roles/caddy/tasks/packages-pacman.yml

@@ -0,0 +1 @@
+---

+ 1 - 0
roles/caddy/tasks/packages-yum.yml

@@ -0,0 +1 @@
+---

+ 17 - 0
roles/caddy/tasks/preflight.yml

@@ -0,0 +1,17 @@
+---
+- name: Assert usage of systemd as an init system
+  assert:
+    that: ansible_service_mgr == 'systemd'
+    msg: "This module only works with systemd"
+
+- name: Get systemd version
+  command: systemctl --version
+  changed_when: false
+  check_mode: false
+  register: __systemd_version
+  tags:
+    - skip_ansible_lint
+
+- name: Set systemd version fact
+  set_fact:
+    caddy_systemd_version: "{{ __systemd_version.stdout_lines[0].split(' ')[-1] }}"

+ 73 - 0
roles/caddy/templates/caddy.service

@@ -0,0 +1,73 @@
+{{ ansible_managed | comment(decoration="; ") }}
+; source: https://github.com/mholt/caddy/blob/master/dist/init/linux-systemd/caddy.service
+; version: 6be0386
+; changes: Set variables via Ansible
+
+[Unit]
+Description=Caddy HTTP/2 web server
+Documentation=https://caddyserver.com/docs
+After=network-online.target
+{% if caddy_systemd_network_dependency == true %}
+Wants=network-online.target systemd-networkd-wait-online.service
+{% endif %}
+{% if caddy_systemd_version | int >= 230 %}
+StartLimitIntervalSec={{ caddy_systemd_restart_startlimitinterval }}
+StartLimitBurst={{ caddy_systemd_restart_startlimitburst }}
+{% endif %}
+
+[Service]
+Restart={{ caddy_systemd_restart }}
+{% if caddy_systemd_version | int < 230 %}
+StartLimitInterval={{ caddy_systemd_restart_startlimitinterval }}
+StartLimitBurst={{ caddy_systemd_restart_startlimitburst }}
+{% endif %}
+
+; User and group the process will run as.
+User={{ caddy_user }}
+Group={{ caddy_user }}
+
+; Letsencrypt-issued certificates will be written to this directory.
+Environment=CADDYPATH={{ caddy_certs_dir }}
+
+ExecStart="{{ caddy_bin_dir }}/caddy" run --environ --config "{{ caddy_conf_dir }}/Caddyfile" {{ caddy_additional_args }}
+ExecReload="{{ caddy_bin_dir }}/caddy" reload --config "{{ caddy_conf_dir }}/Caddyfile"
+
+; Limit the number of file descriptors; see `man systemd.exec` for more limit settings.
+LimitNOFILE=1048576
+{% if caddy_systemd_nproc_limit > 0 %}
+; Limit the number of caddy threads.
+LimitNPROC={{ caddy_systemd_nproc_limit }}
+{% endif %}
+
+; Use private /tmp and /var/tmp, which are discarded after caddy stops.
+PrivateTmp={{ caddy_systemd_private_tmp }}
+; Use a minimal /dev
+PrivateDevices={{ caddy_systemd_private_devices }}
+; Hide /home, /root, and /run/user. Nobody will steal your SSH-keys.
+ProtectHome={{ caddy_systemd_protect_home }}
+; Make /usr, /boot, /etc and possibly some more folders read-only.
+ProtectSystem={{ caddy_systemd_protect_system }}
+; … except {{ caddy_certs_dir }}, because we want Letsencrypt-certificates there.
+;   This merely retains r/w access rights, it does not add any new. Must still be writable on the host!
+ReadWriteDirectories={{ caddy_certs_dir }}
+
+{% if caddy_systemd_capabilities_enabled %}
+; The following additional security directives only work with systemd v229 or later.
+; They further retrict privileges that can be gained by caddy.
+; Note that you may have to add capabilities required by any plugins in use.
+CapabilityBoundingSet={{ caddy_systemd_capabilities }}
+AmbientCapabilities={{ caddy_systemd_capabilities }}
+NoNewPrivileges=true
+
+{% endif %}
+{% if caddy_environment_variables|length %}
+
+; Additional environment variables:
+
+{% for key, value in caddy_environment_variables.items() %}
+Environment={{ key }}={{ value }}
+{% endfor %}
+
+{% endif %}
+[Install]
+WantedBy=multi-user.target

+ 21 - 0
roles/caddy/vars/main.yml

@@ -0,0 +1,21 @@
+---
+# vars file for caddy-ansible
+caddy_github_headers: {}
+
+go_arch_map:
+  i386: '386'
+  x86_64: 'amd64'
+  aarch64: 'arm64'
+  armv7l: 'arm7'
+  armv6l: 'arm6'
+
+go_arch: "{{ go_arch_map[ansible_architecture] | default(ansible_architecture) }}"
+
+caddy_bin: "{{ caddy_bin_dir }}/caddy"
+
+caddy_url: "https://caddyserver.com/api/download?os={{ caddy_os }}&arch={{ go_arch }}\
+           {% for pkg in caddy_packages %}\
+           {% if loop.first %}&{% endif %}p={{ pkg | urlencode() }}{% if not loop.last %},{% endif %}\
+           {% endfor %}"
+
+caddy_use_github: "{{ caddy_packages == [] }}"

+ 8 - 0
tests/caddy/Vagrantfile

@@ -0,0 +1,8 @@
+Vagrant.configure("2") do |config|
+  config.vm.define :node do |node|
+    node.vm.box = "generic/debian10"
+    node.vm.provision "ansible" do |ansible|
+      ansible.playbook = "./nodejs.yml"
+    end
+  end
+end

+ 6 - 0
tests/caddy/caddy.yml

@@ -0,0 +1,6 @@
+---
+- name: caddy test
+  hosts: localhost
+  become: yes
+  roles:
+  - caddy

+ 1 - 0
tests/caddy/roles

@@ -0,0 +1 @@
+../../roles/