20260907 PostgreSQL 更新环境变量不会自动更新 database password


我曾以为在 zeabur dashboard 更新环境变量并重启服务就会自动更新 database password,我天真了。😅

希望朋友们能以我为戒,能跳过这个坑。

在接到 Zeabur 安全事件更新的邮件时,我的第一反应很自然:打开 Zeabur,改数环境变量,重启项目。

面板上的 POSTGRES_PASSWORD 已经是新值了,服务也重新跑起来了。按常见 PaaS 的直觉,这应该已经轮换完成。

然后两件怪事同时出现:

  • 应用改用新密码后,日志变成 password authentication failed for user
  • 旧密码还能连上数据库;

问题不是重启没执行,而是重启没有帮我更新 database password。

环境变量只在空 volume 第一次初始化时生效

Zeabur 的 PostgreSQL 服务会把数据放在持久化 volume 里,路径通常是 /var/lib/postgresql/data

Postgres Docker 官方镜像写得很清楚:POSTGRES_PASSWORD 这类变量,只在数据目录还是空的时候用来创建超级用户。目录里一旦有了数据库,之后再改环境变量、再重启容器,都不会去改已经存在的角色密码。

Zeabur 重启只是把容器拉起来。volume 还在,Postgres 继续用第一次初始化时写入的密码。

所以会出现分叉:

  • Zeabur 面板显示新密码;
  • Postgres server 仍接受旧密码;
  • 应用如果去信面板,就会连错。

正确的轮换顺序

  1. 生成一段 URL 安全的新密码,避免 @ : / % # +,免得写进 DATABASE_URL 还要编码:
openssl rand -hex 32
  1. 打开 PostgreSQL 服务的终端,进入数据库:
psql -U root -d vmemo_prod
  1. 在 Postgres 里改角色密码:
ALTER USER root WITH PASSWORD '新密码';

ALTER USER 一生效,旧密码立刻不能从其他服务连进来。

  1. 马上把应用的 DATABASE_URL 改成带新密码的字面量,不要再留 ${...} 模板。
  2. 重启的是**应用服务**,不是指望重启 Postgres 来改密码。
  3. 最后把 Zeabur 面板里的 PASSWORDPOSTGRES_PASSWORD 改成同一个新值。这一步只是让面板和真实密码重新对齐,它不会反向写入 Postgres。

两个容易误判的点

在 Postgres 容器内部跑 psql,本地 socket 常常是 trust,不校验密码。这会让人误以为“新密码已经生效了”。应用在另一个服务里走 TCP,用的是角色的真实密码。

改密码之后,不要只改 Zeabur 变量。应用连接串不一起改,服务会立刻打不开。

相关链接