概述
用反向代理暴露服务到公网,通常要配 Nginx 虚拟主机、申请 SSL 证书、写 location 规则。改一次配一次,烦不烦?
Nginx Proxy Manager(简称 NPM)把这些全塞进一个 Web 界面。点几下鼠标就能:
- 添加域名转发到你的任意服务
- 自动申请和续期 Let’s Encrypt 证书
- 配 WebSocket、HTTP/2、自定义 404
- 内置访问日志和流量统计
项目地址:https://github.com/NginxProxyManager/nginx-proxy-manager
准备工作
一台 Linux 服务器(推荐 1 核 1G 以上),装了 Docker 和 Docker Compose。
检查一下:
docker --version
docker compose version
两个命令都有输出就行。没装 Docker 的参考这篇文章。
另外你的域名 DNS 要提前解析到服务器 IP。
安装步骤
1. 创建项目目录
mkdir -p ~/nginx-proxy-manager && cd ~/nginx-proxy-manager
2. 编写 docker-compose.yml
cat > docker-compose.yml << 'EOF'
version: "3.8"
services:
app:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
# NPM 管理面板端口
- "81:81"
# HTTP 反向代理入口
- "80:80"
# HTTPS 反向代理入口
- "443:443"
volumes:
# 持久化配置数据
- ./data:/data
# SSL 证书存储
- ./letsencrypt:/etc/letsencrypt
environment:
- DB_SQLITE_FILE=/data/database.sqlite
EOF
三个端口的分工:
| 端口 | 用途 |
|---|---|
| 81 | NPM 管理后台(Web界面) |
| 80 | HTTP 入口,自动跳转 HTTPS |
| 443 | HTTPS 入口,服务最终走这里 |
3. 启动服务
docker compose up -d
等几秒,检查容器状态:
docker compose ps
看到 nginx-proxy-manager 状态是 Up 就对了。
4. 配置防火墙
很多 VPS 默认只开了 22 端口。把 80、81、443 放开:
# 如果你用 ufw
sudo ufw allow 80/tcp
sudo ufw allow 81/tcp
sudo ufw allow 443/tcp
sudo ufw reload
云服务商(阿里云/腾讯云/Hetzner等)还得去控制台安全组放行这三个端口。
初始配置
登录面板
浏览器打开 http://你的IP:81。
默认账号密码:
Email: admin@example.com
Password: changeme
首次登录会要求改邮箱和密码。改完马上记下来。
添加代理
假设你在 3000 端口跑了一个 Web 服务,想通过 your-app.com 访问:
- 点 Hosts → Proxy Hosts → Add Proxy Host
- Domain Names:填
your-app.com - Scheme:
http(除非后端本身走 HTTPS) - Forward Hostname / IP:
127.0.0.1(如果服务在同一台机器) - Forward Port:
3000 - 点 Save
现在浏览器访问 http://your-app.com 就能看到你的服务了。
配置 SSL 证书
上面还是 HTTP,加 HTTPS 只需要多一步:
- 编辑刚才添加的代理
- 切到 SSL 标签
- 勾选 Request a new SSL Certificate
- Force SSL:勾上,强制跳转 HTTPS
- Email:填你邮箱(Let’s Encrypt 要求)
- Agree to Let’s Encrypt Terms of Service:勾上
- 点 Save
等 10-20 秒,证书就下来了。以后自动续期,不用管。
进阶用法
同一台机器多个服务
再买一个域名(或子域名),重复上面的步骤:
api.your-app.com → 127.0.0.1:8000
docs.your-app.com → 127.0.0.1:8080
grafana.your-app.com → 127.0.0.1:3000
一个域名一个代理条目,全都走 443 端口。NPM 自动根据域名分流。
WebSocket 支持
如果反向代理的是 WebSocket 服务(比如 WebSSH、实时聊天):
添加或编辑代理时,Advanced 标签里加:
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
访问列表 / 白名单
不想让全世界访问你的服务?加个访问控制:
- Access Lists → Add Access List
- 填个名字,比如
internal-only - Satisfy:Any(满足任一规则就放行)
- 添加允许访问的 IP 范围,比如
192.168.1.0/24 - 保存后在代理的 Access List 里选它
验证
确认所有东西跑起来了:
# 查看容器运行状态
docker ps | grep nginx-proxy-manager
# 看日志有没有报错
docker logs nginx-proxy-manager --tail 30
# 测试代理是否生效(换个域名测试)
curl -I https://your-app.com
输出应该包含 HTTP/1.1 200 OK 或 301 Moved Permanently。
常见问题
证书申请失败
Let’s Encrypt 要求域名能通过 80 端口被外网访问。检查:
- DNS 解析是否生效(
dig your-domain.com) - 80 端口是否被其他程序占用了
- 防火墙/安全组是否放行了 80 端口
管理面板 81 端口连不上
大概率是防火墙没放行。先在本机确认服务在跑:
curl http://127.0.0.1:81
有 HTML 输出说明 NPM 正常,去检查云服务商的安全组。
后端服务返回 502
Nginx 连不上你的上游服务。排查:
- 后端服务真的在跑吗?(
docker ps) - 地址和端口写对了吗?
- 如果后端是容器,
Forward Hostname要用容器名或 IP,不是127.0.0.1
忘记管理员密码
docker exec -it nginx-proxy-manager /app/start.sh reset
按提示输入邮箱,会生成临时密码。
和 Caddy / Traefik 的区别
| 特性 | NPM | Caddy | Traefik |
|---|---|---|---|
| 操作方式 | Web 界面 | 配置文件 | 配置文件 |
| 上手难度 | ⭐(超简单) | ⭐⭐⭐ | ⭐⭐⭐⭐ |
| 自动 HTTPS | ✅ | ✅ | ✅ |
| Docker 集成 | 手动配 | 手动配 | 原生(自动发现) |
| 动态配置 | 手动添加 | 改文件+重载 | 自动检测容器 |
NPM 适合不想碰配置文件的人。一个家庭服务器、公司内网服务,用 NPM 最省事。如果你在搞微服务、K8s,那 Traefik 更合适。