NGINX 1.28 Stable on Ubuntu 24.04 LTS | cloudimg
Overview
NGINX 1.28 is the current stable mainline release of the most widely deployed web server on the Internet. It serves static content, reverse-proxies application servers, terminates TLS, load-balances across backends, caches, rate-limits, and speaks HTTP/1.1, HTTP/2, and HTTP/3 (QUIC). This cloudimg image installs NGINX 1.28 from the official nginx.org APT repository onto Ubuntu 24.04 LTS (Noble Numbat) and ships a ready-to-edit welcome page plus a sample reverse-proxy server block.
Prerequisites
-
An Azure subscription with permission to create virtual machines
-
An SSH key pair — the public key is uploaded during VM creation
-
A domain name pointed at your VM's public IP if you plan to request a Let's Encrypt TLS certificate
Step 1 — Deploy from the Azure Portal
-
Find NGINX 1.28 Stable on Ubuntu 24.04 LTS by cloudimg in the Azure Marketplace and click Create.
-
On the Basics tab, select or create a Resource Group, choose East US as the region, and set the VM size to Standard_B2s (2 vCPU / 4 GB RAM) for a lightweight reverse proxy, or Standard_D2s_v3 (2 vCPU / 8 GB RAM) and upward for production TLS-terminating workloads.
-
Under Administrator account, choose SSH public key and paste your public key.
-
On the Networking tab, open inbound ports 80 (HTTP) and 443 (HTTPS) in addition to 22 (SSH).
-
Click Review + create, then Create.
Step 2 — Deploy with the Azure CLI
az vm create \
--resource-group \
--name nginx-1-28 \
--image "$(az sig image-version list \
--resource-group AZURE-CLOUDIMG \
--gallery-name cloudimgGallery \
--gallery-image-definition nginx-1-28-ubuntu-24-04 \
--query '[0].id' -o tsv)" \
--size Standard_D2s_v3 \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_rsa.pub \
--public-ip-sku Standard
After the VM starts, open HTTP and HTTPS:
az vm open-port --port 80 --resource-group --name nginx-1-28 --priority 1010
az vm open-port --port 443 --resource-group --name nginx-1-28 --priority 1011
Step 3 — Connect via SSH
ssh azureuser@
On first boot, nginx-firstboot.service marks the image as live and enables nginx.service. The service is a quick one-shot and completes in under a second.
Step 4 — Verify NGINX is Running
Check the service status and listening ports:
sudo systemctl status nginx --no-pager
sudo ss -tln | grep -E ':80|:443'
Confirm the mainline version shipped in this image:
sudo nginx -v
Parse the configuration to make sure it is syntactically valid:
sudo nginx -t
Fetch the landing page locally. The cloudimg welcome page is served from /usr/share/nginx/html/index.html.
curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1/
curl -sI http://127.0.0.1/ | grep -iE '^(HTTP|Server|Content-Type)'
From a browser, open http:/// and you should see the cloudimg NGINX 1.28 landing page. That page is a template — replace it with your own content in Step 5.
Step 5 — Publish Your Own Content
The active document root is /usr/share/nginx/html. Replace the welcome page with your own HTML:
sudo tee /usr/share/nginx/html/index.html > /dev/null
Hello from NGINX
Hello from NGINX 1.28 on Azure by cloudimg.
HTML
Reload NGINX to pick up any file changes without dropping connections:
sudo nginx -s reload
Fetch the new page:
curl -s http://127.0.0.1/ | head -3
For larger sites, upload your content into /usr/share/nginx/html/ or configure an alternate document root in a server block (see Step 6).
Step 6 — Configure a Reverse Proxy Server Block
A sample reverse-proxy server block is shipped at /etc/nginx/conf.d/cloudimg-example.conf.disabled. Rename it and edit the upstream to point at your backend:
sudo cat /etc/nginx/conf.d/cloudimg-example.conf.disabled
Copy it into an active server block — edit the upstream backend block and the server_name line for your domain. For example, to reverse-proxy a Node.js app running on 127.0.0.1:8080:
sudo tee /etc/nginx/conf.d/backend.conf > /dev/null \
--nsg-name \
--name allow-http3 \
--priority 1012 \
--protocol Udp --destination-port-ranges 443 \
--access Allow --direction Inbound
Reload NGINX and verify the QUIC listener is bound:
sudo nginx -t && sudo nginx -s reload
Step 9 — Configure Rate Limiting and Caching
Rate-limit requests per client IP. Define a zone in the http {} block of /etc/nginx/nginx.conf, then apply it in a location block:
http {
limit_req_zone $binary_remote_addr zone=api_zone:10m rate=10r/s;
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=edge_cache:100m max_size=1g inactive=60m use_temp_path=off;
}
server {
location /api/ {
limit_req zone=api_zone burst=20 nodelay;
proxy_pass http://backend;
}
location /static/ {
proxy_cache edge_cache;
proxy_cache_valid 200 1h;
proxy_pass http://backend;
}
}
Reload to activate:
sudo nginx -t && sudo nginx -s reload
Step 10 — Security Hardening
The image ships with server_tokens off already applied, which hides the NGINX version from response headers and error pages. Verify:
curl -sI http://127.0.0.1/ | grep -i '^server:'
Add recommended security headers to your server block:
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Restrict admin endpoints by IP allowlist:
location /admin/ {
allow 203.0.113.0/24;
deny all;
proxy_pass http://backend;
}
Keep NGINX up to date by enabling unattended security upgrades from the nginx.org APT repo:
sudo apt-get update
sudo apt-get install -y --only-upgrade nginx
Step 11 — Everyday Operations
Reload the configuration without dropping connections:
sudo nginx -s reload
Check error and access logs:
sudo tail -50 /var/log/nginx/error.log
sudo tail -50 /var/log/nginx/access.log
Stop, start, or restart the service:
sudo systemctl restart nginx
Support
cloudimg provides 24/7/365 expert technical support. Guaranteed response within 24 hours, one hour average for critical issues. Contact support@cloudimg.co.uk.