独立开发者的异地灾备实践:PostgreSQL 跨云流复制与全链路 SSL 加固

拒绝裸奔!记录一次从 Oracle Cloud 到异地 VPS 的 PostgreSQL 主从同步方案:涵盖 Docker 环境下的数据迁移、双向 SSL 证书校验及防火墙避坑指南。

作为一名独立开发者,最担心的莫过于“单点故障”。虽然 Oracle Cloud 的机器很香,但万一哪天账号被封或机房波动,数据就是命根子。为了实现数据异地实时灾备,我近期完成了一次 PostgreSQL 跨公网的主从同步部署。

这不仅仅是简单的 pg_dump,而是基于流复制(Streaming Replication)的“实时影子库”方案。

1. 需求分析:为什么不直接全量备份?

早期的方案是每天定时跑脚本备份到对象存储,但存在两个痛点:

  • 数据不一致:如果主库在备份间隔内崩掉,会丢失数小时的数据。
  • 恢复慢:紧急情况下,重新拉起容器并还原 TB 级或 GB 级数据的时间成本太高。

我的目标:在另一台 VPS 上维护一个随时待命的只读副本,一旦主库失联,分钟级完成主从切换。

2. 解决方案:流复制 + 双向 SSL 加密

由于数据需要跨越公网传输,安全性是首要考量。

  • 传输层安全:必须开启 SSL,防止数据在公网被嗅探。
  • 身份验证:不使用简单的密码,而是采用 双向证书校验(Cert Authentication)。只有持有我签发的客户端证书的服务器,才有权连接主库进行数据同步。
  • 网络隔离:非标准端口(如 8765)+ 严格的防火墙(iptables/ufw)白名单。

3. 实战避坑指南

坑一:Docker 容器与防火墙的“暗箱操作”

在使用 Docker 暴露端口时,Docker 会自动操作 iptables 规则,导致很多时候即便你没开系统防火墙,端口也是暴露的。

  • 对策:手动在 INPUT 链中通过 -s <备库IP> 锁定来源地址,并持久化规则(iptables-persistent)。

坑二:pg_basebackup 的路径“幽灵”

第一次执行 pg_basebackup 克隆数据时,它生成的 postgresql.auto.conf 会保留当时临时容器的证书路径(比如 /temp_certs)。

  • 对策:克隆完成后,务必手动修正数据目录下的配置文件,将证书路径指向容器启动时的正式挂载路径(如 /var/lib/postgresql/data/certs/)。

坑三:权限!权限!还是权限!

Postgres 对私钥文件的权限极其挑剔。

  • 报错could not open file "server.key": Permission denied
  • 对策:在宿主机执行 chown -R 999:999 修正 UID。即便在宿主机看是 root,在容器里必须是 postgres 用户(UID 999)才能读取。

4. 关键配置概览

主库 pg_hba.conf 安全策略

# 仅允许 replication_user 通过证书验证进行流复制
hostssl replication replication_user 备库IP/32 cert

备库同步配置 (postgresql.auto.conf)

primary_conninfo = 'user=replication_user host=主库IP port=8765 sslmode=verify-ca sslcert=/path/to/client.crt sslkey=/path/to/client.key sslrootcert=/path/to/ca.crt'

5. 迁移与维护的思考

关于数据卷映射,我最终选择了 Bind Mounts(直接路径映射) 而非 Docker Named Volumes。

  • 理由:当需要更换服务器迁移备库时,直接一个 tar 命令打包 /opt/pgsql/data 极其透明。不需要去翻 /var/lib/docker/volumes/ 那些隐秘的哈希目录,迁移效率提升 200%。

最后

高可用架构不是为了炫技,而是为了在意外发生时能睡个好觉。目前这套方案在 Uptime Kuma 的监控下表现稳定,主从延迟几乎保持在 0ms。