What 'https with certificate' local test server do others use?

Background

I developed backup and restore for my app.

While testing I found that it was difficult to persuade some browsers to access files for the restore process.

I decided to tackle the browser trust issue before investigating other causes — that is, to install the app with a manifest, which in turn requires https, which in turn requires a TLS certificate that browsers will fully trust (no challenge).

What I’ve tried

I discovered caddy: “The Ultimate Server with Automatic HTTPS

Very promising. But it also entailed learning how to start/stop/etc stuff with systemd’s systemctl. So I’m learning two things and making slow progress.

My question

What do other people use for a ‘browsers think they’re getting this app from a properly certificated https server’ test environment?

Do I persevere with caddy, or is there an easier way?

Just to be clear. You’re currently using Caddy for testing during development but to set it up you’re installing it globally and having to use systemd to manage it’s lifecycle?

I’m using fiddler classic as a proxy and just set up one simple url rewrite rule. I can then convert any https url like https://localhost or even Microsoft.com to actually hit http://localhost:3000 . This makes the browser think its on the real page so you can even use the regular oauth redirect url. A bonus is that this also works for any Device on your network. this is a great way to Connect iPads or phones directly to your dev server receiving live updates on code save. Just add your proxy server in wifi settings. Really nice to quickly get a feel of the size and how touch control work side by side of the pc screen.

Thank you @dwayne, the implication in your question made me laugh :smiley:

I’m currently trying to use caddy. It was advice on their forum and, as I discovered later, in the documentation, that said manage it using systemd.

Thank you @Atlewee, that sounds good but, from a brief web search, it appears the free version is Windows only — I develop on Ubuntu.

I use localias for these purposes. It maps ports to local addresses that end with ‘.local’ and the browser accepts the HTTPS connection. Hope it works for you!

1 Like

Actually, I wasn’t trying to imply anything. I really was trying to understand your exact situation. However, from your response, what I described does seem to be the case.

I have also used Caddy in some of my projects. I did it via either Devbox or Nix flakes but I never used the HTTPS support. I used it to serve my SPA locally.

No need to use systemd. Everything is scoped to your project.

Thank you, @timinou

Looking at the github pages for localias: it’s running caddy :slightly_smiling_face: …but it does all the setting up for you :grinning_face:

Why don’t you use something like https://packetriot.com/ or https://ngrok.com/ ?

This makes it pretty easy to run the software locally but also have it exposed to the Internet with HTTPS. I personally prefer Packetriot.

Or doesn’t this work in your case?

@dwayne, I thought you were suggesting that it wasn’t a good idea to run something like caddy globally :slightly_smiling_face:

It’s interesting that you say,

My understanding is that modern browsers are suspicious of anything not served https with a valid TLS certificate. So to test locally under real-world conditions requires these.

Thank you for the heads-up on Devbox — Microsoft and cloud-based :slightly_frowning_face: — and Nix flakes — another learning curve :face_with_diagonal_mouth:


Thank you @mywzQxMJ76.

Firstly, I guess, because I’ve never heard of them :laughing:

I’m not looking for run-local/expose-global, or to put anything online yet. I just want to persuade locally run browsers that my locally hosted app is coming from a TLS-signed, https served source, so that the app and browser behave exactly as they will when the app is online.

So far, running caddy via localias is the front runner…

My experience has been that (mobile) Firefox works fine on http://localhost, but (mobile) Chrome will not preserve secure cookies on that scheme/domain, which breaks my site

Well, the ability to access the app globally is just a side effect, I simply use Packetriot to avoid CORS issues or to test realistically.

However, when you finally run your software on a machine using Caddy that would probably be the best test setup.

That’s the wrong Devbox you’re looking at. It’s this one: Devbox: Portable, Isolated Dev Environments. It’s open source, based on Nix, and works locally. It doesn’t have the steep learning curve of Nix and Nix flakes.

1 Like

caddy seems like a good option, maybe is possible to just run the binary $ caddy at least with nginx that is possible.

There is also a bunch free of services to create tunnels to remote servers providing a subdomain and an SSL certificate, useful for testing Oauth, where a valid domain is required.

$ cloudflared tunnel --url http://localhost:3000
$ ngrok http 3000 --domain=myapp.example.com

This will of course expose a local server, and that might not be always desirable, claudeflare tunnel, ngrok and others are free, but they require installing a binary. Its also possible to use ssh to make a reverse tunnel and map a port in running nginx… too complicated.
But this little service seems very cool, no deps!

$ ssh -p 443 -R0:localhost:8080 qr@free.pinggy.io
$ curl https://myapp.a.pinggy.link # :) 

1 Like

Maybe I’m looking at this too simply, but here is where my head goes. If I understand your situation, you want to run locally and serve over https. There is no need to expose the URL on the internet.

The simplest approach might be to:

  1. Create yourself a Certificate Authority cert
  2. Sign a cert with that certificate authority for your webserver
  3. Install the CA on your local system as an authorized CA
  4. Configure your webserver to use your cert (any webserver that supports https will do - many in node, or use Caddy, etc.)
  5. Serve your app through the webserver

There are lots of tutorials on how to generate a CA on linux and how to generate a cert with this CA.

Hopefully I’m not misunderstanding things… :wink:

This can be expanded to support others on your local net just by sending them your CA and having them authorize it locally on their systems.

1 Like

@dta — yes, we have to try to cover all reasonable possibilities.


Thanks, @mywzQxMJ76 Yes, I’m tending towards caddy :slight_smile:


Thank you, @dwayne :slight_smile: Jetify Devbox looks like it might be very useful.


Thank you, @maca@timinou’s suggestion of localias effectively runs $ caddy.

Lots of interesting ideas there :slight_smile:


Thank you, @dirkbj

Yes, that’s correct.

Your enumerated list looks to be what I need.

If I understand stuff so far, caddy does 1,2 and 3.

Hmm… I want to avoid having to send anything (except the website) explicitly to another device; I want the local test ‘experience’ to exactly mimic what happens in production.

I recently looked into creating “self signed certs” automatically for things like elm reactor since it is much nicer to test with HTTPS. The basic idea is this and they mention mkcert.

Like @dirkbj says, creating a cert (especially a self-signed cert) is basically a single openssl command. The annoying thing is adding it to the list of “trusted certs” on your computer, which is different on Mac, Windows, etc.

So from my perspective, if I had something that gave very nice OS-specific instructions on how to add/remove trusted certs, maybe it’s plausible to support self-signed certs more directly. (I haven’t gone further than “knowing how to create my own certs” because I didn’t want to keep looking into the OS-specific details.

4 Likes

Thank you, @evancz

So getting the browser to trust the cert is the most difficult part.

Interesting question here — the accepted answer seems to suggest that adding an xml file and a line in the manifest might do the trick (at least on Android). But it’s quite an old thread…

That answer describes how to have the Android app you are developing trust a certificate. It is not relevant to getting a browser to accept it, although I can’t rule out that there is some way to do that. (the KitKat through Marshmallow section appears to describe installing a certificate globally, but those devices are practically irrelevant these days)

I used mkcert + one local domain per project for years. After my last laptop move I got tired of juggling local domains, trust stores, and all the little setup gotchas.

These days I use a real domain I bought purely for local dev and get proper Let’s Encrypt certs via DNS-01 (prove you control the DNS record; LE doesn’t need to contact the web server). Because it’s a public domain I can put it in public DNS pointing at 127.0.0.1 (and/or other non-routable IPs for LAN testing). I also picked a short .dev since it’s HSTS-preloaded, so no messing around with port 80 / redirects.

This is easy for me because I already run hosting infra and manage lots of certs anyway. For most people it’s probably not worth the hassle just to get nice HTTPS localhost URLs.

So: would the Elm community want a shared setup for this?

Idea:

  • I run a domain like example.dev (name doesn’t matter, just short-ish).

  • You register, grab a tiny CLI, and it gives you a unique subdomain (e.g. abc123.example.dev).

  • The service handles the DNS records and you get a real LE cert for that hostname, with auto-renewal.

  • This CLI tool can be a web server / TLS terminator by itself, so you don’t have to bother setting something up locally.

Now the important part, and the reason this needs some “business” wrapper even though I’m not trying to start a business: to do this at scale the domain must go on the Public Suffix List (PSL). PSL is what makes browsers treat something like .co.uk as a top-level domain. If example.dev is not on the PSL, then all issued certs are just “subdomains of one domain”, and you run into CA rate limits pretty quickly when you’re handing out lots of certs. The PSL policy expects the operator to provide subdomains to unrelated third parties — i.e., it looks like a service, not a private domain. That’s the only reason the structure has to look official.

I’m not looking for a “business opportunity” here. Happy to run it because it’s low-effort for me if there’s real interest. (And I am anyway looking for a good demo for my pghttp project, so all hosting infra would be an example Elm project)! But it’s not worth building unless the community actually wants it and is willing to chip in for the boring costs (short domains aren’t cheap, and there’s some infra to keep it reliable).

If there’s enough interest, I’d aim for something like ~$15/year per person to cover domain + servers. No upsells, no growth plan. If people prefer it lives under the Elm Foundation (or someone trusted), I can help set it up and hand it off.

Would anyone actually use this? Roughly I’d need ~100 people willing to put in ~$15/yr to make the first year make sense.

Thank you @dta, and apologies for misreading the stackoverflow post. Doubtless an element of wishful thinking on my part.


Thank you @damir

In trying to understand your reply I find myself plumbing the depths of my ignorance. From yours and all the other replies, this would appear to be a more complex issue than I at first thought.

This isn’t of course an Elm-specific problem. Given that everyone creating web apps (using any the plethora of technologies) must eventually hit this issue, it’s frustrating that there isn’t already a solution.


Perhaps I might be permitted to branch my question (twice!)…

  1. Why would there not be a web app manifest member that tells the browser, ‘this is a local test site, behave like it’s a live site’ ?

  2. When an app is served on a local https server with a self-signed certificate, apart from the browser complaining about the self-signed certificate, what other inconsistencies have people experienced relative to a live public site?
    In other words, is this actually such a big issue?