Home Data Center - Application Publishing: Reverse Proxy Edition (Part 2)
This article was last updated 287 days ago. The information within may have evolved or changed; if anything is outdated or broken, please feel free to leave a message in the comments section.
Article Abstract
Deploying a reverse proxy in a home broadband environment requires solving the problems of application domain name binding and parameter passing. By assigning a third-level domain name to each application and configuring dynamic resolution to a public IP, combined with reverse proxy tools (such as NGINX, Baota Panel) to set HTTP header parameters like Host and X-Real-IP, it ensures that requests are correctly routed and the client's real information is passed. The solution supports IPv4 multi-dialing scenarios and IPv6 environments, and dynamic resolution is recommended using iKuai or the DDNS-Go plugin. In practical applications, configurations need to be adjusted according to backend service requirements; for example, applications like Nextcloud need to have their access domain names hardcoded in advance to ensure access link integrity and policy matching, making it suitable for home data centers and personal service publishing scenarios.
Qwen3-14B · 2026-06-18

In the previous article, we introduced which method should be used to deploy a reverse proxy for home broadband under different circumstances. In this next article, we will introduce the working principles and key configuration points of reverse proxies.

For a reverse proxy to work properly, two problems need to be solved: the binding of applications and domain names, and the correct configuration of passing parameters.

Reasonably plan the third-level domain names and resolution results corresponding to the applications

Because the basic working principle of a reverse proxy is to identify which target application the request needs to access based on the content of the host field in the HTTP request, the first step is to assign corresponding third-level domain names to different applications (for example, if the second-level domain is example.com, then app1 corresponds to app1.example.com, app2 corresponds to app2.example.com, and so on), and the addresses resolved by each third-level domain name need to correspond to the public IPv4 address of the home broadband (if it is multi-dialing, they need to correspond to the IPv4 public addresses of different WAN ports according to the plan; you can choose any port you like for external publishing, as both Tencent and Alibaba Cloud CDN support customizing the origin server's port).


Why not talk about IPv6? As we mentioned in the previous article, having a public IPv6 address is much simpler; all third-level domain names corresponding to the applications just need to be resolved to the public IPv6 of the reverse proxy device. The IPv4 environment is more complex, so we will use IPv4 addresses as an example. In addition, if the home broadband mentioned in the previous article does not have a public address, you can only use Cloudflare's Tunnel method for deployment. In fact, the access speed feels about the same as Cloudflare's deployment method with a public address, or maybe even faster (because going through the public network makes it easier to be targeted and negatively optimized).


Achieving this step requires that the third-level domain name corresponding to each application can be dynamically resolved to the public IP of the home broadband. The dynamic domain name client is recommended to use the built-in one in iKuai, which supports multiple mainstream domain name providers, and there is no limit on the number of resolved third-level domain names:

image.png

Other methods are also fine, such as the dynamic domain name plugin DDNS-Go in the Merlin software market (if I remember correctly~, it should also support multiple domain name providers), as long as there is no limit on the number of supported records, because one is far from enough.

Pass the required parameters to the upstream application server

The server side of many applications needs to make some strategic judgments based on the content of the requests sent by the client (such as host, referer, X-Real-IP, X-Forwarded-For, etc., in the HTTP request). However, after passing through the reverse proxy, by default, the requests sent by the reverse proxy may not necessarily carry this information (as we said in the previous article, client-to-reverse-proxy and reverse-proxy-to-application are two completely independent processes). The result is a failure to match the application server-side policies, leading to access failure. Therefore, the reverse proxy needs to insert some required information brought in the client request into the request it sends out.

Achieving this step only requires correct configuration in the reverse proxy software according to the actual needs of the application side (for example, both Nextcloud and WordPress need to have their access domain names hardcoded in the application in advance). There are no specific requirements on what software to use to implement the reverse proxy; you can use whatever you are used to: Baota Linux Panel, 1Panel, NPM, or NGINX deployed from source are all fine.

Taking my NGINX configuration as an example to briefly explain the key parameters (this configuration can be placed in the main NGINX configuration, but for better organization, it is recommended to create a separate reverse proxy configuration file for each domain name and then reference it in the main configuration):


proxy_set_header Host host:server_port;  # determines the host field content and access port when the reverse proxy sends requests to the application proxy_set_header X-Real-IP;remote_addr; # assigns the value of variable ' remote_addr' to the X-Real-IP field;proxy_set_header X-Forwarded-For proxy_set_header X-Real-IP;proxy_add_x_forwarded_for; 1TP6 http_upgrade;connection_upgrade; upstream_cache_status;static_filesDpoqv14 0; uri ~* "\.(gif|png|jpg|css|js|woff|woff2)" ) static_filesDpoqv14 1;static_filesDpoqv14 = 0 )

Let's focus on the parameter `proxy_set_header Host`. There are several ways to assign values to variables:

1、$host
Only passes the domain name, without port information. This situation is suitable when the reverse proxy has ports 80 and 443 (for example, the reverse proxy is built on a cloud host). Since ports 80 and 443 are well-known, there is no need for special explanation; this is called a tacit understanding.

2、$host:$server_port
Passes the domain name and port information accessed when the client request reaches the reverse proxy. This is generally the case when the reverse proxy's external listening port is non-standard (not ports 80 and 443). By default, this is the case if the home broadband has a public IP address and is directly published externally. In this case, the information of the reverse proxy's listening port also needs to be told to the application (actually, this statement is inaccurate; strictly speaking, this listening port should be the actual port accessed by the client request, while the public IP address and port are both on the router, so it should be the port mapped on the egress router. However, for convenience, I set the reverse proxy's listening port and the port mapped on the router to be the same). The reason for saying this is that some applications will directly generate access links in the response, and these access links cannot be accessed if they do not carry the real port information published externally.

3、$host:$proxy_port
Passes the domain name accessed when the client request reaches the reverse proxy and the port of the backend application (currently not used, don't know in what scenario it is used)

4、$http_host
Passes the content of the host field when the client request reaches the reverse proxy, which under normal circumstances is equivalent to$host:$server_port, and under abnormal circumstances, if the host field is empty, nothing is displayed, which is quite awkward, so generally it is safer to use$host:$server_port


In addition,proxy_set_header X-Real-IP $remote_addr,proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for,proxy_set_header REMOTE-HOST $remote_addrThese three are all for passing the client's real access address to the backend application (because by default, the application can only see the IP address of the reverse proxy). So, what is the difference between them?

X-Real-IP和REMOTE-HOSTThere is no difference between these two in my configuration. You can see that the values of these two fields are both assigned by the variable$remote_addr, corresponding to the source IP address when the client request reaches this reverse proxy. The key lies inX-Forwarded-For, and its corresponding variable$proxy_add_x_forwarded_for, which is composed of two parts of variables:$http_x_forwarded_for与$remote_addr, separated by commas. So if it passes through multiple proxy servers, and each proxy server is configured withproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, thenX-Forwarded-Forthe display result in this field will be: Proxy Server 3 IP, Proxy Server 2 IP, Proxy Server 1 IP, Client Real Address.


Finally, the upstream server of the reverse proxy is not necessarily the application; it could also be another reverse proxy, such as a web application firewall working in the form of a reverse proxy, and CDN is essentially a reverse proxy as well. This shows that when a client request reaches the real application side, it may have passed through N layers of proxies, which further highlights the importance of correctly configuring parameter passing at each proxy layer.

For specific reverse proxy configuration steps, please refer to the article:Linux Panel Series: Configuring Reverse Proxy and Publishing Using Non-443 Ports和Docker Series: Building Your Own Reverse Proxy Based on NPM Using Docker。

View Related Categories · 3 Matches
📌 Content Structure Prompt:
This content is part of the following knowledge map, where you can view the complete content path: Blog Knowledge Map。
📎 Related Articles
Share this article
The blog content is original, please indicate the source when reposting! The RSS address of the blog is:https://blog.tangwudi.com/feed, welcome to subscribe; if needed, you can join theTelegram Groupto discuss questions together.
No Comments

Send Comment Edit Comment


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗ
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
Kaomoji
Emoji
Little Dinosaur
Flower!
Previous
Next
       

👋 Welcome to “Wudi's Personal Blog”

Here, long-term exploration is mainly carried out around the following directions:

🧱 Personal Digital Infrastructure and Blog System Construction
☁️ Cloudflare and Network Architecture Practice
🧠 AI and Knowledge System Exploration
🛡️ Network Security and Access Optimization
🎵 Music and Sound Cognition
👁️ Cognitive Perspectives and Worldviews