A modular, zero-cost, and fully configurable Nginx reverse proxy setup for macOS. This toolkit allows you to intercept traffic for any production domain (e.g., ssl-proxy-setup.net) and route it to your local development server with fully trusted SSL.
When developing locally, you often need to simulate a production environment, specifically HTTPS and real domain names. This toolkit automates:
- Local DNS: Routing production domains to
127.0.0.1. - SSL Orchestration: Creating locally-trusted certificates using
mkcert. - Reverse Proxying: Forwarding specific paths or entire domains from port 443 to your local dev ports (e.g.,
8083). - Project Switching: Instantly swapping between different proxy configurations.
The toolkit is self-contained. All configurations, certificates, and logs stay within this directory.
.
├── manage.sh # Main CLI controller
├── www/ # Static landing page (index.html)
├── conf/ # Store for all project-specific configs
│ ├── nginx.conf # SYMLINK: Points to the active project
│ └── project-a.conf # Actual config file
├── certs/ # Generated .pem certificates (Git ignored)
├── logs/ # Access/Error logs and PID files (Git ignored)
└── scripts/ # Internal automation logic (cert/host/switch)
To run this setup, you must have the following installed via Homebrew:
- Nginx: The core engine used for proxying.
- mkcert and nss: A simple tool for making locally-trusted development certificates. It creates a local CA in your system keychain.
brew install nginx
brew install mkcert
brew install nssCrucial: Run mkcert -install once after installing to trust the Root CA.
mkcert -installThe toolkit uses a "Master" script (manage.sh) to control the Nginx lifecycle.
| Command | Action |
|---|---|
./manage.sh start |
Launches Nginx using the currently linked config (requires sudo for port 443). |
./manage.sh stop |
Gracefully shuts down the local Nginx instance. |
./manage.sh reload |
Reloads the configuration without dropping connections. |
./manage.sh logs |
Streams the "Flow Logs" (access logs) to your terminal. |
The folder conf/ acts as a library of configurations. Nginx is hard-coded to look for a file named nginx.conf. Instead of a real file, we use a Symlink:
- Switching: When you run
./manage.sh switch <project>.conf, the script deletes the existingnginx.conflink and points it to your chosen project file. - Benefit: This allows you to have 20 different project setups ready to go, but only one active at a time, keeping port 443 clean.
You don't need to write Nginx boilerplate by hand. Use the bootstrap command to generate everything at once.
Run the create command with your desired domain and the local port your app is running on:
./manage.sh create ssl-proxy-setup.net 8083
Boostrap handles this automatically:
- Adds
127.0.0.1 ssl-proxy-setup.netto your/etc/hosts. - Generates SSL certificates in
/certs. - Creates a new config file
conf/ssl-proxy-setup.net.confwith optimized proxy headers.
Once created, link the config and start the service:
./manage.sh switch ssl-proxy-setup.net.conf
./manage.sh start
Make sure that your hosts file maps the new domain to your localhost
./manage.sh host ssl-proxy-setup.net.conf
# or edit it manually
#
sudo vim /etc/hosts
# then add
#
127.0.0.1 ssl-proxy-setup.net
# and save with esc + :wq!If you want to check your /etc/hosts file just run
cat /etc/hostsand look for an entry link
127.0.0.1 ssl-proxy-setup.netVisit https://ssl-proxy-setup.net.
- The Root (/) will show your custom landing page.
- All Sub-paths (/*) will be forwarded to your local server at
localhost:8083.
Chrome uses the macOS System Keychain to verify certificates. Follow these steps to ensure Chrome trusts your local proxy:
- Trust the CA: Ensure you have run
mkcert -installonce and entered your macOS password when prompted. - Verify Keychain:
- Open Keychain Access.
- Search for
mkcert. - Ensure
mkcert development CAis present and marked with a green checkmark (Always Trust).
- Restart Chrome: Completely quit Chrome (
Cmd+Q) and relaunch it to clear the SSL cache. - Flush Sockets: If the "Not Secure" warning persists, go to
chrome://net-internals/#socketsand click Flush socket pools.
MIT
Ideas and pull requests are always welcome. Same for coffee contributions
