Linux Tutorial / Install Nginx and Publish a Website over HTTP and HTTPS

Publishing an Nginx site requires more than installing a package: content paths, listeners, firewall policy, DNS, and TLS must agree. Verify the page locally over HTTP first, then test remote access and the domain before adding and validating HTTPS.

Use network-layer diagnosis for connection failures and firewall and account protection before exposing services. Nginx and certificate-tool versions depend on repositories; follow documentation for the installed packages and distribution.

System configuration exercises use a conventional Ubuntu 26.04 LTS or Rocky Linux 9 VM as the reference environment. Containers, WSL, and other releases can differ in service and package configuration. Prepare console recovery and record your versions using the virtual machine setup lesson.

Prepare the server, name, and access policy

Use a lab Ubuntu or Rocky Linux server with sudo and console recovery. linux-course.test is a local test name, not a name to publish in public DNS. For public deployment, replace it with a real domain you control and review NAT forwarding and provider restrictions. Check whether another service already uses ports 80 or 443.

sudo ss -lntp
cat /etc/os-release

Install Nginx using the distribution package

Use the first block on Ubuntu or the second on Rocky Linux. Review package changes and follow the repository policy. Preserve any existing sites and add a separate server block rather than deleting the default configuration indiscriminately.

sudo apt update
sudo apt install nginx curl
sudo systemctl enable --now nginx
sudo dnf install nginx curl
sudo systemctl enable --now nginx

Create a dedicated document root and full server block

If either path already contains data, back it up and choose another lab name. Store a readable static page under /var/www/linux-course. The example assumes the packaged nginx.conf includes conf.d/*.conf; inspect the actual include structure if your package differs.

sudo install -d -m 755 /var/www/linux-course
printf '<!doctype html><html lang="en"><meta charset="utf-8"><title>Linux course</title><h1>Linux course server works</h1></html>\n' | sudo tee /var/www/linux-course/index.html
sudo chmod 644 /var/www/linux-course/index.html
sudo tee /etc/nginx/conf.d/linux-course.conf > /dev/null <<'EOF'
server {
    listen 80;
    server_name linux-course.test;
    root /var/www/linux-course;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}
EOF
sudo nginx -t

The h1 appears inside the separate HTML page served by the lab, not in this WordPress article. Run the reload below only after nginx -t succeeds. Fix the reported file and line and recheck instead of restarting a working service with invalid configuration.

sudo systemctl reload nginx
curl -i --resolve linux-course.test:80:127.0.0.1 http://linux-course.test/

Expect HTTP 200 and Linux course server works. The --resolve option overrides name-to-address mapping for this request only, without changing system DNS. If the default page appears, inspect the requested hostname, server_name, and loaded configuration.

Separate file access from network exposure

On Rocky Linux with SELinux enabled, inspect labels using ls -Zd /var/www/linux-course. A standard policy path can be relabeled with sudo restorecon -Rv /var/www/linux-course; nonstandard paths may need persistent labeling rules. Do not fix HTTP 403 by disabling SELinux or granting mode 777.

After local validation, permit HTTP 80/tcp and later HTTPS 443/tcp in the intended scope. UFW can add a specific port rule; with firewalld, test http/https services in the actual zone before making only those rules permanent. Review cloud filtering separately and preserve SSH access.

From another machine, request the actual server address with Host: linux-course.test and confirm the same page. If local access works but remote access fails, inspect binding, filtering, routes, and NAT. An HTTP error response instead directs investigation toward the server, resource path, or application.

Configure the real domain and HTTPS

  1. Point the real domain’s A and any AAAA records at the intended public addresses; do not publish an unusable IPv6 address.
  2. Replace server_name, validate with nginx -t, reload, and test HTTP by domain from another network.
  3. Choose the OS and Nginx installation method in the official Certbot instructions. Ubuntu’s package method can use apt install certbot python3-certbot-nginx; verify repository requirements on other distributions.
  4. After validating domain ownership and required port reachability, run sudo certbot --nginx -d ACTUAL_DOMAIN.
  5. Verify certificate hostname, chain, expiry, and redirects, then test renewal with sudo certbot renew --dry-run.

Where HTTP validation is unavailable, use another supported method such as DNS validation. Finishing the local exercise does not establish that public DNS and HTTPS are ready. Do not transmit passwords or tokens during the unencrypted HTTP test stage.

Troubleshoot and roll back only the lab configuration

systemctl status nginx --no-pager
journalctl -b -u nginx -n 50 --no-pager
sudo nginx -t

Inspect the configured error log and request time as well. To remove the exercise, back up and remove only its conf file, validate, and reload. Remove content, certificates, DNS, and firewall changes only after checking dependencies, preserving existing sites, shared certificates, and management rules.

Official references