Contents
前言
其实专业反向代理NPM(nginx Proxy Manager)更合适,只是宝塔linux面板除了做反向代理以外,还能支持源码部署,一举两得,所以一直以来我在LXC上都是跑的宝塔linux面板。不过我现在有需求在macmini上再架设一个反向代理,这个时候NPM就是最佳选择了,所以这篇文章就把安装配置NPM的过程记录一下。
部署npm
创建宿主机需要挂载到容器中的目录
mkdir -p /docker/npm/data
mkdir -p /docker/npm/letsencrypt
搭建npm容器
docker run格式搭建npm的命令如下:
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
初始化npm
使用http://宿主机ip:9481
登录npm:
默认用户名:
[email protected]
,密码:changeme
,登录后会立刻要求修改以下信息:保存后会要求修改密码:
然后正式进入配置界面:
配置反向代理
申请SSL证书(可选)
注:虽然说是可选,但是实际上,现在已经基本是必选项了,否则各种浏览器都会提示不安全,看着也糟心。进行这一步有个前提,就是你有公网IP地址,所以肯定是云主机或者有公网IP的家庭宽带,然后是有一个自己的域名且使用的常见的域名供应商,比如阿里云,腾讯云,cloudflare等。
在"SSL Certificates"菜单下点击红框中的"Add SSL Certificate":
出现如下界面:
填写完以后点击最下方的save进行保存:
成功:
注1:在cloudflare创建api的时候,要选择具体的域名以创建api,不能直接使用Global API Key,否则会报错(具体哪个版本后出现的这个问题我记不清了,好像是因为Global API Key权限太大不安全),在cloudflare创建DNS特定区域API token如下图:
注2:let’s encrypt使用DNSpod进行dns鉴权以后申请的证书和腾讯云上直接申请的1年期免费证书,都是亚洲诚信范围的证书,有同一个主域名下最多20个主机名的限制,这个对应用少的朋友没啥影响,但是对应用多的就有影响了(比如我)。所以如果是同一个主域名,又有腾讯云申请的免费证书,同时你自己用let’s encrypt申请到的证书都是共享这20个额度的,一定要注意。
创建应用的反向代理
假设在cloudflare上我已经将abc.tangwudi.xyz的A记录指向了云主机的公网ip,并且,云主机上需要反代的应用是8080端口上的应用,并启用https服务,那么根据下方步骤配置反向代理。
在红框中的"Hosts"菜单项下点击下方红框中的"Add Proxy Host":
在"New Proxy Host"的"Details"界面配置如下:
关于"Forward Hostname IP"和"Forward Port"怎么填,首先要弄清楚在你的实际环境下npm和需要反代的应用之间的位置关系。为什么这么说?因为"Forward Hostname IP"就是告诉npm用什么地址去访问你部署的应用,而你部署的应用有可能是和npm在不同的主机,也有可能是相同主机的相同bridge,也可能是相同主机的不同bridge,这就导致了npm和应用之间多种可达性,下面我们就以两种场景来进行讨论。
1、npm和应用位于不同的主机
这种方式最简单,因为这种部署方式,应用要对外发布必定做了端口映射(如果是docker方式部署就是使用了-p参数,端口映射就为:前面的端口),所以"Forward Hostname IP"直接填写另一台主机的ip,"Forward Port"直接填写发布的端口即可。
2、npm和应用位于相同的主机
这种方式就复杂了,我估计有些朋友经常被搞晕的就是这种方式,这个时候一般分3种情况:
2.1、npm和应用都接入同一个非默认的bridge
例如使用docker run命令在部署npm和应用的时候都使用了-net=public-net,那么此时就可以在"Forward Hostname IP"直接使用应用的容器名来代替ip,同时"Forward Port"就直接填写应用容器真实端口即可。
2.2、npm和应用都在默认bridge(非docker desktop环境)
默认没有用-net参数的容器都被分配到了默认网桥,默认bridgen与宿主机连接的网卡(docker0)的ip一般都为172.17.0.1(debian上可以用ip addr show docker0命令确认),所以这个时候"Forward Hostname IP"可以直接填写172.17.0.1,"Forward Port"直接填写应用的对外映射端口(既-p参数:前面的端口)。
其实,只要应用在默认bridge就可以用这种方式,就算npm在其他非默认bridge,也可以用172.17.0.1和应用的对外映射端口与应用通信。而这种方式其实可以扩展开来,如果有其他bridge,其网关ip 172.18.0.1,172.19.0.1等都可以有类似的使用方式。
2.3、npm和应用都接入了默认网桥(docker desktop环境)
"Forward Hostname IP"可以直接填写宿主机ip,"Forward Port"直接填写宿主机上映射的真实端口即可(既-p参数:前面的端口)。
为何要区分"docker desktop环境"和"非docker desktop环境"?因为"docker desktop环境"中的虚拟网卡情况和"非docker desktop环境"是不一样的,比如我的macmini是通过docker desktop部署的docker环境,其并没有docker0这个网卡:
所以"ping 172.17.0.1"这个地址也是不通:
而另一个debian上直接部署的docker环境,是有docker0这个网卡的:
也能ping通172.17.0.1:
至于常用的127.0.0.1,这个是操作系统层面反向代理通常使用的,例如宝塔linux面板来做反向代理,或者直接以源码方式部署的nginx来做反向代理等,一般并不适用于通常npm的容器部署方式。
然后配置https,在SSL菜单下做如下图中的设置,然后点击"save"保存:
成功:
注:在"New Proxy Host"界面的"Advanced"菜单,可以填写高级参数,例如传送给后端应用的域名、端口等等,一些特殊情况下,需要反向代理传递不同于访问请求中host字段的域名或者端口的时候,需要使用到该高级参数,例如,我希望访问https://abc.tangwudi.xyz
的请求,到反向代理以后,反向代理传递给后端应用的host实际上是def.tangwudi.xyz,则配置如下:
代码如下:
location /
{
proxy_pass http://172.17.0.1:8080;
proxy_set_header Host def.tangwudi.xyz;
proxy_set_header X-Real-IP remote_addr;
proxy_set_header X-Forwarded-Forproxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST remote_addr;
proxy_http_version 1.1;
proxy_set_header Upgradehttp_upgrade;
}
注:Advanced里的配置会覆盖"Details"菜单里的设置。
反代GUI的访问
前面我们使用的http://宿主机ip:9481
方式来访问npm的gui,这种方式内网里倒是没问题,但是如果是从公网上访问肯定就不行,太不安全了。那么,这个时候可以用npm自己来反代gui页面的访问即可,如下:
之后就可以用
https://npmgui.tangwudi.xyz:9443
来访问gui了(前提是路由器上也映射了9443到192.168.10.133的9443端口)。