Local DNS & Certificates¶
DNS Resolution¶
Custom domains like local.myapp.dev require DNS entries pointing to 127.0.0.1. The simplest approach is to use a public DNS service that already resolves to localhost — no /etc/hosts editing needed.
| Service | Domain Pattern | Example |
|---|---|---|
| lvh.me | *.lvh.me |
app.lvh.me |
| sslip.io | *.127.0.0.1.sslip.io |
app.127.0.0.1.sslip.io |
| nip.io | *.127.0.0.1.nip.io |
app.127.0.0.1.nip.io |
| localtest.me | *.localtest.me |
app.localtest.me |
These services resolve any subdomain to 127.0.0.1 automatically. They require internet access for DNS resolution.
Example prox.yaml using lvh.me:
processes:
frontend: npm run dev
backend: go run ./cmd/server
proxy:
http_port: 6788
domain: lvh.me
services:
app: 3000
api: 8000
With this configuration:
http://app.lvh.me:6788→http://localhost:3000http://api.lvh.me:6788→http://localhost:8000
For multiple projects on the same port, keep DNS pointed at 127.0.0.1 and give each project distinct service hostnames. prox registers those hostnames with the shared proxy daemon automatically. See Shared Proxy Across Projects.
If you prefer a custom domain like local.myapp.dev, add entries to /etc/hosts manually:
If a registered hostname doesn't resolve¶
prox up checks whether each hostname it registers actually resolves on this machine, and warns if one doesn't — this is exactly the .test-domain trap above: Registered domains: app.sec.test looks fine until it's pasted into a browser and comes back NXDOMAIN, because .test needs the local setup on this page and doesn't resolve on its own the way *.lvh.me does.
The check is deliberately quiet the rest of the time. It only warns on a definite "no such host" answer; a slow, offline, or sandboxed resolver — a laptop on a plane, a VPN, a network-restricted CI runner — is reported as "cannot tell", never as "broken", so a perfectly good setup never triggers a false alarm.
HTTPS Certificates¶
One-Time Setup¶
Install mkcert and its CA:
# macOS
brew install mkcert
# Linux
# See https://github.com/FiloSottile/mkcert#installation
# Install the CA into your system trust store (run once)
mkcert -install
If you skip mkcert -install (or run it before installing a browser that keeps its own trust store), prox now surfaces mkcert's own warning about it — Warning: Note: the local CA is not installed in the system trust store., followed by a hint to run mkcert -install and restart prox — instead of reporting every process healthy while HTTPS quietly fails in the browser. The warning is mkcert's own sentence, carried through verbatim, and clears itself automatically once mkcert reports the CA as trusted. It appears when prox generates certificates, which is exactly what happens on a first run like this one; certs that were already generated before the CA broke won't re-trigger the warning until the next generation.
Automatic Certificate Generation¶
When auto_generate: true (the default), prox calls mkcert to generate wildcard certificates on first HTTPS startup. Certificates are stored in ~/.prox/certs/ by default.
No further action is needed — prox handles cert generation automatically.
Manual Certificate Generation¶
If you set auto_generate: false, generate certificates yourself:
Then point prox at the cert files via certs.dir.
Sharing Your CA Across Machines¶
Option A: Each Developer Creates Their Own CA (Simplest)¶
Each developer runs mkcert -install on their own machine. prox auto-generates certs per machine. No coordination needed.
Option B: Share a CA Across Machines¶
For consistent trust (e.g., a team sharing a dev environment):
-
On the source machine, find the CA files:
-
Copy
rootCA.pemandrootCA-key.pemto the target machine securely via a secrets manager (1Password, Vault, etc.). -
On the target machine, point mkcert at the shared CA and install it:
Warning
rootCA-key.pem gives complete power to intercept HTTPS traffic from any machine that trusts it. Store it in a secrets manager — never commit it to version control.