Skip to content

feat: serve lerd.localhost dashboard over HTTPS by default#359

Closed
erhanurgun wants to merge 3 commits into
geodro:mainfrom
erhanurgun:feat/dashboard-https-by-default
Closed

feat: serve lerd.localhost dashboard over HTTPS by default#359
erhanurgun wants to merge 3 commits into
geodro:mainfrom
erhanurgun:feat/dashboard-https-by-default

Conversation

@erhanurgun
Copy link
Copy Markdown
Contributor

@erhanurgun erhanurgun commented May 15, 2026

Summary

  • 443 server block + 301 redirect from port 80, using the existing
    lerd.localhost cert.
  • install and start now issue the cert before writing the vhost.
  • Falls back to HTTP-only when the cert is missing so a fresh install
    does not refuse to start.

Why

Every other .test site is HTTPS by default. The dashboard was not.

Test plan

  • go test ./internal/nginx/ passes (2 new tests).
  • curl -ksI http://lerd.localhost returns 301; https:// returns 200.
  • Deleting the cert and re-running lerd start produces an HTTP-only
    vhost without error.

SS

image

Dashboard previously served over plain HTTP while every other .test
site got TLS by default, leaking the auth cookie to anything sniffing
loopback. EnsureLerdVhost now generates a 443 ssl server (with the
existing lerd.localhost cert produced by mkcert) and 301-redirects
port 80 to HTTPS on both Linux (unix socket proxy) and macOS
(host.containers.internal + X-Lerd-Trust).

Fresh installs run before mkcert has issued the cert; the helper
lerdCertExists keeps the HTTP-only fallback in that window so nginx
does not refuse to start with a missing-cert error. The next start
picks up the freshly issued files.
EnsureLerdVhost reads the cert/key off disk to decide between the
HTTPS vhost and the HTTP-only fallback, so the cert has to exist by
the time it runs. Both install and start now call certs.IssueCert for
lerd.localhost ahead of EnsureLerdVhost. IssueCert is a no-op when the
files already exist, so subsequent starts pay nothing.
@geodro
Copy link
Copy Markdown
Owner

geodro commented May 16, 2026

Hey, thanks a lot for taking the time to put this together. Before we merge I want to push back on the premise though. The dashboard sits on a .localhost domain which is RFC 6761 reserved and always resolves to loopback, so traffic never leaves the machine, and browsers already treat http on localhost as a secure context. Service workers, crypto.subtle and the rest of the platform features work the same as they would over https. The .test sites are a different story because they can be exposed via lerd expose and genuinely cross networks, but lerd.localhost isn't tunnelable. Is there a specific use case driving this on your end, something like LAN access, a remote dev setup or a corporate policy that flags plain http? Happy to reconsider if there's a concrete scenario, just want to make sure we're not adding moving parts for a cosmetic win.

@erhanurgun
Copy link
Copy Markdown
Contributor Author

Thanks for taking the time to discuss this before declining. To be upfront: this PR is cosmetic, and I just noticed your own comment at internal/nginx/manager.go:844-847 already documents the same .localhost reasoning.

Per KISS and YAGNI, I'll leave the merge or close decision to you. Happy either way. Next time I'll start with an issue or discussion before jumping to a PR.

@geodro
Copy link
Copy Markdown
Owner

geodro commented May 16, 2026

Appreciate the graceful reply. Going to close on the YAGNI side. Thanks for the swing.

@geodro geodro closed this May 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants