Readers who have seen my previous articles might remember that I discussed setting up a customized Google mirror in my blog. The Google mirror setup is achieved using an Nginx reverse proxy, with customization handled by Nginxâs built-in `ngx_http_sub_module`. Recently, I also configured load balancing for the associationâs Google mirror, which was a great learning experience. I must say, Nginx is truly an excellent web server!

First, let me share some practical issues I encountered while configuring Nginx reverse proxy and their solutions.
1. Single Host, Multiple Web Services Without Using Domain and Port Access
This issue took me quite some time to figure out, but I eventually came up with a solution that works. I directly added the configuration to the main Nginx configuration file, `nginx.conf`. My approach was to perform a local reverse proxy to map services to their corresponding ports.

For example, I configured a reverse proxy for GitHub. Since I frequently browse GitHub, but access can be slow in my region, I set up a reverse proxy on a server in Hong Kong.

I set up the reverse proxy in the second `server` block, which listens on port 8040. This allows direct access to GitHub using `IP:8040`. However, I also assigned a subdomain pointing to my server, which, by default, listens on port 80. To handle this, I configured a local reverse proxy in the first `server` block to listen for requests from `git.cdtu.site` and forward them to the local port 8040, achieving the desired result.
I reviewed some other solutions online and included a comparison screenshot from another article.
Nginx Multi-Domain Sharing Port 80 Configuration
Adding Nginx Virtual Host Configuration
Create a `vhosts` folder in the Nginx installation directory to store configuration files for each site. Each site corresponds to a virtual host configuration.
Modify the main Nginx configuration file first.

In the main configuration file, the `server`-related content is not configured directly but is instead placed in separate files. The most critical configuration is: `include /usr/local/nginx/vhosts/*.conf;`, which means including all virtual host configuration files in the `vhosts` directory within the `http` module.

Essentially, this approach is similar to mine, except that each `server` block is placed in its own configuration file.

After adding the virtual host configurations, include them in the main configuration file with `include /usr/local/nginx/vhosts/*.conf;`, and then restart Nginx.
2. Common Configurations in Reverse Proxy
The Role of `proxy_set_header` in Nginx
Nginx includes the `ngx_http_proxy_module` to support reverse proxy functionality. The `proxy_set_header` directive is part of this module and is used to set HTTP headers in the configuration file. The meanings of the values set here are identical to those in HTTP requests, except for `Host` and `X-Forwarded-For`.
The `Host` header specifies the hostname of the request. When Nginx is used as a reverse proxy, if the backend server has anti-hotlinking or routing logic based on the `Host` field in the HTTP header, failing to rewrite the `Host` field can cause requests to fail. By default, the reverse proxy server forwards requests with the `Host` field set to the value specified in the `proxy_pass` directive.
Similarly, the `X-Forwarded-For` header indicates the origin of the HTTP request. If the reverse proxy server does not rewrite this header, the backend server will see all requests as originating from the proxy server. This can lead to issues if the backend server has anti-attack mechanisms, as it might block the proxy server. Therefore, itâs common to include the following configurations in a reverse proxy setup:
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Here, `$host` and `$remote_addr` are Nginx variables that can be used directly in configuration files. If the `Host` header is missing from the request, `$http_host` will be empty, but `$host` will default to the main domain name. Therefore, `$host` is generally preferred over `$http_host` to avoid issues when the `Host` header is missing.
The `X-Forwarded-For` header, abbreviated as XFF, represents the original clientâs IP address in an HTTP request. It is only added when the request passes through an HTTP proxy or load balancer. The format is:
`X-Forwarded-For: client1, proxy1, proxy2`
The leftmost value (`client1`) is the original clientâs IP address, and each proxy server appends its IP address to the right.
Blocking Specific `user_agent` Access and Redirecting Based on `user_agent`
For example, on our associationâs Google mirror site, I wanted to prevent search engines from indexing it. To achieve this, I blocked web crawlersâ `user_agent` values and returned a 403 status code.

if ($http_user_agent ~* (baiduspider|360spider|haosouspider|googlebot|soso|bing|sogou|yahoo|sohu-search|yodao|YoudaoBot|robozilla|msnbot|MJ12bot|NHN|Twiceler)) {
return 403;}</
Here, Iâll use the configuration file I wrote for load balancing a Google mirror as an example. In the upstream
block, there are two servers: one is the reverse proxy on the local machine, and the other is a Google mirror I set up on another VPS. You can directly specify the IP and port. By default, I chose the round-robin method.
Why do I say I encountered some pitfalls? Because when I was reviewing configuration files written by others, I noticed their upstream
name was directly set as a domain name. For example, upstream www.xxxxxx.com
. Similarly, in the proxy_pass
configuration, they wrote proxy_pass http://www.xxxxxx.com
. I mistakenly thought this was meant to reverse proxy to the website at that domain, rather than being the name of the upstream
. I was stuck on this for quite a while. Eventually, I decided to give it a try and replaced the part after proxy_pass
with http://
followed by the upstream
name, and it finally worked.
I hope you donât fall into the same trap when configuring this. Of course, the mistakes you make yourself tend to leave a deeper impression.