trahloff/Aldine · 上手攻略

  • 仓库:trahloff/Aldine
  • 链接:https://github.com/trahloff/Aldine
  • 分类:engineering / academic-writing(LaTeX 协作编辑、自托管、Overleaf 替代)
  • 作者:spark
  • 更新:2026-10-26

版本基准:v1.0.1(发布于 2026-10-25,tag commit 5119ad5)。仓库卡采集于 2026-10-26,当时最新提交为 2026-10-25。

1. 是什么

Aldine 是一个自托管、开源的协作式 LaTeX 编辑器,作者定位是"Overleaf 的替代品"(an Overleaf alternative)。它由作者 Tobias Rahloff 维护,AGPL-3.0 许可,主语言 TypeScript。

与 Overleaf 最本质的差别在于存储模型:Aldine 把"项目文件"和"元数据"拆成两条独立的接缝。

  • 项目文件 = 真正的 git 仓库。每个项目在磁盘上就是一个 git repo(DATA_DIR/projects/<id>,默认检出 main),每个分支是一个 git worktree(DATA_DIR/worktrees/<id>/<branch>)。所以分支、历史、diff、合并天然可用,不需要额外适配层。
  • 元数据 = 可插拔的 DataStore。默认是扁平的 JSON 文件(users.json、sessions.json、tokens.json、meta/<id>.json、comments/<id>.json 等),设 DATABASE_URL 后换成 Postgres。

架构上只有两个容器:

浏览器 (React + CodeMirror 6 + Yjs)
   │ HTTP/WS
   ▼
app 容器 (Node 22, Fastify + Hocuspocus)   ←── git repos + worktrees
   │ 共享 /data 卷
   ▼
compiler 容器 (TeX Live + latexmk, 沙箱化, 无外网出口)

实时协作基于 Yjs CRDT,每个文件的每个分支对应一个 Yjs 文档(键格式 project::branch::path),改动以去抖写入的方式直接落进 git worktree,并自动提交。编译产物留在项目树内的 .aldine-out/(不进 git 历史),这正是 latexmk 增量缓存能保持温热的原因——README 声称热重编译约 2 秒。

发布节奏:README 标称 v0.x 时期"年轻",但 CHANGELOG 显示 1.0.0 与 1.0.1 均发布于 2026-10-25,1.0 首次给出了一份关于升级兼容性的正式承诺(见 docs/STABILITY.md)。

2. 解决什么问题

自托管 Overleaf 有几个众所周知的痛点,Aldine 逐个对着解决:

痛点 Overleaf CE / Pro 的现状 Aldine 的解法
评审批注 + 建议修改 批注和 track changes 是 Server Pro 专属 评审模式开箱即用:锚定串行讨论 + 一键接受的替换建议
Git 分支管理 git 集成是 Server Pro 专属 项目本身就是 git repo,UI 里建分支、切分支、合并
GitHub 同步 / PR Overleaf 文档把 GitHub 同步列为 Overleaf Cloud 付费特性 GitHub / GitLab / Gitea / Forgejo 同步 + 直接开 PR/MR
Zotero 集成 Zotero 只出现在 cloud 平台的企业集成列表里 原生 Zotero,支持整个库或单个 collection,无需付费层
部署复杂度 Overleaf Toolkit 要起 sharelatex、mongo、redis 多个容器 两个容器 + 扁平文件,无数据库要迁移
私有模板管理 Server Pro 专属 自有模板放任意 git 仓库,列进 TEMPLATE_REPOS

一句话:如果 Overleaf Community Edition 已经够用,就用 Overleaf CE——README 自己也这么写。Aldine 的存在意义是给那些"想要付费层才有的评审/git/Zotero 能力,又想把整个部署装进自己脑子里的"用户。

3. 快速安装

3.1 最小安装(无需 clone、无需构建)

把下面内容存成 docker-compose.yml,然后 docker compose up -d:

name: aldine

services:
  app:
    image: ghcr.io/trahloff/aldine-app:${ALDINE_VERSION:-1.0.1}
    ports:
      - "8080:3000"
    volumes:
      - aldine-data:/data
      - aldine-secrets:/secrets
    networks: [frontend, backend]
    init: true
    restart: unless-stopped

  compiler:
    image: ghcr.io/trahloff/aldine-compiler:${ALDINE_VERSION:-1.0.1}${ALDINE_TEXLIVE:-}
    volumes:
      - aldine-data:/data
    # The compiler runs untrusted LaTeX. Keep this block.
    networks: [backend]
    mem_limit: 2g
    pids_limit: 256
    cap_drop: [ALL]
    security_opt: [no-new-privileges]
    init: true
    restart: unless-stopped

networks:
  frontend: {}
  backend:
    internal: true # no route to the internet

volumes:
  aldine-data:
  aldine-secrets:

然后打开 http://localhost:8080。就这一步。

也可以 clone 后直接跑(README 明确说两者等价):

git clone https://github.com/trahloff/Aldine && cd Aldine && docker compose up -d

⚠️ 必须保留 name: aldine 这一行。它固定了卷名,而这正是你以后能无缝切换 compose 文件(docker-compose.full.yml)而不丢数据的原因,也是 deploy/backup.sh 能找到卷的前提。

3.2 健康检查

curl localhost:8080/api/health   # → {"ok":true,"name":"aldine"}

就绪信号就是这个返回。首次拉取镜像很慢:TeX Live 在 compiler 镜像里,下载约 2.4 GB、落盘约 5 GB。之后启动就是秒级。

3.3 版本固定与升级

compose 文件里的 ${ALDINE_VERSION:-1.0.1} 意味着新装的实例拿的是当前 release,运行中的实例不会自己变。升级流程:

# .env
ALDINE_VERSION=1.0.1
docker compose pull && docker compose up -d

关键点:docker compose 每次调用都会读 .env,所以后续的 up 会一直停在这个版本上。而 ALDINE_VERSION=… docker compose pull && docker compose up -d 这种"前缀写法"只对第一条命令生效,up 又会把旧版本拉起来——这是个很容易踩的坑。回滚同理:把 .env 改回旧版本号,跑同样两条命令即可。项目数据在 aldine-data / aldine-secrets 卷里,换镜像不动数据。

3.4 备份与恢复

deploy/backup.sh aldine-backup.tar.gz          # 备份 data + secrets 卷
# 恢复:先 docker compose down
deploy/restore.sh aldine-backup.tar.gz

用 Postgres 时默认会一并备份内置数据库;若 DATABASE_URL 指向栈外的数据库,需设 ALDINE_BACKUP_DB=skip 并用该数据库自己的工具备份,否则脚本会拒绝执行。

4. 核心用法

4.1 导入现有 Overleaf 项目

在 Overleaf 里把项目下载为 ZIP,拖到首页即可——根文件会被自动识别,首次排版自动触发。也可以从 GitHub / GitLab / Gitea / Forgejo 直接导入,或把本地项目发布到远端新仓库。

远端同步全部在编辑器 UI 内完成:push/pull 带 ahead/behind 指示,分支可切,冲突 pull 会列出冲突文件并保留你的版本,直到你主动选择远端版本;另外还有服务端 autopush、直接开 PR/MR。自建 GitLab 实例可以让团队实例自动把新项目建到某个 GitLab group 下。个人 access token 即可,不需要注册 OAuth app(团队/多用户场景另需 OAuth 应用配置)。

4.2 分支与合并

项目在 UI 里就是 git repo:建分支 → 独立编辑 → 在 UI 里合并回主分支。因为分支是 worktree,多个分支可以同时编辑、互不干扰。

4.3 打开 MCP,让 Claude 当协作者

Aldine 内置了 MCP server(/mcp 端点)。启用:

# .env
ALDINE_MCP=1
ALDINE_PUBLIC_URL=https://aldine.example.com
ALDINE_SIGNING_SECRET=<至少 32 字符,openssl rand -base64 32>
  • ALDINE_MCP=1 才会 serve POST /mcp;不设则该路由不存在,MCP SDK 根本不加载。
  • 认证二选一:AUTH_ENABLED=1(走 OAuth 2.1 的 "Connect" 按钮,由 Aldine 自己当授权服务器,用户在同意页授权 Claude 能碰哪些项目),或 AUTH_ENABLED 关闭时用静态 ALDINE_MCP_TOKEN。两者都不能留空,否则每个请求都 401。
  • 用户也可以在 Account → Agent access → Access tokens for scripts 自行签发个人 token(前缀 aldn_),放在 Authorization: Bearer … 或 X-Aldine-Token 头里。

连上 claude.ai / Claude Desktop / Cowork / Claude Code 之后,Claude 可以读写 LaTeX、排版、拿到带文件名和行号的报错、在对话里直接显示 PDF。每一次改动都会落成一个作者为 "Claude" 的 git commit,编辑器里弹出 review-and-revert 提示条,一键回滚。详细的安全模型见 docs/AGENT_API.md。

4.4 AI 报错修复(自带 key)

# .env(优先级:OPENROUTER > OPENAI > ANTHROPIC)
OPENROUTER_API_KEY=...
# ALDINE_AI_MODEL=...          # 覆盖模型
# ALDINE_AI_AUTOFIX=1          # 排版失败自动开 Fix 标签页并诊断,无需点击

排版失败时给出自然语言诊断 + 一键修复建议。key 只留在服务端,绝不传到浏览器;不设 key 时 Aldine 就是个 100% 无 AI 的编辑器。

4.5 Zotero 与文献检索

原生 Zotero:可链接整个库或单个 collection,可选 My Library 或任意 group library,无需付费层;.bib 用廉价的版本感知刷新保持同步,引用既可以从搜索面板插入,也可以用 \cite{ 自动补全。

不想配 Zotero 也能查文献:按标题或作者检索(OpenAlex),或直接粘 DOI / arXiv id,一键追加 BibTeX 并插入 \cite{。

4.6 可视化编辑模式

LaTeX 以格式化文本呈现,源码始终权威且 byte-stable(不会重写你没主动编辑过的源文件)。WYSIWYG 数学:点公式弹出 MathLive 编辑器——但含 \label、对齐、注释或换行的公式,MathLive 会重写它,因此这类公式会退回源码模式打开。还有可编辑表格、富文本粘贴转 LaTeX、图片预览 chip、大纲。Ctrl+Enter(Mac 上 ⌘Enter)在光标位于公式或表格源码内时打开对应编辑器。

4.7 其他功能速览

  • 评审模式:选中文字留锚定的串行批注,可附建议替换,作者一键接受。批注高亮、可 resolve/reopen、跟踪编辑。
  • SyncTeX 双向:双击 PDF 跳源码;⌘J 从光标跳 PDF 并高亮闪烁。
  • 模板:内置 article / IAC 会议论文 / beamer / report-thesis 四类通用模板(每个出版商 class 各一个,发布镜像里共 15 个),再加 25 个官方会议与期刊套件(NeurIPS、ICML、ACL、CVPR、Springer Nature、Wiley…)在创建项目时从出版商处下载;也可以用 TEMPLATE_REPOS 从任意 git 仓库拉本组模板。
  • 插件系统:manifest.json + ES module,Zotero / references / AI-fix 都以插件形式实现。
  • 多用户认证(可选):AUTH_ENABLED=1 开启登录、按项目归属与分享(仅邀请或链接);支持 Google / GitHub / ORCID SSO、自建 OIDC(Keycloak、Authik、Authelia、Pocket ID)、邮箱密码(scrypt 哈希 + 可撤销的 HTTP-only cookie 会话);ALDINE_SSO_ONLY=1 彻底禁用密码登录。ALDINE_ADMIN_EMAILS=you@example.org 开启 /admin 面板(账号、活跃用户、项目、编译耗时,仅元数据)。
  • 搜索替换:可跨分支内所有文本文件(含未打开的),支持大小写匹配、全词、正则;Replace all 会实时改所有在线文档并落成一次 commit。

4.8 从源码开发

npm install
npm run dev:server   # API + 协作服务,:3000
npm run dev:web      # Vite 前端,:5173,代理到 :3000
docker build -t aldine-compiler apps/compiler
docker run -d -p 4020:4020 -v $PWD/.data:/data aldine-compiler

npm run typecheck -w apps/web && npm run test -w apps/web
npm run test:github -w apps/server   # GitHub 同步集成测试
npm run test:gitlab -w apps/server   # GitLab 同步集成测试
npm run test:gitea -w apps/server    # Gitea/Forgejo 同步集成测试
npm run test:db -w apps/server       # 数据存储一致性测试

端到端(Playwright,覆盖编译、协作、分支、插件、Zotero):

npx playwright install chromium
DATA_DIR=$(pwd)/.data-e2e PORT=4020 node apps/compiler/server.js &
npm run test:e2e
# 或者对着已在跑的 compose 栈:
ALDINE_URL=http://localhost:8080 npm run test:e2e

5. 典型适用场景

  • 课题组自建 LaTeX 协作环境:导师和学生对同一份论文实时编辑、开分支写自己的章节、最后在 UI 里合并、评审批注带建议修改——这套流程在 Overleaf 免费层走不通,在 Overleaf Server Pro 要付费。
  • 需要 git-native 工作流的学术写作:已经在用 VS Code + LaTeX Workshop + git,但想要一个浏览器端的多人协作层,同时保持"每个项目就是个 repo"的直觉。
  • 论文数据不能出内网:期刊/会议对预印本有 embargo,或涉及未公开审稿意见,Zotero 库也是私有的——自托管把数据完全留在自己的机器上。
  • 想接 AI 助手的写作者:MCP 让 Claude 在编辑器里改稿、排版、把 PDF 拿回对话里,改动全部以 commit 形式可审可回滚。
  • NAS / 家用服务器场景:CasaOS、ZimaOS、TrueNAS 24.10+、Unraid 都有现成的部署模板(deploy/casaos/docker-compose.yml、docs/TRUENAS.md、docs/UNRAID.md)。

不太适合:单纯想一个人写篇 LaTeX 且不关心协作——本地 VS Code + TeX Live 更轻;以及需要 Overleaf 那个庞大模板市场的用户,Aldine 的模板数量级明显更小。

6. 坑与注意

坑 1:CJK 中文支持不在默认镜像里

  • 现象:默认 compiler 镜像用 TeX Live medium scheme + pictures/latexextra/bibtexextra,含 pgfplots、tikz-cd、cleveref、todonotes、minted、biblatex 等,也含阿拉伯语、波斯语、西里尔文、希腊文——唯独不含中日韩(CJK)字族。
  • 影响:中文论文直接编译报缺包/乱码,是国内用户最容易踩的一脚。
  • 修复:用 full 镜像(ALDINE_TEXLIVE=-full,约 2.8 GB 压缩 / 9 GB 落盘,CJK 只在这里),或单独补装 CJK 相关包:
services:
  compiler:
    image: aldine-compiler-local
    build:
      dockerfile_inline: |
        FROM ghcr.io/trahloff/aldine-compiler:1.0.1
        RUN tlmgr install pgfplots tikz-cd

tlmgr 用的是与该 release 构建时相同的 TeX Live 日期快照,所以 release 变老之后这套装法仍然有效。注意 FROM 的 tag 要跟着 ALDINE_VERSION 一起 bump;Compose 在本地构建镜像,arm64 服务器同样适用。

坑 2:.env 里的值不能带行尾注释

  • 现象:.env 中每个变量必须独占一行,值后面的任何字符都会变成值的一部分。
  • 影响:AUTH_ENABLED=1 # 开启认证 会让值变成 "1 # 开启认证",于是认证静默地保持关闭——README 明确点名了这个坑。
  • 修复:注释另起一行写。

坑 3:升级时用 docker compose up -d 前忘了改 .env

  • 现象:ALDINE_VERSION=… docker compose pull && docker compose up -d 这种前缀写法只作用于第一条命令,up 随后把旧版本又启动了。
  • 影响:升级"看起来没生效",还可能造成新旧镜像混用的错觉。
  • 修复:把版本写进 compose 同目录的 .env,然后跑 docker compose pull && docker compose up -d。Compose 每次调用都读 .env,后续 up 就一直停在这个版本。回滚同理,把 .env 改回旧版本号。

坑 4:1.0 之前跨 minor 升级不保证兼容

  • 现象:1.0 之前(0.3→0.4 这种)minor 版本号提升可能改变行为或磁盘布局,patch 版本(0.4.0→0.4.1)则不会。
  • 影响:跨 minor 升级对已有数据的迁移尚未测试。
  • 修复:升级前先 deploy/backup.sh。1.0 之后规则变为:patch 只修 bug;minor 只增设置/MCP 工具/参数/插件 API 成员(弃用但不删除);major 才做移除。docs/STABILITY.md 里列出了 1.x 承诺覆盖和不覆盖的具体范围——注意 Web 界面的布局与措辞不在承诺范围内。

坑 5:只有最新 release 会拿到安全修复

  • 现象:按 SECURITY.md 的说明,只有最新 release 获得安全修复。
  • 影响:长期钉在旧版本等于长期带着已知漏洞。
  • 修复:关注仓库 Releases;用 latest tag 能自动跟随,但要付出失去版本可回滚性的代价。折中做法是定期手动 bump .env 里的 ALDINE_VERSION。

坑 6:Playwright e2e 会因为编译器目录不匹配而全军覆没

  • 现象:e2e 套件自己起 app 在 :3100,但不起 compiler,并且跑在 .data-e2e 上。
  • 影响:如果 compiler 指向的不是同一个目录,所有编译测试都会失败,而 compiler 看起来是健康的——极具迷惑性。
  • 修复:DATA_DIR=$(pwd)/.data-e2e PORT=4020 node apps/compiler/server.js &,或者用 ALDINE_URL=http://localhost:8080 npm run test:e2e 打已经在跑的 compose 栈。README 也提到浏览器测试在 CI 里不跑(需要 TeX Live 容器),本地才跑。

坑 7:MCP / AI / SSO 都默认关闭,且缺凭证时是"静默 401"

  • 现象:ALDINE_MCP=1 若既没有 AUTH_ENABLED=1 也没有 ALDINE_MCP_TOKEN,每个请求都是 401;ALDINE_SIGNING_SECRET 少于 32 字符会直接拒绝启动;ALDINE_PUBLIC_URL 在反向代理后面是唯一可信来源,设错会让 OAuth 回调和 PDF 链接全指向错误 origin。
  • 影响:表现为"Claude 连不上",但日志里看不出原因。
  • 修复:跨多 app 节点时显式设 ALDINE_SIGNING_SECRET(openssl rand -base64 32);多节点不共享 META_DIR 时必须自己设,否则随机生成的密钥会不一致。PDF 链接签名有效期 15 分钟。

坑 8:单 app 节点是官方支持的唯一拓扑

  • 现象:docs/SCALING.md 明确说 "One app node is still the supported topology"。Postgres 已覆盖用户/会话/token/评论/配额,Redis 可共享限流器,但仍有多个 per-process 缓存没迁移:lastWritten(协作写跳过哈希)、tombstoned(删除守卫)、lastPushedHead(远端推送去重,自愈、良性)、autopush 去抖/退避定时器(两节点各推一次,git 容忍重复推送,良性)、bib/label 索引缓存、compileChain(串行化 latexmk)。
  • 影响:想跑多节点的用户会踩到隐性不一致。
  • 修复:先按官方说法单节点部署;确需横向扩展时读 docs/SCALING.md 逐条确认"哪些墙挡在哪",别指望换 DATABASE_URL 就完事。

坑 9:模型与文档版本号存在不一致(需要留意)

  • 现象:docs/STABILITY.md 开头仍写着 "Aldine is at 0.14 today",而 CHANGELOG 显示 1.0.0/1.0.1 发布于 2026-10-25。
  • 影响:读者可能误判当前稳定度与兼容性承诺。
  • 修复:以 CHANGELOG 和 Releases 为准。⚠️ 本篇写作时观测到的 commit 为 5119ad5(tag v1.0.1),子命令与镜像 tag 若在此之后有变动请以仓库当前 main 为准。

坑 10:AGPL-3.0 + CLA 双轨许可,商业化要留意

  • 现象:核心是 AGPL-3.0(自托管随便用;若把修改后的 Aldine 作为服务提供,需要开源你的修改)。但 README 明确说"hosted Aldine service is planned",并接受允许 relicensing 的 CLA 贡献协议,因此未来可能出现商业授权版本。
  • 影响:想在 AGPL 约束下提供托管服务的团队,需要持续关注许可走向。
  • 修复:README 承诺"自托管版本永远是 AGPL-3.0,今天能用的功能不会变成付费层",商标另行处理(TRADEMARK.md)。此外模板目录各带独立 LICENSE:通用模板是 MIT,templates/iac-paper 是 LPPL-1.3c(LaTeX class 惯例许可),出版商 kit 的许可按 tlmgr 报告的为准。

7. 与同类对比

与 Overleaf Community Edition / Server Pro

维度 Aldine Overleaf CE(自托管) git + VS Code + LaTeX Workshop
部署 2 个容器,docker compose up Overleaf Toolkit:sharelatex、mongo、redis 多容器 无(本地)
实时协作 ✅ CRDT,协作者不限 ✅ ❌(只能通过 git 异步)
评审批注 / 建议修改 ✅ ❌ 批注与 track changes 属 Server Pro ❌
UI 内 git 分支 ✅ 项目即 git repo ❌ git 集成属 Server Pro ✅(它本身就是 git)
GitHub/GitLab/Gitea 同步 + PR/MR ✅ ❌ 文档把 GitHub 同步列为 Overleaf Cloud 付费特性 ✅ 原生
Zotero 整个库或单个 collection 官方页仅在 cloud 平台企业集成中提及 靠 Better BibTeX 自动导出
热重编译 ~2s(持久化 latexmk 缓存) README 标注 "Not measured" 本地
模板库 4 个通用模板(发布镜像 15 个)+ 25 个会议/期刊 kit + 自有 git 模板 私有模板管理属 Server Pro CTAN / 自备
包覆盖 medium + pictures/latexextra/bibtexextra + 出版商 class + 多数脚本;缺包一条 tlmgr install 即可;ALDINE_TEXLIVE=-full 拿全量 镜像内 minimal TeX Live,full 需装 scheme-full 你自己装的
富文本 / 可视化编辑 ✅ byte-stable、WYSIWYG 数学、可编辑表格 ✅ Visual Editor,代码开源 ❌
成熟度 刚到 1.0(2026) Overleaf 始于 2011 非常成熟
许可 AGPL-3.0 AGPL-3.0 MIT / 各异

README 里除 "Not measured" 外的每个 Overleaf 单元格都链接到被核对的 Overleaf 页面,核对日期为 2026-10-12。GitHub 同步与 Zotero 两项没找到说明 on-premises 版本的官方页面,故引用 Overleaf 现有的说法。完整带日期的版本在 https://aldine.dev/self-hosted-overleaf/ 。

优势与短板小结

优势:唯一同时满足"自托管 + 评审批注/建议修改 + UI 内 git 分支 + Zotero 原生 + GitHub/GitLab/Gitea/Forgejo 同步 + AI/MCP"的组合。git-native 是它真正差异化的点——别人的 git 集成是加上去的,它的是底座。

短板:成熟度差距明显(1.0 vs 2011 年至今);模板生态远小于 Overleaf;单节点拓扑是硬约束;CJK 需要额外镜像;1.0 之前跨 minor 升级无迁移保证;CI 不跑浏览器测试。

8. 一句话推荐结论

如果你的团队在写 LaTeX 论文,需要评审批注、git 分支和 Zotero 又不想付 Overleaf 的订阅费,Aldine 值得立刻试——两容器 compose 起、约 2 秒热重编译、git-native 项目模型、还有开箱即用的 Claude MCP 接入,是目前最完整的自托管 Overleaf 替代品;但中文用户记得用 ALDINE_TEXLIVE=-full,生产部署务必钉版本 + 定期备份,并且先按单节点拓扑设计。