Server Setup

Very basic server setup for Ubuntu server.

Initial update

apt update
apt upgrade

Create a user

adduser myuser

Add the user to the sudo group if necessary:

adduser myuser sudo

SSH configuration

Upload the user’s public key:

ssh -i ~/.ssh/mykey myuser@host

Set up /etc/ssh/sshd_config:

PermitRootLogin no
StrictMode yes
PubkeyAuthentication yes
PasswordAuthentication no
X11Forwarding no  # Unless you intend to use GUI on the server.

Restart the SSH daemon:

systemctl restart sshd

Enable automatic security updates

sudo apt install unattended-upgrades

Then set up /etc/apt/apt.conf.d/10periodic:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";

Make sure unattended security updates are enabled in /etc/apt/apt.conf.d/50unattended-upgrades:

"${distro_id}:${distro_codename}-security";
"${distro_id}:${distro_codename}-updates";

fail2ban

apt install fail2ban

Firewall

apt install ufw

Allow SSH access and enable the firewall:

ufw allow ssh
ufw enable

Then allow additional ports as required by the services running on the host. For example, for HTTP:

ufw allow 80
ufw allow 443

Logwatch

apt install logtwatch

Send emails daily:

nano /etc/cron.daily/00logwatch

/usr/sbin/logwatch --output mail --mailto admin@domain.com --detail high

Change the address from which the email appears to come:

nano /usr/share/logwatch/dist.conf/logwatch.conf

MailFrom = server-name

Apparmor

apt install apparmor apparmor-profiles

Make sure to install apparmor-profiles, which includes profiles for everyday applications.

Nginx

Run nginx -t at any time to validate the site configuration files.

Modern SSL/TLS Configuration

SSL Config - Generate a config for the web server.

SSL Test - Test the server.

Headers

X-Frame-Options

add_header X-Frame-Options DENY always;

DENY is a better default. Use SAMEORIGIN if the web application requires iframes of its own.

Performance

A few tweaks to improve performance. Write the performance directives into a re-usable snippet:

/etc/nginx/snippets/perf.conf

Then, in the site configuration, include it in the relevant section:

server {
  include /etc/nginx/snippets/perf.conf;
}

Cache-Control

Instruct the browser to cache assets for some period of time. I play with css/js more often than not, so I set the cache time to 1 day. Images can be cached for one week.

location ~* \.(jpg|png)$ {
        expires 7d;
        add_header Cache-Control "public";
}

location ~* \.(css|js)$ {
        expires 1d;
        add_header Cache-Control "public";
}

Compression

Enable compression to reduce data transfer sizes. Compressing small files often bloats them, so adjust the lower bound (1k in the example).

# https://docs.nginx.com/nginx/admin-guide/web-server/compression/
gzip on;
gzip_min_length 1024;

Git

Create a git system user that will own the git repositories:

adduser --system --shell /bin/bash git

Create a directory to store the git repositories:

mkdir /opt/git

Make main the default branch when creating repositories:

git config --global init.defaultBranch main

Create repositories, e.g.:

mkdir /opt/git/repo
cd /opt/git/repo
git init --bare
chown -R git /opt/git/repo

Give other users access to the git repositories by adding their keys to the git user’s authorized_keys (a simple, good-faith setup):

mkdir /home/git/.ssh
touch /home/git/.ssh/authorized_keys # Add keys here
chown -R git /home/git/.ssh
chmod 700 /home/git/.ssh
chmod 400 /home/git/.ssh/authorized_keys

Resources

Ubuntu Server Guide

Debian Unattended Upgrades

Nginx

A Regular Expression Tester for NGINX and NGINX Plus

Understanding Nginx Server and Location Block Selection Algorithms

How to Configure Cache-Control Headers in NGINX