Chapter 4 of 14

A Padlock That Means Something

Half of what you build refuses to work over plain HTTP, and the usual fix — a self-signed certificate and a browser warning you click through — teaches you to ignore the warning that exists to protect you. There is a better answer, and it is one command.

The problem

Browsers have spent a decade moving features behind “secure context”. Over plain HTTP you lose:

  • Service workers. No offline, no push, no PWA — they simply do not register.
  • Secure cookies. Secure and SameSite=None cookies are dropped, which means sessions that behave one way locally and another in production.
  • Most OAuth providers. Many refuse to register a non-HTTPS callback at all, so “log in with…” cannot be tested locally.
  • Clipboard, geolocation, camera, WebAuthn. All secure-context only.

And beyond the features: if you develop over HTTP and deploy over HTTPS, mixed-content bugs and protocol-relative URL mistakes are invisible until production. You are testing a different thing from the one you ship.

The hard way

The usual workaround is a self-signed certificate, which produces a full-page browser warning you click through several times a day. That is worse than it looks, for two reasons.

It trains the reflex. The interstitial exists to stop you proceeding to a site that is lying about who it is, and you are practising proceeding.

And it does not actually work for the things you wanted. A service worker will not register behind an untrusted certificate no matter how many times you dismiss the warning. Neither will an API client that validates certificates — so your app's own server-to-server calls fail in ways that have nothing to do with your code.

One command

grove secure freddy
✓ freddy is now served over HTTPS → https://freddy.test

A real padlock. No warning, no exception, no curl -k. Your browser trusts it, your HTTP client trusts it, your service worker registers.

What happened: grove init created a certificate authority on your machine and added it to the system trust store. grove secure issues a certificate for that site, signed by it. Your system trusts the CA, so it trusts the certificate. That is the whole mechanism, and it is the same one the public web uses — only the authority is yours.

Why a CA on your laptop is safe

A certificate authority your machine trusts is, in principle, a dangerous thing: a CA can vouch for any hostname. If Grove's CA could sign a certificate for google.com, and your system trusts Grove's CA, then anyone who got hold of that key could impersonate Google to you.

So the CA carries a name constraint: it is cryptographically limited to your TLD. A certificate it signs for anything outside .test is rejected by the verifier — not by Grove's politeness, but by the same rules your browser applies to every certificate on the internet. The worst a leaked key can do is impersonate a name that only ever resolves to your own machine.

That claim is not a promise in a document. It is a regression test in Grove's own suite, run through the same verifier browsers use: a Grove-signed certificate for google.com is refused, the identical certificate signed by an unconstrained CA is accepted — proving the refusal is the constraint doing its job and not an unrelated failure — and the certificates Grove actually issues are accepted.

Secure everything, not just what needs it. There is no cost per site and no performance difference worth measuring, and a machine where some sites are HTTPS and some are not is a machine where you will spend an afternoon on a mixed-content bug that only exists locally. grove unsecure <site> reverses it if you ever need the plain version.

What you learned

  • Service workers, secure cookies, OAuth callbacks and WebAuthn need HTTPS — local development without it tests something you do not ship.
  • Click-through warnings train the wrong reflex and still do not enable the features you wanted.
  • grove secure issues a certificate from a CA your system already trusts.
  • The CA is name-constrained to your TLD, enforced by the verifier rather than by good manners.
  • Secure every site. Mixed protocols across a machine cost more than the command does.
Next: in Chapter 5 PHP: several versions at once, pinned per site, with the extensions you need — including the ones no prebuilt binary has.