Skip to content

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:6788http://localhost:3000
  • http://api.lvh.me:6788http://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:

127.0.0.1 local.myapp.dev app.local.myapp.dev api.local.myapp.dev

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.

proxy:
  https_port: 6789
  domain: lvh.me

certs:
  dir: ~/.prox/certs
  auto_generate: true   # default

No further action is needed — prox handles cert generation automatically.

Manual Certificate Generation

If you set auto_generate: false, generate certificates yourself:

mkcert -cert-file cert.pem -key-file key.pem "*.lvh.me" "lvh.me"

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):

  1. On the source machine, find the CA files:

    mkcert -CAROOT
    # e.g., /Users/you/Library/Application Support/mkcert
    
  2. Copy rootCA.pem and rootCA-key.pem to the target machine securely via a secrets manager (1Password, Vault, etc.).

  3. On the target machine, point mkcert at the shared CA and install it:

    export CAROOT=/path/to/shared/ca
    mkcert -install
    

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.