Ubuntu Linux Cloud Install

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 less1
3 – 62
7 – 123
13 – 204


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

Scroll to Top