Lab: Setting up Nginx on Ubuntu (Static, PHP, ASP.NET, TLS)
0. General Information
Learning goals
By the end of this lab you will be able to:
- Install and start Nginx on a fresh Ubuntu Server VM
- Serve a static website (HTML/CSS/JS)**
- Serve a PHP-based website using
php-fpm - Serve an ASP.NET website via reverse proxy to a .NET application
- Secure a virtual host with TLS using a self-signed certificate
- Explain in theory how Let’s Encrypt would be used in a real public setup
1. Prerequisites
- You have a fresh Ubuntu Server VM (no GUI needed).
- You can log in via console or SSH as a user with sudo privileges.
- The VM has internet access for installing packages.
Protocol requirement:
For every step in this lab, write in your protocol:
- The commands you executed
- A short explanation of what you did and why
- Any error messages and how you fixed them
- Screenshots or copy-pasted outputs where useful
2. Basic System Setup
Update & tools:
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl nano unzip3. Install and Test Nginx
Install:
sudo apt install -y nginxCheck service:
systemctl status nginxTest:
curl http://localhost/4. Virtual Host for Static Files (HTTP)
4.1 Add to client hosts file
<VIRTUAL_MACHINE_IP> static.local
On Windows the hosts file can be found under:
C:\Windows\System32\Drivers\etc
4.2 Create directory and sample static site
sudo mkdir -p /var/www/static.local/public
sudo chown -R $USER:$USER /var/www/static.localindex.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Static Site Test</title>
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body>
<h1>Hello from Nginx static site!</h1>
<p>This page is served as a static file.</p>
<p>Time loaded: <span id="time"></span></p>
</body>
</html>style.css
body { font-family: Arial, sans-serif; }
h1 { text-align: center; }script.js
document.addEventListener("DOMContentLoaded", () => {
const span = document.getElementById("time");
span.textContent = new Date().toLocaleString();
});4.3 Nginx configuration
Create:
sudo nano /etc/nginx/sites-available/static.localContent:
server {
listen 80;
server_name static.local;
root /var/www/static.local/public;
location / {
try_files $uri $uri/ =404;
}
}Enable:
sudo ln -s /etc/nginx/sites-available/static.local /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx5. Virtual Host for PHP
5.1 Install PHP-FPM
sudo apt install -y php-fpm php-cli5.2 Sample PHP site
sudo mkdir -p /var/www/php.local/public
sudo chown -R $USER:$USER /var/www/php.localindex.php
<!DOCTYPE html>
<html>
<body>
<h1>PHP is working!</h1>
<p>Current time: <?php echo date('Y-m-d H:i:s'); ?></p>
<p>PHP version: <?php echo phpversion(); ?></p>
</body>
</html>5.3 Nginx config for PHP
Add hosts entry:
<VIRTUAL_MACHINE_IP> php.local
Config:
server {
listen 80;
server_name php.local;
root /var/www/php.local/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
}6. Virtual Host for ASP.NET (Reverse Proxy)
6.1 Install .NET
sudo apt update
sudo apt install -y dotnet-sdk-8.06.2 Create minimal ASP.NET app
mkdir -p ~/aspnet-site
cd ~/aspnet-site
dotnet new web -o WebApp1
cd WebApp1
dotnet run --urls http://localhost:5000Test:
curl http://localhost:50006.3 Nginx reverse proxy config
Hosts entry:
<VIRTUAL_MACHINE_IP> aspnet.local
Config:
server {
listen 80;
server_name aspnet.local;
location / {
proxy_pass http://localhost:5000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}7. TLS with a Self-Signed Certificate
7.1 Create certificate
sudo mkdir -p /etc/ssl/private
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/static.local.key -out /etc/ssl/certs/static.local.crtUse CN = static.local.
7.2 Nginx HTTPS config
server {
listen 80;
server_name static.local;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name static.local;
ssl_certificate /etc/ssl/certs/static.local.crt;
ssl_certificate_key /etc/ssl/private/static.local.key;
root /var/www/static.local/public;
location / {
try_files $uri $uri/ =404;
}
}8. Optional: Let’s Encrypt Theory
- Uses the ACME protocol
- Proves domain control via HTTP-01, DNS-01, or TLS-ALPN-01
- Works with Certbot to automate issuing & renewal
- Requires a public DNS name and publicly reachable server
Example (NOT executed in lab):
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com9. Protocol Checklist
- Static site setup (with sample HTML, CSS, JS)
- PHP site setup
- ASP.NET reverse proxy
- Self-signed TLS
- Let’s Encrypt explanation
- Screenshots or curl outputs where useful