Docs

Local URLs

How the .test domain system works, how to enable it, and what to do when it breaks.


How it works

With local URLs on, you visit http://shop.test instead of http://localhost:8081. Three pieces make it work:

  1. A Traefik container on host port 80 with a file provider. For each project, there's a route mapping Host(<name>.<tld>) to host.docker.internal:<APP_PORT>.
  2. A dnsmasq container on 127.0.0.1:5354 answering address=/.<tld>/127.0.0.1, so anything ending in .<tld> resolves to your machine.
  3. A small file at /etc/resolver/<tld> that tells macOS to use that dnsmasq container for any lookup ending in .<tld>. Port 5354 is used so it doesn't collide with Herd or Valet on :53.

Step 3 is the only one that needs your password. Once. After that, every project you ever create gets its own .<tld> URL with no further prompts.

Enable or change the TLD

Go to Settings, then Local URLs.

  • Enable toggle. Turning it on installs the Traefik + dnsmasq containers and writes the resolver file. The first time, you'll get one macOS password prompt.
  • TLD input. Defaults to sail. You can use any short alphanumeric string. test is the most common choice. Avoid real TLDs (com, net) since they'd hijack real DNS.
  • Resync. Rebuilds the proxy config for every project, restarts the containers, and re-checks the resolver. Useful if something feels off.

Disabling local URLs tears all of that down. Project URLs fall back to localhost:<port>.

HTTPS

With the HTTPS toggle on, the app generates a local certificate authority, installs it into your macOS login keychain, and produces a wildcard cert for *.<tld>. Traefik switches to serving on :443, and your browser stops complaining.

The CA is local to your machine and only trusted by your account. Nothing leaves the laptop.

When things break

If a container got removed or the resolver file went missing, the app notices and surfaces a "Local URLs need repair" toast. Click Fix it and it runs the full resync (which may need your password to re-write the resolver file).

Common causes:

  • Docker Desktop was reset. All containers are gone. Run Resync.
  • Port 80 already in use by Apache, Nginx, Herd, or another service. Stop the conflicting service or change Traefik's port (Resync detects the conflict).
  • Stale resolver file from a previous install of Valet or Herd. Settings, then Resync rewrites it.