数据库类
来源:
intranet-tunnel/docs/docker-build.md→## 六、数据库外部访问(Navicat / DBeaver / pgAdmin)(原文 1233 字符)
六、数据库外部访问(Navicat / DBeaver / pgAdmin)
compose 已把 PostgreSQL 映射到宿主机,可直接用图形化工具连接:
| 参数 | 值 |
|---|---|
| 主机 | 127.0.0.1(本机);若工具装在其它机器上则填宿主机内网 IP |
| 端口 | 5432(可用 .env 的 DB_EXPOSE_PORT 修改) |
| 数据库 | tunnel(.env 的 DB_NAME) |
| 用户名 | tunnel_user(.env 的 DB_USER) |
| 密码 | .env 的 POSTGRES_PASSWORD(默认 change_me_db_password,生产务必修改) |
| SSL | 关闭(容器内网通信,未启用 TLS) |
安全边界
映射只绑定宿主机回环地址,因此本机工具可连,而局域网其它机器与公网均无法直连数据库。
若确需从其它机器连接,必须同时修改两处,缺一不可:
docker-compose.yml中把"127.0.0.1:${DB_EXPOSE_PORT:-5432}:5432"改为"0.0.0.0:...";- 云安全组 / 主机防火墙放行该端口。
更推荐的做法是不放开端口,改用 SSH 隧道:
ssh -L 5432:127.0.0.1:5432 user@your-server然后 Navicat 连接本机的
127.0.0.1:5432。这样数据库始终不对外暴露。
关闭外部访问
注释掉 docker-compose.yml 中 postgres 服务的整个 ports 段即可。服务端容器通过 compose 网络用服务名 postgres 访问数据库,不依赖该端口映射。
实测确认
| 验证项 | 结果 |
|---|---|
| 端口映射 | 5432/tcp -> 127.0.0.1:5432 |
| TCP 连通 | 127.0.0.1:5432 连接成功 |
| 外部客户端 | 从容器外以 host.docker.internal:5432 连接成功;current_database()=tunnel、current_user=tunnel_user、inet_server_port()=5432 |
| 业务表可见 | \dt 列出全部 17 张表,owner 均为 tunnel_user |
| 服务端不受影响 | 重建 postgres 容器后 /healthz 仍返回 database: ok(数据卷保留) |
来源:
halo-kb/备份运维与安全.md→## 0. 结论摘要(原文 2200 字符)
0. 结论摘要
| # | 结论 | 关键证据 | 建议动作 |
|---|---|---|---|
| 1 | 备份链路已跑通并验证可恢复 | 备份 5.5s,sha256sum -c 全 OK,pg_restore -l 解析出 319 条 TOC;恢复进临时库后 表数 34=34、extensions 391=391 | 装 cron(见 B-3) |
| 2 | ~~halo2/backups/ 为空~~ → 已有真实产物 | backups/ 现有 8 个文件、约 61 MB | 无 |
| 3 | halo.log 无轮转,且我第一版 logrotate 规则写错了 | logrotate -d 报 note: 'size' overrides previously specified 'daily' → 退化成「永不到 20M 就永不轮转」 | 用修正版 maxsize 20M(见 B-1) |
| 4 | 宿主上另有一个 PostgreSQL,裸跑 psql 会连错库 | uid=107(postgres) 监听 127.0.0.1:5432,宿主有 /usr/bin/psql | 所有 DB 操作一律 docker exec PostgreSQL …(已固化进脚本) |
| 5 | Docker json-file 日志已经在轮转(无需处理) | daemon.json max-size=100m max-file=5,容器 HostConfig.LogConfig 同值 | 无;日后改它必须 recreate 容器 |
| 6 | 28090 绑 0.0.0.0,全网段可达 | ss 显示 0.0.0.0:28090;从 <内网IP>:28090 与 127.0.0.1:28090 均 HTTP 200 | LAN 内可达即视为暴露;建议改绑内网网卡或前置反代(C-1) |
| 7 | actuator 只有 health 匿名可达,其余全部 302 | 匿名探测 16 个端点:health/liveness/readiness = 200,其余(含 env/beans/heapdump/loggers)全部 302 | 风险低;无需处理 |
| 8 | MiniDocs 匿名可读全部 38 篇文档正文(含 raw) | /apis/api.minidocs.halo.run/v1alpha1/knowledgebases/tech-docs/docs 匿名 200、total=38、phase 全为 published、38 篇都带 raw 正文 | 有意为之;但需明确「公网隧道同源暴露」(C-6) |
| 9 | PostgreSQL 的 halo 角色是 SUPERUSER + BYPASSRLS + REPLICATION | pg_dumpall --globals-only 里 ALTER ROLE halo WITH SUPERUSER INHERIT CREATEROLE CREATEDB LOGIN REPLICATION BYPASSRLS | 建议降权为普通 LOGIN(C-3) |
| 10 | PAT 签名私钥 halo2/keys/pat_id_rsa 是 755,全机任何用户可读 | 755 root:root …/keys/pat_id_rsa,且 halo2、keys 目录都是 755 | 收紧为 600(需 root) |
| 11 | 数据库口令以明文写在 docker-compose.yaml,并出现在容器命令行参数里 | --spring.r2dbc.password=…;docker inspect Halo 对 docker 组任意成员可见 | 文件已是 700;建议改走 env_file(C-3) |
| 12 | external-url 两处不一致,但在我探测到的路径上未见内网地址外泄 | 跳转是相对路径 /login?authentication_required;sitemap 84 条链接全为 https://<服务名>.tunnel.sushike.cloud | 仍在邮件/OAuth 路径有隐患(C-4) |
| 13 | 日志里发现两个真实缺陷 | ①「portfolio 插件 POST …/projects → 500 NPE metadata is null」;②「ai-assistant 因 invalid license 拒绝启动」 | ①待修;②已禁用,无需动作(C-7) |
| 14 | halo-backup.sh 失败会以非 0 退出并留 .FAILED 现场 | 脚本 set -euo pipefail + trap cleanup EXIT | 无 |
来源:
intranet-tunnel/docs/docker-build.md→## 三、持久化目录权限(重要)(原文 916 字符)
三、持久化目录权限(重要)
镜像声明了三个 VOLUME:/app/logs、/app/backups、/app/certs。
这四个目录必须在 VOLUME 指令之前创建并 chown:
RUN mkdir -p /app/data /app/logs /app/backups /app/certs \
&& chown -R tunnel:tunnel /app
VOLUME /app/logs /app/backups /app/certs若顺序写反(先 VOLUME 后 chown,或只 chown 了 /app/data),Docker 会把挂载点建成 root:root,而已知服务端以 tunnel(10001) 运行 —— 文件日志与自动备份会静默失败:容器日志中没有任何报错,只是 /app/logs 一直是空的。
这个问题在本次构建中实测确认过:
| 检查项 | 修复前 | 修复后 |
|---|---|---|
/app/logs 属主 | root:root 755 | tunnel:tunnel 755 |
| tunnel 用户写入 | 不可写 | 可写 |
/app/logs 内容 | 空 | app.log(4461 bytes) |
| 容器日志是否报错 | 无任何报错 | — |
bind mount 场景
若把持久化目录改为绑定宿主机路径(compose 中形如 ./logs:/app/logs),容器内看到的属主由宿主机目录决定,镜像内的 chown 不再生效。Linux 上需要:
mkdir -p ./logs ./backups ./certs
sudo chown -R 10001:10001 ./logs ./backups ./certsDocker Desktop(Windows / macOS)通过文件共享层自动映射权限,通常无需处理。
