I want to start with self hosting something available from internet. Currently I have jellyfin, nas etc but everything is available in local network.
My biggest concern is securing local network. I thought i will run application on separate server, I will use small vps as proxy, but Im not sure if it will be enough
What do you want to expose, something static or dynamic?
It would be a service you wrote or some stablish project?
I would recommend running whichever service you want to expose through a reverse proxy, traefik or caddy. That way you have some sort of “chocking point” where you can control what’s going and it’s already handling some security for you.
The service should be kept updated.
Then you need a ips (intrusion prevention system). Most famous are fail2ban or crowdsec. You feed the ips the service logs and the reverse proxy logs, and ban ips that try to do something strange. I use crowdsec with a bunch of scenarios and their block lists.
At the end you should only have a couple of ports open to the internet. Usually 80 and 443, and whichever port you use for the vpn, i recommend wireguard. So people should only connect to you via 80 or 443 and those ports should be binded to the reverse proxy. Everything else should never be able to enter your network.
If you have all that and keep everything updated the attack surface becomes really small. You’ll get spam bots trying to probe for vulnerabilities but if you keep everything updated they won’t find anything.
Depending on how many people you want to access your service you could also do some aggressive geoblocking, to reduce the number of bot attacks.
The biggest risk here would be a vulnerability on the reverse proxy or the service you use. Keep an eye out for cve and update things regularly. If a vulnerability allows for remote code execution, then mitigation becomes almost impossible besides a good backup plan. If your vpn fails on you you are also fucked. But wireguard is pretty well secured. Bot scans shouldn’t even be able to know you have wg because pings and connections attempts fail silently without proper authentication.
Public server - Pixelfed ;)
I think Pixelfed can sit nicely behind a reverse proxy, to reduce exposure.
I don’t know if there are prebuilt scenarios for pixelfed in crowdsec or fail2ban but it shouldn’t be so hard to at least write something to prevent bruteforce.
Keep stuff that’s not designed to be exposed to the internet on your LAN behind your router’s firewall.
Use a VPN to access your LAN remotely. Tailscale is the easiest way to do this, but I found it not too hard to set up WireGuard.
I was pondering the same for last couple of days and had some thoughts on how to make it feasible. My research led me so far to 2 prerequisites:
- must have Anubis in front
- must have a WAF solution in place that covers at least OWASP Top 10
I found pretty good Caddy documentation that covers both, so I think I’ll deploy a secondary Caddy reverse proxy that’ll perform such ops for public facing services.
Of course, I currently have only 1 Caddy instance reverse proxying my internal services, haven’t reached the part on traffic handling when my devices are connected to the “safe network” (aka my home LAN)
I run my server on the internet, and my security is crowdsec + geo ip block (well, white-list my country’s ip but same idea) and authelia.
Using this setup, I barely ever have even bots randomly pingig me, let alone anyone trying to access my NAS.
My baseline is a public VPS with Pangolin/Crowdsec installed. I have authentik as a login system. Pangolin let’s me put authentik in front of any service so they have to log in hit before the service in question. Helps give a bit of peace of mind with the services which themselves might not be security focused. Also, these pangolin routes are able to block anything outside my country by rules, so that trims a good portion of attacks as well.
Some things don’t like that authentik layer in front though. Audiobookshelf’s phone app for example cant handle it. For that, I route those domains through cloudflare tunnels. Their tunnels do a good job blocking lots of attacks, so not having authentik in front is more acceptable.
But then there’s jellyfin that doesnt want to be on cloudflare tunnels and doesnt want authentik in front. For that, I just have it on my pangolin side with only crowdsec helping. Not ideal, but best I can do without making my grandma install a VPN on a raspberry pi in so her TV can connect or some shit.
And lastly, I have some private services like forgejo that don’t like authentik in front and only I myself care about. I tailscale to those rather than exposing sometimes.
Only other thing I think I need to add sometime is some VLAN separations?
I have oidc setup in both foregejo and Audiobookshelf with authentik as the provider.
What youre talking about is having an app refer to authentik to find out who a user is.
Internet -> audiobookshelf -> asks authentik who it is
In addition to that, you can set pangolin up so that it doesnt even hit that app in the first place at all unless the user is already signed into authentik.
Internet -> pangolin makes user log into authentik before forwarding along -> audiobookshelf -> asks authentik who it is
So if the app in question has a security vulnerability, its not a problem because no one even gets to the app at all to begin to try to exploit it unless they’ve logged into authentik first.
Have you considered Cloudflare Tunnels/Zero Trust. When you use Cloudflare Tunnels/Zero Trust, you don’t need to fiddle with NAT, open any ports, in fact you don’t need any open ports. You just install Cloudflare Tunnels/Zero Trust on your server, connect to your Cloudflare Tunnels/Zero Trust account, and Cloudflare does the rest. To deploy Cloudflare Tunnels/Zero Trust you will need a domain name. Cloudflare will sell you a domain name but I think most get something cheap from NamesCheap or Pork Bun. When you have secured a domain name, switch the nameservers to the ones that Cloudflare assigns you. Jacks a doughnut, Bob’s your uncle.
ETA: Obviously you’ll need port 22 for administration.
sudo ufw default deny incoming
sudo ufw default allow outgoing
Yeah, but if my server is in the local network, I have potential threat that someone will access my lan through public server
Well, you could do network segmentation:
- Put the server in a DMZ or separate VLAN if your router supports it. This isolates it from your main devices (computers, phones, IoT). I’m not sure what router you have buy many consumer routers have a “guest network” that can serve this purpose.
Utilize UFW rules. Mine are:
-
sudo ufw default deny incoming
-
sudo ufw default allow outgoing
-
Anywhere ALLOW IN 192.168.1.0/24
-
22 ALLOW IN 192.168.1.0/24
-
22 on tailscale0 ALLOW IN Anywhere
-
22 (v6) on tailscale0 ALLOW IN Anywhere (v6)
Also:
- sudo ufw allow out to 1.0.0.1 port 53 # DNS only
- sudo ufw allow out to 1.1.1.1 port 53
- sudo ufw deny out to 192.168.1.0/24 # Block LAN access except admin
So now I have SSH capability locally and through Tailscale installed on the server and this prevents the server from initiating connections to other LAN devices. You can do alot with UFW and Fail2Ban in conjunction with Cloudflare Tunnels/Zero Trust.



