Hasura 配置参数详解

详解 Hasura GraphQL Engine v2.51.1 配置体系:HASURA_GRAPHQL_* 环境变量与 serve 参数逐项实测(端口/连接池/管理密钥/JWT/CORS/API 面/Console/日志/事件/WebSocket),每项改值-验证-还原闭环并附生产配置模板。

HasuraHasuraGraphQL2026/10/22

Hasura 配置参数详解

目标:详解 Hasura GraphQL Engine v2.51.1 的配置体系——以 HASURA_GRAPHQL_* 环境变量与 serve 启动参数为主线,逐项实测服务器端口、数据库连接池、管理密钥、JWT 认证、CORS、API 面、Console、日志、事件与 WebSocket 参数,每个参数均给出"改值 → 重启 → 验证 → 还原"的完整实测闭环与生产配置模板。已在 Ubuntu 22.04.5 / 24.04.5 部署实例实测确认默认值与生效方式。

一、环境信息

本章说明实测环境基线,所有参数默认值与生效结果均来自该环境。

  • 操作系统:Ubuntu 22.04.5 LTS(GLIBC 2.35,方案 B 实测)与 Ubuntu 24.04.5 LTS(GLIBC 2.39,方案 A 原生部署实测)
  • Hasura GraphQL Engine:v2.51.1(OSS 社区版,/v1/version 返回 {"server_type":"ce","version":"v2.51.1"})
  • 配置载体:环境变量(HASURA_GRAPHQL_*)、graphql-engine serve 命令行参数
  • 部署形态:原生二进制 + systemd(EnvironmentFile=/etc/hasura/env)与 Docker Compose 两种,配置项完全一致
  • 元数据库:PostgreSQL 14.24 / 16.15;数据源:同实例 hasuradb(含 public.products 示例表)
  • 引擎监听:8080(HTTP API 与服务端 Console)

组件与部署方法见 《Ubuntu 22.04 安装 Hasura GraphQL Engine 指南》,CLI 命令见 《Hasura 常用命令与工具详解》。

二、前置条件

  • 已按安装指南完成部署并验证 /healthz 返回 OK;
  • 拥有管理密钥(本文示例统一 q1w2e3r4);
  • systemd 部署形态下可直接编辑 /etc/hasura/env;Compose 形态下编辑 docker-compose.yaml 的 environment: 段;
  • 熟悉 systemctl restart hasura(原生)或 docker compose up -d(Compose)的重启方式——Hasura 绝大多数参数需重启进程生效。

三、参数查看与修改方式

Hasura 没有主配置文件,配置只有两个入口:环境变量与 serve 子命令参数(环境变量优先级与参数等价,同名时参数覆盖环境变量是官方约定,实际以启动日志为准核对)。

查看当前全部生效值:引擎启动时会把整份生效配置打成一条 JSON 日志。这是核对任何参数是否生效的权威手段(实测:journalctl -u hasura | grep admin_secret_set | tail -1,节选解析后):

{
  "admin_secret_set": true,
  "cors_config": {"allowed_origins": "*", "disabled": false, "ws_read_cookie": null},
  "enable_console": true,
  "enabled_apis": ["metadata", "config", "pgdump", "graphql"],
  "enabled_log_types": ["startup", "http-log", "jwk-refresh-log", "webhook-log", "websocket-log"],
  "events_fetch_batch_size": 100,
  "graceful_shutdown_timeout": 60,
  "jwt_secret": [],
  "live_query_options": {"batch_size": 100, "refetch_delay": 1},
  "log_level": "info",
  "port": 8080,
  "server_host": "HostAny",
  "transaction_isolation": "ISOLATION LEVEL READ COMMITTED",
  "unauth_role": null,
  "use_prepared_statements": true,
  "websocket_connection_init_timeout": "Refined (Seconds {seconds = 3s})",
  "websocket_keep_alive": "KeepAliveDelay {unKeepAliveDelay = Refined (Seconds {seconds = 5s})}",
  "websocket_queue_size": 300
}

修改方式(原生 systemd 部署):编辑 /etc/hasura/env 后重启——

vi /etc/hasura/env
systemctl restart hasura && sleep 5 && systemctl is-active hasura

修改方式(Compose 部署):编辑 docker-compose.yaml 的 environment: 段后 docker compose up -d 重建服务。

⚠️ 注意:systemd 的 EnvironmentFile 按 shell 规则解析值,值内含双引号的 JSON(如 HASURA_GRAPHQL_JWT_SECRET)必须整体用单引号包裹,否则 JSON 被剥引号破坏、引擎启动即 Fatal(第八章实测实录)。

四、参数总览

按功能域汇总本文实测覆盖的参数(默认值为 v2.51.1 实测确认):

功能域环境变量默认值生效观测点(实测手段)
服务器HASURA_GRAPHQL_SERVER_PORT8080启动日志 "port":8081(改后)+ 新端口 healthz 200
服务器HASURA_GRAPHQL_SERVER_HOST*(HostAny)启动日志 server_host
数据库HASURA_GRAPHQL_METADATA_DATABASE_URL必填启动日志 postgres_connection 连接信息
数据库HASURA_GRAPHQL_DATABASE_URL无首次启动自动接入 default 源,export_metadata 可见
数据库HASURA_GRAPHQL_PG_CONNECTIONS / PG_TIMEOUT / PG_CONN_LIFETIME50 / 180 / 600作用于元数据库连接池;数据源池在元数据 connection_info.pool_settings(第六章实测辨析)
鉴权HASURA_GRAPHQL_ADMIN_SECRET未设置启动日志 admin_secret_set;请求头校验行为
鉴权HASURA_GRAPHQL_UNAUTHORIZED_ROLEnull启动日志 unauth_role;匿名请求行为变化
鉴权HASURA_GRAPHQL_JWT_SECRET[](未配置)启动日志 jwt_secret;无 Token 请求报错语变化
网络HASURA_GRAPHQL_CORS_DOMAIN*启动日志 cors_config;OPTIONS/POST 响应头
API 面HASURA_GRAPHQL_ENABLED_APISmetadata, config, pgdump, graphql启动日志 enabled_apis;被关端点返回 404
ConsoleHASURA_GRAPHQL_ENABLE_CONSOLEfalse启动日志 enable_console;/console 200/404
ConsoleHASURA_GRAPHQL_CONSOLE_ASSETS_DIRCDN 加载离线环境指定 /srv/console-assets
开发HASURA_GRAPHQL_DEV_MODEfalse开发辅助 UI 与调试信息开关(第十一章)
日志HASURA_GRAPHQL_LOG_LEVELinfo启动日志 log_level;debug 级日志出现
日志HASURA_GRAPHQL_ENABLED_LOG_TYPESstartup, http-log, jwk-refresh-log, webhook-log, websocket-log移除 http-log 后请求不留日志(实测)
日志HASURA_GRAPHQL_ENABLE_TELEMETRYtrue启动日志 enable_telemetry;遥测上报日志停止
事件HASURA_GRAPHQL_EVENTS_FETCH_BATCH_SIZE100启动日志 events_fetch_batch_size(实测 50→还原 100)
直播查询HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_REFETCH_INTERVAL1000(ms)启动日志 live_query_options.refetch_delay(实测 2000→2)
WebSocketHASURA_GRAPHQL_WEBSOCKET_CONNECTION_INIT_TIMEOUT3(秒)启动日志 websocket_connection_init_timeout(实测 10s)
WebSocketHASURA_GRAPHQL_WEBSOCKET_KEEPALIVE5(秒)启动日志 websocket_keep_alive(实测 30s;⚠️ 变量名无下划线)
WebSocketHASURA_GRAPHQL_WEBSOCKET_QUEUE_SIZE300启动日志 websocket_queue_size
事件HASURA_GRAPHQL_EVENTS_HTTP_POOL_SIZE100事件投递 HTTP 连接池

同名关系说明:每个环境变量基本都有等价的 serve 参数(如 --server-port、--log-level、--admin-secret),完整参数清单可执行 graphql-engine serve --help 查看(实测共 770 行帮助输出,下表仅列与本文实测项对应的映射):

环境变量等价 serve 参数
HASURA_GRAPHQL_SERVER_PORT--server-port <PORT>
HASURA_GRAPHQL_ADMIN_SECRET--admin-secret KEY
HASURA_GRAPHQL_LOG_LEVEL--log-level ARG
HASURA_GRAPHQL_ENABLED_LOG_TYPES--enabled-log-types ARG
HASURA_GRAPHQL_CORS_DOMAIN--cors-domain <DOMAINS>
HASURA_GRAPHQL_ENABLED_APIS--enabled-apis ARG
HASURA_GRAPHQL_JWT_SECRET--jwt-secret <JSON CONFIG>
HASURA_GRAPHQL_UNAUTHORIZED_ROLE--unauthorized-role <ROLE>
HASURA_GRAPHQL_DEV_MODE--dev-mode
HASURA_GRAPHQL_ENABLE_CONSOLE--enable-console

五、服务器与端口

服务器域参数控制 HTTP 监听地址与端口。生产中改端口的常见动机是避让占用或前置反代后仅监听本机。实测把端口从 8080 改为 8081:

# /etc/hasura/env
HASURA_GRAPHQL_SERVER_PORT=8081
systemctl restart hasura && sleep 5
curl -s -w '|%{http_code}\n' http://127.0.0.1:8081/healthz
curl -s -o /dev/null -w '%{http_code}\n' --max-time 3 http://127.0.0.1:8080/healthz || echo "8080 no response"
OK|200
000
8080 no response

启动日志同步确认 "port":8081。改回 8080 重启后 healthz 恢复 OK(实测)。HASURA_GRAPHQL_SERVER_HOST 默认 *(实测启动日志 server_host: "HostAny"),需要只监听内网网卡时改为对应 IP。

六、元数据库与数据源连接

两个连接串是 Hasura 必填配置:HASURA_GRAPHQL_METADATA_DATABASE_URL 指向元数据库(存储表跟踪、权限、事件触发器等 catalog 信息,首次启动自动建表到 catalog 版本 48);HASURA_GRAPHQL_DATABASE_URL 是默认数据源,首次启动自动以 default 名称接入。导出元数据可见源连接配置(实测回显节选):

curl -s -X POST http://127.0.0.1:8080/v1/metadata -H 'Content-Type: application/json' -H 'X-Hasura-Admin-Secret: q1w2e3r4' -d '{"type":"export_metadata","args":{}}'
{"version":3,"sources":[{"name":"default","kind":"postgres","tables":[{"table":{"name":"products","schema":"public"}}],
"configuration":{"connection_info":{"database_url":{"from_env":"HASURA_GRAPHQL_DATABASE_URL"},
"isolation_level":"read-committed","pool_settings":{"connection_lifetime":600,"idle_timeout":180,"max_connections":50,"retries":1},"use_prepared_statements":true}}}]}

连接池参数的作用域辨析(实测结论):HASURA_GRAPHQL_PG_CONNECTIONS / HASURA_GRAPHQL_PG_TIMEOUT / HASURA_GRAPHQL_PG_CONN_LIFETIME 控制的是元数据库连接池(默认 50/180/600)。实测把它们设为 25/60/120 并重启后,export_metadata 里数据源(default 源)的 pool_settings 仍是 50/180/600——数据源连接池不随这组环境变量变化,需通过元数据配置修改。用 replace_metadata 把源池改为 max_connections: 25, idle_timeout: 60 验证(实测回显):

{"message":"success"}
"pool_settings":{"connection_lifetime":600,"idle_timeout":60,"max_connections":25,"retries":1}

reload_metadata 返回 {"is_consistent":true,"message":"success"},随后把元数据还原为 50/180(实测成功还原)。生产模板中两者要分别设置:元数据库池按实例数小配(默认 50 足够),数据源池按业务并发配。

七、鉴权:管理密钥与匿名角色

HASURA_GRAPHQL_ADMIN_SECRET 是引擎的总管理开关:设置后所有请求必须携带 X-Hasura-Admin-Secret 头。本文部署示例统一 q1w2e3r4。三种鉴权行为实测:

不带头(部署后默认,实测回显):

curl -s -X POST http://127.0.0.1:8080/v1/graphql -H 'Content-Type: application/json' -d '{"query":"{ products { id } }"}'
{"errors":[{"message":"\"x-hasura-admin-secret\" required, but not found","extensions":{"path":"$","code":"access-denied"}}]}

带头但密钥错误(实测回显,注意 HTTP 状态码仍是 200,错误在响应体内):

curl -s -w "\nhttp_code=%{http_code}\n" -X POST http://127.0.0.1:8080/v1/graphql -H 'Content-Type: application/json' -H 'X-Hasura-Admin-Secret: wrong-secret' -d '{"query":"{ products { id } }"}'
{"errors":[{"message":"invalid \"x-hasura-admin-secret\"","extensions":{"path":"$","code":"access-denied"}}]}
http_code=200

HASURA_GRAPHQL_UNAUTHORIZED_ROLE=anonymous:为未认证请求指派角色。加入环境变量重启后,启动日志 unauth_role:"anonymous",未认证请求不再要求密钥、而是以 anonymous 角色执行(实测回显——products 表未授予 anonymous 权限,故该角色 schema 中无此字段):

curl -s -X POST http://127.0.0.1:8080/v1/graphql -H 'Content-Type: application/json' -d '{"query":"{ products { id } }"}'
{"errors":[{"message":"field 'products' not found in type: 'query_root'","extensions":{"path":"$.selectionSet.products","code":"validation-failed"}}]}

删除该变量重启后,恢复为要求管理密钥(实测回显同上"不带头")。HASURA_GRAPHQL_ADMIN_INTERNAL_ERRORS=false 可在报错中隐藏内部细节,生产建议开启(默认 true,开发期保留便于排障)。

八、JWT 认证

HASURA_GRAPHQL_JWT_SECRET 把引擎从"管理密钥模式"切换/叠加为 JWT 认证模式。配置值是 JSON,典型形态 {"type":"RS256","key":"<公钥 PEM>"}。本章实测踩过的三个坑都有普适价值。

坑一:systemd EnvironmentFile 剥双引号。直接在 /etc/hasura/env 写 HASURA_GRAPHQL_JWT_SECRET={"type":"RS256","key":...},systemd 按 shell 规则把内层双引号剥掉,JSON 被破坏,引擎拒绝启动(journalctl 实测回显):

Fatal Error:- Environment variable HASURA_GRAPHQL_JWT_SECRET: Error in $: Invalid JWK: Could not decode PEM: invalid PEM delimiter found

解决:整个值用单引号包裹。坑二:key 字段必须填公钥。填入 RSA 私钥(无论 PKCS#8 还是 PKCS#1)都报解码失败(实测回显):

Fatal Error:- Environment variable HASURA_GRAPHQL_JWT_SECRET: Error in $: Invalid JWK: Could not decode PEM: fromASN1: X509.PubKey: unknown format:[...]

解决:openssl rsa -in 私钥 -pubout -out 公钥.pem 导出公钥后填入。坑三:JSON 中不存在的字段(如 key_file)会被静默忽略,报 key and jwk_url both cannot be empty。

正确的配置与生效验证(实测):

openssl genrsa -out /etc/hasura/jwt-private.pem 2048
openssl rsa -in /etc/hasura/jwt-private.pem -pubout -out /etc/hasura/jwt-pub.pem
# /etc/hasura/env 追加(单引号包裹,key 填公钥 PEM 内容)
# HASURA_GRAPHQL_JWT_SECRET='{"type":"RS256","key":"-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"}'
systemctl restart hasura && systemctl is-active hasura
active

启动日志出现完整 jwt_secret 配置(实测节选):

"jwt_secret":[{"audience":null,"claims_format":"json","claims_namespace":"x-hasura-...",...}]

未携带 Token 的请求报错语切换为 JWT 模式(实测回显):

{"errors":[{"message":"Missing 'Authorization' or 'Cookie' header in JWT authentication mode","extensions":{"path":"$","code":"invalid-headers"}}]}

同时实测确认:JWT 模式下带正确 X-Hasura-Admin-Secret 的管理请求不受影响(返回查询数据)。删除 JWT 行重启后恢复管理密钥模式(实测 "jwt_secret":[],未认证请求重新要求 x-hasura-admin-secret)。生产建议改用 "jwk_url" 指向鉴权服务的 JWKS 端点实现密钥轮换,并按需配置 audience/issuer/claims_namespace。

九、CORS 与 API 面

9.1 CORS 跨域

HASURA_GRAPHQL_CORS_DOMAIN 控制浏览器跨域放行,默认 *。实测设为 https://app.example.com(重启后启动日志 cors_config.allowed_origins 同步变化)。放行域请求(实测回显——响应带完整 CORS 头):

curl -s -D - -o /dev/null -X POST http://127.0.0.1:8080/v1/graphql -H 'Content-Type: application/json' -H 'Origin: https://app.example.com' -H 'X-Hasura-Admin-Secret: q1w2e3r4' -d '{"query":"{ products { id } }"}'
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET,POST,PUT,PATCH,DELETE,OPTIONS
Access-Control-Expose-Headers: X-Hasura-Query-Cache-Key,X-Hasura-Query-Family-Cache-Key,Warning

非放行域请求:响应体正常返回数据但不带 Access-Control-Allow-Origin 头(CORS 由浏览器执行拦截,服务端不阻断)。预检请求(默认 * 时,实测回显):

curl -s -D - -o /dev/null -X OPTIONS http://127.0.0.1:8080/v1/graphql -H 'Origin: https://app.example.com' -H 'Access-Control-Request-Method: POST' -H 'Access-Control-Request-Headers: content-type,x-hasura-admin-secret'
HTTP/1.1 204 No Content
Access-Control-Max-Age: 1728000
Access-Control-Allow-Headers: content-type,x-hasura-admin-secret
Access-Control-Allow-Origin: https://app.example.com

⚠️ 实测经典坑:端口写法导致静默失效。把配置写成 https://app.example.com:443 后,浏览器实际发送的 Origin: https://app.example.com(HTTPS 默认端口被省略)与配置字面不匹配,放行域的响应也不带 CORS 头(实测对照:不带端口的配置命中放行,带 :443 的配置同请求无 CORS 头)。原则:配置值与浏览器 Origin 的字面形式保持一致,不要补默认端口。另实测发现 v2.51.1 在自定义 CORS 域下对 /v1/graphql 的 OPTIONS 预检返回 500 {"error":"Internal Server Error","code":"unexpected"}(默认 * 时同请求为 204),生产环境若使用预检建议在前置反代处理或保持实测核对。

9.2 API 面控制

HASURA_GRAPHQL_ENABLED_APIS 收紧引擎暴露的 API 域,默认全开(metadata, config, pgdump, graphql)。实测只保留 graphql:

# /etc/hasura/env
HASURA_GRAPHQL_ENABLED_APIS=graphql

重启后启动日志 "enabled_apis":["graphql"],逐端点实测(回显):

curl -s -w '\nhttp_code=%{http_code}\n' -X POST http://127.0.0.1:8080/v1/metadata -H 'Content-Type: application/json' -H 'X-Hasura-Admin-Secret: q1w2e3r4' -d '{"type":"export_metadata","args":{}}'
curl -s -w '\nhttp_code=%{http_code}\n' -X POST http://127.0.0.1:8080/v1/pg_dump -H 'Content-Type: application/json' -H 'X-Hasura-Admin-Secret: q1w2e3r4' -d '{"opts":["-O"],"clean_output":true}'
curl -s -X POST http://127.0.0.1:8080/v1/graphql -H 'Content-Type: application/json' -H 'X-Hasura-Admin-Secret: q1w2e3r4' -d '{"query":"{ products_aggregate { aggregate { count } } }"}'
{"error":"resource does not exist","path":"$","code":"not-found"}
http_code=404
{"error":"resource does not exist","path":"$","code":"not-found"}
http_code=404
{"data":{"products_aggregate":{"aggregate" : {"count" : 3}}}}

被关闭的端点返回 404,GraphQL 数据面不受影响。删除变量重启后恢复四域全开(实测)。生产建议:数据 API 只读场景可进一步用权限模型收紧,config 域仅在需要导出配置时开启。

十、Console 与开发模式

HASURA_GRAPHQL_ENABLE_CONSOLE 控制服务端托管 Console(8080 端口 /console 路径)。实测开关对照:默认(env 中显式 true)时 curl /console 返回 200;设为 false 重启后返回 404 且启动日志 "enable_console":false(实测回显):

{"error":"resource does not exist","path":"$","code":"not-found"}
http_code=404

恢复 true 后回到 200(实测)。注意区分:CLI 版 Console 由 hasura console 在 9695 端口起本地服务(详见 《Hasura 常用命令与工具详解》),与本开关无关;离线/内网环境配合 HASURA_GRAPHQL_CONSOLE_ASSETS_DIR=/srv/console-assets 使用离线静态资源,避免 Console 从公网 CDN 加载资源。

HASURA_GRAPHQL_DEV_MODE 默认 false,开启后 Console 显示开发辅助 UI(API Explorer 提示、跟踪提示等)。实测用校验错误对照了两种模式:{"query":"{ nope }"} 在 dev 开/关下响应体逐字节一致(validation-failed 错误不携带 internal 细节);internal 细节的显隐由权限类错误的 HASURA_GRAPHQL_ADMIN_INTERNAL_ERRORS 控制。开发模式定位是"开发期辅助开关",生产保持 false。

十一、日志体系与遥测

日志等级 HASURA_GRAPHQL_LOG_LEVEL 默认 info。实测改为 debug 并重启:启动日志 "log_level":"debug",且出现 {"level":"debug",...} 行(实测节选):

"level":"debug","timestamp":"2026-10-22T11:36:46.734+0000","type":"unstructured"

排障后还原 info(实测)。日志类型 HASURA_GRAPHQL_ENABLED_LOG_TYPES 默认 startup, http-log, jwk-refresh-log, webhook-log, websocket-log。实测把 http-log 移除后:发出 GraphQL 请求但 http-log 计数保持不变(实测 before=11 / after=11);恢复默认后计数增长到 13(两条新请求日志)——证明日志类型裁剪即时生效。query-log 不在默认集,开启后每条 GraphQL 查询记录操作详情,量大时显著膨胀日志,按需启用。

http-log 行解析(实测单行节选,字段含义就地标注):

{"detail":{"http_info":{"method":"POST","status":200,"url":"/v1/graphql","ip":"127.0.0.1"},
"operation":{"query_execution_time":7.97007e-4,"request_id":"9eaccf58-...","response_size":126,
"user_vars":{"x-hasura-role":"admin"}}},"level":"info","type":"http-log"}

query_execution_time 单位秒,user_vars.x-hasura-role 显示执行角色,request_id 可与响应头 x-request-id 对应用于链路排查。

遥测 HASURA_GRAPHQL_ENABLE_TELEMETRY 默认 true(匿名版本统计上报 telemetry.hasura.io)。实测置 false 重启后启动日志 "enable_telemetry":false。无外网服务器上建议关闭,否则日志会周期性出现遥测上报失败的 http_error 行(实测环境共记录 28 条,关闭后不再新增)。

十二、事件与 WebSocket 参数

事件触发器与订阅(直播查询、WebSocket)相关的批处理参数均可通过启动日志核对生效值。以下为一轮"改值 → 重启 → 读启动日志 → 还原"实测(四个参数一次改、一次还原):

# /etc/hasura/env 追加
HASURA_GRAPHQL_EVENTS_FETCH_BATCH_SIZE=50
HASURA_GRAPHQL_LIVE_QUERIES_MULTIPLEXED_REFETCH_INTERVAL=2000
HASURA_GRAPHQL_WEBSOCKET_CONNECTION_INIT_TIMEOUT=10
HASURA_GRAPHQL_WEBSOCKET_KEEPALIVE=30

重启后启动日志实测回显:

"events_fetch_batch_size":50
"live_query_options":{"batch_size":100,"refetch_delay":2}
"websocket_connection_init_timeout":"Refined (Seconds {seconds = 10s})"

refetch_delay 显示 2——环境变量以毫秒为单位(2000ms),引擎内部以秒记录,二者换算一致。删除以上变量重启后全部回到默认 100 / refetch_delay:1 / 3s / 5s(实测)。

⚠️ 实测变量名坑:HASURA_GRAPHQL_WEBSOCKET_KEEP_ALIVE(多一个下划线)静默不生效(keep_alive 仍为 5s),正确变量名是 HASURA_GRAPHQL_WEBSOCKET_KEEPALIVE(连写,实测 30s 生效)。同类未知变量引擎不报错——每次改配置都要用启动日志核对生效值。

十三、生产配置模板

以下模板面向 8 vCPU / 16GB 内存 / NVMe SSD / 中小并发 OLTP Web API 场景(Ubuntu 22.04 原生 systemd 部署;Compose 形态把同名键移入 environment: 段即可):

# /etc/hasura/env —— Hasura GraphQL Engine v2.51.1 生产模板
## 元数据库(专用库,与业务库分离)
HASURA_GRAPHQL_METADATA_DATABASE_URL=postgres://hasura:q1w2e3r4@127.0.0.1:5432/hasura_metadata
## 数据源连接串(多源时在元数据中接入,保留默认源亦可)
HASURA_GRAPHQL_DATABASE_URL=postgres://hasura:q1w2e3r4@127.0.0.1:5432/hasuradb
## 管理密钥(务必更换为强随机值)
HASURA_GRAPHQL_ADMIN_SECRET=q1w2e3r4
## 元数据库连接池(引擎进程自身)
HASURA_GRAPHQL_PG_CONNECTIONS=50
HASURA_GRAPHQL_PG_TIMEOUT=180
HASURA_GRAPHQL_PG_CONN_LIFETIME=600
## 关闭开发辅助与遥测
HASURA_GRAPHQL_DEV_MODE=false
HASURA_GRAPHQL_ENABLE_TELEMETRY=false
## 生产日志基线:info 等级 + 常规类型(不启用 query-log 防日志膨胀)
HASURA_GRAPHQL_LOG_LEVEL=info
HASURA_GRAPHQL_ENABLED_LOG_TYPES=startup, http-log, webhook-log, websocket-log
## Console 不由服务端托管(经 CI/CD 的 hasura metadata apply 管理元数据)
HASURA_GRAPHQL_ENABLE_CONSOLE=false
## API 面按需收紧(如无 pg_dump 需求)
HASURA_GRAPHQL_ENABLED_APIS=metadata, graphql
## 错误响应隐藏内部细节
HASURA_GRAPHQL_ADMIN_INTERNAL_ERRORS=false
## 端口
HASURA_GRAPHQL_SERVER_PORT=8080

模板要点解读:元数据库与业务数据源分库是生产推荐形态(备份与容量策略独立);Console 关闭后元数据变更走 hasura metadata apply 流水线;query-log 默认不开,需要慢查询分析时临时开启;数据源连接池在元数据 connection_info.pool_settings 中按业务并发设置(默认 50/180/600 适配多数场景)。

十四、常见问题(FAQ)

Q1:改了环境变量重启后"没生效"? 先查变量名拼写(实测 WEBSOCKET_KEEP_ALIVE 写错静默不生效),再读启动日志 admin_secret_set 行的 JSON 核对生效值——这是唯一权威手段。Compose 形态确认执行的是 docker compose up -d(重建服务)而非 restart(不重读 environment 的旧写法)。

Q2:引擎启动即 Fatal,报 Invalid JWK? HASURA_GRAPHQL_JWT_SECRET 的 JSON 被 systemd 剥引号(用单引号整体包裹),或 key 填了私钥/非法字段。该字段要公钥 PEM,合法字段以官方文档为准(第八章三个坑的实录)。

Q3:CORS 配置了域名但前端仍报跨域? 核对配置值与浏览器 Origin 的字面一致性(不要补 :443 这类默认端口,实测会造成静默不匹配);CORS 是浏览器行为,curl 不带拦截,直接 curl 看响应是否携带 Access-Control-Allow-Origin 头来判断。

Q4:/v1/metadata 或 /v1/pg_dump 返回 404? HASURA_GRAPHQL_ENABLED_APIS 收紧所致,按需恢复对应域(9.2 实测)。

Q5:错误响应 HTTP 状态码是 200 却带 errors? v2 引擎对鉴权失败(access-denied)等错误返回 200 + 错误体(第七章实测),监控告警要按响应体 errors 字段判断,不能只看状态码。

Q6:日志里周期性出现 telemetry 上报失败? 无外网或出网受限环境置 HASURA_GRAPHQL_ENABLE_TELEMETRY=false(第十一章实测)。

Q7:连接池参数改了但数据源没变化? PG_CONNECTIONS 系列只作用于元数据库池;数据源池在元数据 connection_info.pool_settings,用 replace_metadata 修改(第六章实测辨析)。

十五、参考链接