From 32b1b13ef42836ed6ba4a4483c6c8867effb6ecf Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Sun, 23 Jan 2022 13:54:56 +0100 Subject: [PATCH] Add ntfy role Installs and configures the ntfysh server to enable notifications. --- group_vars/testing.yml | 1 + roles/ntfy/README.md | 42 ++++++++++++++++++++++ roles/ntfy/defaults/main.yml | 20 +++++++++++ roles/ntfy/handlers/main.yml | 46 ++++++++++++++++++++++++ roles/ntfy/meta/main.yml | 14 ++++++++ roles/ntfy/tasks/main.yml | 38 ++++++++++++++++++++ roles/ntfy/templates/docker-stack.yml.j2 | 25 +++++++++++++ roles/ntfy/templates/server.yml.j2 | 15 ++++++++ roles/ntfy/templates/upstream.json.j2 | 40 +++++++++++++++++++++ roles/ntfy/vars/main.yml | 7 ++++ site.yml | 5 +++ 11 files changed, 253 insertions(+) create mode 100644 roles/ntfy/README.md create mode 100644 roles/ntfy/defaults/main.yml create mode 100644 roles/ntfy/handlers/main.yml create mode 100644 roles/ntfy/meta/main.yml create mode 100644 roles/ntfy/tasks/main.yml create mode 100644 roles/ntfy/templates/docker-stack.yml.j2 create mode 100644 roles/ntfy/templates/server.yml.j2 create mode 100644 roles/ntfy/templates/upstream.json.j2 create mode 100644 roles/ntfy/vars/main.yml diff --git a/group_vars/testing.yml b/group_vars/testing.yml index 13676f5..c27a1ff 100644 --- a/group_vars/testing.yml +++ b/group_vars/testing.yml @@ -12,6 +12,7 @@ landingpage_use_https: no miniflux_use_https: no monica_use_https: no nextcloud_use_https: no +ntfy_use_https: no searx_use_https: no shaarli_use_https: no traggo_use_https: no diff --git a/roles/ntfy/README.md b/roles/ntfy/README.md new file mode 100644 index 0000000..df9bd6d --- /dev/null +++ b/roles/ntfy/README.md @@ -0,0 +1,42 @@ +# ntfy + +A self-hosted notifications service. + +Can take messages sent to the server through simple POST requests on specific topics and +blasts them out to any subscribed receiver on Android, Web, Commandline, or even in other applications. + +Thus can function as a simple cross-platform push message service that fits very well into unix workflows. + +## Defaults + +``` +ntfy_upstream_file_dir: "{{ docker_stack_files_dir }}/{{ stack_name }}" +``` + +The on-target directory where the proxy configuration file should be stashed. + +``` +ntfy_use_https: true +``` + +Whether the service should be reachable through http (port 80) or through https (port 443) and provision an https certificate. +Usually you will want this to stay `true`, +especially on the public facing web. + +``` +ntfy_version: latest +``` + +The docker image version to be used in stack creation. + +``` +subdomain_alias: push +``` + +If the deployed container should be served over a uri that is not the stack name. +By default, it will be set to `push.yourdomain.com` - +if this option is not set it will be served on `ntfy.yourdomain.com` instead. + +The individual `ntfy` options to be changed are very well described on +[the ntfy documentation](https://ntfy.sh/docs/config/). +Together with the default variables for this role it should be easy to find a good pair of settings. diff --git a/roles/ntfy/defaults/main.yml b/roles/ntfy/defaults/main.yml new file mode 100644 index 0000000..14089c2 --- /dev/null +++ b/roles/ntfy/defaults/main.yml @@ -0,0 +1,20 @@ +--- + +ntfy_version: latest + +ntfy_upstream_file_dir: "{{ docker_stack_files_dir }}/{{ stack_name }}" + +ntfy_use_https: true + +subdomain_alias: push + +ntfy_global_topic_limit: "15000" +ntfy_visitor_subscription_limit: "30" +ntfy_visitor_request_limit_burst: "60" +ntfy_visitor_request_limit_replenish: "10s" +ntfy_cache_duration: "12h" +ntfy_attachment_total_size_limit: "5G" +ntfy_attachment_file_size_limit: "15M" +ntfy_attachment_expiry_duration: "5h" +ntfy_visitor_attachment_total_size_limit: "500M" +ntfy_visitor_attachment_daily_bandwidth_limit: "1G" diff --git a/roles/ntfy/handlers/main.yml b/roles/ntfy/handlers/main.yml new file mode 100644 index 0000000..de1b807 --- /dev/null +++ b/roles/ntfy/handlers/main.yml @@ -0,0 +1,46 @@ +## Register reverse proxy +- name: Ensure upstream directory exists + ansible.builtin.file: + path: "{{ ntfy_upstream_file_dir }}" + state: directory + mode: '0755' + become: yes + listen: "update ntfy upstream" + +- name: Update upstream template + ansible.builtin.template: + src: upstream.json.j2 + dest: "{{ ntfy_upstream_file_dir }}/upstream.json" + become: yes + listen: "update ntfy upstream" + +# figure out if upstream id exists +- name: check {{ stack_name }} upstream + community.docker.docker_container_exec: + container: "{{ caddy_container_id }}" + command: > + curl localhost:2019/id/{{ stack_name }}_upstream/ + changed_when: False + register: result + become: yes + listen: "update ntfy upstream" + +# upstream already exists, patch it +- name: remove old {{ stack_name }} upstream + community.docker.docker_container_exec: + container: "{{ caddy_container_id }}" + command: > + curl -X DELETE localhost:2019/id/{{ stack_name }}_upstream/ + become: yes + when: (result.stdout | from_json)['error'] is not defined + listen: "update ntfy upstream" + +# upstream has to be created +- name: add {{ stack_name }} upstream + community.docker.docker_container_exec: + container: "{{ caddy_container_id }}" + command: > + curl -X POST -H "Content-Type: application/json" -d @{{ ntfy_upstream_file_dir }}/upstream.json localhost:2019/config/apps/http/servers/{{ (ntfy_use_https == True) | ternary(caddy_https_server_name, caddy_http_server_name) }}/routes/0/ + become: yes + listen: "update ntfy upstream" + diff --git a/roles/ntfy/meta/main.yml b/roles/ntfy/meta/main.yml new file mode 100644 index 0000000..16d1cd4 --- /dev/null +++ b/roles/ntfy/meta/main.yml @@ -0,0 +1,14 @@ +--- + +galaxy_info: + author: Marty Oehme + description: Installs a self-hosted push notification service through docker-swarm. + license: GPL-3.0-only + min_ansible_version: 2.9 + galaxy_tags: [] + + +dependencies: + - docker + - docker-swarm + - caddy diff --git a/roles/ntfy/tasks/main.yml b/roles/ntfy/tasks/main.yml new file mode 100644 index 0000000..bc64d86 --- /dev/null +++ b/roles/ntfy/tasks/main.yml @@ -0,0 +1,38 @@ +--- +- name: Ensure target directory exists + ansible.builtin.file: + path: "{{ ntfy_upstream_file_dir }}" + state: directory + mode: '0755' + become: yes + +- name: Move ntfy configuration file to target dir + ansible.builtin.template: + src: "server.yml.j2" + dest: "{{ ntfy_upstream_file_dir }}/server.yml" + become: yes + notify: "update ntfy upstream" + +## install ntfy container +- name: Check upstream status + community.docker.docker_container_exec: + container: "{{ caddy_container_id }}" + command: > + curl localhost:2019/id/{{ stack_name }}_upstream/ + register: result + changed_when: (result.stdout | from_json) != (lookup('template', 'upstream.json.j2') | from_yaml) + become: yes + notify: "update ntfy upstream" + +- name: Deploy ntfy to swarm + community.general.docker_stack: + name: "{{ stack_name }}" + state: present + prune: yes + compose: + - "{{ stack_compose }}" + become: yes + tags: + - docker-swarm + notify: "update ntfy upstream" + diff --git a/roles/ntfy/templates/docker-stack.yml.j2 b/roles/ntfy/templates/docker-stack.yml.j2 new file mode 100644 index 0000000..bf0e5a5 --- /dev/null +++ b/roles/ntfy/templates/docker-stack.yml.j2 @@ -0,0 +1,25 @@ +version: '3.4' + +services: + app: + image: "{{ stack_image }}:{{ ntfy_version }}" + healthcheck: + test: ["CMD", "wget", "--spider", "-q", "localhost"] + interval: 1m + timeout: 10s + retries: 3 + start_period: 1m + volumes: + - "{{ ntfy_upstream_file_dir }}/server.yml:/etc/ntfy/server.yml" + - cache:/var/cache/ntfy + networks: + - "{{ docker_swarm_public_network_name }}" + +volumes: + cache: + +networks: + "{{ docker_swarm_public_network_name }}": + external: true + + diff --git a/roles/ntfy/templates/server.yml.j2 b/roles/ntfy/templates/server.yml.j2 new file mode 100644 index 0000000..cbbe8a5 --- /dev/null +++ b/roles/ntfy/templates/server.yml.j2 @@ -0,0 +1,15 @@ +base-url: "https://{{ server_domain }}" +global_topic_limit: "{{ ntfy_global_topic_limit }}" +visitor_subscription_limit: "{{ ntfy_visitor_subscription_limit }}" +visitor_request_limit_burst: "{{ ntfy_visitor_request_limit_burst }}" +visitor_request_limit_replenish: "{{ ntfy_visitor_request_limit_replenish }}" +cache-file: "/var/cache/ntfy/cache.db" +cache_duration: "{{ ntfy_cache_duration }}" +attachment-cache-dir: "/var/cache/ntfy/attachments" +attachment_total_size_limit: "{{ ntfy_attachment_total_size_limit }}" +attachment_file_size_limit: "{{ ntfy_attachment_file_size_limit }}" +attachment_expiry_duration: "{{ ntfy_attachment_expiry_duration }}" +visitor_attachment_total_size_limit: "{{ ntfy_visitor_attachment_total_size_limit }}" +visitor_attachment_daily_bandwidth_limit: "{{ ntfy_visitor_attachment_daily_bandwidth_limit }}" +behind-proxy: true # uses 'X-Forwarded-For' Headers for individual visitors +# TODO i believe Caddy does not set the correct X-Forwarded-For header, see whoami container to check diff --git a/roles/ntfy/templates/upstream.json.j2 b/roles/ntfy/templates/upstream.json.j2 new file mode 100644 index 0000000..a8af36a --- /dev/null +++ b/roles/ntfy/templates/upstream.json.j2 @@ -0,0 +1,40 @@ +{ + "@id": "{{ stack_name }}_upstream", +{% if server_domain is not undefined and not none %} + "match": [ + { + "host": [ +{% if subdomain_alias is not undefined and not none %} + "{{ subdomain_alias }}.{{ server_domain }}" +{% else %} + "{{ stack_name }}.{{ server_domain }}" +{% endif %} + ] + } + ], +{% else %} + "match": [ + { + "path": [ +{% if subdomain_alias is not undefined and not none %} + "/{{ subdomain_alias }}*" +{% else %} + "/{{ stack_name }}*" +{% endif %} + , + "/" + ] + } + ], +{% endif %} + "handle": [ + { + "handler": "reverse_proxy", + "upstreams": [ + { + "dial": "{{ stack_name }}_app:80" + } + ] + } + ] +} diff --git a/roles/ntfy/vars/main.yml b/roles/ntfy/vars/main.yml new file mode 100644 index 0000000..a3c184b --- /dev/null +++ b/roles/ntfy/vars/main.yml @@ -0,0 +1,7 @@ +--- + +stack_name: ntfy + +stack_image: "binwiederhier/ntfy" + +stack_compose: "{{ lookup('template', 'docker-stack.yml.j2') | from_yaml }}" diff --git a/site.yml b/site.yml index 5ed33b7..ecb9933 100644 --- a/site.yml +++ b/site.yml @@ -78,3 +78,8 @@ import_role: role: gitea tags: gitea + + - name: Install ntfy + import_role: + role: ntfy + tags: ntfy