← 返回文章列表

Overleaf部署实战指南

本文详细记录了在 fnOS NAS 上自建 Overleaf 6.2.2 社区版的完整实战过程,涵盖架构规划、overleaf-toolkit 部署、数据目录迁移、TeX Live 宏包安装与持久化、管理员账号创建及 Lucky 反向代理配置,并总结了 7 个关键踩坑点与解决方案。

#Overleaf#NAS#LaTeX#Docker#反向代理

 

部署环境:fnOS(基于 Debian 深度定制)NAS · 2026-08-24 最终成果:Overleaf 6.2.2 社区版 + TeX Live 2026 全量宏包 + 域名 HTTPS 外网访问 + 多人协作 阅读对象:想在 NAS 上自建 Overleaf 的人

一、为什么要在 NAS 上自建 Overleaf

Overleaf 是在线 LaTeX 编辑器,官方 SaaS 版有诸多限制(免费版编译慢、不能调宏包)。自建社区版(CE)的好处:

  • ✅ 完全免费、无限项目、私有部署
  • ✅ 可自由安装 TeX 宏包(ctex 中文支持等)
  • ✅ 多人实时协作(类似 Google Docs 的 LaTeX 版)
  • ✅ 数据完全掌握在自己手里

二、架构总览

外网用户 (IPv6)
    │
    ▼
┌──────────────────────┐
│  Lucky 反代 (fnOS 应用)│  ← 443 端口,HTTPS 终止
│  overleaf.epochwl.top │  ← ZeroSSL 正式证书
└──────────┬───────────┘
           │ 反代转发
           ▼
┌──────────────────────┐
│   sharelatex 容器     │  ← 18080:80
│   (Overleaf 6.2.2)    │
└──────┬────────┬───────┘
       │        │
┌──────▼──┐ ┌───▼──────┐
│ mongo 8 │ │ redis 7  │
└─────────┘ └──────────┘

端口规划(fnOS 上避免冲突):

  • Overleaf Web:18080(避让 8080/8081/8890 等)
  • Lucky 管理:16666
  • Lucky 反代:443
  • mongo/redis:容器内网互连,不暴露宿主机

三、第一步:拉取部署(overleaf-toolkit)

官方推荐用 overleaf-toolkit 部署:

git clone https://github.com/overleaf/toolkit.git
cd toolkit
# 配置
cp config/overleaf.rc.example config/overleaf.rc
cp config/variables.env.example config/variables.env

关键配置项

config/overleaf.rc

OVERLEAF_DATA_PATH=/vol1/1000/docker/overleaf/overleaf
MONGO_DATA_PATH=/vol1/1000/docker/overleaf/mongo
REDIS_DATA_PATH=/vol1/1000/docker/overleaf/redis
GIT_BRIDGE_DATA_PATH=data/git-bridge

config/variables.env(核心):

OVERLEAF_SITE_URL=https://overleaf.epochwl.top   # ← 最终访问地址
OVERLEAF_NAV_TITLE=Overleaf
OVERLEAF_ADMIN_EMAIL=minlonghuo@gmail.com
OVERLEAF_BEHIND_PROXY=true                        # ← 反代模式(必须)
# 注意:OVERLEAF_SECURE_COOKIE 绝对不能设!见踩坑 #7

启动

bin/up -d

⚠️ 坑 #1:国内网络拉 Docker 镜像 sharelatex/sharelatex:6.2.2(约 3GB)可能很慢或超时。建议配置 Docker 国内镜像加速器(如 docker.m.daocloud.io、registry.cn-hangzhou.aliyuncs.com),或用 docker pull 分步拉取。

四、第二步:数据目录迁移(关键!)

为什么必须迁移

overleaf-toolkit 默认把数据放在 toolkit/data/ 下(也就是应用安装目录里)。但 fnOS 上:

  1. /vol1/docker 是系统路径,文件管理器不可见,备份/管理不便
  2. 用户可见的数据目录是 /vol{N}/<uid>/ 形式(如 /vol1/1000/
  3. 升级/卸载应用可能清掉数据目录

迁移步骤

# 1. 先停止服务
cd overleaf-toolkit && bash bin/stop

# 2. 建目标目录(用户可见)
mkdir -p /vol1/1000/docker/overleaf/

# 3. 移动各数据子目录(保留权限)
mv toolkit/data/overleaf   /vol1/1000/docker/overleaf/overleaf
mv toolkit/data/mongo      /vol1/1000/docker/overleaf/mongo
mv toolkit/data/redis      /vol1/1000/docker/overleaf/redis
mv toolkit/data/git-bridge /vol1/1000/docker/overleaf/git-bridge

# 4. 改 overleaf.rc 指向新路径(见上文配置)
# 5. 重新启动
bash bin/up -d

⚠️ 坑 #2:迁移后必须删容器重建docker rm -f sharelatex mongo redis && bin/up -d),因为 docker volume 挂载关系在容器创建时就已经固定,改配置文件后 bin/restart 不生效。

💡 最终目录结构(本机):

/vol1/1000/docker/overleaf/
├── overleaf/    # Overleaf 应用数据(项目、用户上传)
├── mongo/       # 用户/项目数据库
├── redis/       # 缓存
└── texlive/     # TeX Live 宏包(持久化挂载,见踩坑 #4)

五、第三步:TeX Live 宏包安装(最大的坑)

Overleaf 社区版自带 TeX Live 2026,但只有基础包,没有 ctex(中文)、float、booktabs、tikz 等常用宏包。装这些需要 tlmgr。

5.1 踩坑:容器重建 = 宏包全丢

⚠️ 坑 #3(最重要的坑):sharelatex 容器是无状态的,tlmgr 装的宏包写在容器可写层。只要容器被删除重建(docker rm -f),所有手动安装的宏包全部丢失!表现就是:昨天还能编译的中文文档,今天报 File 'ctexart.cls' not found

解决方案:把 texlive 目录持久化挂载到宿主机

# 1. 先把容器内的 texlive 复制到宿主机(一次性)
mkdir -p /vol1/1000/docker/overleaf/texlive
docker cp sharelatex:/usr/local/texlive/. /vol1/1000/docker/overleaf/texlive/

# 2. 修改 docker-compose.base.yml,加一行挂载
# 文件:overleaf-toolkit/lib/docker-compose.base.yml
# 在 volumes 部分追加:
#   - "${TEXLIVE_DATA_PATH:-/vol1/1000/docker/overleaf/texlive}:/usr/local/texlive"

# 3. 重建容器生效
docker rm -f sharelatex && bash bin/up -d

这样以后容器重建,宏包都还在。

5.2 踩坑:tlmgr 卡死(默认源被墙)

⚠️ 坑 #4:tlmgr 默认用 https://mirror.ox.ac.uk/sites/ctan.org/...(英国镜像),国内网络访问极慢甚至卡死——进程看着在跑(ps 有 perl 进程),但 CPU 时间几乎不动,等 13 分钟毫无进展。

解决方案:切换国内镜像源(清华/中科大)

# 清华镜像(推荐,实测 52 个包 13 秒装完)
tlmgr option repository https://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/tlnet
# 或中科大
tlmgr option repository https://mirrors.ustc.edu.cn/CTAN/systems/texlive/tlnet

验证连通性的命令(装之前先测):

curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" \
  https://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/tlnet/tlpkg/texlive.tlpdb
# 期望:200 + 1秒内;如果超时或 FAIL 说明源不可用

5.3 中文支持宏包安装清单

# 中文核心(ctex + xeCJK + fontspec)
tlmgr install ctex xecjk fontspec

# 常用补充
tlmgr install float needspace caption booktabs hyperref amsmath \
              geometry listings biblatex natbib tikz pgf

# 国标参考文献(注意:新版按年份分文件!见坑 #5)
tlmgr install gbt7714

# 刷新文件数据库
mktexlsr

5.4 验证

kpsewhich ctexart.cls    # 应输出 /usr/local/texlive/.../ctexart.cls
kpsewhich xeCJK.sty
kpsewhich fontspec.sty

⚠️ 坑 #5:新版 gbt7714 宏包不再提供 gbt7714.bst,而是按年份分文件:gbt7714-2015-numeric.bstgbt7714-2015-authoryear.bstgbt7714-2025-numeric.bst 等。用 \bibliographystyle{gbt7714-2015-numeric} 这种带年份的名字。

5.5 编译实测

\documentclass{ctexart}
\usepackage{float, booktabs, amsmath, tikz}
\begin{document}
中文测试 $E=mc^2$
\end{document}
xelatex -interaction=nonstopmode test.tex   # 应生成 PDF 无致命错误

六、第四步:创建管理员账号

踩坑:CE 版没有注册页

⚠️ 坑 #6:Overleaf 社区版 6.x 的注册页是写死的(register.pug 模板直接显示"Please contact admin"),没有自助注册功能。只有 0 用户时才有注册表单。所以创建账号必须直接操作 MongoDB

用 Node 脚本直插 MongoDB

在 sharelatex 容器内执行(容器里有 mongodb 和 bcrypt 库):

const mongodb = require("mongodb");
const bcrypt = require("bcrypt");
const MongoClient = mongodb.MongoClient;
const ObjectId = mongodb.ObjectId;

(async () => {
  const client = await MongoClient.connect("mongodb://mongo/sharelatex");
  const db = client.db("sharelatex");
  const users = db.collection("users");

  const email = "minlonghuo@gmail.com";
  const password = "你的密码";
  const now = new Date();
  const hash = bcrypt.hashSync(password, 12);   // ← Overleaf 要求 bcrypt 12 轮!

  await users.deleteMany({ email: email });     // 幂等:先删旧的

  const user = {
    _id: new ObjectId(),
    email: email,
    emailLower: email.toLowerCase(),
    hashedPassword: hash,                       // ← 字段名是 hashedPassword 不是 password!
    first_name: "minlonghuo",
    last_name: "",
    created: now,
    loginCount: 0,
    email_verification: { verified: true, sentAt: now },  // ← 必须 verified,否则登录被拦
    features: { collaborators: -1, versioning: true, trackChanges: true, compileTimeout: 60 },
    isAdmin: true,                              // ← 管理员标记
    holdingAccount: false,
    signUpDate: now,
    samlIdentifiers: [],
    must_reconfirm: false
  };

  await users.insertOne(user);
  console.log("SUCCESS:", email);
  await client.close();
})().catch(e => { console.error(e); process.exit(1); });

执行方式:

docker cp create_user.js sharelatex:/overleaf/create_user.js
docker exec sharelatex bash -c 'cd /overleaf && node create_user.js'
docker exec sharelatex rm -f /overleaf/create_user.js   # 清理

验证登录

# 容器内 curl 模拟登录
curl -s -X POST http://localhost:80/login -H 'Content-Type: application/json' \
  -d '{"email":"minlonghuo@gmail.com","password":"你的密码"}' -D - -o /dev/null
# 期望返回 302,Location: /project

💡 要点

  • 密码字段必须是 hashedPassword(不是 password
  • bcrypt 轮数必须是 12(Overleaf 默认)
  • email_verification.verified 必须为 true
  • 管理员设 isAdmin: true,普通用户 false

七、第五步:域名反代(Lucky)

架构

fnOS 上装 Lucky 应用(/vol2/@appcenter/Lucky),做反向代理:

overleaf.epochwl.top:443  →  http://192.168.10.100:18080

Lucky 配置要点

  1. 打开 Lucky 管理后台:http://NAS_IP:16666(默认路径 /safety/
  2. 反向代理模块 → 添加规则:
    • 前端域名overleaf.epochwl.top
    • 前端端口443
    • 后端地址http://192.168.10.100:18080
    • 证书:绑定 ZeroSSL/Let's Encrypt 证书
  3. 保存后 443 端口立即生效

⚠️ 坑 #7(Lucky 配置导致 443 全挂):改反代规则时如果配置不当(比如证书绑定错误、监听端口配置冲突),443 端口会对所有域名 Connection reset,表现为 TLS handshake error: bad record MAC。排查方法:

# 看监听是否正常
ss -tlnp | grep 443
# 模拟带 Host 头的请求
curl -sk -H "Host: overleaf.epochwl.top" https://[::1]:443/
# 期望 302 跳转;如果 000/Connection reset 说明规则坏了

修复:在 Lucky 后台检查规则(证书是否绑定、端口是否正确),重新保存。

Lucky 配置文件说明

  • 配置存在 /vol2/@appdata/Lucky/data/*.lkcfAES 加密,无法直接读)
  • 管理 API 在 http://127.0.0.1:16666/safety/api/(需要登录 token)
  • 日志在 /vol2/@appdata/Lucky/info.log

八、第六步:HTTPS 证书

为什么必须配证书

  • Lucky 默认自签证书(CN=Lucky),浏览器会报"您的连接不是私密连接"
  • 正式证书(ZeroSSL/Let's Encrypt)→ 地址栏绿锁,无警告

证书申请(Lucky 后台操作)

Lucky 内置 ACME 客户端,支持 Let's Encrypt / ZeroSSL:

  1. Lucky 后台 → SSL 证书模块
  2. 添加证书 → 选择 ACME → 填域名 overleaf.epochwl.top
  3. 验证方式
    • HTTP-01:需要 80 端口(Lucky 需开 80 监听 + 运营商允许 80 入站)——国内宽带 80 常被封,不推荐
    • DNS-01:通过 DNS 服务商 API 验证,推荐。域名在阿里云就用阿里云 AccessKey,Lucky 的 DDNS 模块有现成凭据可复用
  4. 申请成功后把证书绑定到反代规则

验证证书

# 看证书信息
echo | openssl s_client -connect "[你的IPv6地址]:443" -servername overleaf.epochwl.top 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

# 完整访问测试(-k 表示跳过校验,验证链路)
curl -skL https://overleaf.epochwl.top/ -o /dev/null -w "%{http_code} %{url_effective}\n"
# 期望:200 https://overleaf.epochwl.top/login

# 严格校验(验证证书真的有效)
curl -sL https://overleaf.epochwl.top/ -o /dev/null -w "%{http_code}\n"
# 期望:200 或 302(无证书错误)

⚠️ 坑 #8:ZeroSSL/Let's Encrypt 证书有效期 90 天,记得开自动续期或在到期前续期。

九、第七步:内外网登录问题修复

现象

根因(非常隐蔽!)

Overleaf 源码 settings.js 里:

secureCookie: process.env.OVERLEAF_SECURE_COOKIE != null,

只要 OVERLEAF_SECURE_COOKIE 环境变量存在(不管设 true 还是 false!),secureCookie 就是 true

secureCookie=true 时:

  • cookie 带 Secure 标志 → 浏览器只在 HTTPS 下发送
  • 内网用 http://192.168.10.100:18080 访问 → HTTP 不发送 Secure cookie → 每次请求都无 session → Session error

解决方案

必须整行注释/删除 OVERLEAF_SECURE_COOKIE 变量,而不是设为 false:

# variables.env 中:
# OVERLEAF_SECURE_COOKIE=true    ← 删掉或注释整行
# 千万不能写成 OVERLEAF_SECURE_COOKIE=false(等于没改,还是会 Secure!)

改完删容器重建:

docker rm -f sharelatex && bash bin/up -d

验证内外网都能登录

# 容器内模拟内网(无代理头)访问
curl -s -c /tmp/c.txt http://localhost:80/login -D - -o /dev/null | grep -i set-cookie
# 期望:set-cookie 不含 Secure

# 模拟外网(带 X-Forwarded-Proto: https)访问
curl -s -c /tmp/c2.txt -H "X-Forwarded-Proto: https" http://localhost:80/login -D - -o /dev/null | grep -i set-cookie
# 期望:set-cookie 正常

十、踩坑全记录(速查表)

#现象解决方案
1镜像拉取慢docker pull 超时配国内镜像加速器
2数据在默认目录备份/管理不便迁到 /vol{N}/<uid>/docker/,改 overleaf.rc
3改配置不生效环境变量没变必须删容器重建,restart 不重读 env_file
4宏包丢失重建后 ctexart.cls not foundtexlive 目录持久化挂载到宿主机
5tlmgr 卡死进程在但 CPU 不动换清华/中科大镜像源
6CE 无注册页无法自助注册MongoDB 直插 users 集合
7SECURE_COOKIE 坑内网 Session error整行注释该变量(设 false 无效)
8证书 90 天到期访问失败开自动续期
9Lucky 443 全挂bad record MAC检查反代规则证书/端口配置
10外网打不开只能局域网访问NAS 无公网 IPv4,域名只有 IPv6;用支持 IPv6 的网络或内网穿透

十一、日常运维要点

1. 备份

# 数据目录(项目/用户/数据库)是重中之重
/vol1/1000/docker/overleaf/{overleaf,mongo,redis}
# texlive 宏包可备份可重装(重装用清华源很快)

2. 常用命令

# 查看状态
docker ps | grep -E "sharelatex|mongo|redis"
docker logs sharelatex --tail 50

# 停止/启动(overleaf-toolkit)
cd overleaf-toolkit
bash bin/stop
bash bin/up -d

# 进容器
docker exec -it sharelatex bash

3. 容器重建恢复清单(重要!)

如果需要重建 sharelatex 容器,按此顺序:

# 1. 确认挂载还在(texlive 持久化)
docker inspect sharelatex | grep -A2 texlive
# 期望:/vol1/1000/docker/overleaf/texlive -> /usr/local/texlive

# 2. 重建
docker rm -f sharelatex && cd overleaf-toolkit && bash bin/up -d

# 3. 验证宏包还在
docker exec sharelatex kpsewhich ctexart.cls
# 期望:有输出(说明持久化生效,宏包没丢)

# 4. 如果宏包丢了(早期没持久化的版本):
bash /vol2/@apphome/hermes-agent/data/workspace/reinstall_tex_pkgs.sh

4. 新增用户(给协作者开账号)

复用上面的 MongoDB 直插脚本,改 email/password/isAdmin: false 即可。


附录:完整部署命令速览

# ========== 1. 部署 ==========
git clone https://github.com/overleaf/toolkit.git
cd toolkit
cp config/overleaf.rc.example config/overleaf.rc
cp config/variables.env.example config/variables.env
# 编辑 config/overleaf.rc     → 数据路径
# 编辑 config/variables.env  → SITE_URL / ADMIN_EMAIL / BEHIND_PROXY=true
bash bin/up -d

# ========== 2. 数据迁移 ==========
bash bin/stop
mkdir -p /vol1/1000/docker/overleaf/
mv data/{overleaf,mongo,redis,git-bridge} /vol1/1000/docker/overleaf/
# 改 overleaf.rc 路径
docker rm -f sharelatex mongo redis && bash bin/up -d

# ========== 3. texlive 持久化 ==========
mkdir -p /vol1/1000/docker/overleaf/texlive
docker cp sharelatex:/usr/local/texlive/. /vol1/1000/docker/overleaf/texlive/
# 改 docker-compose.base.yml 加挂载
docker rm -f sharelatex && bash bin/up -d

# ========== 4. 宏包安装(清华源) ==========
tlmgr option repository https://mirrors.tuna.tsinghua.edu.cn/CTAN/systems/texlive/tlnet
tlmgr install ctex xecjk fontspec float needspace caption booktabs \
              hyperref amsmath geometry listings biblatex natbib tikz pgf gbt7714
mktexlsr

# ========== 5. 建账号(MongoDB 直插) ==========
# 见上文 Node 脚本

# ========== 6. Lucky 反代 + 证书 ==========
# Lucky 后台(16666)操作,见上文

# ========== 7. 验证 ==========
curl -skL https://overleaf.epochwl.top/ -o /dev/null -w "%{http_code} %{url_effective}\n"
# 期望:200 https://overleaf.epochwl.top/login

本文档基于实际部署过程,由deepseek v4 flash根据聊天记录整理,环境:fnOS NAS,Overleaf 6.2.2 CE,TeX Live 2026。