Basic website setup

Setting up DNS records

A typical domain name will need the following DNS records (replace highlighted values as required):

Type Hostname Value TTL (seconds)
A example.com 127.0.0.1 3600
CNAME www.example.com example.com 43200
NS example.com ns1.nameserver.com 1800
NS example.com ns2.nameserver.com 1800
NS example.com ns3.nameserver.com 1800

The following records are required to route e-mail to the correct servers:

Type Hostname Value Priority TTL (seconds)
MX example.com mx1.emailserver.com 10 14400
MX example.com mx2.emailserver.com 10 14400
Type Hostname Value TTL (seconds)
TXT example.com v=spf1 include:spf.emailserver.com ~all 3600
SRV _autodiscover._tcp.example.com emailserver.com 43200
CNAME mail.example.com emailserver.com 43200
CNAME autoconfig.example.com emailserver.com 43200
CNAME autodiscover.example.com emailserver.com 43200

Configure a website with nginx

Install the nginx webserver first.

sudo apt-get update
sudo apt-get install nginx

Create a new folder to store the website files:

sudo mkdir -p /var/www/example.com

Grant the correct permissions:

sudo chown -R user:user /var/www/example.com
sudo chmod 755 /var/www

Create a new configuration file by copying from the default example:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com

Add the following server block to the file (change as required):

server {
        listen   80;
        listen   [::]:80;

        root /var/www/example.com;
        index index.html;

        server_name example.com;
}

Create a symbolic link between sites-available and sites-enabled so nginx will serve our website:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com

Check your configuration for syntax errors and restart nginx if there were no errors:

sudo nginx -t
sudo service nginx restart

Setup SSL using Let's Encrypt & nginx

Tutorial copied from DigitalOcean.

Install certbot:

sudo apt-get update
sudo apt-get install certbot

Add the following to your server block in your website's nginx configuration file ( /etc/nginx/sites-available/... ):

location ~ /.well-known {
                allow all;
        }

Request a certificate with the following command:

sudo certbot certonly -a webroot --webroot-path=/var/www/html -d example.com -d www.example.com

Generate a strong Diffie-Hellman group to further increase security:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Now create a configuration snippet pointing to the SSL Key and certificate ( /etc/nginx/snippets/ssl-example.com.conf ). Add the following:

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

Create another config snippet for strong encryption settings ( /etc/nginx/snippets/ssl-params.conf ) and add the following:

# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Open up your website's nginx configuration file and add the following to the server block to enable HTTPS:

listen 443 ssl;
listen [::]:443 ssl;
include snippets/ssl-example.com.conf;
include snippets/ssl-params.conf;

Also add the following server block to your config file to reroute HTTP traffic to HTTPS:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

Setup HTTP Basic Auth with nginx

In order to add basic authentication we will need to create a password file. We need apache2_utils for this:

sudo apt-get install apache2-utils

Use the following command to generate a .htpasswd file (in your website root). Replace the path and user:

sudo htpasswd -c /etc/nginx/.htpasswd exampleuser

Finally, add the following two lines to the nginx location you want to be authenticated, and reload nginx:

location /example_location {
    ...
    auth_basic "Restricted";
    auth_basic_user_file /var/www/example_website.com/.htpasswd;
    ...
}
sudo systemctl reload nginx

Nginx will now ask for authentication each time a client tries to connect to that specific location.

Add Timeouts to HTTP Basic auth

To do this we will use Fail2Ban to monitor nginx' error logs. Fail2Ban will then monitor for repeated failed login attempts and block the originating ip address.

First of all install Fail2Ban.

sudo apt-get update
sudo apt-get install fail2ban

Create a copy of the jail.conf file in the fail2ban directory.

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

We then create the filter that will search for any failed HTTP basic auth failed logings. Open the file "/etc/fail2ban/filter.d/nginx-auth.conf" and add the following:

[Definition]
failregex = no user/password was provided for basic authentication.*client: <HOST>
              user .* was not found in.*client: <HOST>
              user .* password mismatch.*client: <HOST>
ignoreregex = </host></host></host> 

Then open the jail.local file you created earlier ( /etc/fail2ban/jail.local ) and add the following:

[nginx-auth]
enabled = true
filter = nginx-auth
action = iptables[name=NoAuthFailures, port=80, protocol=tcp]
logpath = /var/log/nginx/error.log
bantime = 3600 # 1 hour
maxretry = 3

Restart fail2ban and it will begin to ban any recurring failed logins.

sudo systemctl fail2ban restart 

You can also use the following command to see if the setup works:

fail2ban-regex /var/log/nginx/localhost.error_log /etc/fail2ban/filter.d/nginx-auth.conf