[GH-ISSUE #182] Unable to autostart the daemon (if set, key file must exist) #144

Closed
opened 2026-05-07 00:20:32 +02:00 by BreizhHardware · 4 comments

Originally created by @A-Nicoladie on GitHub (Mar 21, 2022).
Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/182

Hi,

I am discovering and testing ntfy and I have a small problem:
The installation went well and after launching the service, I receive all expected notifications.

But after a reboot, the service does not start automatically 😟
It seems to be an access rights issue (maybe), but I'm not sure what's the best approach to solve this.

Here some info:

systemctl enable ntfy and systemctl start ntfy return no error.

sudo -H -u root bash -c '/usr/bin/ntfy serve'
2022/03/21 13:36:01 Listening on :PRIVATE[https]
2022/03/21 13:37:01 Stats: 0 message(s) published, 0 in cache, 0 successful mails, 0 failed, 3 topic(s) active, 3 subscriber(s), 1 visitor(s)
sudo -H -u ntfy bash -c '/usr/bin/ntfy serve'
if set, key file must exist
systemctl list-units | grep ntfy
● ntfy-client.service          loaded failed failed    ntfy client
● ntfy.service                 loaded failed failed    ntfy server
cat /etc/ntfy/server.yml
base-url: "https://PRIVATE"
listen-http: "-"
listen-https: ":PRIVATE"
key-file: /etc/letsencrypt/live/PRIVATE/privkey.pem
cert-file: /etc/letsencrypt/live/PRIVATE/fullchain.pem
cat -n /var/log/syslog
...
6031	Mar 21 14:59:42 PRIVATE systemd[1]: Started ntfy server.
6032	Mar 21 14:59:43 PRIVATE ntfy[4491]: if set, key file must exist
6033	Mar 21 14:59:43 PRIVATE systemd[1]: ntfy.service: Main process exited, code=exited, status=1/FAILURE
6034	Mar 21 14:59:43 PRIVATE systemd[1]: ntfy.service: Failed with result 'exit-code'.
6035	Mar 21 14:59:43 PRIVATE systemd[1]: ntfy.service: Service hold-off time over, scheduling restart.
6036	Mar 21 14:59:43 PRIVATE systemd[1]: ntfy.service: Scheduled restart job, restart counter is at 1.
6037	Mar 21 14:59:43 PRIVATE systemd[1]: Stopped ntfy server.
...
cat /lib/systemd/system/ntfy.service
[Unit]
Description=ntfy server
After=network.target

[Service]
User=ntfy
Group=ntfy
ExecStart=/usr/bin/ntfy serve
Restart=on-failure
AmbientCapabilities=CAP_NET_BIND_SERVICE
LimitNOFILE=10000

[Install]
WantedBy=multi-user.target
ls -l /usr/bin/ntfy
-rwxr-xr-x 1 root root 18725152 mars  17 00:39 /usr/bin/ntfy
sudo -H -u root bash -c 'ls -l /etc/letsencrypt/live/PRIVATE/privkey.pem'
lrwxrwxrwx 1 root root 44 janv. 27 04:02 /etc/letsencrypt/live/PRIVATE/privkey.pem -> ../../archive/PRIVATE/privkey20.pem
sudo -H -u ntfy bash -c 'ls -l /etc/letsencrypt/live/PRIVATE/privkey.pem'
ls: cannot access '/etc/letsencrypt/live/PRIVATE/privkey.pem': Permission denied
sudo -H -u root bash -c 'ls -l /etc/letsencrypt/archive/PRIVATE/privkey20.pem'
-rw-r--r-- 1 root root 1708 janv. 27 04:02 privkey20.pem
Originally created by @A-Nicoladie on GitHub (Mar 21, 2022). Original GitHub issue: https://github.com/binwiederhier/ntfy/issues/182 Hi, I am discovering and testing ntfy and I have a small problem: The installation went well and after launching the service, I receive all expected notifications. But after a reboot, the service does not start automatically 😟 It seems to be an access rights issue (maybe), but I'm not sure what's the best approach to solve this. Here some info: `systemctl enable ntfy` and `systemctl start ntfy` return no error. <!-- ------------------------------ Run as root ------------------------------ --> <details open> <summary>sudo -H -u root bash -c '/usr/bin/ntfy serve'</summary> ``` 2022/03/21 13:36:01 Listening on :PRIVATE[https] 2022/03/21 13:37:01 Stats: 0 message(s) published, 0 in cache, 0 successful mails, 0 failed, 3 topic(s) active, 3 subscriber(s), 1 visitor(s) ``` </details> <!-- ------------------------------ Run as ntfy ------------------------------ --> <details open> <summary>sudo -H -u ntfy bash -c '/usr/bin/ntfy serve'</summary> ``` if set, key file must exist ``` </details> <!-- ------------------------------ systemctl list-units ------------------------------ --> <details> <summary>systemctl list-units | grep ntfy</summary> ```shell ● ntfy-client.service loaded failed failed ntfy client ● ntfy.service loaded failed failed ntfy server ``` </details> <!-- ------------------------------ ntfy.service ------------------------------ --> <details> <summary>cat /etc/ntfy/server.yml</summary> ```ini base-url: "https://PRIVATE" listen-http: "-" listen-https: ":PRIVATE" key-file: /etc/letsencrypt/live/PRIVATE/privkey.pem cert-file: /etc/letsencrypt/live/PRIVATE/fullchain.pem ``` </details> <!-- ------------------------------ ------------------------------ --> <details> <summary>cat -n /var/log/syslog</summary> ``` ... 6031 Mar 21 14:59:42 PRIVATE systemd[1]: Started ntfy server. 6032 Mar 21 14:59:43 PRIVATE ntfy[4491]: if set, key file must exist 6033 Mar 21 14:59:43 PRIVATE systemd[1]: ntfy.service: Main process exited, code=exited, status=1/FAILURE 6034 Mar 21 14:59:43 PRIVATE systemd[1]: ntfy.service: Failed with result 'exit-code'. 6035 Mar 21 14:59:43 PRIVATE systemd[1]: ntfy.service: Service hold-off time over, scheduling restart. 6036 Mar 21 14:59:43 PRIVATE systemd[1]: ntfy.service: Scheduled restart job, restart counter is at 1. 6037 Mar 21 14:59:43 PRIVATE systemd[1]: Stopped ntfy server. ... ``` </details> <!-- ------------------------------ ntfy.service ------------------------------ --> <details> <summary>cat /lib/systemd/system/ntfy.service</summary> ```ini [Unit] Description=ntfy server After=network.target [Service] User=ntfy Group=ntfy ExecStart=/usr/bin/ntfy serve Restart=on-failure AmbientCapabilities=CAP_NET_BIND_SERVICE LimitNOFILE=10000 [Install] WantedBy=multi-user.target ``` </details> <!-- ------------------------------ ntfy ------------------------------ --> <details> <summary>ls -l /usr/bin/ntfy</summary> ``` shell -rwxr-xr-x 1 root root 18725152 mars 17 00:39 /usr/bin/ntfy ``` </details> <!-- ------------------------------ SSL Live ------------------------------ --> <details> <summary>sudo -H -u root bash -c 'ls -l /etc/letsencrypt/live/PRIVATE/privkey.pem'</summary> ``` lrwxrwxrwx 1 root root 44 janv. 27 04:02 /etc/letsencrypt/live/PRIVATE/privkey.pem -> ../../archive/PRIVATE/privkey20.pem ``` </details> <details> <summary>sudo -H -u ntfy bash -c 'ls -l /etc/letsencrypt/live/PRIVATE/privkey.pem'</summary> ``` ls: cannot access '/etc/letsencrypt/live/PRIVATE/privkey.pem': Permission denied ``` </details> <!-- ------------------------------ SSL Archive --> <details> <summary>sudo -H -u root bash -c 'ls -l /etc/letsencrypt/archive/PRIVATE/privkey20.pem'</summary> ``` -rw-r--r-- 1 root root 1708 janv. 27 04:02 privkey20.pem ``` </details>
BreizhHardware 2026-05-07 00:20:32 +02:00
  • closed this issue
  • added the
    question
    label
Author
Owner

@binwiederhier commented on GitHub (Mar 21, 2022):

Hey @A-Nicoladie thanks for trying out ntfy. Yeah that looks like a permissions issue.

The ntfy systemd service runs as use ntfy as you have already figured out, so key and cert file have to be readable by that user. There are multiple ways to solve this:

1. Run ntfy behind a proxy (nginx, Apache2, caddy, ...)

If you run ntfy behind a proxy (instructions here: https://ntfy.sh/docs/config/#nginxapache2caddy), you can put all of the cert management in there and run multiple services on different subdomains as well. It's the most common approach, unless you are only running ntfy and nothing else.

In this case, you'd run ntfy on :1234/http or some other port (not https) and let nginx handle the SSL termination.

2. Run ntfy systemd service as root (don't do this )

You can systemctl edit ntfy and manually override the User/Group like this. This way, you'll be able to read the cert no matter what.

[Service]
User=root
Group=root

3. Copy certs to /etc/ntfy and chown them

You can copy the cert and keyfile from /etc/letsencrypt/... to /etc/ntfy and make sure that they are readable by the ntfy user by chown ntfy:ntfy ... them. Then also make sure that you have a post_hook in the certbot config, like this:

root@ntfy:/etc/cron.d# cat /etc/letsencrypt/renewal/ntfy.sh.conf
# renew_before_expiry = 30 days
version = 0.40.0
archive_dir = /etc/letsencrypt/archive/ntfy.sh
cert = /etc/letsencrypt/live/ntfy.sh/cert.pem
privkey = /etc/letsencrypt/live/ntfy.sh/privkey.pem
chain = /etc/letsencrypt/live/ntfy.sh/chain.pem
fullchain = /etc/letsencrypt/live/ntfy.sh/fullchain.pem

# Options used in the renewal process
[renewalparams]
...
post_hook = /script/to/move/and/chown/the/keyfiles.sh
<!-- gh-comment-id:1073992295 --> @binwiederhier commented on GitHub (Mar 21, 2022): Hey @A-Nicoladie thanks for trying out ntfy. Yeah that looks like a permissions issue. The ntfy systemd service runs as use `ntfy` as you have already figured out, so key and cert file have to be readable by that user. There are multiple ways to solve this: ### 1. Run ntfy behind a proxy (nginx, Apache2, caddy, ...) If you run ntfy behind a proxy (instructions here: https://ntfy.sh/docs/config/#nginxapache2caddy), you can put all of the cert management in there and run multiple services on different subdomains as well. It's the most common approach, unless you are only running ntfy and nothing else. In this case, you'd run ntfy on `:1234/http` or some other port (not https) and let nginx handle the SSL termination. ### 2. Run `ntfy` systemd service as root (don't do this :no_entry:) You can `systemctl edit ntfy` and manually override the `User`/`Group` like this. This way, you'll be able to read the cert no matter what. ``` [Service] User=root Group=root ``` ### 3. Copy certs to `/etc/ntfy` and chown them You can copy the cert and keyfile from `/etc/letsencrypt/...` to `/etc/ntfy` and make sure that they are readable by the ntfy user by `chown ntfy:ntfy ...` them. Then also make sure that you have a `post_hook` in the `certbot` config, like this: ``` root@ntfy:/etc/cron.d# cat /etc/letsencrypt/renewal/ntfy.sh.conf # renew_before_expiry = 30 days version = 0.40.0 archive_dir = /etc/letsencrypt/archive/ntfy.sh cert = /etc/letsencrypt/live/ntfy.sh/cert.pem privkey = /etc/letsencrypt/live/ntfy.sh/privkey.pem chain = /etc/letsencrypt/live/ntfy.sh/chain.pem fullchain = /etc/letsencrypt/live/ntfy.sh/fullchain.pem # Options used in the renewal process [renewalparams] ... post_hook = /script/to/move/and/chown/the/keyfiles.sh ```
Author
Owner

@A-Nicoladie commented on GitHub (Mar 21, 2022):

Thank you !
Copy certs work like a charm.

(Running ntfy behind a proxy seems a bit complicated for me at the moment.)

<!-- gh-comment-id:1074062891 --> @A-Nicoladie commented on GitHub (Mar 21, 2022): Thank you ! Copy certs work like a charm. (Running ntfy behind a proxy seems a bit complicated for me at the moment.)
Author
Owner

@binwiederhier commented on GitHub (Mar 21, 2022):

Glad I could help. Don't forget the post_hook, otherwise you're gonna have a bad time in 3 months. Be kind to future-you.

<!-- gh-comment-id:1074066530 --> @binwiederhier commented on GitHub (Mar 21, 2022): Glad I could help. Don't forget the `post_hook`, otherwise you're gonna have a bad time in 3 months. Be kind to future-you.
Author
Owner

@A-Nicoladie commented on GitHub (Mar 21, 2022):

Yes, you right 😁
I tried to force a renewal (certbot renew --force-renewal) to see if files changes. All is OK 😉

<!-- gh-comment-id:1074084932 --> @A-Nicoladie commented on GitHub (Mar 21, 2022): Yes, you right 😁 I tried to force a renewal (`certbot renew --force-renewal`) to see if files changes. All is OK 😉
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ntfy#144
No description provided.