
Breaking out ntfy.sh on my Synology NAS
I didn’t need this, I didn’t want this, I wanted less distractions and less notifications… until I saw what ntfy.sh could do for me.
Table of Contents
- ntfy.sh
- Synology and containers
- What do you need?
- The basics
- Configuration
- Getting terminal access for the ntfy cli
ntfy.sh
So, what is ntfy.sh? In a nutshell, it is awesome. It’s basically a message queue that accepts messages for a certain topic from a myriad of sources and then relays those to a client application like the accompanying iOS or Android apps or the web app. There are hosted tiers available but it’s also possible to self host with the full pro functionality, allowing you to tweak and turn all the dials.
Some use case examples, you ask?
- I run home automation and each time someone rings the bell, I want to be notified. So, I hook up an ESP32 and make that do an HTTP call each time to my homeautomation topic on my ntfy.sh installation. I subscribe to that topic on the iOS app and boom… instant push notification on my iPhone every time someone’s at the door.
- I run automated PowerShell scripts every night and I want to be notified about the exit status after it runs. I add an “
Invoke-RestMethod -Method POST -Uri https://ntfy.example.nl/scriptmonitor -Body "Your script finished running! Here's the status: $status"
” at the end and I subscribe to the scriptmonitor topic on my phone.
Awesome! Of course there are many many options to configure and publish messages. Many of which I won’t cover here today. Fortunately, the documentation is quite extensive and both user and admin-friendly.
Synology and containers
Now there are plenty of options available to run ntfy.sh if you choose to self host. From direct debian packages to pre-built docker images, choose whatever suits your needs. I however, found myself already in possession of a great option: containers on my Synology NAS.
My particular model (the DS224+ running DSM 7.2) supports the Synology-built and maintained Container Manager add-on package and this is what I chose to use to set up my ntfy.sh instance. It’s lightweight, regularly updated, simple to use, and can pull from the Docker Hub repository.
Some models may not support Container Manager and other models may only support direct Docker installations. For current support for Container Manager, visit the official Synology add-on page.
Today, I will only describe my experiences with Container Manager so your mileage may vary if you choose to go for some other option. All of this is provided without warranty and is a best effort to help you get going. If you find anything not to (your) best practices or if you have any other suggestions, please let me know in the comments!
What do you need?
- A supported Synology NAS model running an up-to-date version of DSM. (If you don’t like up-to-date devices, please don’t connect it to the internet as your botnet participation will not help the rest of us.)
- The latest Container Manager package installed from the Synology Package Center.
- An account on your Synology that is a member of the administrators role/group.
- A public domain name.
- A static external IP address for your Synology’s internet connection.
- Basic understanding on how to configure DNS-records. (I will not cover DNS-configuration in detail in this blog as it is different with each registrar/hoster.)
- Basic understanding on how to configure port forwarding on your router/modem.
- Plenty of time to go troubleshoot.
The basics
Before we start talking configuration, let’s look at and understand the basic setup I have implemented on my own Synology. I’m aware it omits plenty of important other (transparant) systems, but this is basically it:

Persistent storage
If you have little to no knowledge about running containers, one thing you should know is that they are virtualized and ephemeral. Once you spin it up, the application inside will get its own little container that it can write to and read from whilst it is running. Stop or restart the container and everything is reset and you start afresh with everything back to the initial state as if just downloaded. So, if you want your configuration and other data to be persistent, you’re going to have to give the container access to storage outside of the container. We’ll do this in the form of a directory on our NAS.
Reverse proxy
Once you build the project inside Synology Container Manager, the underlying system will set up a private virtual network for your containers to connect to. Whilst the containers will be able to talk amongst each other and to the Synology NAS hosting the virtual network, other devices on your network (including your router/modem) will not.
This means that if we want to be able to reach the ntfy.sh instance from the internet through a forwarded port on your router/modem, we will have to make the container available to your internal network. One way (and the simplest) we can do this is by using the Synology built-in Reverse Proxy service. This will translate traffic to and from your container to a routable IP address. Without this, your container is basically isolated to the virtual network and no messages from the outside will be able to get through.
An added benefit to using this feature is that we can automatically request a Let’s Encrypt SSL certificate for the public domain name that we are going to publish our ntfy.sh instance to.
Whilst ntfy.sh itself also supports SSL/HTTPS out of the box, it does not support automatic requests to Let’s Encrypt. This means we would be going to either manually replace certificates every so often, set up additional automation or buy a certificate. Yikes.
Configuration
Persistent storage
Go to File Station and find the docker folder in the sidebar that was automatically created when you installed Container Manager.

Inside this folder, we’ll create the folders that we’re going to give the container access to (called mapping) so it can persist some configuration and data files. Go ahead and create the directory tree below, so it matches the screenshot.

- /docker/ntfy.sh/var/cache/ntfy
- /docker/ntfy.sh/var/lib/ntfy
- /docker/ntfy.sh/etc/ntfy
If you get the names or tree wrong, the mapping we define in the compose.yaml file later will not work.
Container Manager
Open up Container Manager and hop onto the Project tab.
Click Create to create your first project. This is where we’ll define what container we want to spin up and how they should interact with the Synology as a host.
Give your project a name like ntfysh and select the ntfy.sh folder you just created under the docker directory.
For Source, select Create docker-compose.yml so we can copy the yaml content below into the code input. This is a modified version of the official ntfy.sh Docker compose yaml, designed to work with Synology.
There are some lines you may want to edit to suit your particular scenario. Please don’t forget to also use any changed values in later steps if you do.
- If you want to change your time zone, edit line 10 of the yaml code below. For all valid TZ identifiers, check this Wikipedia list.
- If you created the file tree in an earlier step differently, make sure to edit the directory mappings here. These lines map the persistent storage to the container. Do not change anything after the first semicolon.
- If you want to change the port the application inside the container is published on, edit line 16 of the yaml code below and substitute 1201 for another port. I picked 1201 at random because it was available for me. Make sure the port is unique and not used by any other service or container on your Synology NAS. Don’t change the 80, as this is container-internal and should not be changed unless you later also change the server.yml file.
version: "2.3"
services:
ntfy:
image: binwiederhier/ntfy
container_name: ntfy
command:
- serve
environment:
- TZ=Europe/Amsterdam
volumes:
- /volume1/docker/ntfy.sh/var/cache/ntfy:/var/cache/ntfy:rw
- /volume1/docker/ntfy.sh/var/lib/ntfy:/var/lib/ntfy:rw
- /volume1/docker/ntfy.sh/etc/ntfy:/etc/ntfy:rw
ports:
- 1201:80
healthcheck:
test: ["CMD-SHELL", "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1"]
interval: 60s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped
YAMLPaste the correct yaml code into the Source field so it looks like the screenshot below.

Click Next to continue to the next page and click Next again. We do not want to set up Web Station, as we will be using the built-in Reverse Proxy.

Click Next to continue to the next page and click Done. Make sure to check to start the project after creation. This will automatically download the Docker image and build the container for you afterwards.

Container Manager will now pull the Docker image from the Docker Hub repository and download it to your NAS. It will then create the necessary virtual network, container and attempt a start. Although the container will likely start successfully, there are a couple more things we need to configure before we can start using our ntfy.sh instance.
ntfy.sh configuration
When starting, the ntfy service will look for the server.yml file in /etc/ntfy/. Luckily, we put this directory in our mappings. Meaning that if we place the file in the /docker/etc/ntfy/ folder we created, ntfy.sh will simply pick it up from there and start with the settings in it. Handy!
The official template file is available from the ntfy.sh GitHub but I have extracted the settings I needed and put them below for you to use as an example.
There are so many more configuration and integration options available than just the ones I configured. Unfortunately, I won’t be able to cover each and every one of them so my setup is very basic. If you want an explanation about the different settings, please refer to the template file mentioned earlier and the official documentation.
- On line 4, change the url so it reflects the domain you’re going to publish it to. If you want to publish it to ntfy.example.org on port 8080, use https://ntfy.example.org:8080 as your value. Again, make sure that the port is not already in use by another service on your Synology NAS.
- If you decided to change the port 80 in the docker-compose.yml, even though I told you not to, change it on line 7 too.
- Optionally, if you want to use web push notifications, follow the instructions here and edit lines 37, 38 and 40 accordingly. You will need terminal access to ntfy, which I will discuss in a later section.
Unless you want to make any other changes, copy the yaml code and save it under /docker/etc/ntfy/server.yml on your NAS so the container can pick it up. I added/left short descriptions as comments for reference.
# ntfy server config file
# Public facing base URL of the service. Change!
base-url: "https://YOURDOMAINNAME:8080"
# Container-internal port that the ntfy service listens on. Don't change!
listen-http: ":80"
# Where to store message cache. Don't change!
cache-file: "/var/cache/ntfy/cache.db"
# How long to store messages in cache. Optionally change!
cache-duration: "12h"
# Where to store user database. Don't change!
auth-file: "/var/lib/ntfy/user.db"
# Default/anonymous user access: read-write (default), read-only, write-only or deny-all. Optionally change!
auth-default-access: "deny-all"
# Needed because we are running ntfy behind a reverse proxy. Don't change!
behind-proxy: true
# Enable the sign up form on the web app. Optionally change!
enable-signup: false
# Enable the login form on the web app. Optionally change!
enable-login: true
# Enable the creation of reserved topics. Optionally change!
enable-reservations: true
# This makes sure iOS notifications can be sent to Apple devices. Don't change!
upstream-base-url: "https://ntfy.sh"
# This makes sure iOS notifications can be sent to the web app/browsers. Do change (some of it)!
web-push-public-key: YOURKEY
web-push-private-key: YOURKEY
web-push-file: /var/cache/ntfy/webpush.db
web-push-email-address: YOUREMAIL
# This sets log levels and log location. Optionally change!
log-level: info
log-format: text
log-file: /var/cache/ntfy/ntfy.log
YAMLAfter placing the server.yml file, open up Container Manager and hop onto the Container tab. Click the row for the ntfy container, click Actions and restart the container.

After the container has restarted, it should have now picked up the settings we entered into the server.yml file.
Domain name/DNS
You are going to want to publish your ntfy.sh instance on a public domain like ntfy.example.org. You will need this if you want it to have a valid SSL certificate and you need one of those if you want push notifications to work. Because somehow, browsers don’t trust web push from unsecured websites… odd.
Anyways, configure the DNS-records for your domain so that the A or CNAME record like ntfy.example.org points to your external IP address. The one that your Synology is accessing the internet from. You’re going to need this later.
Reverse Proxy
To set up the built-in Reverse Proxy feature, open up the Synology Control Panel and select Login Portal. Open the Advanced tab and click the Reverse Proxy button to start configuring it.

Assuming you have not used this feature before, you should be presented with an empty list. Let’s change that! Click Create and start filling in the correct settings.
Give your new Reverse Proxy a name like ntfy.sh.
For the source, select the HTTPS protocol, fill in the public facing domain you want to use like ntfy.example.org and include a port that your Synology NAS will publish your application. Again make sure that this isn’t a port that your Synology already uses elsewhere. I selected 1202 because it was available and near to the port I used earlier.
Because we will be issuing a valid certificate, also enable HSTS. This will make sure SSL policies will be strictly adhered to and will increase security for your ntfy instance.
For the destination select the HTTP protocol, fill in localhost for the hostname and 1201 for the port, unless you have changed this in the docker-compose.yml file when setting up your container project.

Lastly, go to the Custom Header tab, click Create and select Websocket. This should automatically create the two headers as shown below. These headers direct the client to upgrade to a more secure channel, again increasing security.


Click Save to start your Reverse Proxy. After saving, your Synology NAS will now serve the ntfy.sh service, translating from port 1202 on its own interface to 1201 on the docker container’s virtual network interface to port 80 inside the docker container.
Once you have set up the Reverse Proxy, you should request and assign a Let’s Encrypt SSL certificate for it. Refer to the official Synology knowledge base article for more information on how to set this up.
Port forwarding
The last thing to set up is port forwarding! Open the management site for your router/modem and forward a port like 8080 from the WAN interface to port 1202 on the Synology’s IP address. If you remember, port 8080 is the outward facing port we also included in the server.yml configuration for the ntfy service.
When you’re done, the traffic flow should be as follows:
- Client wants to visit https://ntfy.example.org:8080 and resolves it through DNS to your external IP.
- Client requests the web service for ntfy.example.org on your external IP on port 8080.
- Router/modem reroutes the traffic coming from port 8080 on its WAN interface to port 1202 on the Synology’s interface.
- Synology translates the traffic coming from port 1202 on its own interface to port 1201 on the docker container and negotiates and adds SSL on the incoming traffic coming from the client over the internet.
- Docker translates the traffic coming from port 1201 and feeds it into the container, where ntfy listens to it on port 80.
I used a different port for each of the translations, even when it wasn’t always needed technically. Hoping that by doing this, it’s easier to differentiate between the different interfaces and translations that take place.
Getting terminal access for the ntfy cli
Great! The container is running, we can access it from the internet, now what? Well, you probably don’t have any admin users or tiers yet. We can create these through the ntfy cli. However, to get there, we need terminal access to the container that it runs in. How? Let me show you.
Again, open up Container Manager and hop onto the Container tab. Click the row for the ntfy container, click Actions and select Open terminal.

When you do, you’ll immediately get an error that no teletype terminal was found. No worries, this is expected. Click Ok to dismiss the error.
Next, click the chevron to the right of Create and select Launch with command.

For the command, enter sh and click Ok to open a terminal that has a shell available for you to issue commands.

Click the newly created sh terminal in the sidebar to switch to it and start using commands. For more information on how to configure ntfy through the ntfy cli, please refer to the official documentation. There is more information available specifically on how to create users/admins and administer access and how to create your first tiers.
