Install and Use ntfy
Introduction
In my previous post, I used QQ Mail as the notification service for ChangeDetection. That was just for quickly getting started with ChangeDetection, but it wasn’t necessary since there are several open-source notification systems available, such as ntfy. This article will walk through the installation and usage of ntfy, which is quite straightforward. However, I encountered some issues when integrating it with ChangeDetection, and this post will cover the solutions to those problems as well.
Installation and Configuration
Docker compose
The ntfy Web UI uses the Notifications API, which requires HTTPS, so we need to launch an Nginx container.
1 | version: "3" |
ntfy Configuration
Manually create the configuration file: /etc/ntfy/server.yml
. For specific configuration options, refer to the template provided by the official site. My configuration includes the following options:
1 | base-url: "https://<host_IP>:40043" |
By default, ntfy doesn’t persist messages, only forwarding them in real-time. This can lead to message loss in two scenarios:
- ntfy is online, but the client experiences a network issue. Upon reconnection, the client won’t receive messages sent during the outage.
- The client is online, but ntfy goes offline before forwarding a message. Upon restarting, the message is lost.
Using the cache-file
essentially turns ntfy into a message queue, mitigating these issues. The duration for which messages are cached is set by cache-duration
.
ntfy also supports sending images and attachments, but since I don’t need those features, I didn’t configure them.
Nginx Configuration
For Nginx and SSL certificate setup, refer to my previous post.
The official document provides an Nginx template. Here’s my configuration:
1 | user nginx; |
VM NAT and Host Firewall
My host machine is running Win10, with a Linux VM running Docker via VMware. Therefore, I have to configure VM NAT and open up the host’s firewall. You can refer to this post for more details.
I opened port 40043 on the host to enable local network sharing.
Usage
For a basic Hello World example, see the official site. I won’t go into it here.
Access Control
You might have noticed that my configuration file includes:
1 | auth-default-access: "deny-all" |
By default, clients connected to ntfy have no read or write permissions for any topics. This is the most secure setup, but it’s also the most cumbersome to manage.
To add a test
topic and allow everyone to read/write:
1 | / # ntfy access everyone test rw |
Integration with ChangeDetection
Access Control
For the ChangeDetection
topic, I created a writer and a reader:
1 | / # ntfy access |
Remembering these users’ passwords can be tricky. I use a randomly generated long password for the writer, making this user essentially one-time use for a single topic. If I forget the password, I’ll just create a new user. For the reader, I use a short, easy-to-remember password (with some risk of being cracked).
Notification URL
According to the official documentation, the notification URL for ChangeDetection is:
1 | ntfys://ChangeDetectionPublisher:<password>@<VM_IP>:40043/ChangeDetection |
- Since I’m using HTTPS, the prefix is
ntfys
; if using HTTP, it would bentfy
. - Regardless of which Docker network the container is in, it will correctly resolve the host’s IP (which in this case is the VM’s IP), no matter which network the IP belongs to (e.g., Docker network, VMware adapter network).
Container CA Certificate Configuration
After configuring the ChangeDetection notification URL and clicking test, the following error appeared:
1 | (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1006)'))) |
This error is expected because Nginx is using a self-signed SSL certificate, and the ChangeDetection container doesn’t trust my self-created CA certificate.
Solution 1: Trust the Certificate in the Container
First, copy the self-signed certificate into the container:
1 | docker cp /path/to/your/certificate.crt <container_name>:/usr/local/share/ca-certificates/ |
Then, inside the container, update the CA certificates:
1 | update-ca-certificates |
Finally, restart the container.
This solution works for curl
, wget
, and similar commands, but it doesn’t work for ChangeDetection because it’s developed in Python. Python doesn’t use the OS’s certificates but instead uses the certifi
package’s certificates. So, the focus should be on making Python trust the certificate rather than the container.
Solution 2: Use the REQUESTS_CA_BUNDLE
Environment Variable
Modify the ChangeDetection Docker Compose file:
1 | services: |
This method is also not correct for ChangeDetection, as setting this environment variable overrides the entire set of existing certificates, meaning ChangeDetection will only trust the ntfy certificate and won’t trust any certificates on the internet. Since ChangeDetection needs to access the internet, this creates a conflict.
For some scripts, like the one I previously wrote about “Display Original Filenames in Jellyfin”, using this environment variable can still be quite handy.
Solution 3: Add the Certificate to the certifi
Package
Enter the container:
1 | python |
Then restart the container.
This is the only viable solution at the moment.
For containers, it’s okay if the certifi
package gets messed up, because you can always create a new container. For hosts, consider creating a new venv
or conda env
for this task, so you don’t damage your existing environment.
After testing ChangeDetection again, everything is working fine. The integration is completed 😁.