Skip to content

Trusting the local certificate

You built something you want to try on your phone: a screen you log into, or an app you can add to the home screen and open offline. On your computer it all works. You run monoceros share, open the address on your phone, and the login won’t go through - or the app refuses to install. Nothing in your code is broken. Here is why, and the one small step that fixes it.

Two things your app relies on only work on pages the browser considers trustworthy - and on a phone, by default, your shared app is not one of them.

Logging in. Signing in with Keycloak (or any similar login) does a little cryptography in the browser to keep the exchange safe from tampering. Browsers only allow that on pages they trust. On your computer the app runs at an address ending in .localhost, which browsers trust automatically, so the login works. Your phone reaches the app by your computer’s network name or IP address instead, which gets no such free pass - so the login quietly fails before it even reaches Keycloak.

Installing it and using it offline. An app you can install to the home screen and open without a connection is powered by a service worker: a small helper the browser runs in the background to cache the app, serve it offline, and handle push notifications. Browsers only let a service worker run on a trusted page. Without one you lose exactly that - no install to the home screen, no offline mode, no notifications; it stays an ordinary browser tab.

The common thread: the browser grants these only to pages it trusts, and here “trusted” means HTTPS - the little padlock in the address bar. Your own machine’s .localhost addresses are trusted as a special case; a phone on your network is not.

What share does, and the one thing you do once

Section titled “What share does, and the one thing you do once”

monoceros share serves your app over HTTPS, so the phone gets a trusted page and both problems disappear. The padlock needs a certificate to back it, so Monoceros creates one on your machine - a small local “certificate authority”, saved at ~/.monoceros/ca/rootCA.pem. It never leaves your computer, and nothing is sent anywhere.

There is one catch. A certificate is only believed if the device has been told to trust who issued it. So each device you open the app on trusts this certificate once - after that, shared apps just load, with the padlock and no warning. monoceros share prints the exact path to the file every time it starts.

Each computer has its own certificate authority, named after that machine - for example Monoceros Local CA (your-computer). So if you run Monoceros on a few machines and trust each on the same phone, they stay easy to tell apart in its trust store.

The host itself reaches apps at http://<name>.localhost through the proxy, which needs no certificate. You only need this if you open the share URL (the .local name or LAN IP over HTTPS) on the host too.

Adds the CA to the system keychain as a trusted root. Covers Safari and all Chromium browsers (Chrome, Edge, Brave).

  1. Trust the CA:

    Terminal window
    sudo security add-trusted-cert -d -r trustRoot \
    -k /Library/Keychains/System.keychain \
    ~/.monoceros/ca/rootCA.pem
  2. Restart the browser.

This is where trusting the CA matters most - it is what makes an installable PWA and its login work over share. First get rootCA.pem onto the device (AirDrop, a cloud drive, or email), then:

Trust is a two-step process, and the second step is the one that is easy to miss - without it you get “this connection is not trusted”.

  1. Open the transferred rootCA.pem. iOS shows “Profile downloaded”.

  2. Settings → General → VPN & Device Management → tap “Monoceros Local CA” → Install (enter your passcode).

  3. Settings → General → About → Certificate Trust Settings → turn the switch on for “Monoceros Local CA”.

  4. Open the share URL in Safari.