首页
/ Nocodb 对接私网 PostgreSQL:Private CA 证书 + Traefik 生产部署实战

Nocodb 对接私网 PostgreSQL:Private CA 证书 + Traefik 生产部署实战

2026-09-04 18:43:41作者:丁柯新Fawn

在私有云或本地机房环境中,PostgreSQL 往往只信任自签或私有 CA 签发的证书。Nocodb 官方提供了一个可直接落地的部署模板 docker-compose/examples/postgres-private-ca,演示如何让 Nocodb 通过私有 CA 证书(ssl.ca 内联 PEM 内容)安全连接外部 PostgreSQL,同时用外部 Redis 承载缓存、用 Traefik 自动签发 Let's Encrypt 证书暴露 HTTPS 入口。读完本文,你将掌握该模板的完整配置方法(db.jsondocker.envdocker-compose.yml 逐项说明)、CA 证书转单行字符串的实操命令,以及 Nocodb 源码中 NC_DB_JSON_FILE 的解析链路与 SSL 文件路径的安全边界,从而能将其迁移到自己的内网部署场景。

一、适用场景与组件架构

该模板面向的核心场景是:数据库使用私有或自签 CA 证书(本地机房数据库、私有云环境)。官方 README(docker-compose/examples/postgres-private-ca/README.md)将组件职责概括为三点:

  • PostgreSQL:外部数据库,通过自定义 CA 证书建立 SSL 连接;
  • Redis:外部部署,Nocodb 仅通过 URL 连接;
  • 反向代理:Traefik,基于 Let's Encrypt 自动签发 HTTPS 证书。

对应的 docker-compose.yml 中定义了三个服务:

服务 镜像 职责
nocodb nocodb/nocodb:latest 主应用,监听 8080,承载 API 与前端,挂载 db.json
worker nocodb/nocodb:latest 独立 worker 容器,通过 NC_WORKER_CONTAINER: 'true' 标记,仅处理异步任务
traefik traefik:v3.6 80/443 入口,HTTP 强制跳转 HTTPS,ACME 自动证书

关键设计点:

  1. App 与 Worker 共享数据卷:两者都挂载了 nocodb_data:/usr/app/data./nocodb/db.json:/usr/app/data/db.json,保证元数据库连接配置一致。
  2. Worker 依赖 App 健康检查通过才启动depends_on.nocodb.condition: service_healthy,避免在元数据库尚未就绪时 worker 先启动报错。
  3. worker 不挂 Traefik 标签exposedbydefault=false 且 worker 没有任何 traefik.http.* 标签,意味着 worker 只在内网 nocodb-network 中工作,不对外暴露端口。
  4. Traefik 仅挂载只读的 docker.sock/var/run/docker.sock:ro 用于发现容器标签,ACME 状态持久化在 ./letsencrypt/acme.json

从源码结构看,NC_WORKER_CONTAINER 这个开关在主进程入口 packages/nocodb/src/Noco.ts 中被读取:为 true 时跳过 Web 服务启动,仅注册任务监听;Redis 任务模块 packages/nocodb/src/modules/jobs/redis/jobs-redis.ts 也按同一变量决定 worker 模式行为,这与 compose 文件中 app/worker 双容器的拆分是配套的。

二、核心配置:nocodb/db.json(私有 CA 的关键)

模板中的 nocodb/db.json 是整篇部署的灵魂——Nocodb 的元数据库连接以 JSON 文件形式给出,而不是 URL:

{
  "client": "pg",
  "connection": {
    "host": "your-private-db-host.internal",
    "port": "5432",
    "user": "nocodb",
    "password": "CHANGE_ME_db_password",
    "database": "nocodb",
    "ssl": {
      "rejectUnauthorized": true,
      "ca": "-----BEGIN CERTIFICATE-----\nPASTE_YOUR_CA_PEM_HERE_AS_ONE_LINE\n-----END CERTIFICATE-----"
    }
  }
}

逐项说明:

  • client: "pg":指定使用 PostgreSQL 驱动(对应源码中 DriverClient 枚举);
  • connection.host/port/user/password/database:标准连接五要素,port 以字符串形式给出,示例使用内网域名 your-private-db-host.internal,部署时替换为你的私有数据库地址;
  • ssl.rejectUnauthorized: true这是私有 CA 场景与"裸自签证书"场景的本质区别——开启严格校验后,Node.js TLS 握手会校验证书链,此时必须提供 ca,否则握手失败;
  • ssl.ca:内联的单行 CA 证书 PEM 内容,换行符已转义为 \n

为什么用内联内容而不是 caFilePath

源码中其实同时支持两种写法。在 packages/nocodb/src/utils/nc-config/helpers.tsxcUrlToDbConfig同文件metaUrlToDbConfig 中,URL 查询参数形式的 caFilePath / certFilePath / keyFilePath 会在启动时被读取为文件内容并回填到 ssl.ca 等字段。此外,packages/nocodb/src/helpers/resolveSslFileConfig.ts 是所有外部数据库连接(CE 与 EE 的 SqlClientFactory,见 SqlClientFactory.ts)共用的"文件路径 → 内联内容"解析入口。

resolveSslFileConfig 带有明确的安全约束:它先执行 validateDbConnectionSslPaths 策略守卫(云环境默认拦截文件路径 SSL,自托管可用 NC_DISABLE_DB_SSL_FILE_PATHS 打开),并且读取失败时只抛出统一文案 Failed to load SSL certificate configuration,避免通过错误差异探测宿主机文件是否存在。也就是说,文件路径方式存在策略与可用性门槛,而本模板采用的内联 ca 字符串写法在容器场景下更直接:证书内容随 db.json 一起以只读方式挂载进容器,不依赖容器内文件系统路径,也不触及上述策略守卫。

CA 证书转单行字符串

README 给出的转换命令如下,将多行 PEM 压缩为一行、换行替换为 \n(同时去除 \r):

awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' your-ca.pem

将输出粘贴为 db.jsonca 字段的值即可。注意两点:

  1. NF 过滤会丢弃空行,因此证书中间的空行不会保留——PEM 主体是连续 base64 行,通常没有空行,一般 PEM 证书可直接使用;
  2. 粘贴后 db.json 必须仍是合法 JSONca 的值是一个 JSON 字符串,其中的 \n 是 JSON 转义序列,最终解析回真实换行的 PEM 文本。

启动链路:NC_DB_JSON_FILE 如何被消费

docker.env 中声明 NC_DB_JSON_FILE=/usr/app/data/db.json,而容器内该路径正是 ./nocodb/db.json 的挂载点。解析链路可以在源码中完整印证:

  1. 环境入口 packages/nocodb/src/utils/nc-config/NcConfig.tscreateByEnv() 读取 process.env.NC_DB_JSON_FILE(优先级:NC_DB URL > NC_DB_JSON 内联 JSON > NC_DB_JSON_FILE 文件);
  2. 文件不存在时直接抛出 NC_DB_JSON_FILE not found: <path>NcConfig.ts#L110),容器启动即失败,这是部署后最快的排错信号;
  3. 文件内容被 JSON.parse 后作为元数据库 DbConfig,随后 metaDbCreateIfNotExist()NcConfig.ts#L155-L180)会通过 SqlClientFactory.create 真正建立一次连接并尝试 createDatabaseIfNotExists——这意味着带私有 CA 的 SSL 握手在此刻就会发生:如果 ca 内容错误或 rejectUnauthorized 严格校验失败,app 容器会在健康检查窗口内反复报错,不会"静默降级"。

三、docker.env:环境变量逐项说明

docker.env 全部内容及说明:

# Database
NC_DB_JSON_FILE=/usr/app/data/db.json

# Redis
NC_REDIS_URL=redis://your-redis-host:6379

# Public URL (email links, webhooks, OAuth redirects). Set to your public-facing URL.
NC_SITE_URL=https://nocodb.example.com

# Settings
NC_SECURE_ATTACHMENTS=true
NC_DISABLE_MUX=true
变量 示例值 说明
NC_DB_JSON_FILE /usr/app/data/db.json 元数据库连接 JSON 的容器内路径,指向 compose 挂载的 ./nocodb/db.json
NC_REDIS_URL redis://your-redis-host:6379 外部 Redis 地址。模板要求你替换为真实地址;Redis 承担缓存与任务队列职责
NC_SITE_URL https://nocodb.example.com 对外公开 URL,用于邮件链接、Webhook 回调、OAuth 重定向。应设置为 Traefik 路由的域名,且必须是最终对外可达的 HTTPS 地址
NC_SECURE_ATTACHMENTS true 附件安全模式。源码 packages/nocodb/src/modules/noco.module.ts 中该值为 true 时改变附件模块的注册方式,适合对外暴露的部署
NC_DISABLE_MUX true 关闭多路复用/内嵌通道,配合外部 PostgreSQL + 外部 Redis 的完全外部化部署

修改要点(来自 README 的 Usage 清单):

  • docker.env:设置 NC_REDIS_URL
  • docker-compose.yml:把 nocodb.example.com 替换为你的域名(注意 traefik.http.routers.nocodb.rule 中的 Host 规则与 NC_SITE_URL 保持一致),把 admin@example.com(ACME 邮箱)替换为真实邮箱;
  • nocodb/db.json:设置数据库主机、凭据、端口,并把 ca 替换为你的 CA 证书单行内容。

四、docker-compose.yml:完整编排解析

App 服务(nocodb)

nocodb:
  image: nocodb/nocodb:latest
  env_file: docker.env
  deploy:
    mode: replicated
    replicas: 1
  restart: unless-stopped
  volumes:
    - nocodb_data:/usr/app/data
    - ./nocodb/db.json:/usr/app/data/db.json
  networks:
    - nocodb-network
  labels:
    - 'traefik.enable=true'
    - 'traefik.http.routers.nocodb.rule=Host(`nocodb.example.com`)'
    - 'traefik.http.routers.nocodb.entrypoints=websecure'
    - 'traefik.http.routers.nocodb.tls.certresolver=letsencrypt'
  healthcheck:
    test: ['CMD-SHELL', 'wget -q --tries=1 --spider http://localhost:8080/api/v1/health || exit 1']
    interval: 30s
    timeout: 5s
    retries: 5
    start_period: 30s
  • 健康检查请求 http://localhost:8080/api/v1/health,30 秒探测一次、5 秒超时、5 次重试、30 秒启动宽限——这与 worker 的 service_healthy 依赖联动:只有 app 真正通过健康检查(即元数据库连接已建立、私有 CA 握手成功),worker 才会启动;
  • deploy.mode: replicatedreplicas: 1 是 swarm 风格声明,在普通 docker compose 下等价于单副本,可保留原样。

Worker 服务(worker)

worker:
  image: nocodb/nocodb:latest
  env_file: docker.env
  environment:
    NC_WORKER_CONTAINER: 'true'
  depends_on:
    nocodb:
      condition: service_healthy
  restart: unless-stopped
  volumes:
    - nocodb_data:/usr/app/data
    - ./nocodb/db.json:/usr/app/data/db.json
  networks:
    - nocodb-network

worker 与 app 共用 env_file 与数据卷,唯一差异是 NC_WORKER_CONTAINER: 'true'(该变量在 packages/nocodb/src/Noco.ts 处被主流程读取,worker 模式下不对外提供 Web 端口,也不注册面向用户的 Controller,参见 packages/nocodb/src/modules/auth/auth.module.ts)。拆分 worker 的收益是把导入导出、报表类异步任务与 API 请求隔离,互不抢占资源。

Traefik 服务(traefik)

traefik:
  image: traefik:v3.6
  command:
    - '--providers.docker=true'
    - '--providers.docker.exposedbydefault=false'
    - '--entryPoints.web.address=:80'
    - '--entryPoints.websecure.address=:443'
    - '--entryPoints.web.http.redirections.entryPoint.to=websecure'
    - '--entryPoints.web.http.redirections.entryPoint.scheme=https'
    - '--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web'
    - '--certificatesresolvers.letsencrypt.acme.email=admin@example.com'
    - '--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json'
  ports:
    - '80:80'
    - '443:443'
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - ./letsencrypt:/letsencrypt
  restart: unless-stopped
  networks:
    - nocodb-network
  • exposedbydefault=false:只有显式打了 traefik.enable=true 标签的服务才暴露,worker 因此天然隐身;
  • 80 端口仅用于 HTTP→HTTPS 301 重定向与 ACME HTTP-01 挑战,业务流量全部走 443 的 websecure
  • ACME 状态落在宿主机 ./letsencrypt/acme.json,容器重建不丢证书;
  • 前提条件:域名 A 记录必须指向本服务器公网 IP,否则 HTTP 挑战无法通过、证书签发失败。

五、部署步骤与验证

README 给出的标准流程(在仓库 docker-compose/ 目录下执行;cp 的目标可以放到任意位置,但需保持 ./nocodb/db.json./letsencrypt 等相对路径结构):

cp -r examples/postgres-private-ca ./my-deployment
cd my-deployment
# 1. 编辑 docker.env: 设置 NC_REDIS_URL
# 2. 编辑 docker-compose.yml:
#    - 将 nocodb.example.com 替换为你的域名
#    - 将 admin@example.com 替换为你的邮箱
# 3. 编辑 nocodb/db.json:
#    - 填写数据库 host、凭据、port
#    - 将 ca 值替换为你的 CA 证书内容(单行,\n 表示换行)
docker compose up -d

部署后的建议验证顺序:

  1. docker compose ps 观察三个服务状态,重点确认 nocodbhealthy——它意味着带私有 CA 的元数据库连接已经建立成功(NcConfig.metaDbCreateIfNotExist 在启动时完成了真实握手);
  2. 查看 app 日志:若 CA 内容有误,会看到元数据库连接/建库失败相关报错,而不是前端 502;
  3. 访问 https://<你的域名>,确认证书由 Let's Encrypt 签发、页面可登录;
  4. 确认 NC_SITE_URL 与域名一致后,测试一次邀请邮件或 Webhook,验证出站链接指向正确。

六、迁移到私有环境的检查清单

  • [ ] CA 证书 PEM 已用 awk 命令转为单行,db.json 整体可被 JSON.parse(可用 python3 -m json.tool nocodb/db.jsonjq 快速校验);
  • [ ] ssl.rejectUnauthorized 保持 trueca签发数据库证书的 CA(或完整证书链中缺的上级 CA),而不是数据库服务器证书本身;
  • [ ] docker.envNC_REDIS_URL 指向真实 Redis,网络策略允许容器访问 Redis 6379 与私有数据库 5432;
  • [ ] docker-compose.yml 的 Host 规则、ACME 邮箱、NC_SITE_URL 三处域名保持一致;
  • [ ] 80/443 端口对公网开放(ACME 挑战与 HTTPS 入口需要),而 8080 端口不对外暴露(模板未发布该端口,仅容器网络内可达)。

参考文件

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
983
503
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384