When deploying a new Ubuntu server there are a few steps that should be taken in order to make sure it’s secure. This should provide a fairly secure default setup. However, as more software is added further measures will need to be taken in order to secure the server.
Page Nav
- Bare Metal Installations
- New User setup
- Setup Public Key Auth
- Disable Root login and remove Password Auth
- Basic UFW setup
- Setup Fail2Ban
- Setting up automatic updates
Bare Metal Installations
Note: It is now an option to install openssh during installation.
Originally I wrote this tutorial for setting up a new server on a cloud hosting provider. Those already come setup with an ssh server; but if you’ve downloaded your Ubuntu from the site and are setting it up on a bare metal server, it needs an extra step.
First, you’ll want to update the repo list
sudo apt update
Next install the openssh server.
sudo apt install -y openssh-server
Once it’s installed you can start the service.
sudo systemctl start sshd.service
# check the status
sudo systemctl status sshd.service
# it might need to be enabled
sudo systemctl enable sshd.service
After creating a new user and adding keys the sshd_config file should be modified to disable root login and password authentication.
sudo vi /etc/ssh/sshd_config
Note: If you are completing a bare metal install you can go ahead and skip over disabling the root user and creating another user as that’s already taken care during the install process.
New User setup
After initially launching a cloud server they have likely provided a root login. Go ahead and use it to log into your server.
ssh root@<ip address>
Create a new user, this will be used as the main login account and for system administration tasks.
useradd newuser
Be sure to set a strong password for the account.
passwd newuser
Later in this setup guide, I’ll go over how to setup public key authorization and disable password authentication.
Add Privileges
In this guide, I’m assuming this account should be designated to complete administrative tasks on the server. To do this add this user to the sudo group.
usermod -aG sudo newuser
Setup Public Key Auth
Next generate an SSH key that will be used for authentication into the server. This will allow password authentication to be disabled and make the server that much more secure.
To generate a key pair run the following command in terminal on your local machine:
ssh-keygen -t ed25519 -C "email@example.com"
Note: If you are using a machine that doesn’t support the Ed25519 algorithm. You can generate a key using the following:
ssh-keygen -t rsa -b 4096 -C "email@example.com"
Follow the next steps in setting up the key, setting the name, location, and a pass phrase as desired.
Next copy the public key to the new server. There are a couple ways to go about this. Using the ssh-copy-id command which is pretty straight forward, just enter:
ssh-copy-id newuser@<ip_address>
This will automatically copy your public key over, you can verify everything by check in the ~/.ssh/authorized_keys
file on the server.
It’s also possible to copy it manually. To do this first copy the contents of the public key file from your local machine. This can be found in the ~/.ssh folder, you’ll want to get the contents of the id_ed25519.pub file. Once you have that in the clipboard create the ~/.ssh/authorized_keys on the server (under the newuser home) and paste the contents in there.
Next check the permissions on the ~/.ssh directory
, they should be 700. They can be changed with the following command:
chmod 700 ~/.ssh
The authorized_keys file permissions should be 600, set those with the following command:
chmod 600 ~/.ssh/authorized_keys
Before proceeding to the next step. Make sure you can login using the newly created user. Make sure it uses the private key for authentication.
ssh newuser@<ip address>
Disable Root login and remove Password Auth
Now that we have all that setup the next step is to remove the root login and to disable password auth. To do this you’ll have to the sshd_config file. Fire up your favorite terminal text editor and let’s go.
vi /etc/ssh/sshd_config
You might have to search through the file but make sure the following get changed or are set to:
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
PermitRootLogin no
After you’re finished editing that file, the ssh daemon needs to be reloaded for those changes to take effect.
systemctl reload sshd.service
Finally test to make sure that your login works.
Basic UFW setup
To add a little bit more security let’s enable the uncomplicated firewall (UFW). We’ll assume that we’re in our ’newuser’ account for this. The first step is to allow ssh:
sudo ufw allow OpenSSH
Note: this also assumes that we’re using the default ssh port (unless you have changed this in the sshd_config you’ll be on the default port).
Next we can enable the firewall:
sudo ufw enable
Next you’ll want to view other applications on your server and allow them as necessary:
sudo ufw app list
If you have other services that should be publicly available you’ll want to enable those too. But for purposes of this guide I’m just going to show enabling SSH.
Setup Fail2Ban
In order to further protect the new server install Fail2Ban. This will help to find and block malicious login attempts. It does this by monitoring the auth log for failed login attempts, since most password based authentication should be accomplished in 3 or less attempts and ssh key auth should be able to sign in with 1 attempt. It can be assumed that anything more is malicious poking at the server and therefore can be blocked.
Installation, is straight forward:
apt install fail2ban
Next up is to create a local jail file in the following location: /etc/fail2ban/jail.local
This is my default setup, I put max retry to 1 since I have public key auth setup, I shouldn’t fail but if I do I have my ip in the ignore ip list just in case.
[DEFAULT]
bantime = 7200m
findtime = 2880m
maxretry = 2
ignoreip = 127.0.0.1/8 1.1.1.1
[sshd]
enabled = true
maxretry = 1
[ssh]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 1
Setting up a new apt repo
On a fresh install you may want to add additional repositories, in this case you may find this error message:
sudo: add-apt-repository: command not found
What a bummer…don’t worry though, all you need to do is install the software-properties-common package:
Starting in Ubuntu 20.04
sudo apt-get install software-properties-common
For older versions
sudo apt-get install software-properties-common \
python-software-properties
Once this is installed you can go ahead add the new repo, run an apt-get update and finally install your new package.
Setting up automatic updates (optional)
Keeping the system up to date can be a chore, this could be especially troublesome if you have anything else come up and you can’t get to this in a timely manner. Not to worry, you can set the system to apply security updates regularly.
First update the package list.
sudo apt update
Install Unattended Upgrades package
sudo apt install unattended-upgrades
Next enable and start the service.
sudo systemctl enable unattended-upgrades
sudo systemctl start unattended-upgrades
Enable security update by editing /etc/apt/apt.conf.d/50unattended-upgrades
. Make sure the lines with security are uncommented (//).
Unattended-Upgrade::Origins-Pattern {
// Codename based matching:
// This will follow the migration of a release through different
// archives (e.g. from testing to stable and later oldstable).
// Software will be the latest available for the named release,
// but the Debian release itself will not be automatically upgraded.
// "origin=Debian,codename=${distro_codename}-updates";
// "origin=Debian,codename=${distro_codename}-proposed-updates";
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
// Archive or Suite based matching:
// Note that this will silently match a different release after
// migration to the specified archive (e.g. testing becomes the
// new stable).
// "o=Debian,a=stable";
// "o=Debian,a=stable-updates";
// "o=Debian,a=proposed-updates";
// "o=Debian Backports,a=${distro_codename}-backports,l=Debian Backports";
};
It’s also possible to remove unused kernels and related packages along with other dependencies. I personally prefer to remove these manually but here are the settings to adjust.
// Remove unused automatically installed kernel-related packages
// (kernel images, kernel headers and kernel version locked tools).
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
// Do automatic removal of newly unused dependencies after the upgrade
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
// Do automatic removal of unused packages after the upgrade
// (equivalent to apt-get autoremove)
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Rebooting the system. If a kernel update was applied the system will need to reboot for it to be fully patched. I like to set it to reboot at a particular time when the system will be least likely in use.
// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
// Default: "now"
Unattended-Upgrade::Automatic-Reboot-Time "02:00";
Enabling unattended upgrades, run the following command to finish enabling. You will see a prompt with some text and the following question “Automatically download and install stable updates?”; select “Yes”. This will update the /etc/apt/apt.conf.d/20auto-upgrades
file with the appropriate settings based on the previous config adjustments.
sudo dpkg-reconfigure --priority=low unattended-upgrades
Run the same command again and this time select “No” to disable unattended upgrades.
Final Note
I just wanted to note, this isn’t an all encompassing guide but rather a quick starting point to make a brand new server a little bit more secure from all the evil out there in the big wide world. I hope you found this little tutorial helpful. If you happened to find an error or feel that I’ve missed something important, please contact me so I can fix it, I’ll add a link to you as a contributor as a sign of appreciation.