Set up a high-performance Nginx static file server on Ubuntu with sensible cache headers, gzip compression, and SKU-specific performance tuning for optimal delivery of HTML, CSS, JS, images, and downloads.
This guide exists as a tested, machine-readable recipe in the Massed Compute MCP. Connect an AI agent to skip the manual steps and deploy directly from a natural-language prompt.
Need to serve static files fast? This guide walks you through deploying a production-ready Nginx static file server on Ubuntu. You’ll get automatic gzip compression for text content, sensible cache headers for assets, and performance tuning based on your VM size.
Perfect for hosting React/Vue builds, documentation sites, asset CDNs, or download servers. The setup includes directory browsing options and SPA-friendly routing configuration.
| Component | Version | Purpose |
|---|---|---|
| Ubuntu | 22.04 LTS | Base operating system |
| Nginx | 1.18+ | Web server and static file handler |
| systemd | Built-in | Service management |
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 vCPU | 4+ vCPU for high traffic |
| RAM | 2 GB | 4+ GB for large file sets |
| Storage | 20 GB | Size based on content volume |
| OS | Ubuntu 22.04 | Ubuntu 22.04 LTS |
Massed Compute VM Pricing
All SKUs below meet the minimum requirements for this deployment:
| SKU | Description | vCPU | RAM | Storage | Price | Capacity |
|---|---|---|---|---|---|---|
cpu_mini_amd_epyc |
Mini AMD EPYC | 8 | 32 GiB | 400 GB | $0.12/hr | 32 |
cpu_small_amd_epyc |
Small AMD EPYC | 14 | 40 GiB | 800 GB | $0.22/hr | 32 |
cpu_medium_amd_epyc |
Medium AMD EPYC | 28 | 80 GiB | 1600 GB | $0.44/hr | 15 |
cpu_large_amd_epyc |
Large AMD EPYC | 52 | 160 GiB | 3200 GB | $0.82/hr | 6 |
cpu_x_large_amd_epyc |
X-Large AMD EPYC | 100 | 320 GiB | 6400 GB | $1.56/hr | 3 |
cpu_dedicated_amd_epyc |
Dedicated AMD EPYC | 126 | 440 GiB | 10000 GB | $1.98/hr | 2 |
Step-by-Step Deployment
Launch Your VM
Create a new Ubuntu 22.04 instance with at least 2 vCPU and 2 GB RAM. Make sure to attach your SSH key during launch.
ssh ubuntu@YOUR_VM_IP
Wait for the VM to reach Running status before attempting to connect.
Update System and Install Nginx
Update the package index and install Nginx:
sudo apt-get update sudo apt-get install -y nginx
This installs the latest Nginx version available in Ubuntu’s repositories.
Configure Document Root
Create your document root directory and add a test file:
sudo mkdir -p /var/www/html echo "<h1>It works.</h1>" | sudo tee /var/www/html/index.html
Replace /var/www/html with your preferred path if serving different content.
Create Nginx Site Configuration
Create the site configuration file:
sudo tee /etc/nginx/sites-available/static <<EOF
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm;
# Cache common static assets aggressively
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
location / {
try_files \$uri \$uri/ =404;
}
}
EOF
This configuration serves files from your document root with optimized caching for common assets.
Configure Gzip Compression
Add gzip settings for better performance:
sudo tee /etc/nginx/conf.d/gzip.conf <<EOF gzip_types text/plain text/css text/xml application/json application/javascript application/xml application/xml+rss text/javascript image/svg+xml; gzip_min_length 1024; gzip_vary on; EOF
gzip on; here. Ubuntu’s default nginx.conf already enables gzip globally.
Enable Site and Remove Default
Activate your site configuration and disable the default:
sudo ln -sf /etc/nginx/sites-available/static /etc/nginx/sites-enabled/static sudo rm -f /etc/nginx/sites-enabled/default
This ensures your static server runs as the default site on port 80.
Test and Reload Configuration
Validate the configuration and restart Nginx:
sudo nginx -t sudo systemctl reload nginx
If the test passes, your server is ready. If not, check the error message for configuration issues.
Verify the Deployment
Test that everything works correctly:
sudo systemctl is-active nginx
ss -ltnp | grep ':80 '
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1/
You should see active, nginx listening on port 80, and HTTP status 200.
Performance Tuning by SKU
For larger VMs, optimize Nginx’s worker settings based on your SKU class:
| SKU Class | worker_connections | worker_rlimit_nofile | Log Rotation |
|---|---|---|---|
cpu_mini_amd_epyc (8 vCPU) |
1024 (default) | 1024 (default) | daily, keep 7 |
cpu_small_amd_epyc (14 vCPU) |
2048 | 4096 | daily, keep 14 |
cpu_medium_amd_epyc (28+ vCPU) |
8192 | 16384 | weekly, keep 8 |
cpu_large_amd_epyc (52+ vCPU) |
16384 | 32768 | weekly, keep 12 |
Edit /etc/nginx/nginx.conf to apply worker settings, then reload with sudo nginx -t && sudo systemctl reload nginx.
Troubleshooting
Configuration Issues
- “duplicate listen” or “default_server already in use”: Another site config still has
listen 80 default_server. Checkgrep -r "default_server" /etc/nginx/sites-enabled/and remove conflicting files. - 404 for everything: Document root is empty or path is wrong. Verify with
ls -la /var/www/html. - 403 Forbidden: Permission issue. Run
namei -l /var/www/html/index.htmland fix directory permissions.
Feature Additions
- Want directory browsing: Add
autoindex on;inside thelocation /block. - Hosting a React/Vue/Svelte SPA: Replace
try_files $uri $uri/ =404;withtry_files $uri $uri/ /index.html;for client-side routing. - Want HTTPS: See our SSL certificate guide for adding TLS termination.
Skip All of This: Deploy with an AI Agent
This entire guide exists as a tested, machine-readable recipe in the Massed Compute MCP. Instead of running commands manually, connect an AI agent and deploy with natural language.
Add this to your MCP client configuration:
{
"mcpServers": {
"massed-compute": {
"type": "http",
"url": "https://vm.massedcompute.com/api/mcp",
"headers": { "Authorization": "Bearer MC_TOKEN" }
}
}
}
Then say:
The agent will match your request against the recipe catalog (last tested on June 2, 2026), provision the right VM shape, run the setup and verification steps above, and report back with the server IP and status. If any step fails, it stops and provides troubleshooting information.
Quick Setup Reference
For experienced users, here’s the condensed setup:
# Install and configure
sudo apt-get update && sudo apt-get install -y nginx
sudo mkdir -p /var/www/html
echo "<h1>It works.</h1>" | sudo tee /var/www/html/index.html
# Create site config
sudo tee /etc/nginx/sites-available/static <<'EOF'
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
location / {
try_files $uri $uri/ =404;
}
}
EOF
# Configure gzip
sudo tee /etc/nginx/conf.d/gzip.conf <<'EOF'
gzip_types text/plain text/css text/xml application/json application/javascript application/xml application/xml+rss text/javascript image/svg+xml;
gzip_min_length 1024;
gzip_vary on;
EOF
# Enable site
sudo ln -sf /etc/nginx/sites-available/static /etc/nginx/sites-enabled/static
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
Frequently Asked Questions
01Can I serve multiple directories or domains?
This recipe creates a single-site configuration. For multiple domains, create additional server blocks in separate config files with different server_name directives. Remove default_server from additional sites.
02How do I add HTTPS support?
Install Certbot for Let’s Encrypt certificates: sudo apt-get install certbot python3-certbot-nginx, then run sudo certbot --nginx -d your-domain.com. This automatically updates your Nginx config with SSL settings.
03What’s the maximum file size I can serve?
Nginx has no built-in file size limits for static content. The practical limit is your storage capacity and network bandwidth. For very large files (>1GB), consider adding sendfile on; and tcp_nopush on; to nginx.conf for better performance.
04Can I password-protect certain directories?
Yes, use HTTP basic auth. Install apache2-utils, create a password file with sudo htpasswd -c /etc/nginx/.htpasswd username, then add auth_basic "Protected"; auth_basic_user_file /etc/nginx/.htpasswd; to the location block you want to protect.
05How do I monitor traffic and performance?
Nginx logs are in /var/log/nginx/. Enable the status module by adding location /nginx_status { stub_status on; allow 127.0.0.1; deny all; } to your server block, then check curl localhost/nginx_status for real-time stats.











