🦊

A public URL that only works at home

  • #TIL
  • #network

An almost useless DNS record

I own the requet.fr domain for personal use. I added a DNS record wiring zappette.home.requet.fr to 192.168.1.67. Chances are this URL doesn’t work for you. That’s because you are not connected to my home wifi.

Motivation

I am developing brequet/zappette - GitHub, a locally served TV-remote-like application so I can easily deal with my TV-slave laptop (another post coming about Zappette). I used tokio-rs/topcoat - GitHub to build this webapp. I serve it locally on my home network. I wanted to install it as a PWA on my phone, however, being served to the local network from the TV laptop, it uses HTTP: browsers require HTTPS to install PWAs!

Goal: get HTTPS at home

These are the solutions I considered:

  • Self-signed certificate (or a local CA): works, but then I have to install the certificate on my phone, and on every other device, and renew everything by hand. Pretty annoying.
  • Certificates for IP addresses: Let’s Encrypt now issues publicly-trusted certificates for bare IPs (since January 2026!). However, to validate one, it has to connect to the IP itself, so public IPs only. 192.168.1.67 is unreachable by design. Dead end.
  • Tailscale: from what I’ve heard, this could be a clean solution to my issue; however, I haven’t tried it yet and I feel like it would be overkill for now.

AI gave me an additional idea I didn’t know about: I already own a domain. A DNS record costs nothing, and it turns out you can even get a proper certificate without exposing the laptop: TIL about DNS-01.

How it’s done

Plain and simple:

  • Added a DNS A record so the URL points at the TV laptop’s private IP
  • Installed Caddy on the laptop to forward incoming requests to the webapp

How does the certificate even get issued?

Fair question, since the whole point is that no one from outside can reach the laptop. To issue a certificate, Let’s Encrypt first needs proof that you control the name. The usual way (called HTTP-01) is for Let’s Encrypt to connect to the server itself and read a secret file you published at a well-known URL: this cannot work here, since the domain points at a private IP. The DNS-01 challenge solves exactly this: instead of proving you control the server, you prove you control the name. So I set it up on AWS to publish a one-time secret as a TXT record at _acme-challenge.zappette.home.requet.fr. Let’s Encrypt reads it through public DNS and can then issue the certificate. Caddy does this dance automatically at every renewal through my DNS provider’s API, so certificates renew themselves forever. That’s the kind of low-maintenance solution I wanted!

Result

A zero-maintenance setup; at home zappette.home.requet.fr cleanly points to my TV-connected laptop and the webapp is served over HTTPS: I can install it as a PWA on my phone. This gives me more ideas for future homeware!