Skip to main content

Ubuntu VPS Setup Guide

Setting up your Ubuntu server · VPS Management

Step-by-step Ubuntu server setup and hardening guide.

Getting a VPS

You need a Linux VPS (Virtual Private Server) to follow this guide. Any Ubuntu LTS version works.

Some great VPS provider options are DigitalOcean, Hetzner, Linode, Vultr.

Accessing Your VPS

After creating a VPS instance (for example your DigitalOcean droplet), you will be provided an IP address as well as login password. Use the credentials to log into the server.

ssh root@SERVER_IP_ADDRESS

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 section 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).

Warning: Before doing this, ensure that you can login with another (non-root) user account (see Managing Users above).

sudo vi /etc/ssh/sshd_config

# Change the following line
PermitRootLogin yes
# to
PermitRootLogin no

Restart ssh service for this change to effect.

sudo systemctl restart sshd

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

I would also recommend using a non-common port for SSH.

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

Docker Setup

Docker Installation

Follow the official installation guide: Install Docker Engine on Ubuntu

Add your user to docker group to avoid using sudo:

sudo usermod -aG docker $USER
# Log out and back in for group changes to take effect

Configure Docker Security

Edit /etc/docker/daemon.json:

{
  "icc": false,
  "userland-proxy": false,
  "no-new-privileges": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Restart Docker to apply configuration:

sudo systemctl restart docker

Run Docker without root privileges using rootless mode for additional security isolation.

Web Server

Caddy provides automatic HTTPS without complex configuration.

Install Caddy: Installation Guide

Basic configuration in /etc/caddy/Caddyfile:

example.com {
    root * /var/www/example.com
    file_server
    encode gzip
}

# Reverse proxy with automatic HTTPS
api.example.com {
    reverse_proxy localhost:8080
}

Start and enable Caddy:

sudo systemctl enable --now caddy

Note: Caddy obtains and renews SSL certificates automatically. No certbot needed.

Use nginx with Let's Encrypt certificates if you prefer traditional web server setup.

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.

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
IPv6=yes

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.

Intrusion Prevention

CrowdSec provides community-driven threat intelligence.

Install CrowdSec:

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
sudo apt update
sudo apt install crowdsec

CrowdSec automatically detects services and shares threat data while maintaining privacy.

Start and enable CrowdSec:

sudo systemctl enable --now crowdsec

Install the firewall bouncer to automatically block detected IPs:

sudo apt install crowdsec-firewall-bouncer-iptables

View current detections and bans:

sudo cscli decisions list
sudo cscli alerts list

CrowdSec provides community threat intelligence while fail2ban works with local patterns.

Fail2ban (Alternative)

For environments that prefer fail2ban:

sudo apt install fail2ban

Basic SSH protection in /etc/fail2ban/jail.local:

[DEFAULT]
bantime = 1800
findtime = 600
maxretry = 3
ignoreip = 127.0.0.1/8

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3

Enable and start:

sudo systemctl enable --now fail2ban

Note: While both solutions help reduce invalid login attempts, they don’t eliminate the need for strong authentication. Use SSH key authentication as described above.

Monitoring

Quick Setup with Netdata

One-line installation for immediate system insights:

bash <(curl -Ss https://my-netdata.io/kickstart.sh)

Access at http://your-server:19999 - no configuration needed.

What you get:

  • Real-time system metrics (CPU, memory, disk, network)
  • Application monitoring (web servers, databases)
  • Alert notifications
  • Beautiful, responsive web interface

Configure firewall for Netdata:

sudo ufw allow 19999/tcp

Use Prometheus + Grafana for custom dashboards, metrics collection, and advanced alerting.


Relevant Guides & Tutorials

Helpful resources for further reading and advanced configurations:

Official Documentation
Comprehensive Security Guides
DigitalOcean Community Tutorials
Modern Security Practices
Published: · Updated:
ubuntu vps sysadmin docker caddy security
· Edit this page