1. 安装npm
mkdir npm && cd npm
vim docker-compose.yml
2. 将下面的内容复制到 docker-compose.yml 文件:
services:
npm:
image: 'jc21/nginx-proxy-manager:latest'
networks:
- npm
restart: unless-stopped
ports:
- '80:80' # Nginx 的 80 端口
- '443:443' # Nginx 的 443 端口
- '81:81' # Nginx Proxy Manager 的管理端口
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
# 定义网络以便 NPM 与其他容器通信
networks:
npm:
name: npm
attachable: true
启动 NPM:
docker compose up -d
在服务正常启动的情况下,现在已经可以通过 http://{服务器公网 IP}:81 访问 NPM 的网页端了。
信息
如果无法通过端口访问到 NPM,可以检查是否在服务器提供商开放了 81 端口。

首次进入页面会提示创建管理员账户,需要注意的是:邮箱一定要是合法邮箱,后续涉及到 SSL 证书签发。
至此,我们已经完成了 Nginx Proxy Manager 的搭建,之后就可以用它给我们的 Halo 或者其他 Web 应用做反向代理了。
配置 Halo 的反向代理
-
配置 Halo 的 Docker 编排,需要将
npm的网络加入到 Halo 的容器,之后就可以使用 Halo 的服务名作为hostname在 NPM 的内部进行反向代理了。services:
halo:
image: registry.fit2cloud.com/halo/halo:2.25
container_name: halo
restart: on-failure:3
depends_on:
halodb:
condition: service_healthy
networks:
# 加入 npm 网络
- npm
- halo
volumes:
- ./halo2:/root/.halo2
ports:
- "8090:8090"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health/readiness"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
environment:
# JVM 参数,默认为 -Xmx256m -Xms256m,可以根据实际情况做调整,置空表示不添加 JVM 参数
- JVM_OPTS=-Xmx256m -Xms256m
command:
- --spring.r2dbc.url=r2dbc:pool:postgresql://halodb/halo
- --spring.r2dbc.username=halo
# PostgreSQL 的密码,请保证与下方 POSTGRES_PASSWORD 的变量值一致。
- --spring.r2dbc.password=openpostgresql
- --spring.sql.init.platform=postgresql
# 外部访问地址,请根据实际需要修改
- --halo.external-url=http://localhost:8090/
halodb:
image: postgres:15.4
restart: on-failure:3
networks:
# 加入 npm 网络
- npm
- halo
volumes:
- ./db:/var/lib/postgresql/data
healthcheck:
test: [ "CMD", "pg_isready" ]
interval: 10s
timeout: 5s
retries: 5
environment:
- POSTGRES_PASSWORD=openpostgresql
- POSTGRES_USER=halo
- POSTGRES_DB=halo
- PGUSER=halo
networks:
npm:
external: true
halo:
name: halo
```
配置完成之后,需要使用 `docker compose up -d` 命令重建 Halo 容器。
-
进入 NPM 仪表盘,点击代理服务进入代理服务配置页面。

-
添加代理配置

- 域名:配置想要代理到 Halo 的域名,需要提前在域名服务商解析到当前服务器
- 协议:选择 http
- 转发主机名 / IP:填写 Halo 容器的服务名,比如上方示例中的
halo - 转发端口:8090
以上配置为必须修改,界面中的其他配置可以按需选择,但其中的缓存资源不建议打开,可能不会完全遵守 Halo 的缓存策略。
配置完成之后,就可以尝试访问域名。
-
配置 SSL,点击 SSL 选项卡,勾选 申请新证书 之后保存即可,同时建议勾选 强制 SSL,这样在访问 http 协议的地址时会自动跳转到 https 协议的地址。

至此,我们已经完成了在 Nginx Proxy Manager 配置 Halo 反向代理并添加 SSL 证书的全过程。
进阶配置:性能与安全(可选)
前文已完成基础反向代理与 SSL,对大多数博客已经够用。本节介绍在 NPM 中追加性能优化与安全响应头配置,两个目标:
- 性能:让 JavaScript、字体、JSON 等静态资源也参与 gzip 压缩;调大 proxy buffer 避免响应落盘
- 安全:补齐 securityheaders.com 认可的安全响应头,默认可拿到 A 评级
信息
本节所有配置均为反代层通用优化,与具体主题无关,适用于任何 Halo 实例。
在 NPM 中找到自定义配置入口
- 进入 NPM 仪表盘,在 Hosts → Proxy Hosts 点开 Halo 的代理记录进行编辑
- 切换到 Advanced 标签页
- 把下面的内容粘贴到 Custom Nginx Configuration 文本框
- 保存后 NPM 会自动 reload nginx,无需重建容器
推荐的自定义配置
# ---- gzip 压缩:补齐 NPM 默认未覆盖的 JS、字体、JSON 等 MIME 类型 ----
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_types
text/css
text/javascript
application/javascript
application/x-javascript
application/json
application/xml
application/rss+xml
application/atom+xml
image/svg+xml
font/ttf
font/otf
font/woff
font/woff2;
# 若目录下存在 .gz 预压缩文件则优先使用
gzip_static on;
# ---- proxy buffer:避免较大响应被临时写入磁盘 ----
proxy_buffers 16 32k;
proxy_buffer_size 64k;
proxy_busy_buffers_size 128k;
# ---- 安全响应头:加 always 确保错误页也会返回 ----
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# HSTS 请在确认 HTTPS 稳定运行后再启用,见下文说明
# add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# ---- RSS 路径别名:Halo 默认 RSS 为 /rss.xml ----
rewrite ^/rss$ /rss.xml permanent;
rewrite ^/feed$ /rss.xml permanent;
提示
gzip_types 不要再列 text/html,nginx 默认已经对其启用 gzip,重复声明会产生 duplicate MIME type 警告。
关于 HSTS
Strict-Transport-Security 会告诉浏览器未来只能通过 HTTPS 访问当前域名。一旦启用且 max-age 较长,浏览器会缓存该策略直到过期,期间无法回退到 HTTP。因此建议:
- 在 HTTPS 证书可正常续签、基础设施稳定运行 1–2 周后再启用
- 先从
max-age=300(5 分钟)起步验证,确认无误再逐步调大到63072000(2 年) preload表示提交到浏览器内置 HSTS 列表,提交后撤销非常困难,确有必要再加
验证配置是否生效
# 查看安全响应头
curl -I https://your-halo-domain.example.com/ \
| grep -iE "x-content-type|x-frame|x-xss|referrer-policy|permissions-policy"
# 检查 JavaScript 是否启用了 gzip
curl -IH "Accept-Encoding: gzip" \
https://your-halo-domain.example.com/themes/<your-theme>/source/main.js \
| grep -i content-encoding
浏览器侧也可以在 DevTools → Network → Response Headers 中确认。