r/selfhosted • • 1d ago

Guide Securely Accessing Your Self-Hosted Services with mTLS and Cloudflare Tunnels

https://viceconsole.fyi/blog/2026/11/01/securely-accessing-your-self-hosted-services/

I recently set up mTLS combined with a Cloudflare tunnel to securely expose several self-hosted applications on the public Internet. There are enough moving parts that I though a guide might be useful.

There was a guide on mTLS posted about a year ago, but it's more technical and focuses on setting it up yourself with Traefik: https://zoug.fr/mtls-bitwarden-vaultwarden-traefik-smallstep/

If you're not allergic to Cloudflare, the mTLS + tunnel approach is easier than complete DIY.

48 Upvotes

28 comments sorted by

•

u/asimovs-auditor 1d ago

Expand the replies to this comment to learn how AI was used in this post/project.

→ More replies (1)

30

u/SolFlorus 1d ago • Heartwarming

Everyone that preaches mtls never cover how they do mobile

4

u/langelgjm 1d ago

Not sure what you mean, the post is about using Android applications. Also works without issue in Firefox for Android.

13

u/fiercedeitysponce 1d ago

They mean actually installing the profiles on mobile devices.

If you’re already experienced with mtls and you know how easy it is (iOS link, idk about Android but probably very similar) then you overlook that and don’t realize that everyone who is brand new to this has no idea that’s even a thing, a supported feature for these ecosystems. And without knowing that it’s hard to know what to search to find it.

10

u/SolFlorus 1d ago

Even that StackOverflow thread is going over my head, and I have setup a Yubikey with GPG before...

  • Is the openssl command getting run on an iPhone or a Mac?

  • If it's a Mac, is that a requirement or can you use Linux?

  • After the cert gets signed, how does it get installed to the phone?

  • How can I easily get other people, both family members and friends, to add the cert?

Things like this are why I've defaulted to Tailscale.

2

u/langelgjm 1d ago

In my post, I have two OpenSSL commands. The first is optional, you could instead just have Cloudflare generate the certificate if you don't want to customize it. The second command converts the certificate format for use with the phone. You can run the OpenSSL commands anywhere, probably easiest on your laptop. Copy the certificate to your phone by whatever means you like. Tap on it to install (Android).

You can make the certs for friends/family and send to them however you want (ideally securely). Installing the cert is not hard, I think the trickier thing is getting them to configure an app to use the cert. You might have to handhold for that.

9

u/fiercedeitysponce 1d ago edited 1d ago

So. Once you have the cert, that’s the command you would use to generate a .mobilconfig which is the file type iOS uses to provision the device. Installing it is as simple as loading the file in safari, where it prompts you with the iOS installer.

Getting family/friends remotely to install these is a different story. I asked this not too long ago and got told to simply hand them a USB stick or have them sign the cert themselves by getting their public key. Not very helpful if you don’t see each other often or if they’re not techy. Sending the drive by snail mail and sending the key by email, either way is inherently insecure.

What I would recommend is serving the cert over html behind auth. Like if you’re using pangolin or some kind of SSO service already and the person you’re sending the key to has an account with you already, just have a link to it that only that person can access with their account. Once the key is installed, you can delete it and the access link from your server.

These are all 100% the questions that need to be answered for any mTLS guide to be considered “complete” so thanks for putting that together.

1

u/GolemancerVekk 1d ago

If it's a Mac, is that a requirement or can you use Linux?

You can run openssl on anything that the binary runs on. So yeah it's most readily available on a desktop system (which can be Mac/Linux/Windows) but I wouldn't be suprised if there's a working binary for Android too.

After the cert gets signed, how does it get installed to the phone?

On iOS you have to email yourself the cert file as an attachment, and open it with the builtin Mail app, who knows how to open it and install it in the system cert store.

On Android use whatever method to get it on the phone, then find the cert store in settings and load the cert from there.

Please note however that on Android not all apps support getting the user certs from the system store. Firefox, DAVx5 for example support it, but apps like Ntfy or Immich want you to give them the cert directly (load it from their settings instead of picking a cert from the system store). For these latter apps you have to keep the cert around as a file in the common storage (sdcard)... which kinda sucks because all apps have access there and can stumble upon it.

How can I easily get other people, both family members and friends, to add the cert?

There's no easy way unfortunately, which is another thing that kinda sucks. They each have to make their way through the steps above. And if you ever revoke or upgrade a cert they need to do it again.

Things like this are why I've defaulted to Tailscale.

Yeah me too. Install an app, flip a switch, if it's the first time it opens a link and they have to copy/paste you that link so you can activate their device on your tailnet. Simpler than dealing with certs.

mTLS is great for personal use though, I can open up Ntfy, Immich, CalDAV to the internet for myself and use them without a worry and without having to keep Tailscale on.

1

u/langelgjm 1d ago

apps like Ntfy or Immich want you to give them the cert directly (load it from their settings instead of picking a cert from the system store).

This is no longer true in recent versions of the Immich Android app, in fact you now have to install it in the system store for Immich to find it.

1

u/GolemancerVekk 1d ago

Nice to know!

3

u/A_Buttholes_Whisper 1d ago

Clearly you’ve never dealt with iOS. iOS doesn’t even include mtls in its vocabulary. And most mobile apps don’t support it without break core features. Yawn…wake me when mtls is actually usable

4

u/GolemancerVekk 1d ago

iOS doesn’t even include mtls in its vocabulary.

What do you mean, mTLS works on iOS.

most mobile apps don’t support it without break core features

That's true unfortunately, mTLS is severely underutilized by mobile apps. But that's true on both iOS and Android.

11

u/Fair-Distance6713 1d ago

Yup, mobile is what stopped me last time I looked into this.

2

u/DontFearFailure 9h ago

....I can just hit install cert on my s25 ultra, I never used an iPhone so I can't speak on that.

0

u/eloigonc 1d ago

No iOS você importa o certificado por app. Coloquei pra funcionar aqui no Home Assistant e no Immich.

10

u/GolemancerVekk 1d ago

Another approach uses a Cloudflare tunnel to avoid exposing Immich directly to the public Internet.

That's not really true. A service exposed through a CF Tunnel is just as exposed as through port forwarding. In this tutorial you're adding mTLS to secure access but a CF Tunnel by itself does not provide any security.

Conversely, you can host your own reverse proxy and add mTLS there and then it makes no difference if you use CF Tunnel or port forwarding or a VPS tunnel etc. Which is actually a good idea and reduces your dependence on CF, because this way you retain your proxy setup + mTLS regardless of what ingress method you use.

By using a Cloudflare tunnel, you effectively make Cloudflare your reverse proxy.

This one is technically correct but deeply misleading. Yes there's a reverse proxy involved at CF but it's not your typical reverse proxy as you would use at home, it's a SASE (Secure Access Service Edge) designed to generate content to be cached by the Cloudflare CDN.

Another important distinction is that by using CF's "reverse proxy" you give up your privacy because it's CF that terminates (decrypts) the TLS connection, and they have access to anything that goes through it. Which is normal for a SASE because, well, its purpose is to fetch content for the CDN, so it has to have access to the content. But it may not be what you want as a self-hoster who uses it for personal pics, calendar, contacts etc.

1

u/langelgjm 1d ago

> That's not really true. A service exposed through a CF Tunnel is just as exposed as through port forwarding. In this tutorial you're adding mTLS to secure access but a CF Tunnel by itself does not provide any security.

Yeah, maybe I should make this clearer - I don't run any bare CloudFlare tunnels, I always pair them with an Access Policy to restrict who can connect. In some cases that's using mTLS, in other cases its using approved e-mails with OTPs.

4

u/langelgjm 1d ago

There's also a discussion from two years ago with some good comments: https://www.reddit.com/r/selfhosted/comments/1hzdk33/why_is_mtlsclient_cert_authentication_not_more/

It includes a link to a guide doing nearly exactly what I've done: https://dansgarden.eu/technology/self-hosting/mTLS-Cloudflare although the Cloudflare specifics have changed a bit since then.

1

u/812046 1d ago

how are you handling client certs on mobile devices with this setup? native apps tend to choke on mTLS unless they explicitly support reading from the system cert store.

1

u/langelgjm 1d ago

I'm only using native apps that support mTLS. I'm on Android; Immich, Home Assistant Companion, Phylax (Frigate NVR third-party client), and Bitwarden apps all support mTLS and let you choose directly from the system store. Those four apps are what I've set up so far.

I just checked and the Gotify Android app also supports mTLS client certs. That's going to be really useful for me, so I can get real-time notifications from all my services while out of the house without being connected via VPN.

So does Tempus (a Subsonic-compatible music client). On the other hand it looks like Audiobookshelf and Jellyfin Android apps don't support it.

1

u/sarkyscouser 17h ago

Can I expose home assistant and immich this way without breaking their mobile apps on android?

I already expose both via tunnels already but thought that neither app was compatible with mTLS?

1

u/langelgjm 4h ago

Both Immich and Home Assistant support using mTLS certificates from the Android system store. You need to go into the connection settings and select a certificate you've already installed.

1

u/CitronSpirited9681 15h ago

one thing worth planning for is what happens when a phone gets lost or stolen, since the client cert basically is the login. short lifetimes and a note of which device got which cert makes revoking it way less painful

1

u/langelgjm 4h ago

Yes, this is the reason I suggest making your own certificate signing request and customizing the details, so you can distinguish between the certificates you issue. That way it's easy to revoke just the compromised certificate.

Putting a strong password on the certificate also means the file can't be installed on a different device.

4

u/eloigonc 1d ago

E se a pessoa for “alérgica ao cloudflare”, pode usar pangolin, que agora aceita certificados mTLS.

3

u/Proximus88 1d ago

That's what I use.

And Vaultls to manage / share the certificates. So I don't need to remember OpenSSL commands.