Skip to content
yisusvii
Go back

Security Checklist for Your Home Linux Workstation Exposed to the Internet

Suggest Changes

By

Table of Contents

Open Table of Contents

The trend: everyone has a mini server at home now

Raspberry Pi 5s, used ThinkCentre/OptiPlex mini PCs, Intel NUCs, even old laptops — a lot of us are running Ubuntu (or Debian) boxes at home and punching holes in the home router so we can reach them from anywhere. Self-hosted dashboards, code servers, Nextcloud, Immich, Home Assistant, a personal WireGuard VPN — the “home lab” has quietly become a real production environment.

The problem: the moment you forward a port or put that box on a public address, it stops being a toy. Shodan, Censys, and hundreds of botnets scan the entire IPv4 space continuously. An exposed SSH port gets its first brute-force probes within minutes of appearing online. Default passwords, password-based SSH, an open Docker daemon, or an unpatched kernel are all it takes for your “workspace” to become part of someone’s crypto-mining fleet — or a pivot point into your home network where your laptop, NAS, and cameras live.

So: how secure is it? As secure as your worst default. This post is the checklist I run on every home Linux machine before it touches the internet, plus a script that automates most of it.


✅ Security Checklist

1. User & permission hygiene

2. SSH lockdown (the #1 attack surface)

3. Firewall — default deny inbound

4. System & updates

5. Remote access beyond SSH

6. Monitoring & detection

7. The nuclear option: don’t expose anything

The most secure checklist is the one where no inbound port is open:

If you can use either, do. Everything below then protects you against your own network instead of the whole internet.


🤖 Hardening script

Script below automates: sudo user creation, SSH key-only auth with allowlist, ufw default-deny with explicit ports, fail2ban, and unattended security upgrades. Run it as root (or with sudo) on a fresh Ubuntu/Debian machine, from a local console or with a second session open — SSH changes can lock you out if your key isn’t in place.

#!/usr/bin/env bash
# home-harden.sh — baseline hardening for a home Linux box exposed to internet
# Usage: sudo ./home-harden.sh <username> "<ssh-public-key>"
set -euo pipefail

USER_NAME="${1:?usage: $0 <username> <ssh-public-key>}"
SSH_KEY="${2:?usage: $0 <username> <ssh-public-key>}"
SSH_PORT=22          # change if you want a non-default port
ALLOW_WEB=false      # set true to open 80/443

echo "==> System update"
apt-get update -y && apt-get upgrade -y
apt-get install -y ufw fail2ban unattended-upgrades openssh-server

echo "==> Create user: ${USER_NAME}"
if ! id "${USER_NAME}" &>/dev/null; then
  adduser --disabled-password --gecos "" "${USER_NAME}"
  usermod -aG sudo "${USER_NAME}"
fi

echo "==> Install SSH key, lock permissions"
USER_HOME=$(getent passwd "${USER_NAME}" | cut -d: -f6)
mkdir -p "${USER_HOME}/.ssh"
echo "${SSH_KEY}" >> "${USER_HOME}/.ssh/authorized_keys"
chmod 700 "${USER_HOME}/.ssh"
chmod 600 "${USER_HOME}/.ssh/authorized_keys"
chown -R "${USER_NAME}:${USER_NAME}" "${USER_HOME}/.ssh"
chmod 700 "${USER_HOME}"

echo "==> Harden sshd"
cat > /etc/ssh/sshd_config.d/99-hardening.conf <<EOF
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
AllowUsers ${USER_NAME}
MaxAuthTries 3
LoginGraceTime 20
X11Forwarding no
AllowTcpForwarding no
EOF
sshd -t   # validate config before restart — aborts on error

echo "==> Firewall: default deny inbound"
ufw --force reset
ufw default deny incoming
ufw default allow outgoing
ufw allow "${SSH_PORT}/tcp" comment 'SSH'
if [ "${ALLOW_WEB}" = true ]; then
  ufw allow 80/tcp comment 'HTTP'
  ufw allow 443/tcp comment 'HTTPS'
fi
ufw --force enable

echo "==> fail2ban for SSH"
cat > /etc/fail2ban/jail.local <<EOF
[sshd]
enabled  = true
port     = ${SSH_PORT}
maxretry = 3
bantime  = 1h
findtime = 10m
EOF
systemctl enable --now fail2ban

echo "==> Automatic security updates"
dpkg-reconfigure -f noninteractive unattended-upgrades

echo "==> Restart SSH"
systemctl restart ssh

echo
echo "DONE. Before closing this session, open a NEW terminal and verify:"
echo "  ssh -p ${SSH_PORT} ${USER_NAME}@<host>"
echo "If login works, you are safe to disconnect."

Verify afterwards

# from outside your network
nmap -sV <your.public.ip>
ssh -p 22 <user>@<your.public.ip>   # must work with your key, password must fail

Honest bottom line

A home server on the internet is fine if you treat it like the exposed asset it is: keys only, default-deny firewall, automatic patching, fail2ban, and ideally a VPN overlay so nothing is public at all. The checklist takes 20 minutes; the script takes 2. The botnets scanning your IP take 0 minutes to find you — don’t give them anything to work with.


Suggest Changes
Share this post on:


Previous Post
e2e: An Open-Source, Agent-Driven End-to-End Testing Framework for Web and Mobile
Next Post
Security Thursdays by yisusvii — 2026-10-01