Pomerium是一款基于零信任理念的开源反向代理,它站在内部服务前面,统一处理身份认证和访问授权,让原本只能靠VPN访问的内网应用可以安全地暴露出去。相比Nginx直接反代,Pomerium最大的特点是把认证和授权做进了代理层,支持对接Google、GitHub、OIDC等身份提供商,并且可以按路由粒度配置谁能访问、以什么身份访问。本文将以容器化部署为主线,从单容器运行到Docker Compose编排,再到配置文件细节与常见问题排查,完整走一遍部署流程。

一、部署前的准备工作
1. 域名与DNS规划
Pomerium要求所有被代理的服务都使用域名访问,并且建议采用子域名共享Cookie的方式。例如你的根域名是ipipp.com,那么Pomerium自身认证服务可以用authenticate.ipipp.com,被代理的Grafana可以用grafana.ipipp.com,两个域名都需要解析到运行Pomerium的那台服务器IP上。共享父域可以让Pomerium把会话Cookie设置在.ipipp.com上,用户登录一次即可访问所有下游应用。
建议提前准备好三类记录:认证服务域名、被代理应用域名、以及可选的统一入口域名。如果暂时没有公网DNS,也可以在内网DNS服务器或者本机hosts文件里做解析,测试阶段完全够用。
2. 证书与密钥生成
Pomerium默认使用HTTPS通信,需要准备证书。最省事的方案是配合宿主机上的acme.sh或certbot申请Let's Encrypt证书,然后挂载进容器。另外还需要生成两个关键密钥:共享密钥(SHARED_SECRET)用于Pomerium内部组件间通信加密,Cookie密钥(COOKIE_SECRET)用于加密会话。生成方式如下:
# 生成32字节的共享密钥并转成base64 openssl rand -base64 32 # 生成Cookie密钥,必须是32字节的base64字符串 head -c 32 /dev/urandom | base64 # 可选:生成签名密钥,用于JWT签名,ECDSA P-256 openssl ecparam -genkey -name prime256v1 | openssl ec -out ec.pem
注意Cookie密钥必须是32字节对应的base64编码,长度不对容器启动时会直接报错。密钥文件建议放在固定目录,通过volume挂载,不要直接写死在compose文件里提交到代码仓库,避免泄露风险。
二、编写config.yaml核心配置
1. 全局配置项
Pomerium的配置分为环境变量和配置文件两种方式,推荐使用config.yaml,可读性更好且支持策略热更新。一个基础的全局配置如下:
# 监听地址
address: :8443
# 认证服务的对外域名
authenticate_service_url: https://authenticate.ipipp.com
# 证书配置
certificates:
- cert: /pomerium/cert.pem
key: /pomerium/privkey.pem
# 会话Cookie所在域名,注意前面有个点
cookie_domain: ipipp.com
cookie_secret: 你的base64密钥
shared_secret: 另一个base64密钥
# 身份提供商配置,以通用OIDC为例
idp_provider: oidc
idp_client_id: pomerium-client
idp_client_secret: 客户端密钥
idp_provider_url: https://sso.ipipp.com/realms/main
# 管理界面签名密钥,用于生成访问JWT
signing_key: /pomerium/ec.pem其中idp_provider_url指向你的OIDC提供商地址,比如Keycloak、Auth0或者企业自建SSO。回调地址需要在身份提供商那边登记为https://authenticate.ipipp.com/oauth2/callback,这个地址漏配是新手最常见的翻车点。
2. 路由策略配置
策略部分决定了哪个域名转发到哪个后端、允许谁访问,这是Pomerium的核心价值所在。写法是每条策略一个from到to的映射,再叠加授权规则:
policy:
- from: https://grafana.ipipp.com
to: http://grafana:3000
allowed_users:
- alice@ippipp.com
- bob@ippipp.com
- from: https://wiki.ipipp.com
to: http://wiki:8080
allowed_domains:
- ipipp.com
timeout: 30sto里的地址可以写容器名,只要Pomerium和后端服务在同一个Docker网络里就能直接解析。授权方式除了allowed_users和allowed_domains,还支持allowed_groups对接目录服务、以及自定义表达式实现更复杂的条件判断,比如限制访问时段或要求特定邮箱后缀。
策略文件支持单独引用外部YAML文件,方便把路由规则独立管理。修改策略后重启Pomerium容器即可生效,企业版还支持热加载不用重启。
三、用Docker Compose编排完整服务
1. compose文件编写
实际部署中通常把Pomerium和后端应用放在同一个compose项目里,这样网络互通、统一管理。下面是一个包含Grafana的完整示例:
version: "3.8"
services:
pomerium:
image: pomerium/pomerium:latest
container_name: pomerium
volumes:
- ./config.yaml:/pomerium/config.yaml:ro
- ./certs:/pomerium/certs:ro
ports:
- "8443:8443"
restart: unless-stopped
networks:
- internal
grafana:
image: grafana/grafana:latest
container_name: grafana
environment:
- GF_SERVER_ROOT_URL=https://grafana.ipipp.com
volumes:
- grafana-data:/var/lib/grafana
restart: unless-stopped
networks:
- internal
networks:
internal:
volumes:
grafana-data:这里Pomerium对外暴露8443端口,内部通过Docker网络直接以容器名访问Grafana,不需要把Grafana端口映射到宿主机,安全性更好。证书目录以只读方式挂载,避免容器被攻破后证书被篡改。
2. 启动与验证
执行docker compose up -d启动全部服务,然后用docker compose logs -f pomerium观察日志。正常启动后日志里不会有error级别输出。浏览器访问https://grafana.ipipp.com,应该先被重定向到认证页面,完成OIDC登录后再回到Grafana。
验证授权是否生效可以用浏览器的隐私窗口测试:用一个不在allowed_users列表里的账号登录,Pomerium会返回403页面,说明策略拦截正常工作。
四、常见问题排查与生产建议
1. 重定向循环或Cookie失效
出现反复跳转登录页,多半是Cookie域配置问题。检查cookie_domain是否正确设置,并且访问的域名确实在这个父域之下。另外如果证书没配好导致降级到HTTP,浏览器会拒绝安全Cookie,可以用curl -v确认返回头里的Set-Cookie是否带Secure标记。
2. 502或504错误
502说明Pomerium连不上后端服务,优先检查to地址里的容器名拼写和Docker网络归属,可以进入容器用wget验证连通性。504则是后端响应超时,适当调大对应路由的timeout值,或者排查后端服务本身的性能瓶颈。
3. 生产环境加固
镜像版本建议固定到具体tag而不是latest,避免自动更新带来不兼容变更。Pomerium的配置字段随版本有过多次调整,升级前务必对照官方文档的迁移说明检查配置项。密钥管理方面,生产环境可以把各类secret放到Docker secrets或外部密钥管理服务中,避免明文落在配置文件里。日志层面建议留存访问审计记录,配合日志采集方案可以追溯每一次访问的身份与目标路由。整体来看,跑通第一个应用之后,后续接入新的内网服务只需要在policy里追加一条路由,维护成本非常低。
PomeriumPomerium部署Docker反向代理修改时间:2026-09-07 04:04:57