diff --git a/plays/emma.yml b/plays/emma.yml index 91f87cc..a708cc5 100644 --- a/plays/emma.yml +++ b/plays/emma.yml @@ -40,3 +40,23 @@ - role: any.software.miniflux-podman vars: postgres_data_dir: '/data/miniflux/postgres' + +- name: Set up WebDAV + hosts: emma + become: yes + tags: webdav + roles: + - role: any.common.btrfs-subvolumes + vars: + subvolumes: + - filesystem_uuid: "{{ btrfs_raid.uuid }}" + filesystem_path: "{{ btrfs_raid.path }}" + name: "/webdav/data" + - role: any.software.webdav + vars: + webdav_version: '5.7.4' + data_dir: '{{ btrfs_raid.path }}/webdav/data' + + webdav_user: "{{ vault_webdav_user }}" + webdav_password: "{{ vault_webdav_password }}" + webdav_password_bcrypt: "{{ vault_webdav_password_bcrypt }}" diff --git a/roles/any.software.webdav/files/webdav.Caddyfile b/roles/any.software.webdav/files/webdav.Caddyfile new file mode 100644 index 0000000..8035ec5 --- /dev/null +++ b/roles/any.software.webdav/files/webdav.Caddyfile @@ -0,0 +1,5 @@ +webdav.roosens.me { + reverse_proxy localhost:8018 { + header_down +X-Robots-Tag "none" + } +} diff --git a/roles/any.software.webdav/files/webdav.data.backup.sh b/roles/any.software.webdav/files/webdav.data.backup.sh new file mode 100644 index 0000000..b3c92bd --- /dev/null +++ b/roles/any.software.webdav/files/webdav.data.backup.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +data_dir='/mnt/data1/webdav/data' +snapshot_dir="${data_dir}.snapshot" + +# Read-only snapshot for atomic backup +btrfs subvolume snapshot -r "$data_dir" "$snapshot_dir" || exit $? + +/usr/local/bin/restic backup "$snapshot_dir" + +# Always remove snapshot subvolume, even if restic fails +btrfs subvolume delete "$snapshot_dir" diff --git a/roles/any.software.webdav/files/webdav.service b/roles/any.software.webdav/files/webdav.service new file mode 100644 index 0000000..3827626 --- /dev/null +++ b/roles/any.software.webdav/files/webdav.service @@ -0,0 +1,15 @@ +[Unit] +Description=WebDAV +After=network.target network-online.target +Requires=network-online.target + +[Service] +Type=exec +User=webdav +Group=webdav +ExecStart=/usr/local/bin/webdav --config /etc/webdav/config.toml + +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/roles/any.software.webdav/handlers/main.yml b/roles/any.software.webdav/handlers/main.yml new file mode 100644 index 0000000..79a1cfa --- /dev/null +++ b/roles/any.software.webdav/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: 'restart webdav' + ansible.builtin.service: + name: 'webdav' + state: 'restarted' diff --git a/roles/any.software.webdav/tasks/main.yml b/roles/any.software.webdav/tasks/main.yml new file mode 100644 index 0000000..3ed9fea --- /dev/null +++ b/roles/any.software.webdav/tasks/main.yml @@ -0,0 +1,107 @@ +--- +# Download latest version of binary +- name: Ensure download directory is present + ansible.builtin.file: + path: "/home/debian/webdav/{{ webdav_version }}" + state: directory + mode: '0755' + +- name: Ensure compressed binary is downloaded + ansible.builtin.get_url: + url: "https://github.com/hacdias/webdav/releases/download/v{{ webdav_version }}/linux-amd64-webdav.tar.gz" + dest: "/home/debian/webdav/{{ webdav_version }}/webdav-{{ webdav_version }}.tar.gz" + register: res + +- name: Ensure binary is decompressed + ansible.builtin.shell: + chdir: "/home/debian/webdav/{{ webdav_version }}" + cmd: "tar --extract --gzip --file webdav-{{ webdav_version }}.tar.gz" + when: 'res.changed' + +- name: Ensure binary is copied to correct location + ansible.builtin.copy: + src: "/home/debian/webdav/{{ webdav_version }}/webdav" + remote_src: true + dest: '/usr/local/bin/webdav' + owner: 'root' + group: 'root' + mode: '0755' + when: 'res.changed' + notify: 'restart webdav' + +# Set up system user and data directories +- name: Ensure system group exists + ansible.builtin.group: + name: 'webdav' + gid: 5000 + system: true + state: present + +- name: Ensure system user exists + ansible.builtin.user: + name: 'webdav' + group: 'webdav' + uid: 5000 + system: true + create_home: false + +- name: Ensure subvolume permissions are correct + ansible.builtin.file: + path: "{{ data_dir }}" + state: directory + mode: '0755' + owner: 'webdav' + group: 'webdav' + +# Set up configuration, backup scripts and systemd service +- name: Ensure configuration directory is present + ansible.builtin.file: + path: '/etc/webdav' + state: directory + mode: '0755' + +- name: Ensure config file is present + ansible.builtin.template: + src: 'config.toml.j2' + dest: '/etc/webdav/config.toml' + mode: '0644' + owner: 'root' + group: 'root' + notify: 'restart webdav' + +# - name: Ensure backup scripts are present +# ansible.builtin.copy: +# src: "webdav.{{ item }}.backup.sh" +# dest: "/etc/backups/webdav.{{ item }}.backup.sh" +# owner: 'root' +# group: 'root' +# mode: '0644' +# loop: +# - 'data' + +- name: Ensure Caddyfile is present + ansible.builtin.copy: + src: "webdav.Caddyfile" + dest: "/etc/caddy/webdav.Caddyfile" + owner: 'root' + group: 'root' + mode: '0644' + +- name: Ensure service file is present + ansible.builtin.copy: + src: 'webdav.service' + dest: '/lib/systemd/system/webdav.service' + owner: 'root' + group: 'root' + mode: '0644' + register: res + +- name: systemd-reload + ansible.builtin.systemd_service: + daemon_reload: true + when: 'res.changed' + +# - name: Ensure webdav service is enabled +# ansible.builtin.service: +# name: 'webdav' +# enabled: true diff --git a/roles/any.software.webdav/templates/config.toml.j2 b/roles/any.software.webdav/templates/config.toml.j2 new file mode 100644 index 0000000..33f7c85 --- /dev/null +++ b/roles/any.software.webdav/templates/config.toml.j2 @@ -0,0 +1,31 @@ +address = '127.0.0.1' +port = 8018 + +# Handled by reverse proxy +tls = false + +prefix = '/' +debug = false +noSniff = false + +behindProxy = true +directory = '{{ data_dir }}' + +permissions = 'R' +rulesBehavior = 'overwrite' + +[log] +format = 'console' +# Color output isn't useful when ingested via systemd +colors = false +outputs = ['stdout'] + +[cors] +enabled = false + +[[users]] +username = '{{ webdav_user }}' +password = '{{ webdav_password }}' +permissions = 'CRUD' + +# vim: ft=toml