# 家庭服务器从入门到精通 · 第 5 篇· NPM反向代理从安装到起飞:一条命令搞定HTTPS
本文是「家庭服务器从入门到精通」系列文章,记录了从零搭建家庭服务器的完整过程。
系列:家庭服务器从入门到精通 · 第 5 篇作者:妍杰丽云
标签:
NPM反向代理SSL1PanelDocker
到目前为止,你已经能让外网访问家里的某个端口了。但家里跑着三四十个 Docker 服务------导航站、聊天室、Jenkins、AI 面板------如果每个都在路由器上开一个端口映射,你得配几十条规则,记几十个端口号,还全是 HTTP 明文传输。NPM 就是来解决这个"幸福的烦恼"的:一个端口进,按域名分发给不同服务,就像一栋大楼的前台------访客只认门牌号,前台负责带你去对应的房间。
一、为什么需要反向代理
回顾一下前几篇的成果:
- 第 3 篇 :
yourdomain.top→ 公网 IP(DDNS) - 第 4 篇:路由器 888 → NPM:30080,8443 → NPM:30443
现在访问 `https://<你的域名> 能到达 NPM。但你有几十个服务:
makefile
导航站: <内网服务器>:5000
Jenkins: <内网服务器>:8080
VoceChat: <内网服务器>:3000
QwenPaw: <内网服务器>:9090
... ...(还有 34 个)
如果每个服务都在路由器上开一个端口映射,你得配 38 条规则,记 38 个端口号。而且大部分服务的端口还不是 HTTPS------外网明文传输,不安全,而且路由器一般配置的端口映射也是有限的,我家路由器只能配置32条。
**NPM(Nginx Proxy Manager)**就是来解决这个问题的。它的核心能力:一个端口进,按域名分发给不同内网服务。
css
外网请求
│
├─ nav.yourdomain.top:8443 → NPM → 转发到 :5000(导航站)
├─ jenkins.yourdomain.top:8443 → NPM → 转发到 :8080
├─ chat.yourdomain.top:8443 → NPM → 转发到 :3000
├─ ai.yourdomain.top:8443 → NPM → 转发到 :9090
└─ ...
路由器只需要配两条端口映射。所有流量的分发在 NPM 内部完成。
二、NPM 安装在哪个设备?
关键决策:NPM 装在哪台机器上?
我有三台"设备"(见第 1 篇)。路由器的端口映射只能指向一个 IP ,所以 NPM 必须装在要被映射的那台机器上。
| 候选 | 能不能装 NPM | 理由 |
|---|---|---|
| NAS () | 能,但不推荐 | NAS 是数据心脏,尽量少暴露公网流量 |
| AI Server (<AI 服务器>) | 能 | 但它主要负责 AI,不想掺杂网络流量 |
| webServer (<内网服务器>) | ✅ 最佳 | 本身就是对外服务机,40+ Docker 容器都在上面 |
路由器端口映射也是指向 <内网服务器>。链路一致:
xml
公网 → 路由器:8443 → <内网服务器>:30443 → NPM 容器 → 分发
公网 → 路由器:888 → <内网服务器>:30080 → NPM 容器 → 分发
三、Docker 部署 NPM
在 webServer (<内网服务器>) 上,用 1Panel 或者 docker-compose 部署。
我用的 1Panel,在应用商店搜 nginx-proxy-manager 一键安装,配置好容器和宿主机端口。
| 宿主机端口 | 容器端口 | 用途 |
|---|---|---|
30080 |
80 |
HTTP 入口 |
30443 |
443 |
HTTPS 入口 |
30081 |
81 |
管理面板 |
📌 宿主机 30080/30443 就是第 4 篇路由器映射的目标。NPM 容器内部还是用标准的 80/443,宿主机做了端口转换。
NPM 的管理面板在 `<NPM 管理地址>
makefile
Email: admin@example.com
Password: changeme
首次登录会要求改密码。
四、配置第一条反向代理
以家庭导航站为例------假设导航站跑在 <内网服务器>:5000。
4.1 添加 Proxy Host
NPM 面板 → Hosts → Proxy Hosts → Add Proxy Host:
| 配置项 | 值 | 说明 |
|---|---|---|
| Domain Names | nav.yourdomain.top |
子域名 |
| Scheme | http |
后端服务协议 |
| Forward IP | <内网服务器> |
后端服务所在 IP |
| Forward Port | 5000 |
后端服务端口 |
| SSL | 先不勾 | 后面单独配 |
保存后,NPM 自动生成 Nginx 配置。
4.2 DNS 添加子域名
去阿里云 DNS 解析控制台,给 nav.yourdomain.top 加一条 A 记录,指向你的公网 IP(和主域名一样),或者直接加一条 CNAME 指向 yourdomain.top。
💡 推荐更省事的办法:加一条泛解析
*.yourdomain.top→ 公网 IP。后面所有新增子域名自动生效,不用每次加 DNS 记录。
4.3 验证
外网(手机切 4G)访问:
xml
https://<你的域名>:<端口>
应该能看到导航站页面。
五、SSL 证书:1Panel 自动申请 + 自动续期
HTTP 是明文传输。外网访问最好使用 HTTPS。NPM 自带 Let's Encrypt 申请功能,但有个问题:Docker 容器内的 certbot 续期不稳定,需要定期手动申请,一旦忘记了,域名访问就失败了。
我的方案:用 1Panel 的证书功能接管 SSL,然后把证书"喂"给 NPM。
5.1 为什么用 1Panel 而不用 NPM 自带
| 对比 | NPM 自带 Let's Encrypt | 1Panel 证书管理 |
|---|---|---|
| 续期稳定性 | 偶发失败(尤其国内网络) | 稳定,支持多个 DNS 服务商 |
| 管理方式 | NPM 面板内操作 | 1Panel 统一管理多域名 |
| 推送证书 | 仅 NPM 自己用 | 可以推送到任意路径 |
| 通知提醒 | 无 | 证书到期前邮件/通知提醒 |
5.2 1Panel 申请证书
1Panel → 网站 → 证书 → 申请证书:
| 配置项 | 值 | 说明 |
|---|---|---|
| 类型 | Let's Encrypt | 免费,3 个月有效期 |
| 域名 | *.yourdomain.top, yourdomain.top |
泛域名证书,所有子域名通用 |
| 验证方式 | DNS-01 | 需要阿里云 API 密钥验证 |
| DNS 服务商 | 阿里云 | 1Panel 内置支持 |
| AccessKey | 填入阿里云子账号 Key | 第 4 篇创建的那个 |
| 自动续期 | ✅ 开启 | 到期前自动续,永远不过期 |
🔐 DNS-01 验证比 HTTP-01 更好------不需要开放 80 端口,而且支持泛域名证书。
申请成功后,1Panel 会显示证书详情(域名、到期时间、签发机构)。
5.3 把证书推送给 NPM
这是最妙的一步。1Panel 支持证书推送------把申请好的证书文件复制到指定路径。
在 1Panel 证书管理页面,点刚申请的证书 → 推送 → 添加推送目录:
bash
证书路径: /opt/1panel/apps/nginx-proxy-manager/nginx-proxy-manager/data/data/custom_ssl/npm-3
私钥路径: /opt/1panel/apps/nginx-proxy-manager/nginx-proxy-manager/data/data/custom_ssl/npm-3
📌 为什么要推送到
custom_ssl/npm-3?NPM 的 Docker 数据持久化在/opt/1panel/apps/nginx-proxy-manager/nginx-proxy-manager/data/下,其中custom_ssl目录存放的是 NPM 自定义 SSL 证书 。NPM 内部证书编号从npm-1开始递增,你的第一个自定义证书就是npm-3(前两个是 NPM 自带的默认证书)。
推送后,这个目录下应该有:
bash
npm-3/
├── fullchain.pem # 完整证书链
└── privkey.pem # 私钥
5.4 NPM 里启用 SSL
回到 NPM 面板 → 编辑刚才的 Proxy Host → SSL 选项卡:
| 配置项 | 值 |
|---|---|
| SSL Certificate | Custom(不要选 Let's Encrypt) |
| Certificate | 下拉选 npm-3(NPM 自动识别了 custom_ssl 下的证书) |
| Force SSL | ✅ 勾选(HTTP 自动跳转 HTTPS) |
| HTTP/2 Support | ✅ 勾选 |
保存。现在访问:
xml
https://<你的域名>:<端口>
绿色小锁出现了 ✅。
5.5 续期流程全自动
bash
1Panel 检测证书即将到期
↓
自动调用阿里云 DNS API 续期
↓
新证书生成
↓
自动推送到 custom_ssl/npm-3/
↓
NPM 自动加载新证书(检测到文件变化)
↓
无缝续期,服务不中断
全程零手动。设置一次,永久有效。
六、子域名 + 端口号如何实现内网服务暴露
现在把整个链路串一遍,以一个具体服务为例------VoceChat 聊天服务 跑在 <内网服务器>:3000。
6.1 配置链路
xml
第 1 步:DNS
阿里云 → *.yourdomain.top → 公网 IP
访问 chat.yourdomain.top → 解析到公网 IP
第 2 步:路由器端口映射
8443 → <内网服务器>:30443
流量从公网进入 webServer 的 NPM
第 3 步:NPM 反向代理
chat.yourdomain.top → <内网服务器>:3000
NPM 根据请求的 Host 头匹配规则,转发到后端
第 4 步:SSL
1Panel 泛域名证书 → 推送 custom_ssl → NPM 加载
HTTPS 加密全程
6.2 完整访问效果
| 子域名 | 内网服务 | 外网访问 |
|---|---|---|
nav.yourdomain.top:8443 |
<内网服务器>:5000 | 导航站 |
chat.yourdomain.top:8443 |
<内网服务器>:3000 | 聊天室 |
jenkins.yourdomain.top:8443 |
<内网服务器>:8080 | CI/CD |
git.yourdomain.top:8443 |
<内网服务器>:3001 | Gitea |
ai.yourdomain.top:8443 |
<AI 服务器>:7860 | AI 面板 |
注意最后一行------AI 面板跑在 AIServer (.95) 上,NPM 一样可以转发,只要 webServer 能访问到 <AI 服务器> 就行(都在同一局域网)。
七、常见问题与避坑
Q1:路由器端口映射应该指向哪个 IP?
指向运行 NPM 的那台机器。 我的 NPM 在 webServer (<内网服务器>),路由器映射就指向 .103。
如果你把 NPM 装在别的机器上,记得把路由器映射一起改。指向了错的 IP,外网请求到不了 NPM,自然一片空白。
Q2:为什么是 8443 不是 443?
443 被运营商封了(见第 5 篇)。访问 URL 必须是 https://<你的域名>:<端口>,不要忘了端口号。
💡 嫌 URL 带端口号不好看?存浏览器收藏夹。谁天天手动输 URL 呢。
Q3:新加了一个子域名服务,NPM 配了但访问不了
三步排查:
bash
# 1. DNS 生效了吗
nslookup new.yourdomain.top
# 返回公网 IP 了没有?
# 2. NPM 代理通吗(在 webServer 上测)
curl -I <内网服务地址>
# 内网直接访问后端服务正常吗?
# 3. NPM 配置对了吗
# NPM 面板 → Hosts → 检查 Domain Names 拼写、Forward IP/Port
80% 的情况是 DNS 还没生效(新加的泛解析要等几分钟传播)。
Q4:1Panel 证书推送后 NPM 找不到证书
检查两点:
- 推送的路径对不对:必须是
custom_ssl/npm-X(X 是 NPM 的证书编号) - NPM 的 data 目录是持久化的吗:Docker 映射的宿主机路径和 1Panel 推送的路径是否一致
如果路径对了但 NPM 不认,重启 NPM 容器让它重新扫描 custom_ssl 目录。
Q5:泛域名证书包含所有子域名吗
*.yourdomain.top 覆盖一级子域名:nav.yourdomain.top、chat.yourdomain.top 都算。但 xxx.nav.yourdomain.top(二级子域名)不覆盖。
家庭场景一级子域名完全够用。
Q6:NPM 能代理非 HTTP 服务吗
NPM 主要做 HTTP/HTTPS 反向代理。TCP/UDP 代理(比如 Minecraft 服务器、SSH)需要用 NPM 的 Stream 功能,在面板的 Streams 菜单里配置。
八、NPM 管理的 38 条代理概览
写到这里,我的 NPM 已经管着 38 条代理了。分类如下:
| 类别 | 数量 | 典型服务 |
|---|---|---|
| 网络工具 | 8 条 | NPM 面板、1Panel、路由器管理 |
| 开发工具 | 8 条 | Gitea、Jenkins、IT-Tools、API 文档 |
| AI 服务 | 6 条 | QwenPaw、Ollama、FunASR、Stable Diffusion |
| 影音媒体 | 7 条 | Jellyfin、有声书、视频站、Firefox Docker |
| 生活服务 | 5 条 | 导航站、VoceChat、密码管理、云盘 |
| 其他 | 4 条 | 博客、监控面板、HomeAssistant |
每一条代理的配置都一样------域名 + 后端 IP:端口 + SSL。背后的技术原理完全相同,一旦搞懂了第一条,后面 37 条就是复制粘贴的体力活。
九、总结
xml
┌──────────────────────────────────────────────────┐
│ 公网请求 │
│ https://<你的域名>:<端口> │
└────────────────────┬─────────────────────────────┘
│
┌──────┴──────┐
│ 路由器 │ 端口映射 8443→30443
│ (公网 IP) │
└──────┬──────┘
│
┌──────┴──────┐
│ webServer │ NPM 监听 30443
│ <内网服务器>│
│ │
│ ┌─────────┐ │
│ │ NPM │ │ 根据域名匹配
│ │ SSL证书 │ │ nav → :5000
│ │ (1Panel │ │ chat → :3000
│ │ 自动续) │ │ ...
│ └─────────┘ │
└──────┬──────┘
│
┌──────────┼──────────┐
│ │ │
┌────┴───┐ ┌───┴────┐ ┌──┴─────┐
│ 导航站 │ │ 聊天室 │ │Jenkins │ ...
│ :5000 │ │ :3000 │ │ :8080 │
└────────┘ └────────┘ └────────┘
核心就四步:
| 步骤 | 在哪配置 | 做了什么 |
|---|---|---|
| ① DNS 泛解析 | 阿里云 | *.yourdomain.top → 公网 IP |
| ② 端口映射 | 路由器 | 8443 → <内网服务器>:30443 |
| ③ NPM 反向代理 | NPM 面板 | 子域名 → 内网服务 IP:Port |
| ④ SSL 证书 | 1Panel | 泛域名证书 → 推送 NPM → 自动续期 |
📸 截图占位:1Panel 应用商店 NPM 安装、NPM 面板 Proxy Hosts 列表、1Panel 证书申请页面、证书推送配置、浏览器访问带绿色锁的导航站
🔗 下一篇:导航站自动化------从 NPM 数据库一键生成家庭导航页
💡 系列文章导航 本系列涵盖家庭服务器集群搭建、网络配置、Docker部署、AI应用等方方面面,适合有一定技术基础的读者。