Skip to content
All posts

DevOps4 min read

Bare Metal Linux Server Configuration

This guide walks through the initial setup of a fresh Linux Server.

Isaac Hatilima

Full-stack and DevOps engineer

An engineer at a terminal setting up a rack of bare-metal servers, with a firewall, a network switch, and icons for security, SSH keys and configuration.

πŸ—οΈ Server Setup Guide

This guide walks through the initial setup of a fresh Linux Debian server.
It’s a practical, solid baseline focused on security, usability, and keeping things predictable from day one.

The examples assume a Hetzner server, but the steps apply to most VPS or dedicated setups.

Booting Into Rescue Mode

Start by booting the server into Hetzner Rescue Mode from the control panel.

Once connected, run:

bash
installimage

Follow the installer prompts:

  • Set the hostname to whatever you prefer
  • When prompted, press 2 to save the configuration
  • Press 10 to quit and continue

After the installation finishes, reboot the server and SSH into it normally.

πŸ”„ System Updates and Timezone Configuration

Before doing anything else, bring the system up to date.

Update system packages

bash
apt update && apt upgrade -y && apt autoremove -y

Set timezone, lets assume you are in Berlin

bash
timedatectl set-timezone Europe/Berlin

Install basic utilities

bash
apt install curl wget git htop unzip fail2ban libguestfs-tools -y

These cover most day-to-day needs and basic monitoring.

πŸ‘€ Creating a Non-Root User

Set a password for the root user, it is advisable to use a none root user for day to day operations.

Then create a regular user and grant sudo access:

bash
adduser <username>usermod -aG sudo <username>

πŸ”‘ Configuring SSH Access

Switch to the newly created user and set up SSH keys:

bash
su - <username>mkdir -p ~/.sshchmod 700 ~/.sshnano ~/.ssh/authorized_keyschmod 600 ~/.ssh/authorized_keys

At this point, paste your public SSH key into authorized_keys. From here on, you should work as this user instead of root whenever possible.

πŸ”’ Hardening SSH

Edit the SSH daemon configuration:

bash
nano /etc/ssh/sshd_config

Using a non-default port is optional, but it does reduce noise from automated scans. Recommended changes:

bash
Port <NEW-SSH-PORT>PermitRootLogin prohibit-passwordPasswordAuthentication noPermitEmptyPasswords noUsePAM yesX11Forwarding no

Restart SSH to apply changes:

bash
systemctl restart sshd

Important: Make sure you can log in with your SSH key before closing your current session.

πŸ”₯ Firewall Configuration

Install persistent firewall rules, with 123 being port set above:

IPv4 rules

bash
iptables -A INPUT -i lo -j ACCEPTiptables -A INPUT -p tcp --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPTiptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTiptables -A INPUT -p icmp -j ACCEPTiptables -P INPUT DROPiptables -P FORWARD ACCEPTiptables -P OUTPUT ACCEPT

IPv6 rules

bash
ip6tables -A INPUT -i lo -j ACCEPTip6tables -A INPUT -p tcp --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPTip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPTip6tables -A INPUT -p icmpv6 -j ACCEPTip6tables -P INPUT DROPip6tables -P FORWARD ACCEPTip6tables -P OUTPUT ACCEPT

Save and verify the rules:

bash
netfilter-persistent saveiptables -L -v -nip6tables -L -v -n

πŸ” Final Reboot

Once everything is in place, reboot the server:

bash
reboot

After reboot, reconnect using your new SSH user and port.

βœ… What You Have Now

At this point, the server has:

  • Updated system packages
  • A non-root sudo user
  • SSH key-only access
  • Reduced SSH attack surface
  • Basic firewall rules
  • A clean, predictable baseline

From here, you can safely move on to installing Docker, Proxmox, Kubernetes, or whatever stack you need next.

Written by Isaac Hatilima

I build and run products across web, mobile and infrastructure.

More about me

Planning a release like this?

Tell me what you are working on. We’ll agree on the scope, and I’ll build it and keep it running.

Book a call