I currently have a home server which I use a lot and has a few important things in it, so I kindly ask help making this setup safer.
I have an openWRT router on my home network with firewall active. The only open ports are 443 (for all my services) and 853 (for DoT).
I am behind NAT, but I have ipv6, so I use a domain to point to my ipv6, which is how I access my serves when I am not on lan and share stuff with friends.
On port 443 I have nginx acting as a reverse proxy to all my services, and on port 853 I have adguardhome. I use a letsencrypt certificate with this proxy.
Both nginx, adguardhome and almost all of my services are running in containers. I use rootless podman for containers. My network driver is pasta, and no container has “–net host”, although the containers can access host services because they have the option “–map-guest-addr” set, so I don’t know if this is any safer then “–net host”.
I have two means of accessing the server via ssh, either password+2fa or ssh key, but ssh port is lan only so I believe this is fine.
My main concern is, I have a lot of personal data on this server, some things that I access only locally, such as family photos and docs (these are literally not acessible over wan and I wouldnt want them to be), and some less critical things which are indeed acessible externally, such as my calendars and tasks (using caldav and baikal), for exemple.
I run daily encrypted backups into OneDrive using restic+backrest, so if the server where to die I believe this would be fine. But I wouldnt want anyone to actually get access to that data. Although I believe more likely than not an invader would be more interested in running cryptominers or something like that.
I am not concerned about dos attacks, because I don’t think I am a worthy target and even if it were to happen I can wait a few hours to turn the server back on.
I have heard a lot about wireguard - but I don’t really understand how it adds security. I would basically change the ports I open. Or am I missing something?
So I was hoping we could talk about ways to improve my servers security.
Something you might want to look into is using mTLS, or client certificate authentication, on any external facing services that aren’t intended for anybody but yourself or close friends/family. Basically, it means nobody can even connect to your server without having a certificate that was pre-generated by you. On the server end, you just create the certificate, and on the client end, you install it to the device and select it when asked.
The viability of this depends on what applications you use, as support for it must be implemented by its developers. For anything only accessed via web browser, it’s perfect. All web browsers (except Firefox on mobile…) can handle mTLS certs. Lots of Android apps also support it. I use it for Nextcloud on Android (so Files, Tasks, Notes, Photos, RSS, and DAVx5 apps all work) and support works across the board there. It also works for Home Assistant and Gotify apps. It looks like Immich does indeed support it too. In my configuration, I only require it on external connections by having 443 on the router be forwarded to 444 on the server, so I can apply different settings easily without having to do any filtering.
As far as security and privacy goes, mTLS is virtually impenetrable so long as you protect the certificate and configure the proxy correctly, and similar in concept to using Wireguard. Nearly everything I publicly expose is protected via mTLS, with very rare exceptions like Navidrome due to lack of support in subsonic clients, and a couple other things that I actually want to be universally reachable.
mTLS is great and it’s a shame Firefox mobile still doesn’t support it.
Start with the basics:
- Harden SSH by only allowing public key authentication and use strong keys to authenticate instead of passwords.
- Setup fail2ban (lots of online resources, check Linode guides) to block malicious IPs temporarily.
- If the data you store is something only you should see, then it should not ever be connected to the internet, airgap wherever possible.
- And finally, keep your shit updated.
The single best thing you can do security wise, is to NOT have any personal data on a web facing server.
Separate the data
Rereading it does look like you are doing the things right; so just audit what is on the public side. - your calendar and tasks- cool
Your photo and docs, do those need to be on there?
they are not accessible on the WAN
If they are on a server that is publicly accessible, please move them to a different location
Otherwise you sound like your doing well
Your photo and docs
At least in my case, it’s really handy to share photos with other family members. But certainly you don’t need all of them available on the same public service.
Thats a good point. Maybe I can get away with just temporary file sharing. So when someone wants something I can upload it to the server and send a link. I bet even nextcloud could do that.
Still way less scary then having everything on the server all the time
That was a great answer, thank you so much!
Yes I didnt even notice the family photos and docs dont need to be on that same server. Initially I just put them there to act as a local file share. But you are absolutely right, moving them from the public server is the best thing I can do to protect them.
I will look into setting up a second server for the private stuff that is not publicluly accessible
If this server is publicly accessible and gets pwned, they can use it as a jump box for your internal devices.
Admittedly I’m paranoid, but I’d be looking to:
- Isolate your personal data from any web facing servers as much as possible. I break my own rule here with Immich, but I also…
- Use a Cloudflare tunnel instead of opening ports on your router directly. This gets your IP address out of public record.
- Use Cloudflare’s WAF features to limit ingress to trusted countries at a minimum.
- If you can get your head around it, lock things down more with features like Cloudflare device authentication.
- Especially if you don’t do step 4: Integrate Crowdsec into your Nginx setup to block probes, known bot IPs, and common attack vectors.
All of the above is free, but past step 2 can be difficult to setup. The peace of mind once it is, however, is worth it to me.
does anyone have an actual horror story about anything happening via an exposed web service? let’s set aside SSH