跪拜 Guibai
← All articles
Frontend

Nginx from Zero to a Working Reverse Proxy, with Brew and Self-Signed SSL

By 驳是 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Most developers encounter Nginx only when something breaks or when a project needs to go live. Knowing the exact path differences a Homebrew install introduces, the trailing-slash requirement on `proxy_pass`, and how to generate a local trusted certificate removes the friction that otherwise sends people down hours of search-engine detours.

Summary

Nginx is the default front door for most web projects, but its official documentation buries the practical details beginners need. This walkthrough starts with the correct pronunciation ("engine x") and moves straight into installation on macOS via Homebrew, where the default port shifts to 8080 and the config directory becomes `servers` instead of `conf.d`. Mixing `brew services` and native `nginx` commands for start/stop creates a "Bootstrap failed: 5" error, so picking one method and sticking with it avoids a reinstall.

The configuration section skips theory and builds two real server blocks: one for static hosting with `try_files` for SPAs, and one that proxies an entire site from a CDN origin. A critical detail is that `proxy_pass` to an upstream must end with a trailing slash or Nginx returns 404s. The guide then layers on local HTTPS by generating a self-signed certificate with `openssl` and configuring a 301 redirect from port 80 to 443, along with the browser trust workarounds needed for local dev.

A reference table of 22 built-in Nginx variables and a one-liner shell command to extract all configured `server_name` values from a running instance close out the piece, giving developers a quick way to audit which domains a machine is handling.

Takeaways
Homebrew installs Nginx on port 8080, with a docroot at `/opt/homebrew/var/www` and sub-configs in `servers/`, not `conf.d/`.
Mixing `brew services start nginx` and `nginx -s stop` causes a "Bootstrap failed: 5" error; pick one control method and stay with it.
Change `include servers/*;` to `include servers/*.conf;` so that dropped-in key or pem files don't break the config load.
`nginx -s quit` drains active requests before exiting; `nginx -s stop` kills them immediately. Production should use `quit`.
For static hosting, `try_files $uri $uri/ /index.html;` handles SPA client-side routing without extra rewrite rules.
When proxying to a CDN, `proxy_pass https://somecdn.com/path/;` must end with a trailing slash, or Nginx returns 404.
Generate a 10-year self-signed cert with `openssl req -x509 -newkey rsa:4096 -nodes -keyout local.key -out local.crt -days 3650`.
A 301 redirect from port 80 to 443 is the standard way to force HTTPS in a local dev Nginx setup.
Per-server access and error logs prevent one noisy domain from drowning out another during debugging.
A one-liner `nginx -T | grep server_name` extracts all configured domains, though it includes commented-out entries and doesn't confirm the server is running.
Conclusions

The Homebrew Nginx package changes three defaults (port, docroot, sub-config directory) that are undocumented in Nginx's own manuals, so a developer moving between macOS and Linux will hit silent mismatches.

Nginx's `proxy_pass` trailing-slash behavior is a classic footgun: omitting it replaces the matched location path instead of appending to it, which breaks CDN-proxied SPAs in a way that looks like a routing bug.

Self-signed certificates are treated as a toy, but combined with a 301 redirect and browser trust overrides, they replicate a production HTTPS pipeline closely enough to catch mixed-content and CORS issues before deployment.

Concepts & terms
try_files
An Nginx directive that checks for the existence of files in order and serves the first one found. The common SPA pattern `try_files $uri $uri/ /index.html` falls back to index.html for any path that doesn't match a physical file, letting client-side routing take over.
proxy_pass trailing slash
When `proxy_pass` includes a URI path, a trailing slash determines whether Nginx replaces or appends the matched location. `proxy_pass http://backend/` with a slash replaces the location prefix; without the slash, the full original URI is appended, which often causes 404s.
self-signed certificate
An SSL/TLS certificate signed by its own private key rather than a trusted Certificate Authority. Browsers flag it as untrusted, but it enables full HTTPS locally for testing Service Workers, secure cookies, and mixed-content policies without purchasing a certificate.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗