news 2026/9/5 19:56:58

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Nocodb 对接私网 PostgreSQL:Private CA 证书 + Traefik 生产部署实战

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

【免费下载链接】nocodb🔥 🔥 🔥 A Free & Self-hostable Airtable Alternative项目地址: https://gitcode.com/GitHub_Trending/no/nocodb

在私有云或本地机房环境中,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 中定义了三个服务:

服务镜像职责
nocodbnocodb/nocodb:latest主应用,监听 8080,承载 API 与前端,挂载db.json
workernocodb/nocodb:latest独立 worker 容器,通过NC_WORKER_CONTAINER: 'true'标记,仅处理异步任务
traefiktraefik:v3.680/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.ts 的xcUrlToDbConfig与 同文件 的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.ts 的createByEnv()读取process.env.NC_DB_JSON_FILE(优先级:NC_DBURL >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_URLredis://your-redis-host:6379外部 Redis 地址。模板要求你替换为真实地址;Redis 承担缓存与任务队列职责
NC_SITE_URLhttps://nocodb.example.com对外公开 URL,用于邮件链接、Webhook 回调、OAuth 重定向。应设置为 Traefik 路由的域名,且必须是最终对外可达的 HTTPS 地址
NC_SECURE_ATTACHMENTStrue附件安全模式。源码 packages/nocodb/src/modules/noco.module.ts 中该值为true时改变附件模块的注册方式,适合对外暴露的部署
NC_DISABLE_MUXtrue关闭多路复用/内嵌通道,配合外部 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 端口不对外暴露(模板未发布该端口,仅容器网络内可达)。

参考文件

  • 模板文档:docker-compose/examples/postgres-private-ca/README.md
  • 编排文件:docker-compose/examples/postgres-private-ca/docker-compose.yml、docker.env、nocodb/db.json
  • 配置解析:NcConfig.ts(NC_DB_JSON_FILE读取与元数据库初始化)、helpers.ts(caFilePath等 URL 形式 SSL 参数解析)
  • SSL 解析入口:resolveSslFileConfig.ts、SqlClientFactory.ts
  • worker 模式开关:Noco.ts、noco.module.ts

【免费下载链接】nocodb🔥 🔥 🔥 A Free & Self-hostable Airtable Alternative项目地址: https://gitcode.com/GitHub_Trending/no/nocodb

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 19:56:18

spotDL Spotify音乐下载完整指南

spotDL Spotify音乐下载完整指南 【免费下载链接】spotify-downloader Download your Spotify playlists and songs along with album art and metadata (from YouTube if a match is found). 项目地址: https://gitcode.com/GitHub_Trending/sp/spotify-downloader spo…

作者头像 李华
网站建设 2026/9/5 19:44:35

SG90 360°连续旋转舵机控制方法:用writeMicroseconds实现方向与转速

很多人第一次买 SG90 舵机时&#xff0c;会看到两个版本在货架上并排出现&#xff1a;标准 180 舵机和 360 连续旋转舵机。如果你买的是后者&#xff0c;又习惯性地用 write(90) 想让它转到一个固定角度&#xff0c;很快就会发现问题&#xff1a;舵机要么上电就朝一个方向猛转…

作者头像 李华