配置
Jant 的配置来自两个地方:
- 环境变量:控制基础设施和运行时行为
- 设置页面:站点名称、外观、时区等可在线调整的选项
大多数单站点安装只需要设置一个值:AUTH_SECRET,其余按需配置。
环境变量
使用:
wrangler.toml存放 Cloudflare 的非敏感配置.dev.vars存放本地 Cloudflare secrets.env或进程环境变量,供 Node 和 Docker 使用
必需项
所有运行时都必须设置这个变量:
| 变量 | 说明 |
|---|---|
AUTH_SECRET |
better-auth 用于签名 session cookie 的密钥,至少 32 个字符。不要提交进版本库 |
不要把 AUTH_SECRET 提交进版本库。
- Cloudflare 本地开发:放进
.dev.vars - Cloudflare 生产环境:用
npx wrangler secret put AUTH_SECRET作为 Worker secret 设置 - Node 和 Docker:放进
.env或进程环境变量
公开 URL 和子路径
大多数情况下,这两个变量都不需要设置。Jant 默认从请求的 host 自动推导 origin,并挂载在根路径下。
| 变量 | 说明 |
|---|---|
SITE_ORIGIN |
固定公开 origin,例如 https://example.com。影响 RSS、sitemap、export、auth callbacks 等生成的绝对 URL |
SITE_PATH_PREFIX |
公开路径前缀,例如 /blog。影响所有路由和静态资源路径 |
只有在以下情况才需要设置:
- 站点在反向代理后面,并且反向代理没有正确的传递 Host,导致自动推导的 host 不正确:设置
SITE_ORIGIN=https://example.com - 挂在子路径下(例如
example.com/blog):设置SITE_PATH_PREFIX=/blog - 需要写死域名
Node 和 Docker
在 Node 和 Docker 下,Jant 通过 DATABASE_URL 判断数据库运行时:
file:表示 SQLitepostgres:或postgresql:表示 Postgres
最小 SQLite 示例:
AUTH_SECRET=your-32-plus-character-secret
SITE_ORIGIN=https://your-jant.example
DATABASE_URL=file:./data/jant.sqlite
最小 Postgres 示例:
AUTH_SECRET=your-32-plus-character-secret
SITE_ORIGIN=https://your-jant.example
DATABASE_URL=postgres://USER:PASSWORD@HOST:5432/DBNAME
Node 和 Docker 的常用变量:
| 变量 | 默认值 | 说明 |
|---|---|---|
DATA_DIR |
./data |
默认 SQLite 和本地媒体路径的基础目录 |
LOCAL_STORAGE_PATH |
<DATA_DIR>/media |
覆盖本地媒体目录 |
LOCAL_PUBLIC_URL |
未设置 | 供 Jant 外部直接提供媒体的公开基地址;留空时,Jant 使用自己的 /media/* 路由 |
HOST |
裸 Node 下是 127.0.0.1 |
jant start 的绑定地址 |
PORT |
3000 |
jant start 的绑定端口 |
TRUST_PROXY |
false |
是否信任反向代理传来的转发头 |
官方 Docker 镜像默认把 DATA_DIR 设为 /var/lib/jant,而 Docker Compose 通常会把 TRUST_PROXY=true。
Feed 默认值(可选)
| 变量 | 默认值 | 说明 |
|---|---|---|
MAIN_RSS_FEED |
featured |
控制 /feed 返回 featured 还是 latest |
featured 默认开启是有意为之。Jant 假设很多帖子应该留在站点上,但不一定要自动成为默认订阅 feed 的内容。
分页(可选)
| 变量 | 默认值 | 说明 |
|---|---|---|
PAGE_SIZE |
50 |
timelines 和 APIs 的默认分页大小 |
SEARCH_PAGE_SIZE |
继承 PAGE_SIZE |
只覆盖搜索页分页 |
ARCHIVE_PAGE_SIZE |
继承 PAGE_SIZE |
只覆盖归档页分页 |
只有在搜索页或归档页真的需要和全站不同的分页大小时,才去设置 SEARCH_PAGE_SIZE 和 ARCHIVE_PAGE_SIZE。
存储
存储方式取决于运行时:
| 运行时 | 默认值 | 支持的驱动 |
|---|---|---|
| Cloudflare Workers | r2 |
r2, s3 |
| Node 和 Docker | local |
local, s3 |
Node 不支持 r2。
Cloudflare 不支持 local。
通过 STORAGE_DRIVER 环境变量切换驱动,例如 STORAGE_DRIVER=s3。不设置时使用各运行时的默认值。
对 Node 和 Docker 来说,local 是最快起步的方式;s3 通常是更适合长期生产环境的选择。
本地存储(Node / Docker 下最快起步)
本地存储不需要额外驱动配置。
适合这些场景:
- 想用最简单的方式跑起来
- 本地测试
- 单机的小型安装
默认值:
DATA_DIR=./dataLOCAL_STORAGE_PATH=<DATA_DIR>/media
如果你想把媒体文件放在别处,可以覆盖这个路径:
LOCAL_STORAGE_PATH=/absolute/path/to/jant-media
只有在另一个 Web 服务器会直接托管这些文件时,才设置 LOCAL_PUBLIC_URL。
R2(默认)
Cloudflare Workers 默认使用 R2。
| 变量 | 说明 |
|---|---|
R2_PUBLIC_URL |
直接提供媒体文件的公开 URL |
R2 本身通过 wrangler.toml 中的 [[r2_buckets]] 绑定来配置。
强烈建议设置 R2_PUBLIC_URL。不设置也能工作,但 Jant 就必须通过 Worker 代理每一次媒体请求。
[vars]
R2_PUBLIC_URL = "https://media.yourdomain.com"
S3 兼容存储
适合在这些场景下使用 S3 兼容存储:
- 你想在 Node 或 Docker 下使用更推荐的长期存储方案
- 你想在 Cloudflare 和 Node 之间共用同一套存储后端
- 你更偏好 S3、Backblaze B2、MinIO、DigitalOcean Spaces 或其他兼容服务
- 你需要通过预签名 URL 做浏览器直传
| 变量 | 说明 |
|---|---|
STORAGE_DRIVER |
设为 s3 |
S3_ENDPOINT |
S3 API endpoint |
S3_BUCKET |
Bucket 名称 |
S3_REGION |
Bucket 区域,默认是 auto |
S3_PUBLIC_URL |
上传文件对外提供的公开 URL |
S3_ACCESS_KEY_ID |
访问密钥,必须保密 |
S3_SECRET_ACCESS_KEY |
Secret key,必须保密 |
示例:
[vars]
STORAGE_DRIVER = "s3"
S3_ENDPOINT = "https://s3.us-east-1.amazonaws.com"
S3_BUCKET = "my-bucket"
S3_REGION = "us-east-1"
S3_PUBLIC_URL = "https://cdn.example.com"
这些凭证应该放进 secrets 存储,不要提交进版本库。
浏览器直传的 CORS
如果你使用 STORAGE_DRIVER=s3,bucket 必须为实际上传来源的站点 origin 开启 CORS。
推荐的 CORS 策略:
[
{
"AllowedOrigins": ["https://your-site.example"],
"AllowedMethods": ["GET", "HEAD", "PUT"],
"AllowedHeaders": [
"Content-Type",
"Content-Disposition",
"Cache-Control",
"x-amz-checksum-sha256"
],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
如果你会从多个 origin 上传,就把每个 origin 都显式列出来。
图片变换(可选)
| 变量 | 说明 |
|---|---|
IMAGE_TRANSFORM_URL |
图片变换服务的基础 URL |
如果你使用 Cloudflare 图片变换,请把它指向真正提供图片的域名,并在后面加上 /cdn-cgi/image。
示例:
[vars]
R2_PUBLIC_URL = "https://media.yourdomain.com"
IMAGE_TRANSFORM_URL = "https://media.yourdomain.com/cdn-cgi/image"
或者,当图片仍然通过站点域名代理时:
[vars]
IMAGE_TRANSFORM_URL = "https://yourdomain.com/cdn-cgi/image"
静态资源 CDN(可选)
| 变量 | 说明 |
|---|---|
ASSET_BASE_URL |
构建产物 JS/CSS 的对外基础 URL(例如独立 CDN 域) |
默认情况下,Jant 把打包后的资源放在站点同源的 /_assets/ 下。只有当你想把这些资源部署到独立域名时,才需要设置 ASSET_BASE_URL。
[vars]
ASSET_BASE_URL = "https://cdn.yourdomain.com"
该 CDN 必须允许跨域。 Jant 的客户端代码以 ES module 形式加载(<script type="module">),浏览器对跨源 module 脚本会强制执行 CORS——虽然看起来和普通 JS 没区别,但规则不一样。如果 CDN 不返回 Access-Control-Allow-Origin,浏览器会丢弃响应,站点直接加载失败。
资源服务器有两种配置方式,根据你的部署情况二选一:
方案 A:允许任意来源(最简单)
Access-Control-Allow-Origin: *
打包产物都是内容哈希文件、可公开缓存,因此用 * 是安全的。CDN 可以为所有访问者复用同一个缓存响应。
方案 B:限定为你的站点域名
Access-Control-Allow-Origin: https://yourdomain.com
Vary: Origin
适合同一个 CDN 给多个站点服务、希望按站点隔离的场景。Vary: Origin 必须加上,否则 CDN 可能把上一次的 Allow-Origin 头返回给另一个来源的请求。如果你的 CDN 不支持按 Origin 分缓存键,请使用方案 A。
如果是同源部署(未设置 ASSET_BASE_URL),则不涉及任何 CORS 配置。
Cloudflare R2 / S3(JSON 格式的 CORS 规则)
如果 CDN 是直接对外暴露的存储桶(R2 公开桶,或 S3 + CloudFront),把桶的 CORS 规则设置为:
[
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 86400
}
]
或限定到你的站点域名:
[
{
"AllowedOrigins": ["https://yourdomain.com"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 86400
}
]
- R2:控制台 → 对应桶 → Settings → CORS policy → 粘贴 JSON
- S3:AWS 控制台 → 桶 → Permissions → Cross-origin resource sharing (CORS),或用
aws s3api put-bucket-cors
Caddy / nginx(反向代理的 CDN)
# Caddy
header /_assets/* Access-Control-Allow-Origin "*"
# nginx
location /_assets/ {
add_header Access-Control-Allow-Origin "*" always;
}
Slug(可选)
| 变量 | 默认值 | 说明 |
|---|---|---|
SLUG_ID_LENGTH |
5 |
对无标题帖子自动生成随机 slug 时使用的长度 |
上传大小限制(可选)
| 变量 | 默认值 | 说明 |
|---|---|---|
UPLOAD_MAX_FILE_SIZE_MB |
500 |
非图片上传的最大大小(MB) |
图片本身还有更严格的专用限制。这个设置主要影响视频、音频和 PDF 上传。
内容摘要和 RSS 限制(可选)
| 变量 | 默认值 | 说明 |
|---|---|---|
SUMMARY_MAX_PARAGRAPHS |
5 |
自动生成摘要时的最大段落数 |
SUMMARY_MAX_CHARS |
500 |
自动生成摘要时的最大字符数 |
RSS_FEED_LIMIT |
50 |
RSS feeds 中包含的最大帖子数 |
Settings 页面设置
这些设置可以在初始化完成后,通过 Jant 的 Settings 页面修改。所有设置都可以通过同名环境变量预置初始值——Settings 里改过的值优先级高于环境变量。
| 设置 | 用途 |
|---|---|
SITE_NAME |
站点显示名称 |
SITE_DESCRIPTION |
Meta description 和 feed description |
SITE_LANGUAGE |
主要语言代码 |
TIME_ZONE |
显示时区,例如 UTC 或 Asia/Shanghai |
HOME_DEFAULT_VIEW |
决定首页默认从 Latest 还是 Featured 开始 |
MAIN_RSS_FEED |
决定 /feed 返回什么 |
SITE_FOOTER |
自定义页脚文本 |
SHOW_JANT_BRANDING_ON_HOME |
是否在首页显示 Jant 品牌标识 |
NOINDEX |
请求搜索引擎不要收录这个站点 |
颜色主题、字型主题、自定义 CSS、头像以及其他外观细节,也都在 Settings 里管理。
保留路径
这些顶层路径是保留的,不能作为 post 或自定义页面的 slug:
featured, latest, collections, signin, signout, setup, settings, dash,
api, feed, search, archive, media, pages, reset, compose, new, static, assets,
_assets, healthz, readyz
配置文件
wrangler.toml
把 Cloudflare 的非敏感配置写进 wrangler.toml:
name = "my-jant-site"
main = "index.js"
[vars]
SITE_ORIGIN = "https://myblog.com"
# SITE_PATH_PREFIX = "/blog"
# R2_PUBLIC_URL = "https://media.myblog.com"
# IMAGE_TRANSFORM_URL = "https://media.myblog.com/cdn-cgi/image"
[[d1_databases]]
binding = "DB"
database_name = "my-jant-site-db"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
[[r2_buckets]]
binding = "R2"
bucket_name = "my-jant-site-media"
.env(Node 和 Docker)
Node 和 Docker 下,把这些值放进 .env,或者交给你的进程管理器注入:
AUTH_SECRET=your-32-plus-character-secret
SITE_ORIGIN=https://your-jant.example
DATABASE_URL=file:./data/jant.sqlite
# SITE_PATH_PREFIX=/blog
# TRUST_PROXY=true
有用的模板:
- 仓库根目录下的 Docker / Node 示例:
.env.example - package 内部的 Node 示例:
packages/core/.env.node.example
.dev.vars(本地开发)
本地 Cloudflare secrets 放进 .dev.vars:
AUTH_SECRET=your-32-plus-character-secret
DEV_API_TOKEN=local-debug-token
[email protected]
DEMO_PASSWORD=jant-dev-debug-login
DEMO_MODE=false
DEV_API_TOKEN、DEMO_EMAIL 和 DEMO_PASSWORD 都是本地调试辅助项,不属于正常生产环境配置。
Demo Mode
只有在公开共享的 demo 环境里,才把 DEMO_MODE=true 打开。
效果:
- 强制开启
noindex - 禁用删除账号、修改密码以及一些账号管理操作
- 仅仅设置
DEMO_EMAIL或DEMO_PASSWORD并不会自动开启 demo mode
生产环境 Secrets
Cloudflare 生产环境可以通过 Wrangler 或 Dashboard 设置 secrets:
openssl rand -base64 32
npx wrangler secret put AUTH_SECRET