Best practices for hardening new sever in 2017

When setting up droplets on Digital Ocean it is encouraged to setup some basic security and monitoring. I have read around quite a lot recently on best practices for hardening a new Ubuntu server. Below are the steps I have compiled. Does the community have any suggestions for tweaks to this list including additions or removals?

  1. Create a non-root user [2, 3, 7, 8]
  2. Add non-root to the sudoers group [2, 3, 8]
  3. Add public ssh key to non-root user [1, 2, 3, 8]
  4. Deny all inbound traffic with ufw firewall [1, 3, 4, 7]
  5. Open required ports within the ufw firewall [1, 3, 4, 7]
  6. Update SSH config - Password-less logins [2, 3, 7, 8, 9]
  7. Update SSH config - Disable root login [2, 3, 5, 7, 8, 9]
  8. Update SSH config - Change ssh port [2, 3, 7, 8, 9]
  9. Unattended upgrades [3, 4, 6, 7]
  10. Postfix for emails [2, 3, 6]
  11. Logswatch to send daily summary emails [3]
  12. Fail2ban [2, 3, 7]
  13. Set the timezone to UTC and install NTP [2]
  14. Secure shared memory [5]
  15. Add a security login banner [[5]
  16. Harden the networking layer [5]
  17. Prevent IP spoofing [5]


1. Digital Ocean - 7 Security Measures to Protect your Servers

2. Digital Ocean - What do you do with your first five minutes on a new server

3. Securing a Server with Ansible

4. Ghost on Digitalocean 512MB

5. Tech Republic - How to harden ubuntu server 16-04 security in five step

6. How to configure Auto-Updates on Linux Ubuntu Servers

7. Linode - Securing your Server

8. Rackspace - Linux Server Security Best Practices

9. Best practices for SSH configuration

Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.


As a continuation of the previous response, there’s actually quite a bit more that can be done as far as SSH, such as tuning:




… beyond disabling password authentication and enforcing SSH Keys.

Generally what I recommend only enabling RSA and ED25519 Host Keys. By default, SSH will use all four keys – RSA, DSA, ED25119, and ECDSA. in sshd_config, you’ll see:

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

I’d recommend stripping away the DSA and ECDSA keys unless you know you’ll need them. With the lines removed, we’d only have two HostKey lines, like so:

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

Don’t restart SSH just yet.

You’d then want to regenerate the keys. In most cases, and I’m not 100% sure if this is the case with DigitalOcean (I’ve not asked), the same keys are used for every deployment since most cloud providers use the same image and don’t run a script to regenerate them. That means you could be using the same keys as another Droplet. Even if you’re not, I prefer to regenerate them on my own.

To regenerate, we can do something as simple as first removing the existing keys:

rm -v /etc/ssh/ssh_host_*

That’ll give you a verbose output and tell you what files were removed. We’re removing them all, and will regenerate them using:

ssh-keygen -q -N "" -C "" -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key


ssh-keygen -q -N "" -C "" -o -a 20000 -t ed25519 -f /etc/ssh/ssh_host_ed25519_key

Also, within sshd_config, it’s generally idea to specify MACs, Ciphers, and Kex algos. They aren’t set by default, but we can set them by adding:




We can also completely disable password authentication using both:

PasswordAuthentication no


ChallengeResponseAuthentication no

You can restart SSH now using service ssh restart.

Beyond the above, I would recommend looking at Lynis – an auditing tool. Some things you won’t be able to modify with DigitalOcean – the same or many cloud providers. Others are recommendations, while some are what I would call requirements. It’s pretty detailed.


On #8, that’s more security through obscurity (or by obscurity). It’s really simple to do a port scan that will provide an attacker with any/all open ports.

Even if you change the default SSH from port 22 to another, it wouldn’t take long for someone to use Kali Linux and locate which port is open (mentioning KL as it’s super-easy to setup). If someone has a tool locally, they don’t even need KL (KL just provides all the tools in one distro).

My recommendation would be to setup a VPN, white list the VPN IP (since it’s static) and only allow SSH connections from that IP (or X number of IP’s you require). With this type of setup, connections to the SSH port will be denied if they aren’t from the white listed IP(s).

While on the topic of SSH, I would recommend either a 4096 or 8192 bit key, if using RSA. Otherwise, use ED25519 keys. Either way, always use a passphrase and make sure you use a decent number of KDF rounds when creating the key.

For example, to generate a 4096 bit RSA key, we could use:

ssh-keygen -a 1000 -b 4096 -C "" -o -t rsa

-a specifies # of KDF rounds -b specifies the bit size for RSA keys -C removes the common comment at the end of the key -o specifies that we should use the new format provided by OpenSSH -t specifies the key type (RSA)

For an ED25519 key, we’d use:

ssh-keygen -a 1000 -C "" -o -t ed25519

ED25519 keys don’t accept (i.e. they ignore) the bit size, so we don’t need to pass that in as we do when generating an RSA key.

As for which is more secure – it all depends. The likelihood of someone breaking a 4096 bit RSA key with a decent passphrase is very very slim. The same for the ED25519 key above.

Just make sure you’re not using an insecure passphrase.

That said, I wouldn’t recommend going much higher than 1000 on the rounds as the above keys will take about 8-12 seconds to generate. The more rounds, the longer it’ll take – 20000 rounds took me about 3-5 minutes.

The time it takes to generate will also be the time it takes for you to login when passing your key to the ssh command. So the more KDF rounds, the longer it’ll take for you to authenticate.

On #15, unless you’re legally required to display some sort of legal message to those accessing your server(s), it does little more than throw a message when someone tries to login.

No attacker is going to read it if they are trying to connect manually – on remote or automated attacks, they’ll never even see it.

The rest of it is a pretty standard setup for a base installation. The next steps would be doing what is required for any/all applications that you host on the server.

I personally used this tutorial to harden my digitalocean droplet. It includes, Replacing Password Login With Authorized keys