sysadmin checklist

disclaimer

just a personal checklist for "good enough" security on a new box, not a full hardening guide.

checklist

  • system update
  • install docker
  • virtual memory overcommit
  • firewall
  • ssh config
  • nonroot user
  • fail2ban
  • secure shared memory
  • disable root login
  • tailscale

system update

apt update -y
apt upgrade -y
apt install -y vim curl htop

# Configure 'needrestart' for auto-restart of services after upgrades
sed -i "/#\$nrconf{restart} = 'i';/s/.*/\$nrconf{restart} = 'a';/" /etc/needrestart/needrestart.conf
sed -i "s/#\$nrconf{kernelhints} = -1;/\$nrconf{kernelhints} = -1;/g" /etc/needrestart/needrestart.conf

install docker

# Update package list and install prerequisites
apt update -y
apt install -y ca-certificates curl gnupg

# Add Docker's official GPG key and set up repository
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker and Docker Compose plugins
apt update -y
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

virtual memory overcommit

sysctl vm.overcommit_memory=1
echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf

firewall


# Allow essential traffic for SSH, HTTP, and HTTPS
ufw allow ssh
ufw allow http
ufw allow https

# Uncomment to allow Redis and PostgreSQL traffic if needed
# ufw allow redis
# ufw allow postgres

# Enable UFW
ufw enable

ssh config

# Enable public key authentication, disable password-based login, and enforce other security settings
sed -i -e '/^\(#\|\)PasswordAuthentication/s/^.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i -e '/^\(#\|\)PubkeyAuthentication/s/^.*$/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i -e '/^\(#\|\)PermitEmptyPasswords/s/^.*$/PermitEmptyPasswords no/' /etc/ssh/sshd_config
if ! grep -q "^ChallengeResponseAuthentication" /etc/ssh/sshd_config; then
    echo 'ChallengeResponseAuthentication no' >> /etc/ssh/sshd_config
else
    sed -i -e '/^\(#\|\)ChallengeResponseAuthentication/s/^.*$/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config
fi

# Reload SSH service to apply configuration changes
echo 'Reloading ssh agent'
systemctl reload ssh

nonroot user

# Create a non-root user with sudo access
echo "Setup non-root user"
adduser --disabled-password --gecos "" nonroot
echo "nonroot ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers

# Configure SSH key authentication for the new user
AUTHORIZED_KEYS=$(cat ~/.ssh/authorized_keys)
sudo -H -u nonroot bash -c '
mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
'
sudo -H -u nonroot bash -c "echo '$AUTHORIZED_KEYS' >> ~/.ssh/authorized_keys"

# Add new user to Docker group
usermod -aG docker nonroot

fail2ban

# Install fail2ban to protect against brute-force attacks
echo "Setup fail2ban"
apt install -y fail2ban

# Configure fail2ban settings for SSH
cat <<EOF > /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
filter = sshd
maxretry = 5
findtime = 600
bantime = 600
ignoreip = 127.0.0.1/8
logpath = /var/log/auth.log
EOF

# Restart fail2ban to apply configuration
systemctl restart fail2ban

secure shared memory

echo "Secure shared memory"
echo "tmpfs /run/shm tmpfs defaults,noexec,nosuid 0 0" >> /etc/fstab

disable root login

before disabling root login, copy your ssh pubkey from your workstation to the remote host, to not be locked out after next step :

ssh-copy-id -i ~/.ssh/id_rsa.pub root@remote
# Disable root login over SSH
echo "Disable root user login"
sed -i -e '/^\(#\|\)PermitRootLogin/s/^.*$/PermitRootLogin no/' /etc/ssh/sshd_config

# Reload SSH to apply root login restrictions
systemctl reload ssh