Hosting a static website with nginx

by @ralfebert · updated June 26, 2021

This is my recipe for configuring a static website on Debian 10:


For this tutorial you need to have good knowledge of Linux server administration using a command line shell.

USE THIS ARTICLE AT YOUR OWN RISK: None of the authors, in any way whatsoever, can be responsible for your use of the information contained in these web pages. Do not rely upon any information found here without independent verification.

Setting up nginx

  1. I recommend using a DigitalOcean VM - works fine for many years for myself now (if you use this link, you'll get $100 in credit so you can set up a VM for free).

  2. Create a new droplet and select Debian 10 x64 as Image (Ubuntu should work the same but I didn't test it). Also select the size for your droplet (warning: you can easily upgrade to larger sizes, but it is not possible to downgrade to a size with a smaller disk):

    Create a DigitalOcean droplet
  3. Add an SSH key for logging in to your server without a password:

    Add SSH Key

    If you don't have used SSH keys before, check out the guide How To Use SSH Keys with DigitalOcean Droplets.

  4. Create the Droplet and wait for the VM to be created, then log-in to the system:

    ssh root@serverip
  5. Update all packages:

    apt update && apt upgrade
  6. Enable the firewall so that unconfigured services will not be exposed (the IP ranges of VM providers are frequently scanned for not fully configured servers):

    apt install ufw && ufw allow 22 && ufw logging off && ufw enable && ufw status

    The firewall rules are automatically saved and restored on reboot.

  7. Install the following required packages:

    apt install nginx certbot python3-certbot-nginx
  8. Edit the nginx default configuration:

    nano /etc/nginx/sites-enabled/default

    to return a 404 error by default. This will apply when a request with an unknown domain name if requested.

    server {
    	# return 404 both via IPv4/6 when no other configuration handles the host
    	# '[::]:80' is neccessary for IPv6 - see
    	listen 80 default_server;
    	listen [::]:80 default_server;
    	return 404;

Setting up HTTP

  1. The following steps assume you're setting up a site For every site a separate user is used.

    At first, create a new user for the site:

    adduser $SITE_NAME --disabled-password --gecos ""
  2. Add your SSH public key to the user home so you can log-in as the app user.

    To copy the SSH keys from root to the user:

    mkdir /home/$SITE_NAME/.ssh
    cp ~/.ssh/authorized_keys /home/$SITE_NAME/.ssh/
    chown $SITE_NAME.$SITE_NAME /home/$SITE_NAME/.ssh -R
    chmod go-rwx /home/$SITE_NAME/.ssh -R
  3. Log-out and log-in as the app user:

    ssh www-example@serverip
  4. Create a directory public and create an index.html page:

    mkdir public
    echo "Hello world" > public/index.html
  5. Switch back to the root user and create a configuration file for the site:

    nano /etc/nginx/sites-available/www-example

    Example configuration as a starting point (here a forward from -> is configured as well):

    server {
        listen 80;
        listen [::]:80;
        root        /home/www-example/public;
        charset     utf-8;
        location / {
    server {
        listen 80;
        listen [::]:80;
        return      301$request_uri;
  6. Enable the site configuration:

    ln -s /etc/nginx/sites-available/www-example /etc/nginx/sites-enabled/www-example
  7. Reload nginx if the nginx configuration is valid:

    nginx -t && systemctl reload nginx
  8. Enable port 80 in the firewall:

    ufw allow 80
  9. Check accessing the site using HTTP using the domain name (assuming you changed the DNS entry already, otherwise you could temporarily add it to your /etc/hosts file):

    curl -L
    curl -L

Setting up HTTPs

  1. On Debian, out of the box, adding SSH certificates to a domain works fully automated via the certbot package, including automatic certicate renewal:

    certbot --nginx

    This will ask for which domains certificates should be created. It will then update the site configuration accordingly and also set up a HTTP -> HTTPs redirect.

  2. Allow HTTPs in the firewall:

    ufw allow 443
  3. Reload the nginx configuration:

    nginx -t && systemctl reload nginx
  4. Test accessing your site via http and https:

    curl -L
    curl -L
    curl -L
    curl -L