Ubuntu VPS Setup Guide

Setting up your Ubuntu server · VPS Management

This is an overview of how to setup your Ubuntu virtual private server.

Accessing Your VPS

After creating a VPS instance (e.g. DigitalOcean droplet or Linode linode), you will be provided an IP address as well as login password. Use the credentials to log into the server.


Tips regarding authentication (explained further in SSH Lockdown below)

  • SSH login via root should be disabled
  • Only use ssh key authentication
  • Use a non-common port for ssh

Managing Users

By default, only one user exists: root - a superuser

Creating a new user

Create a new user to avoid using root and it's elevated privileges. While creating a new user, several questions will be asked. You can add additional information about the user but note that only the password is essential.( Press ENTER to skip the rest)

adduser demouser

# you can now give the user access to root privileges (sudo) 

gpasswd -a demouser sudo

Confirm that you can login as this new user before proceeding.

ssh newuser@SERVER_IP

sudo su - # try to access root as user

SSH Lockdown

Disabling root login

Before disabling root login, ensure that you've created a user that can SSH to the server (as explained in User Management above). The user can use the su command to become root (will need root password), or if the user has sudo they can just sudo su - to access root.

Edit /etc/ssh/sshd_config and turn PermitRootLogin to no. Use a different editor if new to vi (ZZ to exit).

Before doing this, ensure that you can login with another (non-root) user account (see User Management above).

sudo vi /etc/ssh/ssh_config

# Change the following line

PermitRootLogin yes
# to

PermitRootLogin no

Restart ssh service for this change to effect.

sudo service sshd restart
SSH Key-Based Authentication

You can now setup public key authentication (recommended). This will enable you to securely login to the server without having to enter your password.

Read how to do this

Public Key Authentication

Public Key authentication enables you to login to a server using ssh public key. This is my recommended method of authentication.

SSH Keys come in a pair; a private and public key.

Generate Key Pair

OpenSSH client is required, this is most likely already installed. You can install it with sudo apt-get -y install openssh-client

Use the following commands to have the key pair generated; accept the defaults by just pressing Enter. You can leave the password empty (optional). You should use existing keys if you already have them.


# alternatively you can use this command to generate a stronger key pair, and tag the keys

ssh-keygen -t rsa -b 4096 -C "Email OR Comment describing key"

The public and private keys will be generate in the default directory ~/.ssh as ~/.ssh/id_rsa.pub and ~/.ssh/id_rsa respectively. The public key (id_rsa.pub) can safely be shared, however, NEVER share your private key (id_rsa).

In order to login with the generate ssh keys, append the contents of the public key to the following file in the VPS ~/.ssh/authorized_keys.

From your computer, you can run either of the following commands. They will require inputting your password once.

# ssh-copy-id is an command that copies the public key automatically


# manually copy the public file (one-line)

ssh USERNAME@SERVER_IP "echo \"$(cat ~/.ssh/id_rsa.pub)\" >> .ssh/authorized_keys"

You can now simply login without entering a password with ssh USERNAME@SERVER_IP.

Disable Password Authentication (Optional): Edit /etc/ssh/sshd_config

sudo vi /etc/ssh/sshd_config

# Uncomment and set PasswordAuthentication to no

PasswordAuthentication no

# Ensure the following lines exist in the file

PubkeyAuthentication yes
ChallengeResponseAuthentication no

Restart ssh service

sudo systemctl reload sshd

I would also recommend using a non-common port for SSH. Read how to do this

Using a custom SSH Port

Edit /etc/ssh/sshd_config and change the Port number to a non-common SSH port (just pick an unused number more that 1025, note: don't use 2222, it's also common)

sudo vi /etc/ssh/sshd_config

# Uncomment and change Port number from 

# Port 22

# to 

Port 2222

# Restart ssh daemon service

sudo service sshd restart

Update Server

  • Update server software:
    sudo apt-get update && sudo apt-get upgrade -y
  • Set desired server hostname: As superuser, edit the files /etc/hostname and /etc/hosts. To update without a restart restart, run this: systemctl restart systemd-logind.service
  • Update the timezone, to your desired timezone. Use dpkg-reconfigure tzdata

Add Swap

Check if swap is already enabled on the server, if enabled, the swap partition will be listed.

sudo swapon -s 

# alternatively 

free -g
# shows free (and used) physical & swap memory (-g = in gb)

If swap is not enabled, check the amount disk space you have available.

df -h

Create swapfile (usu 2x or 1x your RAM)

# Fast Method (fallocate e.g creating 1gb swap)

sudo fallocate -l 1G /swapfile

# Slow method (e.g creating 4gb swap)

### sudo dd if=/dev/zero of=/swapfile bs=1G count=4

Verify space has been allocated

ls -lh /swapfile

Enable Swap

sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

#verify it's enabled

sudo swapon -s

Enable Swap on Reboot/ Start: Edit fstab (/etc/fstab), and add the swap filesystem.

sudo vi /etc/fstab

# Add this line to /etc/fstab

/swapfile   none    swap    sw    0   0

If you are working on a RAM intensive app, e.g Java, consider reducing swappiness and inode cache rate. Read how to do that

Tweak Swappiness

Check the current swappiness (0-100)

cat /proc/sys/vm/swappiness 
# default is usually 60

Change swappiness to your desired value.

sudo sysctl vm.swappiness=20

Enable on restarts

sudo vi /etc/sysctl.conf

# Add this line to /etc/sysctl.conf


Inode Cache Rate

# Check the current inode cache rate

cat /proc/sys/vm/vfs_cache_pressure #usu 60

# Change to desired value

sudo sysctl vm.vfs_cache_pressure=50

# Add to restarts

sudo vi /etc/sysctl.conf

# Add this line to /etc/sysctl.conf

vm.vfs_cache_pressure = 50

Configuring a Firewall

UFW (uncomplicated firewall) is a tool that simplifies configuring of iptables to secure your server. It is an easy to use firewall.

Install ufw (most likely already installed)

sudo apt-get install ufw

Enable IPv6: Edit /etc/default/ufw and set IPv6=yes

sudo vi /etc/default/ufw 

# set


Check ufw status and rules (will be inactive if not yet enabled).

sudo ufw status verbose

Setup default firewall policies

sudo ufw default deny incoming
sudo ufw default allow outgoing
Allow common connections only allow what you use

Allowing SSH connection (default ssh port 22)

sudo ufw allow ssh
# same as: sudo ufw allow 22/tcp 

If you are using different port for SSH (see SSH Lockdown: custom port above), then allow that instead of port 22

sudo ufw allow 2222/tcp

Allow HTTP and HTTPS

sudo ufw allow http
sudo ufw allow https

# the above two commands are the same as                                   

sudo ufw allow 80/tcp                
sudo ufw allow 443/tcp               

Allow SMTP - if sending out mail directly using SMTP

sudo ufw allow 25/tcp

Check all added exceptions (allowed connections)

sudo ufw show added

Enable UFW: Also useful when reloading to update configuration

sudo ufw disable
sudo ufw enable
Reset UFW

In case of errors during configuration, you can reset ufw with the following command

sudo ufw reset

UFW and docker: Docker usually manipulates iptables rules meaning that the ufw restrictions will not apply. Read how to fix that

Here are a few workarounds I've found useful. You can either:

  1. Only bind docker containers to loopback interfaces e.g. docker run -p ""..
  2. Not use port forwarding (-p or -P) esp. if you don't need it.
  3. Add --iptables=false to the docker daemon: Uncomment the following line in /etc/default/docker

    DOCKER_OPTS="--dns --dns --iptables=false"                 

    Restart the docker service for the change to effect sudo service restart docker

  4. Use the host's network docker run --net host..

Intrusion Prevention with Fail2ban

Fail2ban is an open source intrusion prevention software that scans log files and bans IPs with malicious behaviour such as too many invalid login attempts or automated attacks. It primarily focusses on SSH attacks but can be configured to work with other services (e.g Apache, SMTP, FTP) based on their logs.

Install fail2ban

sudo apt-get update
sudo apt-get install fail2ban

Configuring Fail2ban

Fail2ban configuration files are located at the /etc/fail2ban/ directory.

  • The fail2ban configuration profile /etc/fail2ban/fail2ban.conf: this contains settings for fail2ban itself (eg logging level, pid and socket locations).
  • Fail2ban defail jail configuration: /etc/fail2ban/jail.conf: contains declarations for jails (filters and actions), this is usually what you want to customize.

In order to customize fail2ban configs, create .local files at /etc/fail2ban containing your desired configuration settings. Settings in .local will override settings in .conf files. Therefore:

  • copy fail2ban.conf to fail2ban.local (optional)

  • copy jail.conf to jail.local (usu what you'll want to customize)

  • then make changes to the .local files as desired.

sudo cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

To make changes to fail2ban's general settings, update the fail2ban.local file. See examples of how to do this

Customizing general fail2ban settings. Edit the fail2ban config file fail2ban.local.

sudo vi /etc/fail2ban/fail2ban.local

# change log details level (verbosity)

# options  [ CRITICAL | ERROR (default) | WARNING | NOTICE | INFO | DEBUG ]

loglevel = ERROR

# change logfile location ( STDOUT | STDERR (default) | SYSLOG | FILE )

logtarget = /var/log/fail2ban.log 

Restart fail2ban service to make use of your customized configuration sudo systemctl restart fail2ban

Customizing fail2ban

Fail2ban is mainly configured using "jails". A jail is a declaration of filters and actions that fail2ban will follow when protecting services

Customizing fail2ban involves editing the jail.local file.

Read how to do this

Fail2ban jails are a combination of filters and actions for the various services it will protect. Pre-defined filters and templates of how to declare jails are defined in jail.conf, which you copied to jail.local.

To customize your jails, edit the file jail.local

sudo vi /etc/fail2ban/jail.local

The following options are declared when defining jails:

name of pattern to be used to detect matches, each match increments a counter
path to log file to be used by filter (default: /var/log/messages)
number of filter matches (counter) that trigger ban action (default: 3)
reset counter if no filter matches in this time (seconds) (default: 600)
duration (seconds) to ban, negative number for permanent ban (default: 600)

The jail.local file is divided into sections. Jails are defined in their own sections some sections have special uses for example [DEFAULT] includes global configurations that apply to all jails and can be overwritten in each individual jail.

Commonly customized settings in the [DEFAULT] section:

  • ignoreip is used to specify IPs that will not be banned. You can append you IP if you have a dedicate IP you use often ( below is an example)
  • bantime, findtime and maxretry are for changing jail option default values
  • If you wish to enable email, update the values for destemail,sendername and mta
  • Example:
    ignoreip =
    bantime  = 1200
    findtime = 1200
    maxretry = 6

Individual Jail Sections

  • To enable the jail, set the enabled value to true
  • filter is the filter the jail will use should exist in /etc/fail2ban/filter.d
  • logpath defines a logfile to the specific service jail
  • Example: (enable ssh jail for port 22 (default ssh port))
    enabled = true
    port = ssh
    filter = sshd
    logpath = /var/log/auth.log
    maxretry = 5

Restart fail2ban service to make use of your customized configuration

sudo systemctl restart fal2ban

While Fail2ban helps reduce rate of invalid logins, it does not eliminate the risk of weak password authentication. I'd recommend using public key authentication (described in SSH Lockdown above).

Published: March 10, 2018