1. Pick an unused TLD: choose an unregistered TLD that won’t conflict with real domains, such as .home or .lan.
  2. Configure DNS resolver: in my case, AdGuard Home -> Filters -> DNS rewrites -> Add DNS rewrite (*.home points to server’s LAN ip or tailnet ip).
  3. Add reverse proxy rules: in my case, using Caddy, create rules such as
http://serviceName.home {
	reverse_proxy localhost:12345
	}

can also add tls internal to use self-signed certs for this domain.

Bonus: add the private TLD to Firefox, so typing in serviceName.home in address bar will resolve instead of searching for it. To do this, go to about:config, and create a new property browser.fixup.domainsuffixwhitelist.CustomTLDhere set to True. For more comprehensive instructions, see this blog post.