Skip to content

Provision local HTTPS certificates automatically when running Vite with localHttps - #3953

Open
fredericoo wants to merge 4 commits into
previewfrom
fb-local-https-vite-plugin-mkcert
Open

Provision local HTTPS certificates automatically when running Vite with localHttps#3953
fredericoo wants to merge 4 commits into
previewfrom
fb-local-https-vite-plugin-mkcert

Conversation

@fredericoo

Copy link
Copy Markdown
Contributor

TL;DR: Local HTTPS for Vite-based setups required a manual, macOS-flavored mkcert install before Customer Account flows worked. This PR (stacked on #3936) makes certificate provisioning automatic and portable across macOS, Linux, and Windows, mirroring next dev --experimental-https but with a hardened supply chain: mkcert is pinned to an exact release and verified against per-platform SHA-256 checksums, so a compromised "latest" release can never execute.

Before

brew install mkcert
mkcert -install
mkdir -p ~/.shopify/hydrogen/certs
mkcert -cert-file ~/.shopify/hydrogen/certs/local.tryhydrogen.dev.pem \
  -key-file ~/.shopify/hydrogen/certs/local.tryhydrogen.dev-key.pem local.tryhydrogen.dev

After

vite dev              # localHttps() provisions missing certificates on startup
npx hydrogen setup https   # or provision explicitly, ahead of time

What this changes

  • New src/vite/mkcert.ts: downloads mkcert v1.4.4 from GitHub releases for darwin/linux/windows x x64/arm64, refuses anything that does not match the pinned SHA-256 for that platform, caches the binary at ~/.shopify/hydrogen/mkcert/, and re-verifies the checksum before every spawn. Download has a 60s timeout; the write is atomic (tmp + rename) so concurrent dev servers never execute a partial binary.
  • localHttps() provisions missing certificates when vite dev starts (skipped for build, preview, and CI). Any failure degrades to the existing warning, now including the failure reason, the npx hydrogen setup https remedy, and the manual mkcert steps.
  • New hydrogen setup https CLI command and a public provisionLocalHttps() export on @shopify/hydrogen/vite for frameworks that read certificate paths while the config is evaluated, before the Vite plugin runs (Nuxt, SolidStart).
  • Root https:setup script is now cross-platform: it builds the package and runs the CLI instead of a $HOME/mkdir -p shell one-liner.
  • Checksum provenance: hashes are cross-referenced from two independent package registries (Hermit cashapp/hermit-packages and Scoop ScoopInstaller/Extras) and were additionally verified against the live release assets. A test asserts every target pins a distinct checksum.

Developer impact

Extends the existing minor changeset for @shopify/hydrogen: adds the provisionLocalHttps() / ProvisionLocalHttpsOptions exports on @shopify/hydrogen/vite and the hydrogen setup https CLI command. Existing localHttps() / localHttpsDevServer() call sites need no changes; the packaged hydrogen-local-https skill and repo docs now describe the automatic flow.

Out of scope

  • 32-bit Linux ARM (mkcert ships a binary, but no realistic dev machines); unsupported platforms fail with manual instructions instead
  • A download size cap / streaming hash (would only matter under a GitHub + TLS compromise, and the checksum still gates execution)

Risk

  • First vite dev now runs mkcert -install, which installs a root CA into the system trust store and may prompt for a password. This is the same trust decision the manual instructions asked for, but it now happens on dev-server startup. CI environments are excluded (CI env var); non-TTY sudo fails fast into the warning rather than hanging.
  • mkcert v1.4.4 is the latest upstream release (2022, no known CVEs). Re-pinning a future release requires updating the version constant and all six checksums.

How to Test

  1. If you already have certificates, move them aside to simulate a first run: mv ~/.shopify/hydrogen ~/.shopify/hydrogen.bak
  2. pnpm install && pnpm build:pkgs
  3. pnpm --filter @shopify/hydrogen-example-astro https:dev
  4. Confirm the log shows mkcert downloading once, a certificate being generated (password prompt possible), and the app serving on https://local.tryhydrogen.dev:5173 with a trusted certificate.
  5. Stop the server and run pnpm https:setup — it should report the certificates are already in place without re-downloading.
  6. Restore your backup if you made one: rm -rf ~/.shopify/hydrogen && mv ~/.shopify/hydrogen.bak ~/.shopify/hydrogen

@fredericoo fredericoo changed the title Provision local HTTPS certificates automatically with a pinned mkcert Provision local HTTPS certificates automatically when running Vite with localHttps Aug 14, 2026
@fredericoo
fredericoo marked this pull request as ready for review August 14, 2026 15:00
@fredericoo
fredericoo requested a review from a team as a code owner August 14, 2026 15:00
@fredericoo fredericoo self-assigned this Aug 14, 2026

@frandiox frandiox left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I had seen other Vite plugins doing something similar but since we have a core feature like customer accounts, it makes sense we export one 🤔

I'm seeing this but I think it was fixed already in MiniOxygen?

Request must contain a host header.
    at toWeb (file:///...hydrogen/node_modules/.pnpm/@shopify+mini-oxygen@4.2.0_vite@8.0.10_@types+node@22.19.17_esbuild@0.28.1_jiti@2.6.1_t_33b61828dcbe09e87499152c791ecdbb/node_modules/@shopify/mini-oxygen/dist/vite/utils.js:13:11)

Comment thread packages/hydrogen/src/vite/index.ts Outdated
Comment on lines +173 to +174
try {
await provisionCertificates(settings);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a big side effect when running the Vite plugin, and I'm not sure users would notice (it modifies their system to add a certificate).

Would it make sense if we use node:readline/promises or similar to block the process until the user accepts a terminal prompt? (or exit with a nice message otherwise)

That or require a manual setup https command?

Not sure really 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i designed the API to support a setup step separately (useful for CI, as we skip interactive prompts)

but the DX obsessive in me wants to make it just work

the experience is pretty clear, there are logs all throughout the process, users know what's going on, so i'd say keep it?

  1. we can add jsdoc to the httpOnly plugin saying that by using this in vite, if enabled it will create a certificate on your machine
  2. or a prompt to get acceptance first

open to either way

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love the "it just works" but at the same time, this is modifying the system to install a certificate... I feel this is something we should ask confirmation for. Or at least have more than 1 single step to run it: force them to enable it manually and read a comment on top of it, etc.

Alternatively... is there a command we could print to uninstall the cert we just added? Perhaps that would be good enough if someone can just undo, and give them the command when they run dev:https?
It seems there's mkcert -uninstall, and we could wire it up with extra cleaning via npx hydrogen setup https --uninstall or similar? We might need a different CAROOT for mkcert so that it doesn't uninstall different certs though 🤔

@fredericoo

fredericoo commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Nice. I had seen other Vite plugins doing something similar but since we have a core feature like customer accounts, it makes sense we export one 🤔

I'm seeing this but I think it was fixed already in MiniOxygen?

Request must contain a host header.
    at toWeb (file:///...hydrogen/node_modules/.pnpm/@shopify+mini-oxygen@4.2.0_vite@8.0.10_@types+node@22.19.17_esbuild@0.28.1_jiti@2.6.1_t_33b61828dcbe09e87499152c791ecdbb/node_modules/@shopify/mini-oxygen/dist/vite/utils.js:13:11)

yeah i fixed it but it's not released yet

edit: now fixed in preview, using the correct minioxygen version

@fredericoo
fredericoo marked this pull request as draft August 17, 2026 18:12
@fredericoo
fredericoo force-pushed the fb-local-https-vite-plugin-mkcert branch from a5581ff to c9897c6 Compare August 17, 2026 18:21
Base automatically changed from fb-local-https-vite-plugin to preview August 18, 2026 12:50
Assisted-By: devx/07abca81-b031-4579-88c8-bc07dfd3c5aa
Assisted-By: devx/07abca81-b031-4579-88c8-bc07dfd3c5aa
Assisted-By: devx/07abca81-b031-4579-88c8-bc07dfd3c5aa
Assisted-By: devx/05def498-8bdd-48d0-bd5e-35e4667a2f3d
@fredericoo
fredericoo force-pushed the fb-local-https-vite-plugin-mkcert branch from c9897c6 to b5b5d11 Compare August 19, 2026 16:17
@fredericoo
fredericoo marked this pull request as ready for review August 19, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants