[ Back to log ]

How to host a static site on a VPS with Nginx

DevOps

Managed platforms like Vercel or Netlify are great, but sometimes you just want a cheap VPS and complete control over your files. Setting up Nginx and Let’s Encrypt from scratch takes a bit of work, but it’s worth it for the flexibility. Here is how to do it.

Prerequisites

  • A Linux VPS (Ubuntu or Debian works fine).
  • A domain name pointing to your server’s IP address.
  • Basic terminal knowledge.

1. Connect and create a non-root user

You shouldn’t run your server as root. It’s too easy to break things or leave security holes. SSH into your server as root first:

ssh root@your_server_ip

Create a new user (I’ll use deployer) and give them admin rights:

adduser deployer
usermod -aG sudo deployer

Switch to your new user:

su - deployer

Note: For future logins, SSH directly as this user (ssh deployer@your_server_ip).

2. Update your server

Always update your package lists before installing new software:

sudo apt update && sudo apt upgrade -y

3. Configure the firewall

VPS providers often assign IPs that get constantly scanned by bots. You need a firewall. UFW (Uncomplicated Firewall) is the easiest way to handle this. Open up SSH, HTTP, and HTTPS:

sudo apt install ufw -y
sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 443
sudo ufw logging off
sudo ufw enable
sudo ufw status

4. Install Nginx, Certbot, and Git

Now we need the actual web server, the tool to get our free SSL certificate, and Git to pull down our code.

sudo apt install nginx certbot python3-certbot-nginx git -y

5. Fetch your website files with Git

Create a parent directory for your website. Replace example.com with your actual domain.

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

Change the ownership of the directory to your current user. This lets you clone your repository without using sudo:

sudo chown -R $USER:$USER /var/www/example.com

Clone your static site repository into a static folder:

git clone https://github.com/yourusername/your-static-site-repo.git /var/www/example.com/static

(If you just want to test things out without a repo, you can make an index.html file manually instead:)

mkdir -p /var/www/example.com/static
echo "<h1>Hello World from my VPS!</h1>" > /var/www/example.com/static/index.html

6. Configure Nginx

Create a new Nginx server block for your domain:

sudo nano /etc/nginx/sites-available/example.com

Add this configuration. Make sure to swap in your actual domain and file paths:

server {
    listen 80;
    server_name example.com www.example.com;

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

    location / {
        try_files $uri $uri/ =404;
    }

    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;
}

Save and exit (in nano, press Ctrl+O, Enter, then Ctrl+X).

7. Enable the site and reload Nginx

Create a symlink to enable the site:

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

Test your Nginx config for typos:

sudo nginx -t

If it passes, reload Nginx:

sudo systemctl reload nginx

8. Secure your site with SSL

HTTPS isn’t optional anymore. Browsers will flag your site if you don’t have it. Certbot makes this painless:

sudo certbot --nginx -d example.com -d www.example.com

Certbot will ask for an email address and prompt you to agree to the terms. It automatically updates your Nginx config to use the certificate and forces HTTP traffic to HTTPS.

9. Final verification

Test and reload Nginx one last time:

sudo nginx -t && sudo systemctl reload nginx

That’s it. Your site is live. Certbot sets up a background timer to renew your certificates automatically, so you don’t have to touch it again.