Hosting a static website with nginx
This is my recipe for configuring a static website on Debian 10:
Requirements
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
-
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).
-
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):
-
Add an SSH key for logging in to your server without a password:
If you don't have used SSH keys before, check out the guide How To Use SSH Keys with DigitalOcean Droplets.
-
Create the Droplet and wait for the VM to be created, then log-in to the system:
ssh root@serverip
-
Update all packages:
apt update && apt upgrade
-
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.
-
Install the following required packages:
apt install nginx certbot python3-certbot-nginx
-
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 https://serverfault.com/a/842515 listen 80 default_server; listen [::]:80 default_server; return 404; }
Setting up HTTP
-
The following steps assume you're setting up a site example.com. For every site a separate user is used.
At first, create a new user for the site:
SITE_NAME=www-example adduser $SITE_NAME --disabled-password --gecos ""
-
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
-
Log-out and log-in as the app user:
ssh www-example@serverip
-
Create a directory public and create an index.html page:
mkdir public echo "Hello world" > public/index.html
-
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 www.example.com -> example.com is configured as well):
server { listen 80; listen [::]:80; server_name example.com; root /home/www-example/public; charset utf-8; location / { } } server { listen 80; listen [::]:80; server_name www.example.com; return 301 http://example.com$request_uri; }
-
Enable the site configuration:
ln -s /etc/nginx/sites-available/www-example /etc/nginx/sites-enabled/www-example
-
Reload nginx if the nginx configuration is valid:
nginx -t && systemctl reload nginx
-
Enable port 80 in the firewall:
ufw allow 80
-
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 http://www.example.com curl -L http://example.com
Setting up HTTPs
-
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.
-
Allow HTTPs in the firewall:
ufw allow 443
-
Reload the nginx configuration:
nginx -t && systemctl reload nginx
-
Test accessing your site via http and https:
curl -L http://example.com/ curl -L http://www.example.com/ curl -L https://example.com/ curl -L https://www.example.com/