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

Postfix / MTA

sudo apt install postfix mailutils
sudo dpgk-reconfigure postfix

Excerpt:

cat /etc/postfix/main.cf

...
mydestination = localhost, localhost.localdomain
inet_interfaces = loopback-only
...

Restart:

sudo systemctl restart postfix

It does not hurt to double-check that port 25 is not accessible outside the server host. The firewall should also be blocking it anyway (see Firewall section).

Send a test email:

echo "Test mail" | mail -s "Test email subject" admin@domain.com

Check the spam folder if the email is not received.

See also: Ubuntu Server Manual: Postfix.

Logwatch

An MTA is required for logwatch to send emails. See the MTA section.

apt install logtwatch

Change the address from which the email appears to come:

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

mailer = "/usr/sbin/sendmail -t"
TmpDir = /tmp
MailFrom = domain.com

Send emails daily:

nano /etc/cron.daily/00logwatch

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

See also: Ubuntu Server Manual: Logwatch

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

Auto-mount Encrypted Drives

The starting point is that you have a LUKS-encrypted ext4 drive that you want to add to the server. The easiest way to format a drive as such is to use the disk utility on Ubuntu desktop.

Preliminaries

Attach the device. Then find out its mapping in /dev/ and its UUID. These will be used later.

ls /dev/sd*
blkid

The examples below use /dev/sdb1 as the device and 123456 as the UUID.

Create a new key

Create a key that will be used to unlock the encrypted LUKS drive:

mkdir -p /root/keys
dd if=/dev/random of=/root/keys/drive-key bs=32 count=1
chmod 700 /root/keys
chmod 400 /root/keys/drive-key

The above dd command writes the key to the file /root/keys/drive-key. This is an arbitrary choice. The key also won’t be needed by any user other than root, so adjust the permissions accordingly.

Add the key to the device:

cryptsetup luksAddKey /dev/sdb1 /root/keys/drive-key

Enter the passphrase when prompted. Then, verify that a new key slot was created in the device:

cryptsetup luksDump /dev/sdb1

Manual verification

Verify that you can unlock and mount the device manually.

Unlock:

cryptsetup luksOpen /dev/sdb1 mydevice --key-file /root/keys/drive-key

Here, mydevice is an arbitrary name and specifies the unlocked device’s mount point under /dev/mapper/. /dev/mapper/mydevice is the unlocked device following the example above.

Mount:

mkdir -p /mount/mydevice
mount /dev/mapper/mydevice /mount/mydevice

If everything up until this point is successful, then you are good to go.

Unmount and lock the device before proceding:

umount /mount/mydevice
cryptsetup luksClose mydevice

Auto-mount at boot

Edit /etc/crypttab to specify the key used to unlock the device:

# <target name> <source device>     <key file>  <options>
mydevice UUID=123456 /root/keys/drive-key luks

The first name is again arbitrary is the name of the device that will appear under /dev/mapper/ when unlocked.

Then, edit /etc/fstab to mount the device at boot:

/dev/mapper/mydevice /mount/mydevice ext4 defaults 0 0

Note that here, we specify the unlocked device /dev/mapper/mydevice as the device to mount, not /dev/sdb1 or the UUID of the device.

Release Upgrade

Check the current release:

cat /etc/os-release

Upgrade:

sudo do-release-upgrade

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