Comment on Anybody here does mTLS?
I think mTLS is probably overkill here.
For a few unmanaged phones using native apps, you would be adding a second PKI lifecycle on top of the normal application credentials: issuing per-device keys, securely importing them into iOS/Android, handling app-specific certificate selection, expiry, replacement, revocation after loss/reset, and explaining all of that to the users. It works — but it is a lot of machinery for a small private setup.
A WireGuard-style overlay network seems like the more practical solution. WireGuard directly, Tailscale, Headscale, NetBird, or similar would let you make Immich and CalDAV/CardDAV private-only services. Then a new public-facing exploit in one of those services is much less likely to become an immediate “drop everything and patch it right now” event, because there is no publicly reachable login or API endpoint in the first place.
The Matrix part needs one important clarification, though: do you want federation with other Matrix homeservers?
If yes, Matrix cannot simply be made private in the same way. Other homeservers need to reach the federation API; by default that is port 8448, although Matrix delegation can direct federation to another host/port. Matrix clients and federation traffic can also be separated: clients normally use 443, while server-to-server federation defaults to 8448.
So I would split it roughly like this:
- Immich: private overlay/VPN only.
- CalDAV/CardDAV: private overlay/VPN only.
- Matrix, no federation: private overlay/VPN only.
- Matrix, federated: expose only the minimal, dedicated federation endpoint publicly; keep admin interfaces and anything else private. Client access could still be via the overlay, but that has UX implications for mobile push/background connectivity.
mTLS is a reasonable choice when a service must remain publicly reachable but should accept requests only from a tightly controlled set of devices. In your case, putting the services behind a private network seems both simpler and more effective at reducing exposed attack surface.
Also, “I can distribute keystores manually” is exactly the point where this tends to look easy — right up to the first lost phone, OS reset, certificate expiry, or app that suddenly stops offering the certificate picker because mobile ecosystems enjoy making infrastructure administration a lifestyle choice.