DIY Water Leak Sensor with ESP8266 NodeMCU and Homebridge Server 22 Jan, 2023 Comments DIY Water Leak Sensor with ESP8266 NodeMCU and Homebridge Server

A leak at home got me looking at water level sensors, but Arlo’s recent annoucement EOL’ing camera support pushed me over the edge into DIY IoT devices.

Luckily, in a really simple form, a water leak sensor simply uses water to close the circuit; so a closed circuit indicates water (or some other conductor!) was detected between the leads. Note that this set up cannot be used to detect leak of distilled water, because, well, distilled water cannot conduct electricity.

A brief search for a low-cost MCU with ADC and WiFi support turned up the ESP8266 family which costs ~$3 as of this writing. Awesome!

Specifically, I picked up the ‘ESP8266 ESP-12 D1 Mini NodeMCU Lua WeMos D1 Mini WIFI 4M Bytes Module’. I powered the MCU via a micro-USB. Solder 24-gauge wires to the 3.3V and the ADC pins on the chip, and let the open leads on the other ends of the wire lay on the floor where I’d like to detect leaks. And, done – that’s the hardware set up.

Next up, software. Programming for the ESP8266 is pretty straight forward, given the really awesome set of libraries for:

  • Connecting the MCU to WiFi
  • Running a basic web server on the MCU
  • mDNS support so new devices can be auto-discovered
  • And, of course, to read the sensor values via ADC

The next bit is to integrate with HomeKit (using Homebridge). Fortunately, again, I stumbled upon the very simple, and readable dauden/homebridge-nodeMCU repository that I tweaked a bit to include mDNS-based device discovery support. My adaptation of this Homebridge plugin is here, and also includes the NodeMCU code.

Easy peasy!


  • I’m also experimenting running this set up with 2x1.5v AA batteries; the Blink wireless camera has demonstrated that even with a WiFi device onboard, the set up can be made to last ~2 years, but let’s see how efficient this particular set up is!
  • One can of course 3D-print enclosures for this setup and make it appropriately water proof, perhaps? I’ll include 3D-print model files, if I get that far!

Terence Tao on Work 30 Aug, 2021 Comments

Relying on intelligence alone to pull things off at the last minute may work for a while, but, generally speaking, at the graduate level or higher it doesn’t.

Terence Tao’s career advice

Automating Let's Encrypt Certs for DD-WRT with 17 Jan, 2021 Comments Automating Let's Encrypt Certs for DD-WRT with

Following up on previous notes on setting up Let’s Encrypt for private networks and SSL for DD-WRT routers, here’s notes on automating renewal of Let’s Encrypt certificates using

I use Hurricane Electric’s free DNS service for delegating DNS management for the the private subdomains – DNS resolution is handled externally, but certificates are provisioned on the private network. You can find other free DNS providers on the Let’s Encrypt community page.

If you don’t want to make your private subdomain public, you can create a dummy.domain.ext, for example, and fetch wildcard certificates instead. If you are willing to open port 53 on your router and port forward, here’s another alternative. Open to more suggestions, please post them in the comments.

Setup Instructions

  • Prerequistites are a DD-WRT router with exeternal USB storage support. My notes on the setup are here and here.
  • First, delegate your subdomain’s public DNS resolution to by setting up NS records for subdomain.domain.ext to point to ns[1-5], then add the subdomain to via ‘Add a new domain’ page on the ‘Zone Functions’ menu.
  • Then, download, give it execute permissions: chmod +x ./
  • Next, run the following by adjusting the variables as appropriate.
export HE_Username=""
export HE_Password=""

./ --install  \
--home /jffs/etc/ \
--config-home /jffs/etc/ \
--cert-home  /jffs/etc/ \
--accountemail  "email@domain.ext" \
--useragent  "DD-WRT" --force
  • Then copy the corresponding dns_<provider>.sh from to /jffs/etc/
  • Test issuing a new cert: # /jffs/etc/ --issue --dns dns_he -d subdomain.domain.ext --config-home /jffs/etc/ 2>&1 >> /jffs/etc/ --staging --force
  • Revoke the test cert # /jffs/etc/ --revoke -d subdomain.domain.ext --revoke-reason 4 --config-home /jffs/etc/ --staging
  • Issue a production certificate by running the issue command above without --staging option.
  • Setup cron. Remember to prefix the cron command with root as pointed out here.
# Every day at 3 AM:*_*_*
0 3 * * * root /jffs/etc/ --renew --dns dns_he -d subdomain.domain.ext --config-home /jffs/etc/ >> /jffs/etc/ # --staging --force


The Best Test of Truth... 12 Jan, 2021 Comments The Best Test of Truth...

Reading Stratechery’s Tech and Liberty, ‘The Marketplace of Ideas’ section, I see this quote:

The theory of our Constitution is “that the best test of truth is the power of the thought to get itself accepted in the competition of the market,” Abrams v. United States, 250 U.S. 616, 630, 40 S.Ct. 17, 63 L.Ed. 1173 (1919) (Holmes, J., dissenting).

And, the first thing that jumps at me is the implication that Tuth, by this interpretation, is a point-in-time artifact. What’s marketable today is different from yesterday, and arguably, will change tomorrow; the need of each hour would vary, even if history repeats. I realize Justice Holmes is focused on the judgement at hand and this statement is completely accurate in that context.

This may be experience bias, but makes me wonder what would fall into the Vedic interpretation of truth – eternal, changeless, even if interpreted differently by experts: Ekam Sat, Viprah Bahudah Vadanti/एकं सद्विप्रा बहुधा वदन्ति - Rig Veda 1:164:46.

Or, may be I interpreted the above ancient statement as referring to Truth? This is open to interpretation: from the context of Hymn 164, the physical allusion is to a deity, but an overload of the word Sat is Truth, and therefore, the corresponding interpretation would be one of Absolute Truth, if I may. This is the interpretation I’ve grown up with.

What is Truth, to you?

Renewing Let's Encrypt SSL Certificates for Private Networks using DNS Challenge 05 Jan, 2021 Comments Renewing Let's Encrypt SSL Certificates for Private Networks using DNS Challenge

Note to self on setup for auto-renewing Let’s Encrypt SSL certificates from an (almost) private network.

The Usual Rant

This would’ve been really simple if Google Domains provided an API interface to add/update/remove DNS TXT records – and would be fully workable from a fully private network, I could (or maybe should?) use a DNS provider with an API and be done, but this setup is worth documenting for myself. For DNS providers with APIs to change DNS records, Certbot’s DNS plugins are, IMO, easy ways to renew certs. You could also go manual with your own auth, cleanup, and deploy hooks1. Anyway, here goes.

Update 08/30/2021:’s DNS Alias mode can help if you use a free DNS service with API like the excellent Hurricane Electric’s DNS. All it takes is setting up an _acme-challenge.domain CNAME _acme-challenge.alias.domain and issue/renew the cert with --challenge-alias alias.domain parameter.

The Idea

The idea behind this setup is that of the Standalone DNS Authenticator Plugin for Certbot – I just could not get it to work2 out of the box even with port forwarding enabled, so I improvise by replicating the setup. Basically: send DNS resolution requests off to a DNS that you can update really quick (or even better, automate). This is achieved by inserting an NS record for the subdomain in question and pointing _acme-challenge.subdomain to a dummy.subdomain.domain.ext CNAME that sends off resolvers to your new DNS, where you work your magic.


  • A DNS provider with no API support to add/update/remove DNS TXT records.
  • A local/remote instance of AdGuardHome v0.105.03 or later – this nifty application has a REST API with a swagger spec!
  • An internet router that allows port forwarding (forward 53 to your local server hosting AdGuardHome)4 1.
  • Local server with certbot on a private network.

The Setup

For each subdomain of domain.ext, set up these two DNS entries:

  • subdomain NS ns.domain.ext
  • _acme-challenge.subdomain CNAME dummy.subdomain.domain.ext

Pro tip: always use –staging servers else you will run up against the really low (~5 failures/hour) rate limits for production servers.

  • Next, run the certbot command to renew certificate manually: # certbot --manual --preferred-challenges dns certonly -d subdomain.domain.ext --verbose --debug-challenge --staging
  • Go to AdGuardHome > Filters > Custom Filtering Rules and add appropriate entries
    • ||subdomain.domain.ext^$dnsrewrite=NOERROR;A;W.X.Y.Z (private IP is acceptable)5
    • ||_acme-challenge.subdomain.domain.ext^$dnsrewrite=NOERROR;TXT;challenge-txt, where challenge-txt is from the output of certbot command above.
  • Continue the command above, your certificates from staging Let’s Encrypt’s servers would be ready.
  • Revoke these test certs with # certbot revoke --cert-path /etc/letsencrypt/live/subdomain.domain.ext/cert.pem [--staging]
  • Repeat the certbot command without the --staging flag.

Best part – all of this can be automated.1 6

References & Notes

  1. This renewal can be automated by using auth- and deploy- hooks. Example commands certbot -d subdomain.domain.ext --agree-tos --manual --preferred-challenges dns --manual-auth-hook ./ --manual-cleanup-hook ./ --manual-public-ip-logging-ok --force-renewal certonly  2 3

  2. For my record, this command did not work: certbot --non-interactive --agree-tos --email certmaster@domain.ext certonly --preferred-challenges dns --authenticator certbot-dns-standalone:dns-standalone --certbot-dns-standalone:dns-standalone-address= --certbot-dns-standalone:dns-standalone-ipv6-address=:: --certbot-dns-standalone:dns-standalone-port=53 -d subdomain.domain.ext --force-renewal --staging --verbose --debug-challenges 

  3. AdGuardHome v0.105.0+ is required to support dnsrewrite 

  4. By default, only allow allow:, and your public IP: curl -k Temporarily update firewall rules to allow out-of-network requests. This too can be automated via AdGuardHome’s REST API: GET /control/access/list and POST /control/access/set in combination with ufw or similar. 

  5. I ran into SERVFAIL looking up CAA for ... error from certbot. Turns out the problem was a missing A record for subdomain.domain.ext in AdGuardHome, which is where the need for this entry originates from. was very helpful deduce this problem. It was on top of the list of DNS errors reported! 

  6. GET /status, add/update corresponding dnsrewrite entry into user_rules[] and POST /control/filtering/set_rules can be used in conjunction with the auth- and deploy- hook scripts to automate the entries that get inserted for challenge-txt

Original design for Tumblr crafted by Prashanth Kamalakanthan.
Adapted for Tumblr & Jekyll by Sai Charan. Customized theme available on Github.

Sai Charan's blog by Sai Charan is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
Creative Commons License