feat(ntfy):add ntfy server role (#20)
### Description This PR adds a new `ntfy_server` role to configure, start, and test a ntfy container. This container is designed to be secure by default by requiring auth by default ### Related Issue Closes #15 ### Testing Done - [x] verified new container file was created correctly\ - [x] verified ntfy server webui is working and requires auth - [x] verified with automated test that ntfy server is working and accepting post requests ### Checklist - [x] My code follows the project's style guidelines. - [x] I have performed a self-review of my own code. - [x] I have updated the documentation (if necessary). --------- Co-authored-by: Jordan Del Pilar <[email protected]> Reviewed-on: #20
This commit was merged in pull request #20.
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
---
|
||||
github_key_url: https://github.com/redjordan2539.keys
|
||||
base_domain: delpilar.net
|
||||
|
||||
@@ -250,3 +250,36 @@ minecraft_servers:
|
||||
TYPE: PAPER
|
||||
ENABLE_AUTOPAUSE: "true"
|
||||
OPS: redjordan1
|
||||
|
||||
ntfy_web_user: jdelpilar
|
||||
ntfy_web_pass: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
39363231343664626436343130316662336663303939343334353138353864383334363362343362
|
||||
6366633162323162393263336137313534303563353337340a316362653735306538363733333461
|
||||
38626362386263613932366664316630306361313036353839373562663534613962346339626538
|
||||
3866356430663962660a613962396662333538333836666334613064343266376431633463326164
|
||||
39333735343634316336613933303765373934393834663933626439643138663561
|
||||
|
||||
ntfy_users:
|
||||
- username: jdelpilar
|
||||
pass: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
63613562396339323236636436613162633933306338333662633933613832613038313230333165
|
||||
3365636562366165363861353638306264653739396532320a366564346331396266653762306165
|
||||
33333639373532653762363563653534353661366239306265303538376237393438636437393632
|
||||
3138386130306430640a383932383634313764373565636463636233623063613961353961643531
|
||||
35613864303162393362616634626238316334343533646261643063303963383932653534316466
|
||||
31313231643239653865363163623136316234386433393263366537323866326633313261656533
|
||||
313965396432613533653934323464626334
|
||||
level: admin
|
||||
- username: hass
|
||||
pass: !vault |
|
||||
$ANSIBLE_VAULT;1.1;AES256
|
||||
65656330333535306239343935306234633730376361393234376266393837636436313262353939
|
||||
3635653139383864396533373534306236386662643535650a373765303531633563326563663736
|
||||
39666339343439333730373834353962343962383335633466656162356465366537303532623438
|
||||
6361633163623061660a323565346663313238396431373932333562313237326238313235373330
|
||||
33663632333266623162373033376432336538393334386663393866623836663562343936396234
|
||||
38633431623838653035623066346138386234623861316461653430623638656563633261383238
|
||||
353132376664303838316637663035633862
|
||||
level: user
|
||||
|
||||
@@ -32,3 +32,6 @@ all:
|
||||
minecraft_servers:
|
||||
hosts:
|
||||
new-bark:
|
||||
ntfy_servers:
|
||||
hosts:
|
||||
new-bark:
|
||||
@@ -0,0 +1,106 @@
|
||||
# Role: ntfy Server
|
||||
This role sets up, starts and test the ntfy container.
|
||||
This role is designed to only create one ntfy container per host.
|
||||
|
||||
## Tags
|
||||
- ntfy
|
||||
- comms
|
||||
|
||||
## Required Variables
|
||||
Below is an annotated breakdown of the required variables and their structure for this role
|
||||
|
||||
> [!WARNING]
|
||||
> Any variable marked `# !SENSITIVE` **should not** be stored in plain text under any circumstance
|
||||
|
||||
### ntfy User Info
|
||||
Defines users to be set up and used in ntfy.
|
||||
These settings should be defined on each server you plan on setting up ntfy on as they are unique to each server
|
||||
|
||||
```yaml
|
||||
# (required) username of the primary web user of the ntfy webui
|
||||
# this account is used during the role to send a test post request to verify the server is running
|
||||
# this username must also be defined in the below ntfy_users list
|
||||
# format: username
|
||||
ntfy_web_user:
|
||||
|
||||
# (required) password of the above web user
|
||||
# this is used during basic auth to send the test request to the server
|
||||
# !SENSITIVE
|
||||
# format: string
|
||||
ntfy_web_pass:
|
||||
|
||||
# (required) list of users to be created in the ntfy instance
|
||||
# you must defined the above ntfy_web_user in this list
|
||||
ntfy_users:
|
||||
# (required) username of the user to be created
|
||||
# format: username
|
||||
- username:
|
||||
# (required) password hash for the user
|
||||
# for more info on the requirements of this hash please read below
|
||||
# !SENSITIVE
|
||||
# format: string
|
||||
pass:
|
||||
|
||||
# (required) user level of the generated user
|
||||
# you must define at least one admin user per instance
|
||||
# format: choice("user", "admin")
|
||||
level:
|
||||
```
|
||||
### ntfy container Info
|
||||
Defines settings for the ntfy container
|
||||
|
||||
```yaml
|
||||
# (optional) name of the ntfy container
|
||||
# default: ntfy
|
||||
# format: snake_case
|
||||
ntfy_name:
|
||||
|
||||
# (optional) path to ntfy container image
|
||||
# can be set to any container register
|
||||
# default: docker.io/binwiederhier/ntfy
|
||||
# format: URL
|
||||
ntfy_image:
|
||||
|
||||
# (optional) name of the container owner
|
||||
# typically set to the same user as the ansible user
|
||||
# default: {{ ansible_user }}
|
||||
# format: username
|
||||
container_owner:
|
||||
|
||||
# (optional) flag to enable traefik labels in the container
|
||||
# default: true
|
||||
# format: bool
|
||||
ntfy_enable_traefik:
|
||||
|
||||
# (optional) subdomain of the ntfy instance
|
||||
# only used if `ntfy_enable_traefik` == true
|
||||
# default: ntfy
|
||||
# format: string
|
||||
ntfy_subdomain:
|
||||
|
||||
# (optional) port to ntfy webui
|
||||
# only used if `ntfy_enable_traefik` == true
|
||||
# default: 80
|
||||
# format: int
|
||||
ntfy_port:
|
||||
|
||||
# (optional) podman network to bind ntfy container to
|
||||
# default: management-net
|
||||
# format: string
|
||||
ntfy_network:
|
||||
|
||||
# (optional) URL of the ntfy webui
|
||||
# default: ntfy.delpilar.net
|
||||
# format: url
|
||||
ntfy_url:
|
||||
```
|
||||
## Templates
|
||||
|
||||
### ntfy.container.j2
|
||||
This template is used to generate .container files for ntfy services. This template includes a section for traefik labels.
|
||||
|
||||
## Execution
|
||||
To run this role without running all other roles use the following command
|
||||
```bash
|
||||
ansible-playbook site.yaml --tags "ntfy"
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
ntfy_name: ntfy
|
||||
ntfy_image: docker.io/binwiederhier/ntfy
|
||||
container_owner: "{{ ansible_user }}"
|
||||
ntfy_enable_traefik: true
|
||||
ntfy_subdomain: ntfy
|
||||
ntfy_port: 80
|
||||
ntfy_network: management-net
|
||||
ntfy_url: ntfy.delpilar.net
|
||||
@@ -0,0 +1,6 @@
|
||||
- name: Restart ntfy on Change
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ ntfy_name }}"
|
||||
state: restarted
|
||||
scope: user
|
||||
daemon_reload: true
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
- name: Create ntfy Directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ podman_config_base_dir }}/{{ ntfy_name }}/{{ item }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
loop:
|
||||
- "/cache"
|
||||
- "/auth"
|
||||
|
||||
- name: Create ntfy Quadlet
|
||||
ansible.builtin.template:
|
||||
src: ntfy.container.j2
|
||||
dest: "{{ podman_quadlet_base_dir }}/management/{{ ntfy_name }}.container"
|
||||
owner: "{{ ansible_user }}"
|
||||
mode: "644"
|
||||
notify: Restart ntfy on Change
|
||||
|
||||
- name: Flush Handlers
|
||||
ansible.builtin.meta: flush_handlers
|
||||
|
||||
- name: Start ntfy Servers
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ ntfy_name }}"
|
||||
state: started
|
||||
scope: user
|
||||
|
||||
- name: Verify server is running
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ ntfy_url }}/ansible_test"
|
||||
method: POST
|
||||
body: "Deployment Successful! ntfy is online"
|
||||
url_username: "{{ ntfy_web_user }}"
|
||||
url_password: "{{ ntfy_web_pass }}"
|
||||
force_basic_auth: true
|
||||
status_code: 200
|
||||
register: ntfy_health_check
|
||||
until: ntfy_health_check.status == 200
|
||||
retries: 10
|
||||
delay: 3
|
||||
@@ -0,0 +1,57 @@
|
||||
# {{ ansible_managed }}
|
||||
[Unit]
|
||||
After=network-online.target
|
||||
|
||||
StartLimitBurst=10
|
||||
StartLimitIntervalSec=120
|
||||
|
||||
[Container]
|
||||
ContainerName={{ ntfy_name }}
|
||||
Image={{ ntfy_image }}
|
||||
|
||||
Network={{ ntfy_network | default('management-net', true) }}
|
||||
|
||||
AutoUpdate=registry
|
||||
|
||||
Label=category=management
|
||||
Label=owner={{ container_owner | default('jdelpilar', true) }}
|
||||
|
||||
{% if ntfy_enable_traefik | default(true) %}
|
||||
Label=traefik.enable=true
|
||||
Label=traefik.http.routers.{{ ntfy_name }}.rule=Host(`{{ ntfy_url | default(ntfy_name + base_domain, true) }}`)
|
||||
Label=traefik.http.routers.{{ ntfy_name }}.entrypoints={{ traefik_entrypoint | default('websecure', true) }}
|
||||
Label=traefik.http.routers.{{ ntfy_name }}.tls.certresolver={{ traefik_resolver | default('cloudflare', true) }}
|
||||
Label=traefik.http.services.{{ ntfy_name }}.loadbalancer.server.port={{ ntfy_port | default(80, true) }}
|
||||
Label=traefik.docker.network={{ ntfy_network | default('management-net', true) }}
|
||||
Label=traefik.http.routers.{{ ntfy_name }}.tls=true
|
||||
{% endif %}
|
||||
|
||||
Volume={{ podman_config_base_dir }}/{{ ntfy_name }}/cache:/var/cache/ntfy
|
||||
Volume={{ podman_config_base_dir }}/{{ ntfy_name }}/auth:/var/lib/ntfy
|
||||
{% if item.volumes is defined %}
|
||||
{% for volume in item.volumes %}
|
||||
Volume={{ volume }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
Environment=TZ={{ timezone | default('America/Los_Angeles') }}
|
||||
Environment=NTFY_BASE_URL=https://{{ ntfy_url | default(ntfy_name + base_domain, true) }}
|
||||
Environment=NTFY_AUTH_FILE=/var/lib/ntfy/user.db
|
||||
Environment=NTFY_AUTH_DEFAULT_ACCESS=deny-all
|
||||
Environment=NTFY_ENABLE_LOGIN=true
|
||||
Environment=NTFY_REQUIRE_LOGIN=true
|
||||
Environment=NTFY_AUTH_USERS="{% for user in ntfy_users %}{{ user['username'] }}:{{ user['pass'] }}:{{ user['level'] }}{{ ',' if not loop.last }}{% endfor %}"
|
||||
{% if ntfy_env is defined %}
|
||||
{% for key, value in ntfy_env.items() | sort %}
|
||||
Environment={{ key }}={{ value }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
Exec=serve
|
||||
|
||||
[Service]
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
Reference in New Issue
Block a user