Host a static website
Upload a folder of HTML, CSS and images to your VPS and serve it with nginx, a fast and widely used web server. By the end, your site will answer at http://example.com.
Before you begin
- A VPS running Ubuntu 24.04 LTS with a public IP address, for example
203.0.113.10. - SSH access as
rootor as a user withsudorights. This guide uses a sudo user namedalex. - A domain name whose DNS A record points at your VPS IP. If your domain is managed in Lantern DNS, you can add the record in the DNS editor. DNS changes can take a while to spread.
- Your site files on your computer, in a folder with an
index.htmlfile at the top level.
Step 1: Update the server and install nginx
Refresh the list of available packages, install any pending updates, and then install nginx. The -y flag answers "yes" to prompts automatically.
sudo apt update
sudo apt upgrade -y
sudo apt install -y nginx
When nginx installs, it starts itself and serves a "Welcome to nginx" page. You will replace that page with your own in later steps.
Step 2: Allow web traffic through the firewall
Ubuntu includes ufw, a simple firewall. Allow SSH first so you cannot lock yourself out, then allow the nginx web profile (ports 80 and 443), and turn the firewall on.
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx Full ALLOW Anywhere
OpenSSH before running ufw enable. If you skip it, the firewall can block your own SSH connection.Step 3: Create a folder for your site
Create the folder that will hold the site, then give your login account ownership of it so you can upload files without sudo. The -p flag creates any missing parent folders.
sudo mkdir -p /var/www/example.com/html
sudo chown -R $USER:$USER /var/www/example.com
Step 4: Upload your files
Run this command on your own computer, not on the server. scp copies files over SSH. Replace alex and the IP address with your own values.
scp -r ./my-site/* alex@203.0.113.10:/var/www/example.com/html/
Back on the server, confirm the files arrived:
ls /var/www/example.com/html
about.html css images index.html
rsync -av ./my-site/ alex@203.0.113.10:/var/www/example.com/html/ is faster on repeat uploads because it only sends changed files.Step 5: Create an nginx server block
nginx uses "server blocks" to decide what to serve for each domain name. Create a new configuration file for your domain. Inside the editor, paste the contents shown below.
sudo nano /etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
The root line tells nginx where your files live. try_files serves the requested file, or a folder's index file, or a 404 if neither exists.
Next, enable the site, disable the default welcome site, check the configuration for mistakes, and reload nginx:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
The ln -s command enables your site by creating a link. nginx -t tests the configuration without applying it, and reload applies changes without dropping active connections.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Step 6: Test the site
Ask the server for the response headers of your home page. -I fetches headers only, which is a quick way to confirm the status code.
curl -I http://example.com
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Content-Type: text/html
Content-Length: 512
Then open http://example.com in a browser. You should see your home page.
Troubleshooting
- You still see the "Welcome to nginx" page. Check that the default site is gone with
ls -l /etc/nginx/sites-enabled, then runsudo systemctl reload nginx. Your browser may also be caching the old page, so try a private window. - 403 Forbidden. nginx cannot read the files, or there is no
index.html. Check the path withls -l /var/www/example.com/html, and read the error log withsudo tail -n 20 /var/log/nginx/error.log. - The domain does not load but the IP does. DNS has not updated yet. Check it with
dig +short example.com, which should print203.0.113.10. - nginx -t reports an error. The message includes a file name and line number. The most common cause is a missing semicolon or an unmatched brace.
Next steps
Your site is live over plain HTTP, which means visitors' traffic is not encrypted. Add a free TLS certificate next, using certbot. Then read Create custom error pages to make missing-page responses match your site.
Something not working? Chat or email our support team and we will help you get unstuck.
Contact support