Static site deployment

17.03.2020, to see all my rants click here.


What does this give you:

Setting up server

I recommend you create a new Ubuntu Droplet using this referal link. I think the 25GB Droplet for $5 is more than enough.


If you are using Google domains you can set up mail forwarding by following this guide: note this works even if you are not using their name servers - I use Digital Ocean name servers and it works just fine.


ufw allow ssh
ufw allow https
ufw allow http 
ufw enable

New user:

Create non-root user that will be used for uploading the site

adduser <username>
usermod -aG sudo <username>

Create folder for the static site:

cd /var/www/
mkdir mysite
chown -R <username> mysite

On your local machine use this command to copy ssh key on the remote server

ssh-copy-id <username>@<remote>


Install it:

sudo apt-get update
sudo apt-get install nginx

nginx template:

You need to replace all with your own value and /var/www/example with the actual directory

# UPDATED 17 February 2019
# see
# and

# Redirect all HTTP traffic to HTTPS
server {
    listen 80;
    listen [::]:80;
    return 301 https://$host$request_uri;

# SSL configuration
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl_certificate      /etc/letsencrypt/live/;
    ssl_certificate_key  /etc/letsencrypt/live/;

    # Improve HTTPS performance with session resumption
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Enable server-side protection against BEAST attacks
    ssl_protocols TLSv1.2;
    ssl_prefer_server_ciphers on;

    # RFC-7919 recommended:
    #    ssl_dhparam /etc/ssl/ffdhe4096.pem;
    #    ssl_ecdh_curve secp521r1:secp384r1;

    # Aditional Security Headers
    # ref:
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    # ref:
    add_header X-Frame-Options DENY always;

    # ref:
    add_header X-Content-Type-Options nosniff always;

    # ref:
    add_header X-Xss-Protection "1; mode=block" always;

    # Enable OCSP stapling
    # ref.
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/;
    resolver [2606:4700:4700::1111] [2606:4700:4700::1001] valid=300s; # Cloudflare
    resolver_timeout 5s;

    gzip on;
    gzip_types application/javascript image/* text/css;
    gunzip on;

    location ~* \.(jpg|jpeg|png|gif|ico)$ {
        expires 30d;
    location ~* \.(css|js)$ {
        expires 7d;

    # Required for LE certificate enrollment using certbot
    location '/.well-known/acme-challenge' {
        default_type "text/plain";
        root /var/www/html;

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

    location / {
        try_files $uri $uri/ @htmlext;

    location ~ \.html$ {
        try_files $uri =404;

    location @htmlext {
        rewrite ^(.*)$ $1.html last;

copy the template to /etc/nginx/sites-available/<mysite> and create symlink to it in sites-enabled:

ln -s /etc/nginx/sites-available/<mysite> /etc/nginx/sites-enabled/<mysite>

Lets encrypt

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx

Now run this command, it will most likely fail to identify your domains so you have to enter them manually - you will have to enter something like

sudo certbot --nginx certonly

Use rsync to publish your website

Rsync is faster than SFTP because it only transmits the changed items

rsync -azP <build_dir on your laptop> <digital ocean ssh serve details>:/var/www/<mysite>

Restart nginx:

systemctl restart nginx