ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PostgreSQL远程连接配置详解:Odoo部署中监听、认证与网络三层排查

PostgreSQL远程连接配置详解:Odoo部署中监听、认证与网络三层排查 最近帮一个客户把 Odoo 从单机部署拆成“应用一台机器、数据库一台机器”结果卡在了最基础的 PostgreSQL 远程连接配置上。Odoo 日志一直报 connection to server ... failed客户催得急我扒了半小时日志才发现问题不止一处监听地址没改、pg_hba.conf 规则没匹配、云安全组又拦了一道。网上关于这个主题的教程不少但大多只告诉你“改 listen_addresses、改 pg_hba.conf”然后就没有然后了。这篇就以 Odoo 数据库为例把配置 PostgreSQL 允许远程连接的完整过程过一遍。内容包括为什么默认连不上、要改哪三个层面的东西、每种报错分别说明什么问题、odoo.conf 里的 db_host 到底怎么填最后分享一些日志和权限上的收尾技巧。适合正在部署 Odoo 的开发者、被 PG 远程连接报错折磨的运维以及想弄清楚远程连接底层逻辑的朋友。不管你用的是 Ubuntu、CentOS 还是 Windows 上的 PostgreSQL排查思路都一样只是命令稍有出入。1. 为什么 PostgreSQL 默认“拒绝”远程连接Odoo 又为什么非要连它1.1 Odoo 的架构决定了它绕不开 PostgreSQLOdoo 全系列只支持 PostgreSQL 作为主数据库MySQL 那些都不在官方支持范围。Odoo 的模块数据、业务单据、工作流、报表定义全都在 PG 里而且它初始化时会自动创建数据库不是像普通应用那样“建表”就行。所以部署 Odoo 的第一关就是让 Odoo 能顺利连上 PG 并拥有建库的权限。这也是为什么本文标题是“以 Odoo 数据库为例”——表面看是一个数据库连接问题背后是一整套权限、认证、网络配置的叠加。单机部署时Odoo 用 Unix socket 连接本地 PG几乎不会遇到网络问题。一旦你把数据库和应用分开或者你想从笔记本远程连服务器上的 PG 排查数据就要面对整套远程连接配置。很多人就是在这一步被劝退的因为报错信息五花八门而且网上教程经常只覆盖其中一层。1.2 默认安全策略的两个“开关”PostgreSQL 默认的配置哲学是“本地优先、认证从严”主要体现在两处postgresql.conf 中listen_addresses默认值是localhost相当于只监听本机回环地址外网网卡的流量根本进不了 PG 进程。pg_hba.conf 默认只放行 localUnix socket和 127.0.0.1 / ::1 的 TCP 连接其他来源 IP 没有任何匹配规则直接拒绝。可以打个比方PG 就像一栋门禁严格的大楼默认只给本楼住户发门卡访客即使到了楼下也进不了大门。你要做的不是拆掉门禁而是在访客名单上添加可信来源并且规定访客要刷什么卡认证方式。这两个“开关”少改一个远程连接都起不来。1.3 两个典型的远程连接场景场景 AOdoo 应用服务器在 A 机器数据库在 B 机器应用要连数据库。这是最常见的拆分部署。改完服务端配置后A 机器的 odoo.conf 里db_host要填 B 的内网 IP。场景 B你在笔记本上用 DBeaver、Navicat 或者 psql 连接服务器的 PG做数据排查、备份恢复。尽管场景不一样但底层要改的东西完全相同监听地址、认证规则、网络放行。我的建议是先把场景 B 跑通也就是先让本机连远程 PG 成功再让 Odoo 去连。这样能少很多混淆因为 Odoo 的报错里会叠加应用层的问题不容易一眼定位到数据库配置上。2. 动手改造前先把这些东西摸清楚2.1 先确认版本和配置文件到底在哪很多教程直接写一个路径让你去改结果你照着改了个寂寞。不同版本、不同发行版的路径都不一样环境配置目录Debian / Ubuntu/etc/postgresql/{版本}/{集群名}/postgresql.confRHEL / CentOS / Rocky/var/lib/pgsql/{版本}/data/postgresql.confWindowsC:\Program Files\PostgreSQL{版本}\data\postgresql.conf最简单可靠的办法是进入 psql 执行SHOW config_file;和SHOW hba_file;让数据库告诉你它正在读哪个文件。多实例机器上这招尤其好用不会改错实例。顺便执行SHOW port;确认实例实际监听的端口是不是 5432很多人改了半天的端口根本没对上号。版本差别也值得注意。PostgreSQL 10 之后开始支持 scram-sha-256 认证14 之后默认密码加密方式就是 scram。网上大量老教程还停留在 md5 时代新版本照抄 md5 也能用但既然能用更强的认证就优先用 scram。如果是 9.x 老库那另说。2.2 odoo.conf 里的 db_host 到底该填什么Odoo 的所有数据库连接参数都写在 odoo.conf 的[options]段里[options] db_host 数据库IP db_port 5432 db_user odoo db_password 你的强密码关键点db_host留空表示走本地 Unix socket只适合同机部署填localhost或127.0.0.1和留空不同它走 TCP 回环填远程内网 IP 就是走 TCP 去连另一台机器。我见过很多人把 db_host 填成公网 IP但数据库只在内网监听结果 Odoo 一直报 connection refused。反过来也有数据库监听公网但 Odoo 填了内网 IP两边不在同一个网络平面一样连不上。所以填之前先搞清楚数据库到底监听在哪张网卡上。2.3 把网络拓扑画清楚再下手我的习惯是拿到问题先画三层图应用在哪、数据库在哪、客户端从哪连。如果应用与数据库同机只是你想在笔记本远程连那只改数据库所在机器的配置就行如果应用和数据库本来就不在同一台机器那防火墙和安全组也得一起检查。同机部署时Odoo 走 Unix socket认证规则走 pg_hba.conf 里的local行跨机部署时走 TCP认证规则走host行。这两个分支完全不同混在一起想必然卡壳。先想清楚自己属于哪种情况再动手才不会乱。3. 第一件事让 PostgreSQL 不再“只听本机”3.1 listen_addresses 的正确写法和我推荐的用法找到 postgresql.conf 里的listen_addresses默认是注释状态或localhost。改成listen_addresses *或者只监听某个内网 IPlisten_addresses 192.168.1.50两种方式区别很大*表示监听所有网卡包括公网指定 IP 意味着只有那块网卡的流量进来才会被接受。我推荐在明确知道业务网卡 IP 的情况下写具体 IP减少暴露面。如果有多张网卡可以用逗号分隔写成列表。也可以不手动编辑文件用ALTER SYSTEM SET listen_addresses 192.168.1.50;这个命令会把配置写进 postgresql.auto.conf优先级比 postgresql.conf 高而且不用手动找路径。但新手直接编辑文件更直观二者选一个即可别同时乱改否则容易自己也分不清到底哪个值生效。3.2 改完是 restart 还是 reload这是很多人卡住的点listen_addresses属于“需要重启才生效”的参数改完直接 reload 是没用的。pg_hba.conf 则支持 reload改完重载即可。两者的操作完全不同systemctl reload postgresql或pg_ctl reload重读 pg_hba.conf 和多数可动态加载参数。systemctl restart postgresql整个服务重启listen_addresses 才会用新值。在 Debian / Ubuntu 多集群环境下命令可能是systemctl restart postgresql14-main.service。改完记得看状态systemctl status postgresql确认 Active: active (running)。很多人改完就跑了其实服务根本没起来。3.3 验证监听是否生效的三板斧改完监听不一定成功用命令验证ss -lntp | grep 5432看本地监听地址有没有从 127.0.0.1 变成 0.0.0.0 或指定 IP老系统用netstat -an | grep 5432在 psql 里执行SELECT * FROM pg_settings WHERE namelisten_addresses;查看当前配置值如果输出还是127.0.0.1:5432要么文件改错位置要么没重启要么改的实例不对。记住顺序确认文件路径 - 改值 - 重启服务 - ss 验证。这一步过了接下来才是重头戏。4. 真正的重头戏pg_hba.conf 的匹配规则4.1 一行规则是怎么读的五个字段逐个拆监听地址解决的是“数据包能不能进 PG 进程”pg_hba.conf 解决的是“这个来源到底允不允许连、用哪种方式认证”。两者缺一不可。pg_hba.conf 每一行用空格分隔几个字段含义分别是类型localUnix socket、hostTCP、hostsslTCP 且必须 SSL等数据库all 或具体库名多个库用逗号分隔用户all 或具体用户名地址来源 IP 段CIDR 格式比如 192.168.10.0/24认证方法scram-sha-256、md5、trust、password、reject、peer 等Odoo 场景推荐这样加一行host odoo_prod odoo 192.168.10.0/24 scram-sha-256含义是“从 192.168.10.0/24 网段来的主机以 odoo 用户访问 odoo_prod 库必须用 SCRAM 密码认证”。如果你在 Odoo 里建了多个数据库可以写成host all odoo 192.168.10.0/24 scram-sha-256但尽量用具体库名更可控。很多人一上来就抄host all all 0.0.0.0/0 trust看起来“能用了”实际上把数据库完全暴露了后面我会细说为什么不建议。4.2 为什么我强烈不建议 trust 加全网开放网上有些教程图省事告诉你加一行host all all 0.0.0.0/0 trust这一行翻译过来是“任何来源 IP任何用户不需要密码直接放行”。等于把数据库大门拆了。Odoo 里的数据基本是业务命脉一旦被扫描工具碰到数据直接裸奔。trust 是开发环境临时用的不要出现在生产服务器哪怕是内网。远程连接的正确姿势永远是强密码 限定来源网段 scram 认证。SCRAM 认证不会在网络上传明文密码这是它比password认证方式更安全的原因。md5 虽然也不是明文但强度不如 scram新版本里能不用就不用。4.3 Odoo 账号需要的可不止 LOGIN还有 CREATEDB创建 Odoo 专用账号时只给 LOGIN 是不够的。Odoo 初始化时要创建数据库所以账号必须带 CREATEDB 角色属性CREATE ROLE odoo LOGIN PASSWORD StrongPass123 CREATEDB;用 GRANT 给某个库授权并不能替代 CREATEDB。很多“odoo 集成模块提示无权限”的报错根因就是数据库用户没有建库权限。建议这样建CREATE USER odoo WITH PASSWORD StrongPass123 CREATEDB;然后测试连接PGPASSWORDStrongPass123 psql -h 数据库IP -U odoo -d postgres -c SELECT 1;密码用强密码长度至少 16 位大小写数字符号混合。odoo.conf 里是明文存密码的记得把配置文件权限收紧比如chmod 600 odoo.conf。4.4 一个没人提醒你的坑pg_hba.conf 是顺序匹配的pg_hba.conf 从上到下逐行匹配命中一行就不再往后看了。这意味着如果你前面有一条 reject 规则后面再加允许规则也救不回来。例如host all all 0.0.0.0/0 reject host odoo odoo 192.168.10.0/24 scram-sha-256第二个规则永远不会生效因为第一个已经把所有远程请求挡在门外。实际更安全的写法是“先放行特定网段最后兜底拒绝”host odoo_prod odoo 192.168.10.0/24 scram-sha-256 host all all 0.0.0.0/0 reject改完记得 reload 让规则生效systemctl reload postgresql或者在 psql 里执行SELECT pg_reload_conf();。5. 网络层的最后一道关卡防火墙、安全组和端口5.1 Linux 上放行 5432 的两种姿势数据库所在机器自己的防火墙也要放行 5432。Ubuntu / Debian 常见的是 ufwsudo ufw allow from 192.168.10.0/24 to any port 5432 proto tcpCentOS / Rocky 常见 firewalldsudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.10.0/24 port port5432 protocoltcp accept sudo firewall-cmd --reload为什么用源 IP 限制而不是直接allow 5432因为防火墙规则越具体出问题影响面越小。如果 Odoo 应用服务器是固定内网 IP就把那个 IP 写进去不要放整个网段更不要放所有来源。改完防火墙用这条命令验证端口通不通nc -zv 数据库IP 5432如果通会显示 open不通要往下查防火墙、安全组、服务是否监听这三层一层层排除。5.2 云服务器安全组最容易漏的一步云上部署还有一个独立于系统防火墙的层安全组。阿里云、腾讯云、AWS 都一样控制台里要新增入方向规则协议 TCP端口 5432源可以填应用服务器的内网 IP 或你办公网出口 IP。很多人的状态是系统防火墙没开、PG 监听也改了、pg_hba 也配了就是连不上最后发现是安全组没有放行。这个坑我踩过不止一次。经验法则云上排查网络问题先看安全组再看系统防火墙再看监听。顺序反了容易白折腾半天。另外说一句如果 Odoo 应用和数据库都在同一个云内网我强烈建议只通过内网 IP 连数据库不要在安全组里开放公网 5432。这比把密码设得再复杂都管用因为根本没人能触达。5.3 如果数据库跑在 Windows 上如果是 Windows 上的 PostgreSQL可能是测试环境或本地开发除了改配置文件还要在 Windows 防火墙放行 5432。用管理员权限执行netsh advfirewall firewall add rule namePostgreSQL 5432 dirin actionallow protocolTCP localport5432同时确认服务postgresql-x64-...是启动状态。Windows 上改完配置后可以用 Windows 服务管理器重启 PostgreSQL或者用 pg_ctl reload。配置文件路径用SHOW config_file;查最稳默认一般在安装目录下的 data 目录。6. 客户端连不上的五种报错我带你逐个过一遍6.1 先把五种典型报错和原因对上号报错信息大概率原因could not connect to server: Connection refused服务没监听 / 端口不对 / 请求没到服务端Connection timed out网络层不通防火墙或安全组丢包no pg_hba.conf entry for host ...来源 IP 没有匹配的认证规则password authentication failed for user ...密码错误或认证方法不匹配Peer authentication failed for user ...本地 socket 用了 peer远程 host 行也错误配了 peer这里注意一下Connection refused 是服务端主动拒绝一般说明端口上没人监听或者监听地址不包含你连接的这张网卡Connection timed out 更像是包被防火墙丢了客户端发出去就没了回应。区分这两个对定位问题帮助很大。6.2 一条命令把排查范围缩小一半我排查远程连接问题时第一件事不是去看 Odoo 日志而是用 psql 直连数据库PGPASSWORD密码 psql -h 数据库IP -p 5432 -U odoo -d odoo_prod -c SELECT version();如果这条命令报错报错类型会直接告诉你问题在哪一层。如果 psql 报 could not connect再用nc -zv 数据库IP 5432把网络层单独拎出来判断。端口通了但认证失败说明网络没问题问题在 pg_hba 或账号密码上。也可以用连接串方式psql host数据库IP port5432 userodoo dbnameodoo_prod sslmodeprefer很多客户端工具默认会尝试 SSL如果 pg_hba 里只写了 hostssl 规则而客户端没开 SSL也会报错。Odoo 和 psql 默认都能协商 SSL所以通常不用专门处理。6.3 Odoo 报错别只看 Odoo 日志PG 日志才是破案现场Odoo 日志常见这些关键字psycopg2.OperationalError: connection to server at ... failed: no pg_hba.conf entry...FATAL: password authentication failed for user odooFATAL: no pg_hba.conf entry for host 192.168.10.5, user odoo, database odoo_prod, no encryption这些报错其实已经把原因说得很清楚了。但有时候客户端信息不够比如没有显示来源 IP那就得看 PG 日志。我会在 PG 端打开 log_connections 和 log_line_prefix然后在 Odoo 端复现一次连接去 PG 日志里看原始拒绝记录。看到 FATAL 那一行问题定位基本就完成了。6.4 三个我见过无数次的“伪远程”翻车现场地址写了非 CIDR 格式192.168.1.%这种写法是 MySQL 的习惯PG 不认要用192.168.1.0/24。IPv4 规则挡住了 IPv6 客户端客户端解析到 ::1而 pg_hba 里只写了 127.0.0.1/32于是报 no pg_hba entry。解决方案是连接串里写明确的 IPv4 地址或者补上 ::1/128 的规则。改了配置文件没 reloadpg_hba.conf 改完必须要 reload 或重启否则规则不生效。很多人改完文件就以为 OK 了一测还是老错。这三个坑每个都能耗掉你半小时。尤其是第二个出问题的时候客户端明明填的是数据库 IP可 psql 解析到 IPv6规则就是匹配不上特别隐蔽。7. 让这次配置“沉淀”下来日志、权限与安全收尾7.1 把日志调成“人话模式”在 postgresql.conf 里把这些参数打开log_connections on log_disconnections on log_line_prefix %m [%p] %r %u%d 然后 reload。之后每次连接尝试都会记录来源 IP、时间、用户和数据库排错非常高效。%r会显示远端主机和端口一眼看出是谁在连、从哪连的。日志位置Ubuntu 一般在/var/log/postgresql/postgresql-14-main.logCentOS 在/var/lib/pgsql/14/data/log也可以直接用journalctl -u postgresql查。7.2 用户权限最小化能少给就少给Odoo 账号有 CREATEDB 是必须的但除此之外不要随意给 SUPERUSER。日常运维账号和生产业务账号分开。如果只是临时排查问题可以建一个只读账号CREATE ROLE readonly LOGIN PASSWORD tmp_pass; GRANT CONNECT ON DATABASE odoo_prod TO readonly; GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;用完删掉。最小权限原则能让你在出问题的时候少很多麻烦。另外远程连接通常不需要在公网裸奔。如果数据库只能内网访问Odoo 应用和数据库都在同一个私有网络里这是最理想的状态。实在需要从公网访问优先考虑 SSH 隧道等加密通道而不是直接开放 5432 公网端口。7.3 收尾建议从一次部署到可复用的标准动作写这篇的时候我又复盘了一遍自己部署 Odoo 的流程。现在我的习惯是先临时把 listen_addresses 改成具体网卡 IPpg_hba 只放行业务网段防火墙和安全组同步收紧然后在数据库服务器上用 psql 本机验证再用应用服务器远程验证最后才让 Odoo 跑起来。每个环节都有对应的验证命令不跳步。改配置前先备份一份带日期后缀的文件这是成本最低的回滚手段cp pg_hba.conf pg_hba.conf.bak.20260101以后如果接手别人部署的 Odoo 踩到连接坑回到这条思路监听、认证、网络一层一层过基本都能在十几分钟内定位。这比到处找万能配置靠谱得多。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进