<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ntfy on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/ntfy/</link><description>Recent content in Ntfy on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Mon, 03 Feb 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/ntfy/index.xml" rel="self" type="application/rss+xml"/><item><title>Command chaining with NTFY for long running commands</title><link>https://blog.iankulin.com/command-chaining-with-ntfy-for-long-running-commands/</link><pubDate>Mon, 03 Feb 2025 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/command-chaining-with-ntfy-for-long-running-commands/</guid><description>&lt;p&gt;&lt;a href="https://ntfy.sh/"&gt;NTFY&lt;/a&gt; is a great open-source push notification service that&amp;rsquo;s self-hostable or free to use (although I suggest you &lt;a href="https://liberapay.com/ntfy"&gt;pay for it&lt;/a&gt; as I do). I&amp;rsquo;ve written before how I use it with &lt;a href="https://blog.iankulin.com/uptime-kuma-nfty/"&gt;UptimeKuma&lt;/a&gt; for my uptime monitoring, but another common use is just when I&amp;rsquo;m initiating long-running commands and backgrounding them.&lt;/p&gt;
&lt;p&gt;This magic is possible since we can just &lt;code&gt;curl&lt;/code&gt; to send a NTFY notification. For example:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl -d &amp;#34;😀 demo push message via NTFY&amp;#34; ntfy.sh/blog_demo
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since I&amp;rsquo;m subscribed to the &amp;ldquo;blog_demo&amp;rdquo; topic in NTFY, this message will be pushed to my phone and watch:&lt;/p&gt;
&lt;img src="https://blog.iankulin.com/images/img_0056.png" width="640" alt=""&gt;
&lt;p&gt;How I use this is with &amp;lsquo;command chaining&amp;rsquo;. In Linux, you can stack commands together with the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; characters like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mkdir test_dir &amp;amp;&amp;amp; echo &amp;#34;success&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will create the directory, then print &amp;ldquo;success&amp;rdquo; to the shell. I could use it like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;nohup rsync -rvits --bwlimit=20 &amp;#34;/volume1/media/video/Movies/Night of the Living Dead (1968)/&amp;#34; ds1_admin@100.78.2.105:&amp;#34;/volume1/media/video/Movies/Night of the Living Dead (1968)&amp;#34; &amp;gt; output.log 2&amp;gt;&amp;amp;1 &amp;amp;&amp;amp; curl -d &amp;#34;💾 upload to vm500-kr complete&amp;#34; ntfy.sh/blog_demo &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Both commands will run in the background, and the output of the first command is directed into the &amp;lsquo;output.log&amp;rsquo; file. If the rsync file transfer (that is going to take all night) finishes successfully, then the message saying it&amp;rsquo;s complete will be sent.&lt;/p&gt;
&lt;p&gt;What about if it fails? Well, posix has you covered here too. There&amp;rsquo;s a &lt;code&gt;||&lt;/code&gt; chaining operator that only runs if a command fails.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;mkdir invalid/name &amp;amp;&amp;amp; (echo &amp;#34;Directory created successfully.&amp;#34;) || (echo &amp;#34;Failed to create directory.&amp;#34;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the command above, if we already have a directory called &lt;code&gt;invalid&lt;/code&gt;, the &lt;code&gt;mkdir&lt;/code&gt; will work and we&amp;rsquo;ll get the message &amp;ldquo;Directory created successfully.&amp;rdquo;. If &lt;code&gt;invalid&lt;/code&gt; doesn&amp;rsquo;t exist, the command will fail and we&amp;rsquo;ll get the message &amp;ldquo;Failed to create directory.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Note that I&amp;rsquo;ve added some parenthesis - it makes things clearer for the reader, and the command line parser.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s apply this to our slow file transfer:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;nohup rsync -rvits --bwlimit=20 &amp;#34;/volume1/media/video/Movies/Night of the Living Dead (1968)/&amp;#34; ds1_admin@100.78.2.105:&amp;#34;/volume1/media/video/Movies/Night of the Living Dead (1968)&amp;#34; &amp;gt; output.log 2&amp;gt;&amp;amp;1 &amp;amp;&amp;amp; curl -d &amp;#34;💾 upload to vm500-kr complete&amp;#34; ntfy.sh/blog_demo || curl -d &amp;#34;⚠️ upload to vm500-kr failed!&amp;#34; ntfy.sh/blog_demo &amp;amp;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we&amp;rsquo;ll get a push message for completion or failure. There is one more little bit of housekeeping to do though. When we curl ntfy like this, it actually returns some JSON:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-12-28-at-11.00.08-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-12-28-at-11.00.08-am.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since we&amp;rsquo;re running this whole thing backgrounded, we really want that to go to the &lt;code&gt;output.log&lt;/code&gt; file with the other output:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;nohup rsync -rvits --bwlimit=20 &amp;#34;/volume1/media/video/Movies/Night of the Living Dead (1968)/&amp;#34; ds1_admin@100.78.2.105:&amp;#34;/volume1/media/video/Movies/Night of the Living Dead (1968)&amp;#34; &amp;gt; output.log 2&amp;gt;&amp;amp;1 &amp;amp;&amp;amp; curl -d &amp;#34;💾 upload to vm500-kr complete&amp;#34; ntfy.sh/blog_demo &amp;gt;&amp;gt; output.log || curl -d &amp;#34;⚠️ upload to vm500-kr failed!&amp;#34; ntfy.sh/blog_demo &amp;gt;&amp;gt; output.log &amp;amp;
&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>SSH login notification</title><link>https://blog.iankulin.com/ssh-login-notification/</link><pubDate>Mon, 13 May 2024 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/ssh-login-notification/</guid><description>&lt;p&gt;&lt;a href="https://unsplash.com/photos/brown-bell-on-white-concrete-wall-4VRzuA4UxSY?utm_content=creditShareLink&amp;utm_medium=referral&amp;utm_source=unsplash"&gt;&lt;img src="https://blog.iankulin.com/images/nick-fewings-4vrzua4uxsy-unsplash.jpg" width="400" alt="Photo by Nick Fewings Unsplash
"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My VPS&amp;rsquo;s are usually locked down so just ports 80 &amp;amp; 443 (for web server) and 22 (for ssh) are open. That&amp;rsquo;s great for reducing the attack surface, but having ssh open is a potentially disastrous vulnerability. For this reason I often close that at the cloud firewall level as well, but it has to be open when I&amp;rsquo;m making changes or running the weekly ansible update/cleanup playbooks.&lt;/p&gt;
&lt;p&gt;To make things a bit safer, I run &lt;a href="https://blog.iankulin.com/beginning-node-app-security/"&gt;Fail2Ban&lt;/a&gt; on the ssh logs, and also have notifications turned on via &lt;a href="https://ntfy.sh/"&gt;Ntfy&lt;/a&gt;. Ntfy is so useful I make an annual donation to support it&amp;rsquo;s development and help with Phil&amp;rsquo;s server costs. I recommend you do to. In fact, my setup for getting a notification on my watch everytime someone ssh&amp;rsquo;s into one of my VPS&amp;rsquo;s is just copied directly from &lt;a href="https://docs.ntfy.sh/examples/#__tabbed_1_1"&gt;Phil&amp;rsquo;s examples&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="changes"&gt;Changes&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re not logged in as root (that should be turned off) you&amp;rsquo;ll need to run all these as sudo.&lt;/p&gt;
&lt;p&gt;Edit &lt;code&gt;/etc/pam.d/sshd&lt;/code&gt; to add these lines to the bottom:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# at the end of the file
session optional pam_exec.so /usr/bin/ntfy-ssh-login.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then create the file &lt;code&gt;/usr/bin/ntfy-ssh-login.sh&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#!/bin/bash
if [ &amp;#34;${PAM_TYPE}&amp;#34; = &amp;#34;open_session&amp;#34; ]; then
 curl \
 -H prio:high \
 -H tags:warning \
 -d &amp;#34;SSH login: ${PAM_USER} from ${PAM_RHOST}&amp;#34; \
 ntfy.sh/your-unique-notification-string
fi
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;but replace &lt;code&gt;your-unique-notification-string&lt;/code&gt; with whatever string you&amp;rsquo;re monitoring with the app. Note that if you&amp;rsquo;re using the shared (rather than self hosted) service, these are public. If I&amp;rsquo;d used mine here, you&amp;rsquo;d be able to use it to spam my phone with alerts. For this reason, many people use GUIDs.&lt;/p&gt;
&lt;p&gt;We need to make this executable:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;chmod +x /usr/bin/ntfy-ssh-login.sh
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And restart the ssh daemon&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo systemctl restart sshd
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then log out, and ssh back in, and you should get the notification.&lt;/p&gt;</description></item><item><title>Uptime Kuma &amp; NTFY</title><link>https://blog.iankulin.com/uptime-kuma-ntfy/</link><pubDate>Wed, 15 Feb 2023 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/uptime-kuma-ntfy/</guid><description>&lt;p&gt;&lt;a href="https://github.com/louislam/uptime-kuma"&gt;Uptime Kuma&lt;/a&gt; is a monitoring tool suitable for self-hosting, and as well as being a good tool for monitoring the status of your network and applications, it&amp;rsquo;s a nice smallish app to get started on Docker containers.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2023-02-05-at-6.41.24-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-02-05-at-6.41.24-am.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since it&amp;rsquo;s in a container, you need to create a volume for it and pass it in to persist your settings. Then it&amp;rsquo;s just a matter of adding each item you want to monitor. There&amp;rsquo;s a heap of fancy options for this, the only three I&amp;rsquo;ve used are ping - just pings an address, http(s) - requests a page and checks the header for a 200, and http(s) keyword - looks at the returned page for a keyword in the html.&lt;/p&gt;
&lt;p&gt;You choose the time intervals for all these. Additionally you can set up a notification for each. This is a great idea - I&amp;rsquo;m not sitting in my datacentre command room watching Uptime Kuma all day, I need to know on my phone if a CAT5 cable&amp;rsquo;s been pulled out inadvertently while I was vacuuming.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s lots of options for how to do this, including messaging platforms such as Telegram and Discord. I had a look on &lt;a href="https://www.reddit.com/r/selfhosted/comments/z0gpr2/free_push_service_for_uptime_kuma/"&gt;r/selfhosted&lt;/a&gt; to see what was recommended, and discovered &lt;a href="https://ntfy.sh/"&gt;NTFY&lt;/a&gt; which is an amazing little service. It has Android and iOS apps, in the app you subscribe to an endpoint, then a notification can be sent to your phone with a simple http get, for example:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl -d &amp;#34;This message will pop up on phone&amp;#34; ntfy.sh/ian_test
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2023-02-05-at-12.39.22-pm.png" alt=""&gt;&lt;/p&gt;
&lt;img src="https://blog.iankulin.com/images/img_4055.jpg" width="192" alt=""&gt;
&lt;p&gt;The &lt;code&gt;ian_test&lt;/code&gt; part of the url is called the &lt;em&gt;topic&lt;/em&gt;, and in the app you can subscribe to several topics. It&amp;rsquo;s worth noting this is all completely open. Anyone can send messages to the ian_test topic, and anyone can receive them. You should choose a topic name that&amp;rsquo;s likely to be unique, and be mindful that you&amp;rsquo;re leaking intelligence. For example:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl -d &amp;#34;CCTV offline - 12 George St&amp;#34; ntfy.sh/maquarie_bank
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;would not a be a good use case. Get something more secure for that application. It&amp;rsquo;s probably not going to be free.&lt;/p&gt;
&lt;p&gt;Speaking of which, NTFY is free, including the server. It is possible (and probably a good idea since then you could add a little security) to self host it. It&amp;rsquo;s such a great little tool, and just so immediately and completely achieved what I wanted with zero drama and low effort, I hit the &lt;a href="https://github.com/sponsors/binwiederhier"&gt;github sponsor button for it&lt;/a&gt;.&lt;/p&gt;</description></item></channel></rss>