Skip to content

nginx: HTTP site first, then HTTPS

In this section, we install nginx, make sure a simple HTTP site works, and then upgrade it to HTTPS with TLS certs.

Goal: at the end, visiting http://www.curvature.blog works, and later https://www.curvature.blog works.


2.1 Install nginx and verify default page

  • login as vpsadmin and install nginx

    shell
    sudo apt update
    sudo apt install nginx
  • check nginx status

    shell
    sudo systemctl status nginx
  • verify on browser

    • visit your server IP in a browser
    • you should see nginx default page

2.2 Basic website file layout

For a simple site, we use the default web root:

  • default web root is /var/www/html

  • default index page (Debian) is index.nginx-debian.html

  • edit the index page to confirm you are serving your own content

    shell
    sudo vim /var/www/html/index.nginx-debian.html

2.3 Add a server block for your domain

We want nginx to respond correctly when browser uses your domain name (not just IP).

There are multiple valid ways. In our notes, we directly added a server block (later we can move it into sites-available).

  • edit nginx main config (one working approach)

    shell
    sudo vim /etc/nginx/nginx.conf
  • add a simple server block

    nginx
    http {
      ...
      server {
        listen 80;
        server_name www.curvature.blog;
        root /var/www/html;
        index index.nginx-debian.html;
      }
    ...
    }
  • test nginx config

    shell
    sudo nginx -t
  • reload nginx

    shell
    sudo systemctl reload nginx

2.4 Verify domain works (common pitfall)

At this stage:

  • visiting http://YOUR_SERVER_IP should work
  • visiting http://www.curvature.blog should also work

If IP works but domain does not:

  • check DNS A record points to the correct VPS IP
    bash
    ping -c 3 www.curvature.blog
    # The output IP should exactly match your VPS IP. If not, DNS hasn't propagated or is set incorrectly.
  • check nginx server_name matches exactly (www.curvature.blog)
    bash
    sudo nginx -T | grep server_name
    # Ensure there are no typos in the domain name in your config.
  • check port 80 is open (firewall / provider rules)
    bash
    sudo ss -tuln | grep :80  # Checks if nginx is actively listening on port 80
    sudo ufw status | grep 80 # Checks if your firewall allows traffic on port 80
  • check nginx is actually loading the config you edited
    bash
    sudo nginx -t
    # If you want to see the entire configuration tree Nginx is currently using:
    sudo nginx -T

2.5 Common problems we encountered (and fix)

  • problem: nginx -t fails / nginx cannot reload

    • common cause: syntax errors in config
    • one specific mistake we made: wrote server() instead of server{}
    • fix:
      • correct the block syntax (server { ... })
      • re-run nginx -t until it is successful
      • then reload nginx
  • problem: IP works but domain shows refused to connect or connection reset

    • common causes:
      • DNS not propagated / wrong record
      • firewall / provider blocks port 80
      • Browser caching / HSTS: If your browser previously visited this domain via HTTPS, it will force a connection to port 443. Since Nginx is currently only on port 80, it refuses the connection.
    • fix:
      • confirm DNS points to VPS IP
      • test using curl -v http://www.curvature.blog on the server to bypass browser caching.
      • test the domain in a fresh "Incognito/Private" browsing window.

2.6 Upgrade to HTTPS (high-level plan)

Once HTTP works, we add HTTPS:

  • obtain TLS certificate (we used acme.sh + webroot mode)
  • install cert/key to a stable location (e.g. /etc/nginx/cert/)
  • add an HTTPS server block listening on 443
  • redirect HTTP (80) to HTTPS (443)
  • reload nginx and verify with browser / curl

(Details of cert issuance are recorded in the acme.sh section.)


2.7 HTTPS server block skeleton (for later)

After you have cert files ready, nginx HTTPS block typically includes:

  • listen 443 ssl http2;
  • ssl_certificate and ssl_certificate_key
  • TLS 1.3 enabled
  • X25519 curve preferred
  • optional HSTS header

2.8 Quick checklist for this stage

After this section, you should have:

  • nginx installed and running
  • a working HTTP page under /var/www/html
  • http://www.curvature.blog works
  • nginx config passes nginx -t
  • ready to proceed to certificate + HTTPS setup