Two years ago, when I decided to expose a small Kubernetes cluster I set up at home to the internet, I saw brute-force attacks starting on my SSH port from 3 different IP addresses within the first 7 minutes. This incident reminded me once again how quickly our homelab can become a target when exposed to the outside world, and how critical security steps are. In this post, drawing from my own experiences, I will detail 7 critical security steps you absolutely must implement before exposing your homelab to the internet.
Exposing your homelab to the internet offers flexibility and accessibility, but it also brings serious security risks. These steps are not just a simple checklist, but lessons learned from years of experience and some "fires" I've had to put out. Each step focuses on closing a potential attack vector and making your systems more resilient.
Why Are Network Segmentation and Firewall Rules Critical?
The first and most important step when exposing a homelab to the internet is to logically segment your network and manage traffic between these segments with strict rules. In my homelab, I separate critical services (databases, management interfaces) from internet-facing web services using VLANs. This ensures that even if a vulnerability is found in a web application, an attacker cannot easily access other systems on the internal network.
ℹ️ VLAN Segmentation
VLANs (Virtual Local Area Network) allow devices to be on different logical networks even if they are physically on the same switch. This way, an internet-facing web server and a sensitive database server can be isolated from each other by being assigned to different VLANs, even if they are connected to the same physical switch. For example, we can designate one VLAN for "DMZ"-like internet-facing services and another as "Internal" for internal network resources.
Firewall rules are a fundamental layer that completes network segmentation. You should only open the ports and protocols you need to the outside world, and by default, block everything else. For example, for a web server, it's logical to open only ports 80 (HTTP) and 443 (HTTPS), while keeping the SSH (22) port accessible only from a specific IP address or via VPN. I generally use ufw (Uncomplicated Firewall) because it has a quick and understandable syntax.
# Allow only SSH (22), HTTP (80), and HTTPS (443) ports
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp from 192.168.1.100 # Allow SSH only from a specific IP
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Last year, in a client's test environment, I accidentally defined a firewall rule that opened all ports on a virtual machine. About 4 hours later, I received an alert: there were external connection attempts on the PostgreSQL port (5432). Fortunately, this was just a test server and contained no critical data, but this incident showed me once again that I should always define firewall rules with the "least privilege" principle. Network segmentation and correct firewall rules are the first and most effective way to minimize your attack surface.
How to Ensure Secure Remote Access?
The most secure way to access your homelab over the internet is to use a VPN or an SSH bastion host, rather than directly opening ports. Directly exposing the SSH port (default 22) to the internet, as I mentioned above, will make you a target within seconds. In my homelab, I use a WireGuard-based VPN. This encrypts all my traffic and only allows access through the VPN tunnel, preventing many external threats.
💡 Tips for SSH Security
You can make it harder for automated scanners by moving the SSH service from the default port 22 to a different, high port number. However, this is not a security layer, just a "hiding" method, and it's not sufficient on its own. Most importantly, disable password authentication and only allow access with SSH keys. Additionally, automatically banning IP addresses that make failed attempts with tools like
fail2banis very effective against SSH brute-force attacks.
Using SSH keys is much more secure than password-based authentication. On my servers, I set password authentication no and only allow access with strong, passphrase-protected SSH keys. Furthermore, by setting up an SSH bastion host, I manage all external SSH access from a single point and access other servers on the internal network only by jumping through this bastion. This ensures that the SSH ports of internal servers remain closed to the internet.
# Critical settings to be made in the /etc/ssh/sshd_config file
Port 22222 # A different port instead of the default 22
PasswordAuthentication no # Disable password access
PermitRootLogin no # Prevent direct root login
ChallengeResponseAuthentication no
UsePAM yes
AllowUsers mustafa # Allow only specific users
# Simple fail2ban configuration (jail.local)
[sshd]
enabled = true
port = 22222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600 # Ban for 1 hour
On the backend server of one of my side projects, even though I had moved the SSH port to a different port, I forgot to install fail2ban. About a week later, while reviewing the logs, I noticed continuous SSH attempts from dozens of different IP addresses. This showed me once again how important even a simple fail2ban setup is. Secure remote access is key to keeping your homelab's gateway to the outside world strong.
Why Is Running Services with Minimum Privileges Important?
Every service running in your homelab is a potential security vulnerability. Ensuring these services run with the principle of least privilege greatly limits the damage an attacker can do to your system in case of a vulnerability. Whether it's a web server, a database server, or a containerized application, no service should run with root privileges.
I generally use systemd units to run services under a specific user and group. For example, the Nginx web server runs under the www-data user, while PostgreSQL runs under the postgres user. These users should have no other privileges on the system. I also actively use systemd's security features like CapabilityBoundingSet, PrivateTmp, and NoNewPrivileges.
# Example systemd unit file (/etc/systemd/system/myservice.service)
[Unit]
Description=My Awesome Service
After=network.target
[Service]
ExecStart=/usr/local/bin/myservice
User=myserviceuser # Run the service under this user
Group=myservicegroup # Run the service under this group
WorkingDirectory=/opt/myservice
ReadWritePaths=/opt/myservice/data # Allow write access only to this directory
CapabilityBoundingSet=CAP_NET_BIND_SERVICE # Grant only necessary capabilities
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
[Install]
WantedBy=multi-user.target
While working on a production ERP, a service was accidentally configured to run with root privileges. When a vulnerability was discovered, it took seconds for the attacker to completely compromise the system. This taught me that service privilege isolation is not just a good practice, but a vital security measure. The same principle applies to containers; running Docker containers with non-root users and granting only necessary privileges to the container is critically important.
Why Are Keeping Up-to-Date and CVE Tracking Necessary?
Keeping software up-to-date, applying security patches in a timely manner, and tracking CVE (Common Vulnerabilities and Exposures) notifications are a continuous part of securing your homelab. Developers constantly discover new vulnerabilities and release patches for them. Failing to apply these patches leaves your system vulnerable to known exploits.
I generally install the unattended-upgrades package on my Linux servers to ensure security updates are applied automatically. However, this is not always sufficient. Especially for critical services and kernel updates, I perform manual checks and careful planning. I regularly follow CVE databases and relevant security lists (e.g., NVD - National Vulnerability Database).
⚠️ Kernel Vulnerabilities
Kernel vulnerabilities are usually the most critical as they affect the core of the system and can lead to full system compromise. For example, a vulnerability like CVE-2026-31431 could allow an attacker to execute code at the kernel level. In such cases, blacklisting relevant kernel modules or applying the update as soon as possible is vital.
Once, over a weekend, I realized I was using an old version of an HTTP proxy software installed on one of my servers. A critical remote code execution (RCE) vulnerability had been patched in that software about 3 months prior. Luckily, this vulnerability had not yet been exploited. This situation showed me how important it is to regularly check the versions of all installed software and their known CVEs, in addition to automatic updates. I list installed packages with the dpkg -l command and occasionally check them manually.
# Enable automatic security updates for Debian/Ubuntu
sudo apt update
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades # Run the setup wizard
Staying current requires continuous effort, but this effort is definitely worth it when considering the cost and reputation damage a potential cyberattack could cause. Outdated software or an unpatched kernel can turn your homelab into an "open door."
Why Are Logging and Monitoring (Observability) Vital?
When you expose a homelab to the internet, you must have a robust logging and monitoring infrastructure to understand what's happening on your systems. Attacks are usually not instantaneous; attackers try to leave traces in the system. You need logs and metric data to detect and respond to these traces. In my systems, I use journald for centralized log collection and Prometheus/Grafana for metric monitoring.
journald is a great tool for collecting and managing logs on Linux systems. It makes logs from all services and system components accessible from a single place. Additionally, I use the auditd service to monitor system calls, file accesses, and privilege escalation attempts for deeper security auditing. In the event of or after an attack, these logs are critically important for forensic analysis.
The combination of Prometheus and Grafana allows me to visualize the real-time status of everything in my homelab (CPU, memory, disk I/O, network traffic, application metrics). When defined thresholds are exceeded (e.g., a server's CPU usage goes above 90% or disk usage exceeds 80%), I receive instant notifications. This is indispensable for anomaly detection.
# View the last 100 logs of a specific service
journalctl -u nginx.service -n 100
# Find failed SSH attempts within a specific time range
journalctl _COMM=sshd | grep "Failed password" | tail -n 20
# Monitor file accesses with auditd (example rule)
# /etc/audit/rules.d/10-custom.rules
# -w /etc/passwd -p wa -k passwd_changes
# sudo service auditd restart
Last winter, I noticed that a Redis server on my own servers suddenly started consuming high CPU. The anomaly was clearly visible on my Grafana dashboard. When I examined the logs, I saw numerous external connection attempts and that Redis was subjected to some brute-force attacks. If I hadn't had a monitoring system, I might have noticed this much later and faced more serious problems. Logging and monitoring are the "eyes and ears" of your homelab.
Why Are Strong Password Policies and Multi-Factor Authentication (MFA) Essential?
Using strong and unique passwords for all accounts in your homelab and implementing Multi-Factor Authentication (MFA) wherever possible are fundamental pillars of cybersecurity. Weak passwords are one of the easiest ways for an attacker to gain access to your system. Often, users use the same password in multiple places, which sets the stage for "credential stuffing" attacks.
I create and manage all my passwords using a password manager (e.g., Bitwarden or Keepass). This allows me to use complex and unique passwords longer than 16 characters for each service. Additionally, I use MFA (e.g., TOTP-based Google Authenticator or FIDO2 security keys) wherever possible, including SSH access, server panels, web services, and even VPN connections.
🔥 Credential Stuffing
Credential stuffing is when an attacker uses username and password combinations obtained from a data breach to try and gain access to different websites and services. If you use the same password in multiple places, all your other accounts are at risk as a result of a data breach in one service. MFA is one of the strongest defense layers against such attacks because even if your password is compromised, access cannot be gained without the second factor.
In a client project, I managed to crack a user's password on an old system within about 10 minutes using a common password list like "rockyou.txt". This showed me that password policies are not just a rule, but truly a security layer. Especially for user accounts of any internet-facing service, enforcing MFA dramatically increases access security.
# TOTP MFA setup with PAM on Debian/Ubuntu (simple example)
sudo apt install libpam-google-authenticator
# Each user runs the google-authenticator command in their home directory
# This creates the /home/user/.google_authenticator file and displays the QR code.
# Add the following line to /etc/pam.d/sshd:
# auth required pam_google_authenticator.so
Strong passwords and MFA form the first and most critical line of defense for your homelab against unauthorized access attempts from the outside. Without these two principles, all other security measures remain weak.
Why Is a Backup and Recovery Plan Indispensable?
Despite all security measures, an attack or hardware failure is always possible. This is why having a comprehensive backup and recovery plan is indispensable for your homelab. Regularly backing up your data and storing these backups in a secure location prevents you from losing your data in case of a disaster.
In my homelab, I back up critical data daily using borgbackup to an external disk or cloud storage, encrypted. borgbackup minimizes backup size with its deduplication feature while also ensuring data integrity and confidentiality. As part of my backup plan, I occasionally perform restore attempts from these backups to ensure my recovery plan works.
ℹ️ 3-2-1 Backup Rule
The 3-2-1 rule is the gold standard for backup strategies:
- Have 3 copies of your data (original + 2 backups).
- Store them on 2 different storage media (e.g., primary disk and external disk).
- Keep 1 copy offsite (e.g., cloud storage). This rule greatly reduces the risk of losing all your data due to a single point of failure.
Last year, one of the disks in a RAID array failed, and all data on my server became inaccessible. Fortunately, I had regular backups and was able to restore the entire system to new disks within about 6 hours. This incident showed me how important not only backing up is, but also periodically testing those backups. A backup is meaningless if it doesn't work.
# Simple backup command with borgbackup
# First, a repository is created: borg init --encryption=repokey-blake2 /mnt/backup/my_repo
# Then, a backup is taken:
borg create --stats --progress /mnt/backup/my_repo::'{hostname}-{now}' /home/mustafa/data /var/www/html
A backup and recovery plan is the last link in the security chain. In case all preventative measures fail, it is the only thing that will protect your data and ensure the continuity of your operations. Therefore, never overlook this step.
How to Perform Security Audits and Continuous Improvement?
Homelab security is not a one-time task; it's a continuous cycle of auditing and improvement. As new vulnerabilities emerge, software is updated, or new services are added, you need to re-evaluate your security posture. Performing regular security audits and remediating identified vulnerabilities ensures the long-term security of your homelab.
In my homelab, I use simple security scanners (e.g., nmap for port scans or nikto for web vulnerability scans) to check how I appear from the outside. I also regularly review auditd logs or get summary reports with tools like logwatch to detect unusual activities. This helps me understand if an attacker is trying to infiltrate my system from the inside or outside.
💡 Simple Security Scanning Tools
- nmap: Used to discover devices and open ports on the network. With the
nmap -sV -p- <IP_ADDRESS>command, you can scan all ports and get version information of running services.
- nikto: A web server scanner that scans for known vulnerabilities, server configuration errors, and other security flaws on web servers. It can be used with the
nikto -h <URL>command. Running these tools periodically on your own systems helps you understand your external security surface.
When I add a new service to my homelab, I apply all security steps (firewall, permissions, logging) by default and always perform an internal security audit before publishing it. A few years ago, when I added a new API to the backend of my Android spam application, I forgot to implement rate limiting. After a while, I noticed a large number of requests to the API, and this negatively affected the server's performance. This simple mistake reminded me that every new addition or change must be carefully evaluated from a security perspective.
# Scan for open ports from outside on my homelab server
nmap -sV -p- localhost
# or
nmap -sV -p- <MY_EXTERNAL_IP_ADDRESS> # To check how I appear from the internet
Security audits and continuous improvement ensure that your homelab adapts to the changing threat landscape and remains secure in the long run. Remember, security is not a destination, but a continuous journey; it requires constant attention and learning.
Conclusion: Homelab Security Is a Mindset
The brute-force attack I experienced in the early days of exposing my homelab to the internet taught me how critical it is to be proactive about security. These 7 steps are a summary of my years of experience and the problems I've encountered. From network segmentation to backups, each step is designed to make your homelab more resilient against cyberattacks.
It's important to remember that no system is 100% secure. However, by implementing these steps, you significantly reduce your attack surface, minimize the impact of a potential attack, and ensure your systems are continuously monitored. This diligence in exposing your homelab to the internet helps protect not only your own data but also the networks and other users connected to you. Security is not a product, but a mindset; it requires continuous attention and learning.
Top comments (0)