Deploy a static website with Nginx and free HTTPS
A static website — plain HTML, CSS and JavaScript files — is the fastest, cheapest and most secure kind of site you can run. There's no database to hack and nothing to update every week. This guide shows how to put one online on your own Linux server with Nginx and a free HTTPS certificate. It's exactly how this site is hosted.
What you need
- A VPS running Ubuntu or Debian, with root (or sudo) access.
- A domain name whose DNS
Arecord points to your server's IP address. - Your website files (at minimum an
index.html).
1. Install Nginx
sudo apt update
sudo apt install nginx
sudo systemctl enable --now nginx
Open http://your-server-ip in a browser. If you see the "Welcome to nginx" page, the web server is running. If not, check that ports 80 and 443 are open in your firewall:
sudo ufw allow 'Nginx Full'
2. Upload your site
Create a folder for the site and copy your files into it. From your own computer you can use scp or rsync:
sudo mkdir -p /var/www/example.com
rsync -avz ./site/ root@your-server-ip:/var/www/example.com/
3. Create an Nginx server block
Create /etc/nginx/sites-available/example.com:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
try_files tells Nginx to serve the exact file if it exists, then a folder's index.html, and otherwise return a 404. Enable the site and reload:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Always run nginx -t before reloading. It checks the configuration for errors, so a typo never takes your site offline.
4. Add free HTTPS with Let's Encrypt
Certbot requests a certificate and configures Nginx for you:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
Choose the option to redirect HTTP to HTTPS. Certificates last 90 days, and Certbot installs a timer that renews them automatically. You can test renewal with:
sudo certbot renew --dry-run
5. Make it fast
A few lines inside the server block make a noticeable difference:
gzip on;
gzip_types text/css application/javascript image/svg+xml;
location ~* \.(css|js|png|jpg|jpeg|webp|svg|woff2)$ {
expires 30d;
add_header Cache-Control "public";
}
Compression shrinks text files, and caching headers let returning visitors load images and stylesheets from their own browser instead of downloading them again. Also compress your images (WebP is usually much smaller than PNG or JPEG) — they're almost always the heaviest part of a page.
6. Updating the site
To publish changes, just upload the new files again with the same rsync command. There's no restart needed: Nginx serves the new files immediately.
Common problems
- 403 Forbidden: Nginx can't read the files. Check permissions:
sudo chmod -R o+rX /var/www/example.com. - Default Nginx page still shows: remove the default site with
sudo rm /etc/nginx/sites-enabled/defaultand reload. - Certbot fails: make sure DNS points to the server and port 80 is reachable from the internet; Let's Encrypt needs it to verify the domain.
- "Address already in use": another program is using port 80 or 443. Find it with
sudo ss -ltnp | grep -E ':80|:443'.
That's it — a fast, secure website with automatic HTTPS, for the cost of a small server.