DB-유

Initial Server Setup on Ubuntu 20.04

· linux, ubuntu, security

20.04 has been out long enough for the first point release, so it's my default for new servers now. It brings OpenSSH 8.2, Python 3.8 and kernel 5.4 with WireGuard built in; ufw, netplan and systemd-timesyncd behave as on 18.04. My checklist barely changed, but I rewrote it anyway because I kept looking up the SSH option names.

Here it is: sudo user, key-only SSH, firewall, hostname and time, automatic security updates, and a few extras I now do on every box. You need a fresh 20.04 server with root access and an SSH key on your workstation (ssh-keygen -t ed25519 if you don't have one).

Update first

apt update && apt full-upgrade -y
apt install -y vim curl htop net-tools
[ -f /var/run/reboot-required ] && reboot

Admin user

adduser deploy
usermod -aG sudo deploy

While still root, copy your key to the new user rather than typing it in:

rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy

That preserves the 700/600 permissions and sets ownership in one step. It assumes root's authorized_keys already holds your key, which is how most cloud providers provision the image.

SSH hardening

Edit /etc/ssh/sshd_config:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2

On OpenSSH 8.2 ChallengeResponseAuthentication still works but KbdInteractiveAuthentication is the current name. Also note that 20.04's OpenSSH refuses ssh-rsa signatures using SHA-1 by default in newer builds, so very old clients with RSA keys may need updating; ed25519 keys sidestep the issue.

sshd -t && systemctl restart ssh

Confirm ssh deploy@203.0.113.60 works in a new window before closing the root session.

Firewall

ufw allow OpenSSH
ufw enable
ufw status verbose

Hostname and time

hostnamectl set-hostname app02.example.com
echo "127.0.1.1 app02.example.com app02" >> /etc/hosts
timedatectl set-timezone Europe/Berlin
timedatectl

systemd-timesyncd is active by default; timedatectl should report System clock synchronized: yes. timedatectl timesync-status (new since 18.04) shows the server it is using and the current offset.

Unattended security updates

apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades

Then in /etc/apt/apt.conf.d/50unattended-upgrades, uncomment and set:

Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Mail "admin@example.com";

I leave automatic reboots off on servers and schedule them myself; /var/run/reboot-required and the Mail option tell me when one is due. A surprise reboot at the wrong moment is worse than a delayed patch.

Small extras

Swap is not created by most cloud images; a small swap file keeps the OOM killer at bay on a 1 GB instance:

fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
sysctl vm.swappiness=10
echo 'vm.swappiness=10' > /etc/sysctl.d/99-swappiness.conf

Snap is preinstalled and lxd is often seeded as a snap you will never use. If the host will not use snaps, snap list and remove what is there; otherwise leave it.

Final check

sudo -v
sudo ufw status
sudo sshd -T | grep -iE 'permitrootlogin|passwordauthentication|kbdinteractive'
timedatectl | grep -E 'Time zone|synchronized'
swapon --show

From your workstation, ssh root@203.0.113.60 should return Permission denied (publickey).

Notes

  • sign_and_send_pubkey: no mutual signature supported when connecting from an older workstation. The client is offering an RSA key with SHA-1 and the server refuses. Update the client's OpenSSH or generate an ed25519 key.
  • sudo: unable to resolve host app02.example.com: Name or service not known. The /etc/hosts line from the hostname section is missing.
  • ufw enable prints ERROR: problem running ufw-init . Usually a leftover iptables rule from a provider agent or Docker. ufw disable, iptables -F, and ufw enable again resolves it on a fresh host.
  • fallocate: fallocate failed: Operation not supported on some filesystems. Use dd if=/dev/zero of=/swapfile bs=1M count=1024 instead, then continue with chmod, mkswap and swapon.

Under twenty minutes, and later posts on a "fresh Ubuntu 20.04 server" assume this baseline.