Nginx Proxy Manager 搭建:Web界面管理反向代理和SSL证书

概述

用反向代理暴露服务到公网,通常要配 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

三个端口的分工:

端口用途
81NPM 管理后台(Web界面)
80HTTP 入口,自动跳转 HTTPS
443HTTPS 入口,服务最终走这里

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 访问:

  1. Hosts → Proxy Hosts → Add Proxy Host
  2. Domain Names:填 your-app.com
  3. Scheme:http(除非后端本身走 HTTPS)
  4. Forward Hostname / IP:127.0.0.1(如果服务在同一台机器)
  5. Forward Port:3000
  6. Save

现在浏览器访问 http://your-app.com 就能看到你的服务了。

配置 SSL 证书

上面还是 HTTP,加 HTTPS 只需要多一步:

  1. 编辑刚才添加的代理
  2. 切到 SSL 标签
  3. 勾选 Request a new SSL Certificate
  4. Force SSL:勾上,强制跳转 HTTPS
  5. Email:填你邮箱(Let’s Encrypt 要求)
  6. Agree to Let’s Encrypt Terms of Service:勾上
  7. 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";
}

访问列表 / 白名单

不想让全世界访问你的服务?加个访问控制:

  1. Access Lists → Add Access List
  2. 填个名字,比如 internal-only
  3. Satisfy:Any(满足任一规则就放行)
  4. 添加允许访问的 IP 范围,比如 192.168.1.0/24
  5. 保存后在代理的 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 OK301 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 的区别

特性NPMCaddyTraefik
操作方式Web 界面配置文件配置文件
上手难度⭐(超简单)⭐⭐⭐⭐⭐⭐⭐
自动 HTTPS
Docker 集成手动配手动配原生(自动发现)
动态配置手动添加改文件+重载自动检测容器

NPM 适合不想碰配置文件的人。一个家庭服务器、公司内网服务,用 NPM 最省事。如果你在搞微服务、K8s,那 Traefik 更合适。

这篇文章对你有帮助吗?