Will be looking into the essentials of securing a Linux server as part of my daily write-up of creating a Newsletter Service for Engineers.
I wanted to get set up the Infrastructure first before having a working building pipeline instead of rushing my way through in the end trying to get the server up and running quickly.
I'm using Digitial Ocean's droplet running Ubuntu 22.04(LTS) here but any other Linux VPS can also be used from any provider. Just make sure you have all the privileges and you may have to do some tweaks in the commands depending on your system
Connect to the instance
You will be most likely connecting as the root user for the first time. If you have specified your password when creating a VPS then use it to SSH or add SSH key pair (recommend)
Let's get all packages updated and avoid any vulnerabilities and pending patches.
//Ubuntu apt update && apt upgrade // CentOS/RHEL Stream and Fedora dnf upgrade //Alpine apk update && apk upgrade //Arch Linux pacman -Syu //CentOS 7 yum update //OpenSuse zypper update
Adding a limited user account
root user has unlimited privileges on the system and we should not be using it for day-to-day operations. Using a limited user account also prevents us from accidentally breaking our system.
adduser johndoe // CentOs / Fedora useradd example_user && passwd example_user
Some of the tasks would still require administrative privileges which we will perform with the help of
sudo granting us elevated privileges temporarily
adduser john_doe sudo // CentOS / Fedora usermod -aG wheel example_user
Now we can exit from the instance and re-login from the limited user account
> exit > ssh email@example.com
A nice part of having sudo is that it also logs all the commands performed by users.
Hardening SSH Access
The essentials of hardening your SSH server are
Using ssh-key pair for authentication
sshconfig on server
Using SSH Key Pairs for authentication
SSH key pairs are secure keys cryptographically generated that help authenticate and identify a unique user. They are harder to replicate and you don't have to remember the credentials unlike your passwords
Creating a key pair
We need to generate our key pair (public and private). Most Linux systems already come with the handle utility
ssh-keygen to create a key pair.
We will generate a 4096-bit RSA key pair. You can also generate using a different algorithm for encrypting. While creating a key-pair you will be asked to enter a passphrase, you can also skip this step but it's recommended to use a passphrase. A passphrase ensures the private key can't be decrypted without it and hence nobody else can use your private key if in the worse it gets leaked.
If you already have a generated a SSH Key pair, this command will overwrite it
ssh-keygen -b 4096
Upload the public key
We have to add our public in
~/.ssh/authorized_keys on our server, otherwise, it won't accept any request from any unknown user.
ssh-copy-id firstname.lastname@example.org // Using scp to copy the file > mkdir -p ~/.ssh && sudo chmod -R 700 ~/.ssh/ > scp ~/.ssh/id_rsa.pub email@example.com:~/.ssh/authorized_keys
Finally, you would want to restrict access to your SSH keys if you have multiple users on the server
sudo chmod -R 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
Now when you exit and log back into the server it will automatically log in or ask for your passphrase if you haven't opted to save it in the keychain
Restricted SSH config
Open the ssh daemon config in an editor on your server
sudo nano /etc/ssh/sshd_config
Disallow root logins over SSH
Since we have created a limited user account we don't need root access over SSH anymore.
sudoprovides us access to almost all operations. But incase if we ever need to log-in as a
rootmost VPS provider have a recovery console on the browser which basically is like physically connecting to the instance. If you don't have a recoverly console option you can also skip this step
# Authentication: ... PermitRootLogin no
Disable SSH password authentication
We don't need password authentication anymore and disabling password authentication ensures nobody can attempt to log in or bruteforce into our SSH
SSH key pair identiy are limited to every system. If you use multiple devices to log-in it's better to add those SSH key pairs in the authorised keys before performing this step or you can also skip this step
# Change to no to disable tunnelled clear text passwords PasswordAuthentication no
Disable additional protocol
By default, the ssh daemon listens to both
IPv6. If you only use one which is usually
IPv4 we can update the config to disable accepting connections from
It only affects the SSH dameon otherwise services will still be accessible over both protocols
# Port 22 AddressFamily inet
Changing the SSH port
Additionally, you can also update the ssh daemon to listen to a different port instead of
22 by default. I tend to leave it because the server will be secure enough till the end and usually you can use port scanning utilities to identify open ports anyway
# Port 22 AddressFamily inet
Restart the SSH service
// Systemmd (Ubuntu, Debian, CentOS, Fedora) sudo systemctl restart sshd // SystemV sudo service sshd restart
Configure a Firewall
I prefer to restrict the use of a Firewall provided by the VPS provider which usually has a UI to update the Firewall config on the fly from the dashboard. It allows me to restrict SSH or certain other services ;
Postgres Database from my IP address. Since I also own and host VPN to connect to the instance the IPs don't change but in-case if I ever have to add additional IP, it's easier to log in to the dashboard and update the firewall settings.
Additional things you can do
Add a custom hostname
The compute instance usually has a specific purpose or domain that represents it and it would be better when we log in and see that in the terminal instead of localhost
hostnamectl set-hostname engg-updates
So now when you log you will see the following in the terminal
Add a custom timezone
Most of us would prefer the server running in our timezone which will also help in debugging something easily
timedatectlmay not be available in all distributions. So look for alternatives for updating the time-zones
timedatectl list-timezones | grep 'America' timedatectl set-timezone 'America/New_York'
Lastly, these are just the most basic steps to secure any Linux server. Additional security layers depend on the intended use and you may need to use a monitoring system, access control, fine-tune sudo, restrict exposed services and more