Nginx Core Configuration After Deploy: 3-Layer Structure, Static Hosting, Reverse Proxy & Multi-Site
This guide explains Nginx core configuration after one-click deployment, covering config file locations across OSes, the three-layer structure (global, events, HTTP), and three practical scenarios: static resource hosting with try_files for SPA routing, reverse proxy for CORS resolution and backend hiding, and multi-site deployment via multiple server blocks, plus troubleshooting tips for common errors.
Locating the Nginx Configuration File
The main configuration file is nginx.conf. Its default location depends on the installation method:
Linux (manual or scripted): /usr/local/nginx/conf/nginx.conf macOS (Homebrew): $(brew --prefix)/etc/nginx/nginx.conf Windows (manual):
your_nginx_install_dir/conf/nginx.confTwo Essential Operations
1. Edit the Configuration
vim /usr/local/nginx/conf/nginx.confSave and exit: press ESC, type :wq, press Enter.
2. Apply the Configuration (Required for Changes to Take Effect)
# Step 1: Validate syntax
nginx -t
# Step 2: Reload without downtime
nginx -s reloadCommon Pitfall: Forgetting to run nginx -s reload after editing. The author recounts a real incident where two engineers spent two hours debugging a config that never reloaded because neither had executed the reload command.
Three-Layer Structure of nginx.conf
The file is organized into three hierarchical blocks. An analogy: a residential complex.
Layer 1: Global Block (Complex-Wide Rules)
worker_processes 1; # Worker processes, set to CPU cores (2/4), default 1 is fine
error_log logs/error.log; # Error log path, first place to check on issues
pid logs/nginx.pid; # PID file, leave alonePrinciple: Do not modify.
Layer 2: Events Block (Traffic Rules)
events {
worker_connections 1024; # Max connections per worker, default 1024 suffices
# High concurrency (hundreds of simultaneous users) can raise to 2048/4096, but avoid excess
}Principle: Leave default; changing can cause instability.
Layer 3: HTTP Block (Core: Each Building = A Site/App)
http {
include mime.types; # Recognize html, css, js, images, etc.
default_type application/octet-stream; # Unknown files served as binary
# Performance optimizations, copy as-is
sendfile on;
keepalive_timeout 65;
# server block: each building = a site/application (focus here!)
# Deploy 2 frontend projects → write 2 server blocks
server {
listen 8080; # Listen port (match deployment port)
server_name 192.168.1.100; # Server IP, use localhost for local test
# location block: match request path, configure specific rules
location / {
root html; # ⚠️ Core param: static resource root (main thing you change)
index index.html index.htm; # Default index, leave alone
}
}
}Summary: 80% of daily config changes happen inside the HTTP block's server and location blocks. Global and events blocks should stay untouched.
Three Common Configuration Patterns (Copy, Adjust Paths, Run)
1. Static Resource Hosting (Most Common: Deploy Frontend Projects, Images, Files)
Scenario: Serve a Vue/React dist folder or local image/document directories via Nginx (e.g., http://server-ip:8080 shows the frontend app).
server {
listen 8080; # Custom port to avoid conflicts (e.g., 80, 443)
server_name 192.168.1.100; # Replace with your server IP, localhost for local test
# Frontend project (dist folder)
location / {
root /usr/local/nginx/web/dist; # Key: absolute path to your dist folder
index index.html index.htm;
try_files $uri $uri/ /index.html; # Critical: solves SPA router refresh 404 (Vue history mode)
}
# Optional: separate image folder
location /images/ {
root /usr/local/nginx/static; # Actual path becomes /static/images/
autoindex on; # Optional: enable directory listing
expires 1d; # Optional: cache images 1 day
}
# Optional: separate document folder
location /docs/ {
root /usr/local/nginx/static; # Actual path becomes /static/docs/
autoindex on;
expires 7d; # Cache documents 7 days
}
}Three Beginner Traps:
Paths must be absolute (e.g., /usr/local/xxx), not relative ( ../dist), otherwise Nginx cannot locate files.
SPA router refresh 404: always include try_files $uri $uri/ /index.html;; omitting it causes blank pages.
After editing, run nginx -t to validate, then nginx -s reload to apply, then test access.
2. Reverse Proxy Configuration (Solves CORS, Hides Backend IP)
Scenario: Frontend calls backend APIs (e.g., http://127.0.0.1:8000/api) and hits CORS errors, or you want to hide the backend server IP for security.
Core Principle: Frontend requests Nginx; Nginx forwards to backend; backend responds to Nginx; Nginx returns to frontend. Nginx acts as a middleman.
server {
listen 8080; # Frontend access port (match frontend deployment port)
server_name localhost; # Local test: localhost; production: IP/domain
# Frontend static hosting (same as above)
location / {
root /usr/local/nginx/web/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
# Core: Reverse proxy backend APIs (all /api/* requests forwarded to backend)
location /api/ {
proxy_pass http://127.0.0.1:8000/; # Key: replace with your backend address
# Note: trailing / is mandatory, else path becomes /apiuser instead of /api/user
proxy_set_header Host $host; # Pass request host
proxy_set_header X-Real-IP $remote_addr; # Pass real client IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Pass proxy chain IPs
}
# Optional: proxy another backend (e.g., /backend/*)
location /backend/ {
proxy_pass http://192.168.1.101:9000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Two Reverse Proxy Gotchas: proxy_pass must end with / (e.g., http://127.0.0.1:8000/), otherwise the proxied path breaks.
CORS is resolved automatically: frontend now calls http://localhost:8080/api/xxx (no backend IP), eliminating cross-origin issues.
Test with curl http://localhost:8080/api/user; successful backend response confirms config works.
3. Multi-Site Configuration (Multiple Projects on One Server)
Scenario: One server hosts two frontend projects (e.g., personal blog + test project) or one frontend + one backend, without extra Nginx instances. Just add multiple server blocks inside the http block.
# First site: Personal blog (port 8081)
server {
listen 8081; # Unique port per site
server_name localhost;
location / {
root /usr/local/nginx/web/blog; # Blog project path
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
# Second site: Test project (port 8082)
server {
listen 8082; # Different port
server_name localhost;
location / {
root /usr/local/nginx/web/test; # Test project path
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
# Optional: second site's reverse proxy
location /api/ {
proxy_pass http://127.0.0.1:8001/; # Second backend address
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Troubleshooting Configuration Errors (Covers 90% of Beginner Issues)
1. Validation Errors ( nginx -t Fails)
invalid number of arguments→ Parameter syntax wrong (e.g., worker_processes typed as worker_process). unknown directive → Directive misspelled (e.g., proxy_passs). no such file or directory → Path incorrect (e.g., dist folder path wrong; verify absolute path).
General fix: Check the line number in the error message, compare with provided examples, correct spelling, paths, or missing semicolons.
2. Nginx Fails to Start ( nginx Command Errors)
# 1. Check error log (most effective, shows exact cause)
tail -f /usr/local/nginx/logs/error.log
# 2. Common causes and fixes:
# Cause 1: Port occupied → Kill occupying process or change server listen port
# Cause 2: Config file error → Re-run nginx -t, fix reported errors
# Cause 3: Permission denied → Linux: use sudo nginx; macOS: run without root3. Browser Cannot Access (Nginx Runs but Returns 404/502/Timeout)
404: Either root path is wrong (Nginx can't find files) or missing try_files for SPA routing.
502: Reverse proxy misconfiguration; verify proxy_pass address is correct and backend service is running.
Timeout: Server firewall blocking the port; on Linux open with firewall-cmd --add-port=8080/tcp --permanent.
Closing Remarks
This second article fills the gaps from the previous one-click deployment guide. The three core configurations — static hosting, reverse proxy, multi-site — are copy-paste ready; just swap paths. Nginx configuration boils down to: remember the three-layer structure, apply the three patterns, and that covers daily needs.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Engineer Tang's Implementation Study Notes
Old Tang | Pseudo-full-stack tech player: writes code without going bald, manages projects without going crazy, delivers without staying up late. No formal tutorials here, only a "slacking-off" practical manual that cures system pain points. Focuses on Shell, SQL, Java, and delivery, turning complexity into simplicity and making efficiency fun.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
