this post was submitted on 02 Apr 2025
109 points (98.2% liked)

Selfhosted

45411 readers
522 users here now

A place to share alternatives to popular online services that can be self-hosted without giving up privacy or locking you into a service you don't control.

Rules:

  1. Be civil: we're here to support and learn from one another. Insults won't be tolerated. Flame wars are frowned upon.

  2. No spam posting.

  3. Posts have to be centered around self-hosting. There are other communities for discussing hardware or home computing. If it's not obvious why your post topic revolves around selfhosting, please include details to make it clear.

  4. Don't duplicate the full text of your blog or github here. Just post the link for folks to click.

  5. Submission headline should match the article title (don’t cherry-pick information from the title to fit your agenda).

  6. No trolling.

Resources:

Any issues on the community? Report it using the report flag.

Questions? DM the mods!

founded 2 years ago
MODERATORS
 

Inspired by this comment to try to learn what I'm missing.

  • Cloudflare proxy
  • Reverse Proxy
  • Fail2ban
  • Docker containers on their own networks

Another concern I have is does it need to be on a separate machine on a vlan from the rest of the network or is that too much?

all 50 comments
sorted by: hot top controversial new old
[–] [email protected] 1 points 2 hours ago

To add some points, that I do:

  • Proper logging: So I could realize something unusual is going on
  • rootless podman container: harder to escalate privileges and gain root
  • Apparmor: same, plus it could trigger suspicious log entries
[–] [email protected] 1 points 4 hours ago* (last edited 4 hours ago)

As many others have said, not allowing inbound WAN connections into my LAN is an important step. I also run k3s on my server with Calico as the CNI and make heavy use of network policies to keep anything I’m running from misbehaving. That, along with easy ingress makes k3s worth it for me over Docker Compose. I use OpenWRT on my router and force certain devices to run through a VPN and block other devices from the internet entirely.

[–] [email protected] 5 points 7 hours ago* (last edited 7 hours ago)

They aren't on the internet mainly.

My router (opnsense) has a wireguard server which is how I access things when out of the house.

I do have a minecraft server for my friends and I, but that VM is on its own network isolated from everything else.

[–] [email protected] 1 points 6 hours ago

NPM, Nginx

If I need remote access, I just log into NPM and I have certain URL's created for Plex, or Sonarr, Radarr etc. No issues so far.

[–] [email protected] 17 points 1 day ago (1 children)

I put up a sign that says, "No hackers allowed plz"

[–] [email protected] 4 points 21 hours ago (1 children)
[–] [email protected] 7 points 8 hours ago

"All your containers are belong to us."

[–] [email protected] 9 points 1 day ago* (last edited 1 day ago) (1 children)

Some I haven't yet found in this thread:

  • rootless podman
  • container port mapping to localhost (e.g. 127.0.0.1:8080:8080)
  • systemd services with many of its sandboxing features (PrivateTmp, ...)
[–] [email protected] 2 points 8 hours ago (2 children)

I assume #2 is just to keep containers/stacks able to talk to each other without piercing the firewall for ports that aren't to be exposed to the outside? It wouldn't prevent anything if one of the containers on that host were compromised, afaik.

[–] [email protected] 2 points 6 hours ago (1 children)

It's mostly to allow the reverse proxy on localhost to connect to the container/service, while blocking all other hosts/IPs.

This is especially important when using docker as it messes with iptables and can circumvent firewall like e.g. ufw.

You're right that it doesn't increase security on case of a compromised container. It's just about outside connections.

[–] [email protected] 2 points 5 hours ago

OK, yah, that's what I was getting at.

[–] [email protected] 1 points 7 hours ago (1 children)

Containers can talk to each other without any ports exposed at all, they just need to be added to the same docker network.

[–] [email protected] 1 points 5 hours ago* (last edited 5 hours ago) (1 children)

I was getting more at stacks on a host talking, ie: you have a postgres stack with PG and Pgadmin, but want to use it with other stacks or k8s swarm, without exposing the pg port outside the machine. You are controlling other containers from interacting except on the allowed ports, and keeping those port from being available off the host.

[–] [email protected] 2 points 5 hours ago (1 children)

You can do that by joining the containers to the same docker network, you don't need to expose ports even to localhost.

[–] [email protected] 1 points 4 hours ago

I mustn't be communicating well, but that's fine.

[–] [email protected] 5 points 1 day ago (1 children)

One thing I do is instead of having an open SSH port, I have an OpenVPN server that I’ll connect to, then SSH to the host from within the network. Then, if someone hacks into the network, they still won’t have SSH access.

[–] [email protected] 2 points 1 day ago* (last edited 1 day ago)

I do the same, but with Wireguard instead of OpenVPN. The performance is much better in my experience and it sucks less battery life.

[–] [email protected] 3 points 1 day ago* (last edited 1 day ago)

Fail2ban config can get fairly involved in my experience. I'm probably not doing it the right way, as I wrote a bunch of web server ban rules


anyone trying to access wpadmin gets banned, for instance (I don't use WordPress, and if I did, it wouldn't be accessible from my public facing reverse proxy).

I just skimmed my nginx logs and looked for anything funky and put that in a ban rule, basically.

[–] [email protected] 9 points 1 day ago
  • Fail2ban
  • UFW
  • Reverse Proxy
  • IPtraf (monitor)
  • Lynis (Audit)
  • OpenVas (Audit)
  • Nessus (Audit)
  • Non standard SSH port
  • CrowdSec + Appsec
  • No root logins
  • SSH keys
  • Tailscale
  • RKHunter
[–] [email protected] 33 points 1 day ago (5 children)

Disable password authentication on SSH

Enable firewall and block all ports you're not using(most firewalls do this by default)

Switch to a LTS kernel(not security related, but it keeps things going smooth... Technically it is safer since it gets updated less often so it is a bit more battle tested? Never investigated whenever a LTS kernel is safer than a standard one)

Use Caddy to proxy to services instead of directly exposing them out

HTTPS for web stuff(Caddy does it automatically)

[–] [email protected] 3 points 8 hours ago

Caddy or any other (reputable) reverse proxy. I think Nginx Proxy Manager would be best for beginner thanks to GUI.

[–] [email protected] 18 points 1 day ago (1 children)
[–] [email protected] 2 points 1 day ago (1 children)
[–] [email protected] 8 points 1 day ago (2 children)

There are ip lists that let you iptables drop all traffic from China and Russia.

Strongly recommend.

[–] [email protected] 1 points 3 hours ago* (last edited 3 hours ago)

My UDM has this capability. I've blocked quite a few countries that it logged as trying to get into my network. Great little internet cylinder.

[–] [email protected] 5 points 1 day ago (1 children)

I was auto banning all countries but my own but now I’m hosting one resource that has an audience including Chinese…

Good advice outside of this use case! :)

[–] [email protected] 3 points 1 day ago

Yeah, there were other countries to ban, but those 2 cut my attacks down 90%.

Also consider a honeypot that triggers when anyone tries to ssh it at all.

[–] [email protected] 8 points 1 day ago

Dropping instead of blocking might technically be better because it wastes a bit more bot time and they see it as "it doesn't exist" rather than an obsticle to try exploits on. Not sure if that is true though.

For me:

  • ssh server only with keys

  • absolutely no ssh forwarding, only available to local network via firewall rules

  • docker socket proxy for everything that needs socket access

  • drop non-used ports, limit IPs for local-only services (e.g. paperless)

  • crowdsec on traefik for the rest (sadly it blocks my VPN IPs also)

  • Authelia over everything that doesn't break the native apps (jellyfin and home assistant are the two that it breaks so far, and HA was very intermittent so I made a separate authelia rule and mobile DNS entry for slightly reduced rules)

  • proper umask rules on all docker directories (or as much as possible)

  • main drive FDE with a separate boot drive with FDE keyfile on a dongle that is removed except for updates and booting to make snatch-and-grabs useless and compromising bootloader impractical

  • full disk encryption with passworded data drives, so even if a smash and grab happens when I leave the dongle in, the sensitive data is still encrypted and the keys aren't in memory (makes a startup script with a password needed, so no automated startups for me)

For more info, I followed a lot of stuff on: https://github.com/imthenachoman/How-To-Secure-A-Linux-Server

[–] [email protected] 10 points 1 day ago (1 children)

This, but I prefer nginx.

And no real need for tailscale or cloudflare. If you do not like to depend on a third party service, either port forward and ddns or an external vps+wire guard if you have gcnat

[–] [email protected] 1 points 8 hours ago (1 children)

This is a valid solution but honestly how is using VPS not depending on third party?

[–] [email protected] 1 points 6 hours ago

It is, but you are free to switch at any time provider, there is no technological lock in like with cloudflare or tailscale (i know there is a free self hostable version, not talking about that).

So just rent a new one and switch your wireguard there.

[–] [email protected] 24 points 1 day ago (2 children)

I don't put it on the Internet.

I have automatic updates enabled and once in a while I scan with Nessus. Also I have backups. Stuff dying or me breaking it is a much greater risk than getting hacked.

[–] [email protected] 17 points 1 day ago (2 children)

I agree - I don’t expose anything to the internet other than the WireGuard endpoint.

I’m only hosting services that my immediate family need to access, so I just set up WireGuard on their devices, and only expose the services on the LAN.

I used to expose services to the internet, until one of my #saltstack clients was exploited through a very recent vulnerability I hadn’t yet patched (only a week or so since it was announced). I was fortunate that the exploit failed due to the server running FreeBSD, so the crontab entry to download the next mailicious payload failed because wget wasn’t available on the server.

That’s when I realised - minimise the attack surface - if you’re not hosting services for anyone in the world to access, don’t expose them to everyone in the world to exploit.

[–] [email protected] 12 points 1 day ago

I don’t expose anything to the internet other than the WireGuard endpoint.

This is the way

[–] [email protected] 2 points 1 day ago

TBF if you want, you can have a bastion server which is solely whitelisted by IP to stream your content from your local server. It's obviously a pivot point for hackers, but it's the level of effort that 99% of hackers would ignore unless they really wanted to target you. And if you're that high value of a target, you probably shouldn't be opening any ports on your network, which brings us back to your original solution.

I, too, don't expose things to the public because I cannot afford the more safe/obfuscated solutions. But I do think there are reasonable measures that can be taken to expose your content to a wider audience if you wanted.

[–] [email protected] 1 points 1 day ago (1 children)

Is Nessus free for personal use?

[–] [email protected] 4 points 1 day ago

For up to 16 endpoints or something like that, yes.

[–] [email protected] 4 points 1 day ago

Tailscale and being at my house is the only two ways in so I feel those are pretty good for me.

[–] [email protected] 9 points 1 day ago

Just tailscale really.

My services are only exposed to the tailscale network, so I don't have to worry about otger devices on my LAN.

A good VPN with MFA is all you really need if you are the only user.

[–] [email protected] 6 points 1 day ago

in the context of the comment you referenced:

Definitely have the server on its own VLAN. It shouldn't have any access to other devices that are not related to the services and I would also add some sort of security software.

If you have a public service that you expect to have multiple users on you definitely should have some level of monitoring whether it is just the application logs from the forum that you want to host or further have some sort of EDR on the server.

Things I would do if I was hosting a public forum:

  • Reverse proxy
  • fail2ban
  • dedicated server that does not have any personal data or other services that are sensitive
  • complete network isolation with VLAN
  • send application logs to ELK
  • clamAV

And if the user base grows I would also add:

  • EDR such as velociraptor
  • an external firewall / ips
  • possibly move from docker to VM for further isolation (not likely)
[–] [email protected] 5 points 1 day ago (2 children)

My new strategy is to block EVERY port except WireGuard. This doesn't work for things you want to host publicly ofc, like a website, but for most self host stuff I don't see anything better than that.

[–] [email protected] 2 points 1 day ago (1 children)

My new strategy is to block EVERY port

Wow! All 65535 +/-, in and out? That's one way to skin a cat.

[–] [email protected] 3 points 1 day ago (1 children)

ez pz:

#!/usr/sbin/nft -f
table inet filter {
    chain input {
        type filter hook input priority raw; policy accept;
        iif "lo" accept
        ct state established,related accept
        iif "enp1s0" udp dport 51820 accept
        iif "enp1s0" drop
    }

    chain forward {
        type filter hook forward priority raw; policy accept;
        iif "lo" accept
        ct state established,related accept
        iif "enp1s0" udp dport 51820 accept
        iif "enp1s0" drop
    }

    chain output {
        type filter hook output priority raw; policy accept;
    }
}
[–] [email protected] 1 points 1 day ago* (last edited 1 day ago)

I've seen it done as such:

sudo ufw deny out 1:19/tcp sudo ufw deny out 1:19/udp sudo ufw deny out 22:52/tcp sudo ufw deny out 22:52/udp sudo ufw deny out 54:79/tcp sudo ufw deny out 54:79/udp sudo ufw deny out 81:122/tcp sudo ufw deny out 81:122/udp sudo ufw deny out 124:442/tcp sudo ufw deny out 124:442/udp sudo ufw deny out 444:65535/tcp sudo ufw deny out 444:65535/udp

But your way seems a bit more elegant

[–] [email protected] 2 points 1 day ago

I do this too. Took me a little effort to set things up, but now its so easy.

[–] [email protected] 3 points 1 day ago

use a cheap vlan switch to make an actual vlan DMZ with the services' router

use non-root containers everywhere. segment services in different containers

[–] [email protected] 3 points 1 day ago

Default block for incoming traffic is always a good starting point.
I'm personally using crowdsec to good results, but still need to add some more to it as I keep seeing failed attacks that should be blocked much quicker.

[–] [email protected] 2 points 1 day ago (1 children)

I expose some stuff through IPv6 only with my Synology NAS (I am CGNATED) and I have always wondered if I still need to use fail2ban in that environment...

My Synology has an auto block feature that from my understanding is essentially fail2ban, what I don't know is if such a feature works for all my exposed services but Synology's.

[–] [email protected] 1 points 1 day ago

My Synology has an auto block feature that from my understanding is essentially fail2ban, what I don’t know is if such a feature works for all my exposed services but Synology’s

I'd be surprised if it works for custom services. Fail2ban has to know what's running and haw to have access to its log file to know what is a failed authentication request. The best you can do without log access is to rate limit new tcp connections. But still you should know what's the service behind because 5 new SSH sessions per minute and IP can be reasonable 5 new http1.0 connections likely cannot load a single html page.