qatlasd 服务端 CLI 参考¶
qatlasd 是 Go binary,单文件 ~30 MB,自带 SPA + PocketBase + SQLite。继承 PocketBase 全部命令 + QuantumAtlas 自有的 service / pat / storage 子命令树。
全局 flag(PocketBase 内置)¶
| Flag | 默认 | 含义 |
|---|---|---|
--dir <path> |
<binary_dir>/pb_data |
PocketBase data 目录(自动从 QATLAS_PB_DATA_DIR 注入) |
--debug |
false | 详细日志 |
--encryptionEnv <var> |
— | DB 加密 key 来源 env var |
--queryTimeout <sec> |
30 | SQL 查询超时 |
--version |
— | 打印版本 |
--dir 自动注入
server 启动时会按 QATLAS_PB_DATA_DIR 自动把 --dir=<path> 插到 cobra 命令行第一个位置——所以你不需要也不应该在 systemd unit 的 ExecStart 里硬写 --dir=。直接在 .env 改 QATLAS_PB_DATA_DIR= 就好。
serve:启动 HTTP server¶
全局 / 继承 flag(PocketBase 内置)¶
| Flag | 默认 | 含义 |
|---|---|---|
--http <host:port> |
127.0.0.1:8090 或域名 → 0.0.0.0:80 |
HTTP bind |
--https <host:port> |
域名时 0.0.0.0:443,否则空 |
HTTPS bind + 自动 LE |
--origins <list> |
[*] |
CORS 允许的 origin |
--dir <path> |
<binary_dir>/pb_data |
PocketBase data 目录(会被 QATLAS_PB_DATA_DIR 自动覆盖) |
--encryptionEnv <var> |
— | DB 加密 key 来源 env var |
--queryTimeout <sec> |
30 | SQL 查询超时 |
--dev |
false | dev 模式(不要在生产用) |
qatlasd 自有 flag(v0.17.0+,20 个,easytier 风格)¶
每个 flag 旁标 [env: QATLAS_FOO=],等价 env var 名 = qatlasd serve --help 看到的标注:
| Flag | 等价 env | 默认 |
|---|---|---|
--public-url <url> |
QATLAS_PUBLIC_URL |
— |
--user-header <name> |
QATLAS_USER_HEADER |
— |
--edge-name <name> |
QATLAS_EDGE_NAME |
— |
--force-tcp4 |
QATLAS_FORCE_TCP4 |
false |
--wiki-dir <path> |
QATLAS_WIKI_DIR |
<.env 目录>/../QuantumAtlas-Wiki |
--raw-dir <path> |
QATLAS_RAW_DIR |
${XDG_DATA_HOME}/qatlasd/raw |
--data-dir <path> |
QATLAS_DATA_DIR |
${XDG_DATA_HOME}/qatlasd/data |
--pb-data-dir <path> |
QATLAS_PB_DATA_DIR |
${XDG_DATA_HOME}/qatlasd/pb_data |
--system-pat <token> |
QATLAS_SYSTEM_PAT |
— |
--system-pat-scopes <csv> |
QATLAS_SYSTEM_PAT_SCOPES |
*(全 scope) |
--neo4j-uri <bolt://...> |
NEO4J_URI |
— |
--neo4j-username <user> |
NEO4J_USERNAME |
— |
--neo4j-password <pw> |
NEO4J_PASSWORD |
— |
--neo4j-database <db> |
NEO4J_DATABASE |
— |
--s3-endpoint <url> |
QATLAS_S3_ENDPOINT |
— |
--s3-public-endpoint <url> |
QATLAS_S3_PUBLIC_ENDPOINT |
— |
--s3-bucket-pdf <name> |
QATLAS_S3_BUCKET_PDF |
— |
--s3-bucket-md <name> |
QATLAS_S3_BUCKET_MD |
— |
--s3-bucket-images <name> |
QATLAS_S3_BUCKET_IMAGES |
— |
--s3-bucket-openalex <name> |
QATLAS_S3_BUCKET_OPENALEX_SNAPSHOT |
— |
--s3-access-key-id <id> |
QATLAS_S3_ACCESS_KEY_ID |
— |
--s3-secret-access-key <sec> |
QATLAS_S3_SECRET_ACCESS_KEY |
— |
优先级:CLI flag > OS env > .env 文件 > 内置 default。
OAuth 4 字段没有 CLI flag
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET / QATLAS_ALLOWED_GITHUB_LOGINS / QATLAS_ADMIN_GITHUB_LOGINS 只能走 env / .env。原因:auth provider 在 PocketBase Bootstrap 阶段注册,跑在 cobra parse argv 之前,CLI flag 来不及。详见 issue #6。
例子:
# 默认 127.0.0.1:8090
qatlasd serve
# 监听公网(前面必须有反代)
qatlasd serve --http=0.0.0.0:4200
# docker 一行起,不要 .env
docker run --rm -p 4200:4200 \
-v /srv/qatlas/pb_data:/data \
ghcr.io/iai-ustc-quantum/qatlasd:v0.17.0 serve \
--http 0.0.0.0:4200 \
--pb-data-dir /data \
--neo4j-uri bolt://neo4j.example:7687 \
--neo4j-username neo4j --neo4j-password ... \
--s3-endpoint https://rustfs.example \
--s3-bucket-pdf qatlas-pdf --s3-bucket-md qatlas-md \
--s3-bucket-images qatlas-images \
--s3-access-key-id ... --s3-secret-access-key ...
# 显式 .env 路径
QATLAS_DOTENV=/etc/quantum-atlas/.env qatlasd serve
完整字段语义见 server-config.md。
service:管理 systemd / launchd 服务¶
跨平台 service 管理(用 kardianos/service)。
service install¶
qatlasd service install [--name qatlasd] [--mode user|system]
[--dotenv-path <path>] [--bind <host:port>]
[--dry-run] [--force]
| Flag | 默认 | 含义 |
|---|---|---|
--name |
qatlasd |
service unit 名(Linux 上是 <name>.service) |
--mode user\|system |
TTY 下交互式询问;非 TTY 必填 | user-level systemd unit vs system-level(system 需要 sudo) |
--dotenv-path |
$QATLAS_DOTENV → ~/QuantumAtlas/.env → ./.env |
写入 unit 的 Environment=QATLAS_DOTENV= |
--bind |
127.0.0.1:4200 |
serve --http= 的值 |
--dry-run |
false | 渲染 unit 到 stdout,不写盘 |
--force |
false | 已有同名 unit 直接覆盖(非 TTY 必填) |
行为:
- 解析 mode(user / system)
- 解析 .env 路径
- 渲染 unit 内容(含 hardening)
- TTY 模式下问
[Y/n]确认 - 写 unit +
systemctl daemon-reload+systemctl start
非交互模式(CI / curl|sh 后跑):
service install 的 systemd hardening¶
Linux 上渲染的 unit 自带这些 sandbox 选项:
[Service]
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=no
LockPersonality=true
RestrictRealtime=true
ReadWritePaths=<.env dir> <wiki dir> <data dir>
ReadWritePaths 缺一会让 restart 失败
ReadWritePaths= 里列的任何目录不存在都会让 service restart 拿 status=226/NAMESPACE。改 .env 的存储路径后必须确保新路径存在 + systemctl daemon-reload。
service start|stop|restart|status¶
跟 systemctl <op> qatlasd 100% 等价(library 是 systemctl 的薄 wrapper)。
service uninstall¶
停服务 + 删 unit 文件 + daemon-reload。不会删 pb_data / raw / data——那是数据,需要你手动 trash-put。
pat:直接操作 PAT(救急用)¶
绕开 /api/pat 直接读写 pb_data。需要在 server 主机上跑(因为依赖 PocketBase DB 文件)。
pat mint¶
qatlasd pat mint --user <email|id> --name <name>
--scopes <s1,s2,...> --expires-in-days <N>
[--description <text>]
| Flag | 必填 | 含义 |
|---|---|---|
--user |
✅ | 目标用户(email 或 users record id) |
--name |
✅ | token 显示名(≤80 字符) |
--scopes |
✅ | 逗号分隔的 scope,如 papers:write,wiki:read |
--expires-in-days |
✅ | 1–365 |
--description |
❌ | 备注(≤200 字符) |
输出包含明文(仅一次)。
pat list¶
按 user 过滤;--json 出机读格式。不包含明文 / 哈希——只有 prefix + 元数据。
pat revoke¶
硬删除该 PAT record,下次该 token 调任何端点立刻 401。
pat scopes¶
打印当前编译进 binary 的 scope 词表(同 GET /api/pat/scopes 返回内容,但不用起 HTTP):
qatlasd pat scopes
# papers:read Read paper catalog metadata (stats, needs-mineru)
# papers:write Upload paper PDFs / Markdown and run MinerU jobs (implies papers:read)
# wiki:read Read Wiki pages / search / stats
# wiki:write Trigger Wiki git sync (implies wiki:read)
# graph:read Query Neo4j (stats / schema / Cypher)
storage:对象存储维护¶
仅 S3 / RustFS 后端可用。
storage prune¶
删除 noncurrent S3 object versions(即被 --overwrite 覆盖掉的旧版本)。
qatlasd storage prune [--prefix <key-prefix>] [--older-than <duration>]
[--keep-last <N>] [--yes] [--dry-run] [--json]
| Flag | 默认 | 含义 |
|---|---|---|
--prefix <path> |
"" (整个 bucket) | 只处理这个 key 前缀 |
--older-than <dur> |
"" (不限) | 仅删比此年龄更老的版本(Go duration 或 30d / 1y) |
--keep-last <N> |
0 (不限) | 每个 key 保留最近 N 个 noncurrent 版本 |
--yes |
false | 真删(不带 = dry-run) |
--dry-run |
true | 干跑预览;没有 --yes 即使 --dry-run=false 也不删 |
--json |
false | 每行一个 JSON 对象(机读) |
默认 dry-run + --yes 双保险
storage prune 默认 dry-run。要真删必须 --yes,避免手抖删数据。
示例:
# 预览:删 90 天前的所有 noncurrent
qatlasd storage prune --older-than 90d
# 真删,每个 key 保留最近 5 个 noncurrent,超出的删
qatlasd storage prune --keep-last 5 --yes
# 只处理 2025-11 的 cohort
qatlasd storage prune --prefix pdf/2511/ --older-than 30d --yes
永远不会删的对象:current version、delete marker、metadata sidecar(LocalStore)。
详见 RustFS 部署。
superuser:PocketBase 内置¶
qatlasd superuser upsert <email> <password>
qatlasd superuser create <email> <password>
qatlasd superuser delete <email>
管理 PocketBase admin UI 登录(/_/)。日常运维不依赖 admin UI,仅在需要看 DB 结构或临时调试时用:
migrate:PocketBase 数据库迁移¶
迁移文件在 pb_migrations/(迁移目录默认在 pb_data 旁)。每次启动 server 时自动跑 pending migrations,所以手工调用通常不必要。
--help / -h¶
每个 subcommand 都有 --help,输出真实当前版本的 flag 集合(这份文档可能滞后于代码):