After deploying a new Ubuntu Linux server on Digital Ocean or Linode, there are a few customization steps I take to improve usability and security of the server. These instructions are assuming you’ve install Ubuntu Linux 20.04 LTS.
Set Hostname
hostnamectl set-hostname domain.tld
Rebuild Hosts File
shortname=$(hostname | cut -d"." -f1) defaultdev=$(ip ro ls|grep default|awk '{print $5}') primaryaddr=$(ip -f inet addr show dev "$defaultdev" | grep 'inet ' | awk '{print $2}' | cut -d"/" -f1 | cut -f1) cp /etc/hosts /etc/hosts.old printf "%s\\t%s\\n" "127.0.0.1" "localhost" > /etc/hosts printf "%s\\t%s\\t%s\\n" "$primaryaddr" "$(hostname)" "$shortname" >> /etc/hosts cat /etc/hosts
Check the output at the end of the command to make sure the hosts file looks similar to this
127.0.0.1 localhost 192.168.1.100 domain.tld domain
Update Package Repository
apt update
Install Strong Entropy
apt -y install haveged pollinate
Schedule re-seeding random number generator at boot
(crontab -l ; echo "@reboot sleep 60 ; /usr/bin/pollinate -r" )| crontab -
SSH Server Hardening
Backup SSH Server Config files
cp /etc/ssh/sshd_config /etc/ssh/backup.sshd_config cp /etc/ssh/moduli /etc/ssh/backup.moduli
Security Changes to sshd_conf
sed -i '/X11Forwarding/c\X11Forwarding no' /etc/ssh/sshd_config sed -i 's/^#HostKey \/etc\/ssh\/ssh_host_\(rsa\|ed25519\)_key$/\HostKey \/etc\/ssh\/ssh_host_\1_key/g' /etc/ssh/sshd_config sed -i 's/^HostKey \/etc\/ssh\/ssh_host_\(dsa\|ecdsa\)_key$/\#HostKey \/etc\/ssh\/ssh_host_\1_key/g' /etc/ssh/sshd_config echo -e "\n# Restrict key exchange, cipher, and MAC algorithms\nKexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256\nCiphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr\nMACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com\nHostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com" > /etc/ssh/sshd_config.d/ssh-audit_hardening.conf
Remove small Diffie-Hellman moduli
awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.safe mv /etc/ssh/moduli.safe /etc/ssh/moduli
Regenerate SSH Server Keys
rm /etc/ssh/ssh_host_* ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N "" ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
Restart OpenSSH server
service ssh restart
Generate New Root SSH Keys
rm ~/.ssh/id_rsa -f ~/.ssh/id_ed25519 ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N "" ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
Swap File
If on Azure, see the instruction below for Swap File on Azure.
If a swap partition was not created by the deployment, create one based on the amount of RAM installed.
Installed RAM (GB) | Swap File (GB) |
---|---|
2 or less | 1 |
3 – 6 | 2 |
7 – 12 | 3 |
13 – 20 | 4 |
Create swap file (example for 1GB swap file)
fallocate -l 1G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Swap File on Azure
The Azure WALinuxAgent will automatically create a swap file on the resource (temporary) drive.
cp /etc/waagent.conf /etc/waagent.conf.save sed -i '/ResourceDisk.Format/c\ResourceDisk.Format=y' /etc/waagent.conf sed -i '/ResourceDisk.EnableSwap/c\ResourceDisk.EnableSwap=y' /etc/waagent.conf sed -i '/ResourceDisk.SwapSizeMB/c\ResourceDisk.SwapSizeMB=4096' /etc/waagent.conf service walinuxagent restart
Create Linux Update Scripts
cat > /usr/local/bin/linux-update << EOF apt-get -y autoremove --purge sync apt-get clean apt-get autoclean apt update apt -y full-upgrade sync update-grub echo "Press Enter to reboot or Ctrl-C to abort..." read aa sync reboot EOF cat > /usr/local/bin/linux-cleanup << EOF apt-get -y autoremove --purge sync update-grub EOF chmod +rx /usr/local/bin/linux-update /usr/local/bin/linux-cleanup
Install Various Useful Packages
apt -y install apport apt-transport-https aptitude at build-essential byobu command-not-found curl dnsutils ethtool git htop man ntpdate patch psmisc screen software-properties-common sosreport update-motd update-notifier-common vim zip unzip
Harden IPv4 Network
cat > /etc/sysctl.conf <<EOF # IP Spoofing protection net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Ignore ICMP broadcast requests net.ipv4.icmp_echo_ignore_broadcasts = 1 # Disable source packet routing net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 # Ignore send redirects net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 # Block SYN attacks net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 2048 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 5 # Log Martians net.ipv4.conf.all.log_martians = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 # Ignore ICMP redirects net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.default.secure_redirects = 0 EOF
If you are not using IPv6, disable it
cat >> /etc/sysctl.conf <<EOF # Disable IPv6 net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 EOF
Restrict Root Login to Console
cp /etc/securetty /etc/securetty.old cat > /etc/securetty <<EOF console tty1 tty2 tty3 tty4 tty5 tty6 EOF
Configure Time Services
Set Local Time Zone
dpkg-reconfigure tzdata
Define Time Servers
sed -i '/^#NTP=/c\NTP=time.google.com' /etc/systemd/timesyncd.conf
Restart Time Sync
systemctl restart systemd-timesyncd ntpdate -u time.google.com
Journal Log Cleanup
(crontab -l ; echo "@daily journalctl --vacuum-time=30d --vacuum-size=1G" )| crontab -
Unattended Security Updates
Install unattended-upgrades package
apt install unattended-upgrades
Enable automatic upgrades
echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections dpkg-reconfigure -f noninteractive unattended-upgrades
Configure apt options
cat > /etc/apt/apt.conf.d/10periodic <<EOF APT::Periodic::Download-Upgradeable-Packages "1"; APT::Periodic::AutocleanInterval "1"; EOF
Configure only security updates and reboot time (2:00am)
cat > /etc/apt/apt.conf.d/50unattended-upgrades <<EOF Unattended-Upgrade::Allowed-Origins { "\${distro_id}:\${distro_codename}"; "\${distro_id}:\${distro_codename}-security"; "\${distro_id}ESM:\${distro_codename}"; }; Unattended-Upgrade::Package-Blacklist { }; Unattended-Upgrade::Automatic-Reboot "true"; Unattended-Upgrade::Automatic-Reboot-Time "02:00"; EOF
Configure Download Timer Service
rm -rf /etc/systemd/system/apt-daily.timer* cat > /etc/systemd/system/apt-daily.timer <<EOF [Unit] Description=Daily apt download activities [Timer] OnCalendar=*-*-* 6,18:00 RandomizedDelaySec=6h Persistent=true [Install] WantedBy=timers.target EOF rm -rf /etc/systemd/system/apt-daily-upgrade.timer* cat > /etc/systemd/system/apt-daily-upgrade.timer <<EOF Description=Daily apt upgrade and clean activities After=apt-daily.timer [Timer] OnCalendar=*-*-* 0:25 RandomizedDelaySec=30m Persistent=true [Install] WantedBy=timers.target EOF systemctl daemon-reload
Update to Latest Linux Kernel
Install new Kernel
apt -y install --install-recommends linux-virtual-hwe-20.04
reboot and reconnect with putty as root user
reboot
Remove old kernel packages and dependencies
apt-get -y autoremove ; apt -y purge linux-generic linux-headers-generic linux-image-generic linux-virtual linux-headers-virtual linux-image-virtual
Make sure all Linux packages are up-to-date and reboot when prompted
linux-update
Suggested Next Steps
- Emerging Threats and Geo-Protection (Ubuntu)
- Virtualmin LAMP Server or Virtualmin LEMP Server
- Webmin System Administration Console