Preface
Actually, a professional reverse proxy like NPM (Nginx Proxy Manager) is more suitable. However, since the aaPanel Linux panel can support source code deployment in addition to serving as a reverse proxy, killing two birds with one stone, I have always run aaPanel Linux panel on LXC. But now I need to set up another reverse proxy on my Mac Mini, and at this time, NPM is the best choice. Therefore, this article records the process of installing and configuring NPM.
Deploy npm
Create directories on the host that need to be mounted to the container
mkdir -p /docker/npm/data
mkdir -p /docker/npm/letsencrypt
Build the npm container
The command to build npm in docker run format is as follows:
docker run --name npm -d --restart=always \
-p 9480:80 \ #http代理端口,请根据实际环境修改,如果部署在公网上又有合法80端口就填80
-p 9481:81 \ #gui管理端口,请根据实际环境修改
-p 9443:443 \ #https代理端口,请根据实际环境修改,如果部署在公网上又有合法443端口就填443
-v /docker/npm/data:/data \ # 映射宿主机对应目录到npm容器里的data目录
-v /docker/npm/letsencrypt:/etc/letsencrypt \ #这里是存放lets encrypt证书的地方,如果需要外部更新,比如OHTTPS之类的供应商定期来更新,就需要操作这个目录,当然,lets encrypt本身申请的证书也在这个目录里面
jc21/nginx-proxy-manager:latest
Initialize npm
Usehttp://宿主机ip:9481Log in to npm:

Default username:
[email protected], password:changeme, and you will be asked to modify the following information immediately after logging in:
After saving, you will be asked to change your password:

Then officially enter the configuration interface:

Configure reverse proxy
Apply for SSL certificate (optional)
Note: Although it is said to be optional, in reality, it is basically a must-have now, otherwise various browsers will prompt that it is insecure, which is also annoying to look at. There is a prerequisite for this step, which is that you have a public IP address, so it must be a cloud host or home broadband with a public IP, and then you have your own domain name and use a common domain name provider, such as Alibaba Cloud, Tencent Cloud, Cloudflare, etc.
Under the "SSL Certificates" menu, click "Add SSL Certificate" in the red box:

The following interface appears:

After filling it out, click "Save" at the bottom to save:

Success:

Note 1: When creating an API in Cloudflare, you must select a specific domain name to create the API, and you cannot directly use the Global API Key, otherwise an error will be reported (I can't remember exactly which version this problem appeared after, it seems to be because the Global API Key has too much permission and is insecure). The creation of a DNS specific zone API token in Cloudflare is shown in the figure below:


Note 2: Certificates applied for after Let's Encrypt uses DNSpod for DNS authentication and 1-year free certificates applied for directly on Tencent Cloud are both TrustAsia certificates, which have a limit of a maximum of 20 hostnames under the same primary domain name. This has little impact on friends with few applications, but it does affect those with many applications (like me). Therefore, if it is the same primary domain name, and you have a free certificate applied for from Tencent Cloud, and at the same time the certificates you applied for using Let's Encrypt yourself all share this 20-quota limit, you must pay attention.
Create a reverse proxy for the application
Assuming that on Cloudflare I have pointed the A record of abc.tangwudi.xyz to the public IP of the cloud host, and the application on the cloud host that needs to be reverse proxied is the application on port 8080, and the HTTPS service is enabled, then configure the reverse proxy according to the steps below.
Under the "Hosts" menu item in the red box, click "Add Proxy Host" in the red box below:

Configure as follows in the "Details" interface of "New Proxy Host":

Regarding how to fill in "Forward Hostname IP" and "Forward Port", you must first clarify the positional relationship between npm and the application that needs to be reverse proxied in your actual environment. Why say so? Because "Forward Hostname IP" tells npm what address to use to access your deployed application, and your deployed application may be on a different host from npm, or on the same bridge of the same host, or on different bridges of the same host. This leads to multiple reachabilities between npm and the application. Below we will discuss two scenarios.
npm and the application are located on different hosts
This method is the simplest. Because in this deployment method, the application must have port mapping to be published externally (if deployed via Docker, the -p parameter is used, and the port mapping is the port before the colon :). Therefore, "Forward Hostname IP" can be directly filled with the IP of the other host, and "Forward Port" can be directly filled with the published port.
npm and the application are located on the same host
This method is complicated. I estimate that some friends are often confused by this method. At this time, it is generally divided into 3 situations:
1. Both npm and the application are connected to the same non-default bridge
For example, if the docker run command is used to deploy both npm and the application with -net=public-net, then at this time you can directly use the application's container name instead of the IP in "Forward Hostname IP", and at the same time, "Forward Port" can be directly filled with the real port of the application container.
2. Both npm and the application are in the default bridge (non-Docker Desktop environment)
By default, containers that do not use the -net parameter are assigned to the default bridge. The IP of the network card (docker0) connecting the default bridge to the host is generally 172.17.0.1 (which can be confirmed with the ip addr show docker0 command on Debian). Therefore, at this time, "Forward Hostname IP" can be directly filled with 172.17.0.1, and "Forward Port" can be directly filled with the application's externally mapped port (i.e., the port before the colon in the -p parameter).
In fact, as long as the application is in the default bridge, this method can be used. Even if npm is in another non-default bridge, it can also communicate with the application using 172.17.0.1 and the application's externally mapped port. And this method can actually be expanded. If there are other bridges, their gateway IPs such as 172.18.0.1, 172.19.0.1, etc., can have similar usage.
3. Both npm and the application are connected to the default bridge (Docker Desktop environment)
"Forward Hostname IP" can be directly filled with the host IP, and "Forward Port" can be directly filled with the real port mapped on the host (i.e., the port before the colon in the -p parameter).
Why distinguish between "Docker Desktop environment" and "non-Docker Desktop environment"? Because the virtual network card situation in the "Docker Desktop environment" is different from that in the "non-Docker Desktop environment". For example, my Mac Mini is a Docker environment deployed through Docker Desktop, which does not have the docker0 network card:

Therefore, pinging the address "172.17.0.1" also does not work:

On the other hand, another docker environment deployed directly on Debian does have the docker0 network card:

And it can also ping 172.17.0.1:

As for the commonly used 127.0.0.1, this is typically used for reverse proxying at the operating system level, such as using the Baota Linux panel for reverse proxying, or using Nginx deployed directly from source code for reverse proxying, etc. It is generally not applicable to the usual container deployment method of npm.
Then configure HTTPS, make the settings in the SSL menu as shown in the figure below, and then click "save" to save:

Success:

Note: In the "Advanced" menu of the "New Proxy Host" interface, you can fill in advanced parameters, such as the domain name, port, etc., passed to the backend application. In some special cases, when the reverse proxy needs to pass a domain name or port different from the host field in the access request, this advanced parameter needs to be used. For example, if I want to accesshttps://abc.tangwudi.xyzrequests, and after reaching the reverse proxy, the host passed by the reverse proxy to the backend application is actually def.tangwudi.xyz, then the configuration is as follows:

The code is as follows:
location / remote_addr;proxy_add_x_forwarded_for; remote_addr;http_upgrade;
Note: The configuration in "Advanced" will override the settings in the "Details" menu.
Reverse proxy GUI access
Previously, we used thehttp://宿主机ip:9481method to access the NPM GUI. While this method works fine on the intranet, it is definitely not feasible to access it from the public internet as it is too insecure. In this case, you can use NPM itself to reverse proxy the access to the GUI page, as follows:


After that, you can use
https://npmgui.tangwudi.xyz:9443to access the GUI (provided that port 9443 is also mapped to port 9443 of 192.168.10.133 on the router).