Skip to main content

How to Build a Secure, Minimized Ubuntu Server for Homelabs

· By Pankajbhai Chavda · 4 min read

If you are spinning up a new Proxmox VM or bare-metal Docker host, clicking "Next" through the default Ubuntu Server installer is a mistake. You end up with a bloated system full of packages you will never use.

Igor's LAB experts say that, if you want a lean, efficient homelab, you need to be doing an Ubuntu Server Minimized install. In this process we remove documentation, human-friendly utilities, and arbitrary localization files. So you are left with a lightweight operating system that is best for running containers and services. It eats less RAM, has a smaller attack surface, and runs apt upgrade in seconds.

But just installing it is not enough. Today, I am walking you through my exact playbook for installing and hardening a minimized Ubuntu server. In this installation we also cover a massive SSH trap in modern Ubuntu that catches almost everyone off guard. So let's build a server that's lean, mean, and secure.

The Installation

Boot up your standard Ubuntu Server ISO. You don't need a special download for this — "Minimized" is just an option in the regular installer.

Network Setup: Don't leave this on DHCP. Select your interface, go to IPv4 -> Manual, and set a static IP.

The Golden Toggle: When it asks for your base system, switch it from the standard server to "Ubuntu Server minimized".

Storage: If you don't know logical volumes, then uncheck "Set up this disk as an LVM group." A standard ext4 partition is faster and much easier to recover if your homelab crashes.

SSH: Check the box to "Install OpenSSH server" so we can remote in later.

Snaps: We want to install Docker natively, not as a Snap package, to avoid weird networking conflicts.

Reboot the machine, pull the ISO, and log in.

The Post-Install Hardening Playbook

A fresh new install is basically always insecure against attacks. So we are going to lock this down right now.

Automate the Boring Stuff

First, update the system and make sure security patches install themselves so you don't need to always watch.

sudo apt update && sudo apt upgrade -y
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

Hit "Yes" when prompted, as shown in the screenshot.

select yes when configuring unattended upgrades option open.

The Great SSH Trap

We need to disable password logins and change the default SSH port. But first, from your local desktop (not the server), push your Ed25519 SSH key to the new server so you don't lock yourself out.

ssh-copy-id username@your_server_ip

Now, back on the server, let's write a strict SSH config.

sudo nano /etc/ssh/sshd_config.d/99-custom.conf

Paste the code below into your file. I am using port 2222, but you can pick whatever you like.

Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Note: If you are on Ubuntu 24.04 or 26.04, simply restarting SSH right now will do absolutely nothing. Modern Ubuntu uses systemd socket activation for SSH, which aggressively binds to port 22 and ignores your custom config. You will just get a "Connection refused" error when you try to log in.

To apply your custom port, you have to kill the socket and switch back to the classic SSH service.

sudo systemctl disable --now ssh.socket
sudo systemctl enable --now ssh.service
sudo systemctl restart ssh

Important: Do not close your current terminal window yet! Open a new tab on your local machine and test the new connection using ssh -p 2222 username@your_server_ip to make sure it works first.

Slam the Door with UFW

Let's enforce a default-deny rule, making sure to allow our new SSH port first.

Note: Be sure to change 2222 in your command below; use the port you chose in your SSH config file, otherwise UFW will block your connection.

sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp 
sudo ufw enable

Fix Your Fail2Ban Setup

Most tutorials tell you to edit jail.local. But don't do this — it gets messy. Use the jail.d directory.

Also, Ubuntu uses systemd for its logging, so Fail2Ban won't actually be able to read your SSH logs unless you install the Python systemd backend.

sudo apt install fail2ban python3-systemd -y
sudo nano /etc/fail2ban/jail.d/99-custom.local

Add this block so it monitors your custom port using the correct backend.

[sshd]
enabled = true
port = 2222
filter = sshd
backend = systemd
maxretry = 3
findtime = 600
bantime = 3600

Enable it and start it up:

sudo systemctl enable fail2ban
sudo systemctl restart fail2ban

Expected Output:

enable and restart fail2ban service.

Kernel Lockdown

Finally, let's tweak the kernel to ignore ping floods, block spoofing, and disable IPv6.

sudo nano /etc/sysctl.d/99-security.conf

Paste this block into the file.

net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

To apply it live, run the command below.

sudo sysctl -p /etc/sysctl.d/99-security.conf

Expected Output:

security confige file

Wrapping Up

That’s it. You now have a hyper-efficient, minimized server that’s practically bulletproof against basic attacks. Your RAM usage will stay flat, and bots won't be able to brute-force your standard SSH port.

About the author

Pankajbhai Chavda Pankajbhai Chavda
Updated on Aug 13, 2026
-