这次我们来看一个自托管 LaTeX 工作区项目:TexLite。从项目定位来看,它的关键词是两个——“轻量”和“自托管”。用过 Overleaf 的人应该理解在线写 LaTeX 的体验:浏览器打开编辑器,左边写源码,右边预览 PDF,不用在本地装 TeX 发行版。TexLite 想做的事情,就是把类似的体验拆下来,装到你自己的服务器上,让论文、技术文档、数学公式工程都留在自己手里,不经过第三方平台。
这篇文章我会从部署开始讲,然后依次展开功能验证、接口集成、资源占用、常见排错和最佳实践。如果你正在纠结“要不要自己搭一套 LaTeX Web 工作区”,或者已经在搭但遇到了问题,这篇文章可以直接收藏。
先说清楚硬件门槛。LaTeX 本身不是 GPU 密集型应用,编译 PDF 主要吃 CPU 和内存。TexLite 这类轻量级自托管项目的优势在于,不需要一台高配机器,普通的 2 核 4G 服务器就能跑起来,日常写文档完全够用。真正吃资源的通常不是 Web 服务本身,而是 TeX Live 编译工具链和文档编译过程中的临时文件。这篇文章的重点也不是理论,而是怎么在真实环境里把服务跑起来、测通、用上。
1. 核心能力速览
在动手之前,先给一个整体能力参考。需要说明的是,由于项目处于“Show HN”阶段,部分细节要以仓库 README 和实际版本为准,下面表格里的内容我会标注哪些是从项目定位可以直接得到的信息,哪些是需要实测确认的部分。
| 能力项 | 说明 |
|---|---|
| 项目类型 | 自托管 LaTeX 在线工作区 |
| 核心定位 | 轻量级、自托管,数据掌握在自己手里 |
| 主要功能 | 在线编写 LaTeX 源码、编译 PDF、项目管理,具体功能边界以项目文档为准 |
| 部署方式 | 可通过容器或本地进程部署,推荐方式以 README 为准 |
| 硬件要求 | 普通 x86/ARM 服务器即可,2 核 4G 内存可满足个人和小团队写作 |
| 网络要求 | 局域网可直接访问,公网访问需配合反向代理和认证 |
| 是否支持 API | 不确定,需要看项目是否暴露编译接口,本文会给出通用对接思路 |
| 是否支持批量 | 可以通过编译脚本或任务队列对多个.tex文件批量处理 |
| 适合场景 | 个人文档管理、团队协同写作、论文排版、教材与笔记整理 |
| 不适合场景 | 对 Overleaf 模板市场、完整审阅流程有强依赖的团队 |
从项目标题可以确定的信息有三点:自托管、轻量、面向 LaTeX 工作区。这就意味着服务跑在你自己可控的机器上,而不是云端订阅服务;资源占用经过刻意控制,不会像完整版 Overleaf Community Edition 那样需要多个容器协同;功能围绕 LaTeX 文档工作流展开,不是通用的在线办公套件。
2. 为什么需要自托管 LaTeX 工作区
2.1 解决了什么问题
本地写 LaTeX 的典型痛点是环境维护。每年系统升级、换电脑、换发行版,都要重新装一遍 TeX Live、配一遍编辑器、折腾中文支持和中文字体。如果是多人协作,更麻烦:每个人的本地环境不一样,同一份文档在不同机器上编译出来的 PDF 可能有差异。
在线 LaTeX 服务解决了环境一致性问题,但引入了另一个问题——数据不在自己手里。论文没写完的草稿、公司内部的技术文档、带有未公开数据的报告,传到第三方平台总是有顾虑。TexLite 这类自托管工作区的价值就在这里:把“云端编辑 + 统一编译环境”的方式搬到自己的服务器上。
轻量级是这个项目比较关键的定位。自托管服务最怕重,如果为了跑一个写文档的工具,需要部署三个容器、吃 8G 内存、还得配 Redis,那很多人直接放弃。轻量意味着你可以在旧笔记本、小主机、云服务器上快速跑起来,维护成本低,也更容易长期使用。
2.2 适用场景与边界
适合这种工作区的人,我总结为三类。
第一类是单人写作者,学生或者科研人员,需要管理多篇论文、课程报告、建模文档。这类人不需要复杂的协作系统,只要能稳定编译 PDF、有项目文件管理就行了。
第二类是自托管爱好者,已经有了 NAS 或云服务器,想减少对在线服务的依赖,顺便把文档统一存到自己的存储里。
第三类是小团队,几个人合作写技术方案、产品文档、标书。这类场景对同时编辑的要求不太高,但是对“统一编译环境、导出 PDF、查看编译日志”有明确需求。
不太适合的场景也要说清楚。如果你的团队对 Overleaf 的模板库有强依赖,需要一键套用各类期刊模板,习惯用完整的审阅批注功能,那轻量级自托管项目大概率无法完全替代。它更适合从零起步、自己管理模板的情况。另外,如果你完全没有接触过 LaTeX,首选还是先学语法和社区工具,自托管工作区只是把环境复杂性的问题解决了,并不降低写作本身的门槛。
2.3 使用边界与合规提示
涉及自托管服务,有几个边界必须注意。
第一,文档内容安全。工作区如果部署在公网可访问的服务器上,必须开启身份认证,不要裸奔暴露在公网。第二,如果用于公司或项目组,要确认文档是否包含敏感信息,建议仅在内网访问。第三,如果用在线服务导入的模板和文档,要确认模板的许可证允许自托管使用。第四,不要把公网端口直接映射到工作区服务,应该通过反向代理加 HTTPS 访问。
3. 环境准备与前置条件
3.1 服务器要求
先给一套能够保证流畅体验的配置参考。这里的数字不是 TexLite 的具体要求,而是基于 LaTeX 编译和 Web 服务的常见开销给出的建议值:
| 项目 | 最低要求 | 建议配置 |
|---|---|---|
| CPU | 1 核 | 2 核以上 |
| 内存 | 2G | 4G 以上 |
| 磁盘 | 10G 可用空间 | 30G 以上,用于缓存 TeX Live 包和文档历史 |
| 操作系统 | Linux x86_64 | Ubuntu 22.04 / Debian 12 / Windows 也可,但 Linux 最佳 |
磁盘空间要重点说明一下。TeX Live 完整安装接近 8 到 10G,如果项目文档还保存编译产物,并且保留多版本历史,磁盘会很快增长。部署之前先规划好数据目录。
3.2 软件依赖
不同项目的依赖不同,但自托管 LaTeX 工作区一般绕不开几样东西:
- TeX Live 或具体 LaTeX 编译工具链,这是编译 PDF 的基础。
- Node.js 或 Python,取决于项目后端实现,用于运行 Web 服务。
- Docker / Docker Compose,如果项目提供容器化部署方式。
- Nginx 或 Caddy,用于反向代理和 HTTPS。
建议在部署前先确认几个版本信息:操作系统的包管理器、是否已安装 TeX Live、是否已有 Docker 环境、服务器上 80/443 端口是否被占用。
3.3 网络与端口规划
如果只在内网使用,服务跑起来后直接通过http://服务器IP:端口访问即可。如果要公网使用,需要规划好:
- 工作区服务监听端口(假设是 8080,以项目实际配置为准)。
- 反向代理监听 80/443。
- 是否配置域名和 HTTPS 证书。
- 防火墙规则,只放行必要的端口。
部署前用下面的命令检查端口占用:
sudo ss -tlnp | grep -E ':8080|:80|:443'如果输出有结果,说明端口已被占用,需要换端口或先停掉占用进程。
4. 安装部署与启动方式
4.1 通用容器部署模板
TexLite 如果提供 Docker 部署方式,通常推荐用 Docker Compose 一步起服务。下面给一个通用模板,服务名、镜像名和环境变量一定要替换成项目 README 中的实际值。
services: texlite: image: your-registry/texlite:latest container_name: texlite restart: unless-stopped ports: - "8080:8080" volumes: - ./data:/data # 文档数据目录 - ./workspace:/workspace # 源码工作区,按项目说明调整 environment: - TZ=Asia/Shanghai # 以下为占位变量,请按 README 填写 # - TEXLITE_SECRET=change-me # - TEXLITE_PORT=8080启动方式:
docker compose up -d docker compose logs -f texlite容器日志提示服务启动成功后,访问http://127.0.0.1:8080验证。
如果你的机器没有 Docker,也可以考虑单容器运行:
docker run -d \ --name texlite \ -p 8080:8080 \ -v $(pwd)/data:/data \ your-registry/texlite:latest这里要提醒一句:不要把镜像名直接拿来用。自托管项目经常需要自己构建镜像,仓库里一般会有 Dockerfile,你可以拉到源码后手动构建。
4.2 本地进程部署通用流程
如果项目不依赖容器,或者你更习惯本地部署,流程一般是:
# 1. 克隆代码 git clone https://github.com/your-account/texlite.git cd texlite # 2. 安装依赖,命令取决于项目语言 # npm install 或 pip install -r requirements.txt # 3. 确认 TeX Live 已安装并能调用编译命令 which pdflatex which xelatex which latexmk # 4. 启动服务 # npm run start 或 python app.py启动后注意观察终端输出,通常会出现监听地址和端口。如果是首次部署,建议在前台启动一次,确认没有报错后再切到后台。前台启动的好处是错误信息直接可见,排查问题更快。
4.3 反向代理配置
反向代理的作用是让你通过https://tex.example.com访问服务,而不是记一串端口号。下面是一段 Nginx 配置模板:
server { listen 80; server_name tex.example.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300s; proxy_send_timeout 300s; } }配置好之后执行:
sudo nginx -t sudo systemctl reload nginx如果服务通过 WebSocket 做实时预览,Nginx 配置里还需要加升级头:
proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";5. 功能测试与效果验证
部署完成只是第一步,接下来要按功能逐项验证。下面是一套针对 LaTeX 工作区的测试流程,建议按顺序执行。
5.1 基础文档创建测试
测试目的:确认 Web 界面能正常创建项目、编辑文件、保存文件。
操作步骤:
- 登录工作区。
- 新建一个 LaTeX 项目,命名如
test-doc。 - 新建主文件
main.tex。 - 输入最简单的 LaTeX 文档内容,重点是验证编译链路通不通。
\documentclass{article} \begin{document} Hello, TexLite! \end{document}预期结果:文件能保存,界面上能看到项目目录结构。
判断标准:如果保存按钮或自动保存生效,刷新页面后内容仍在。如果刷新后文件消失,排查存储目录挂载是否生效。
5.2 PDF 编译测试
这是核心功能。在main.tex中保留基础文档,触发编译。
预期结果:编译成功后生成 PDF,界面能预览或下载。
常见失败原因:
- 编译引擎选择错误,比如项目默认
pdflatex,但文档包含中文。 - 缺少必要宏包。
- 编译超时,文档结构复杂而服务器性能不足。
建议编译时把日志打开,观察是否有红色报错行。日志是最有效的排查入口。
5.3 中文文档和 XeLaTeX 测试
LaTeX 工作区绕不开中文支持。最简单的测试是编译一个带中文的文档:
\documentclass{article} \usepackage{ctex} \begin{document} 这是一个中文 LaTeX 文档测试。 \end{document}如果项目支持选择编译引擎,把引擎切换为xelatex。中文文档编译失败,最常见的原因是未装ctex宏包或缺少中文字体。
在服务器上可以这样检查:
kpsewhich ctex.sty fc-list :lang=zh | head -5如果kpsewhich没有输出,说明ctex宏包没装,需要安装完整的 texlive-lang-chinese。如果fc-list没有输出,说明系统缺少中文字体,安装字体或字体包即可。
5.4 项目文件管理测试
测试目的:验证多文件项目是否能正常管理。
在同一个项目中新建chapter1.tex,在main.tex中通过\input{chapter1.tex}引入,然后编译。
\documentclass{article} \usepackage{ctex} \begin{document} \input{chapter1.tex} \end{document}预期结果:子文件内容正常出现在生成的 PDF 中。
这个测试很重要,因为真实写作几乎都是多文件结构:主文件引入章节、图表、参考文献。如果项目对子目录引用的符号链接处理不好,会出现编译找不到文件的问题。
5.5 公式和特殊文档测试
LaTeX 的硬实力在数学公式。测试一个带公式的文档:
\documentclass{article} \usepackage{amsmath} \begin{document} \begin{equation} E = mc^2 \end{equation} \end{document}然后测试带图片、表格的文档,重点看是不是所有依赖的宏包都可用。轻量级自托管项目为了控制体积,通常会裁剪 TeX Live 的宏包集。如果你常用某些宏包,部署时确认已经在编译环境中安装。
6. 接口 API 与批量任务思路
6.1 提前确认:是否暴露 API
很多自托管 LaTeX 工作区会提供编译接口,方便外部系统对接。如果你拿到 TexLite 的仓库后,想确认它是否提供 HTTP API,按这几个思路查:
- 查看 README 中是否有
API或HTTP章节。 - 查看项目中是否有
api、routes、endpoints相关目录。 - 启动服务后访问根路径之外的常见路径,如
/docs、/api/docs、/health。
如果项目没有暴露 HTTP API,也不影响批量编译,因为你可以直接在服务器上调用 LaTeX 命令行工具。
6.2 通用编译 API 调用模板
如果 TexLite 暴露了编译接口,请求方式大概率是以下的模式之一,具体路径和参数以实际项目接口文档为准:
curl -X POST http://127.0.0.1:8080/api/compile \ -H "Content-Type: application/json" \ -d '{ "project": "test-doc", "file": "main.tex", "engine": "xelatex" }'返回结果可能包含编译日志和 PDF 下载地址:
{ "success": true, "pdf": "/api/projects/test-doc/output/main.pdf", "log": "/api/projects/test-doc/log/compile.log" }用 Python 调用的通用模板:
import requests import json url = "http://127.0.0.1:8080/api/compile" payload = { "project": "test-doc", "file": "main.tex", "engine": "xelatex" } response = requests.post(url, json=payload, timeout=300) if response.status_code == 200: data = response.json() print("编译成功,PDF 下载地址:", data.get("pdf")) else: print("编译失败,状态码:", response.status_code) print(response.text)注意:这里的接口路径是通用模板,不是 TexLite 的实际接口。一定要查看项目文档后再对接,不要直接照搬。
6.3 批量编译任务设计
虽然 Web 工作区本身不一定提供批量任务,但你可以用命令行脚本实现批量编译。思路是定义一个项目列表,逐个编译并把日志和 PDF 归档。
#!/bin/bash # 批量编译脚本示例,需要按实际环境调整 PROJECTS_DIR="/workspace/projects" OUTPUT_DIR="/workspace/outputs" for project in "$PROJECTS_DIR"/*; do name=$(basename "$project") echo "正在编译项目:$name" cd "$project" || continue xelatex -interaction=nonstopmode -halt-on-error main.tex > "$OUTPUT_DIR/$name.log" 2>&1 status=$? if [ $status -eq 0 ]; then echo "$name 编译成功" cp main.pdf "$OUTPUT_DIR/$name.pdf" else echo "$name 编译失败,查看日志:$OUTPUT_DIR/$name.log" fi done在批量编译时要注意三点:
- 加日志记录,方便失败后定位问题。
- 编译命令加上
-halt-on-error参数,遇到错误立即停止,而不是一直往下执行。 - 失败重试要有间隔,不要无间隔密集调用。
6.4 与编辑器/工作流集成
工作区编译能力还可以集成到现有工作流里。例如:
- 搭配 Git 钩子,推送后自动编译并生成 PDF。
- 与文件同步工具配合,把编译产物同步到共享目录。
- 通过定时任务,对批量文档做定时编译。
这些集成的可行性,取决于 TexLite 是否提供文件系统访问接口或 CLI 工具。项目如果只是纯 Web 应用,没有 CLI,那就直接用命令行 LaTeX 工具做集成,跳过中间层。
7. 资源占用与性能观察方法
7.1 观察哪些指标
自托管 LaTeX 工作区的性能瓶颈不在 Web 服务,而在编译过程。建议重点观察四个指标:CPU、内存、磁盘、网络。
CPU:xelatex编译是 CPU 密集型任务,编译大文档时会把单个内核跑满。观察命令:
top -p $(pgrep -d, -f xelatex)内存:轻量级 Web 服务通常只占几十到几百 MB 内存,但编译大型文档时 TeX 引擎的内存占用会明显上升。内存不足时,编译会直接失败。观察命令:
free -h磁盘:工作区会存储源码、编译产物、日志、包缓存。如果保留多次编译的历史 PDF,磁盘占用会持续增加。观察命令:
du -sh /data /workspace 2>/dev/null如果项目使用容器,最直接的方式是:
docker stats texlite实时看 CPU、内存、网络和磁盘占用。
7.2 编译性能优化
LaTeX 编译慢,通常不是 Web 服务的问题,而是编译流程可以优化。几个常用手段:
- 使用
latexmk做增量编译,只重编译修改过的部分,比每次都全量编译快很多。 - 使用
-file-line-error参数配合日志定位,减少人为排查时间。 - 减少每次编译保留历史产物,或用定时任务定期清理临时文件。
- 在服务器配置不高的场景下,避免同时启动多个编译任务,避免 CPU 争抢。
- 把不常用的宏包和文档工程拆成独立项目,避免一个项目越积越重。
7.3 轻量级项目为什么会“越跑越重”
很多自托管项目跑一段时间后变慢,常见原因有三个。
第一是日志增长。Web 服务日志、编译日志越积越多,需要按天或按大小轮转。第二是文档历史版本。每次编译都保留 PDF 快照,磁盘空间消耗很快,建议设置保留策略,只保留最新 5 到 10 个版本。第三是依赖包缓存。TeX Live 的包缓存可能占用几个 G,如果磁盘紧张,可以按需清理。
8. 常见问题与排查方法
自托管 LaTeX 工作区的问题主要集中在编译环境、端口、权限和前端连接这几类,下面用表格直接给排查路径。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 页面打不开 | 端口未监听或防火墙拦截 | ss -tlnp查端口监听,curl 127.0.0.1:8080测本机访问 | 调整服务监听地址、放行防火墙端口 |
| 编译报错缺少宏包 | TeX Live 宏包集被裁剪 | kpsewhich ctex.sty检查宏包是否存在 | 安装缺失的宏包或完整 texlive-lang-chinese |
| 中文 PDF 乱码 | 未用 XeLaTeX 编译或缺少中文字体 | fc-list :lang=zh检查系统字体 | 切换编译引擎到 xelatex,安装中文字体 |
| 编译超时 | 文档过大或服务器性能不足 | 观察top中编译进程是否存活 | 增加latexmk增量编译,拆分大文档 |
| PDF 预览未更新 | 浏览器缓存或 WebSocket 断连 | 刷新页面,查看浏览器控制台日志 | 清理缓存,检查 WebSocket 代理升级头 |
| 保存文件失败 | 数据目录权限不对 | ls -l /data查看目录属主 | 修改目录权限或容器内用户 UID / GID |
| 容器启动后立即退出 | 环境变量、数据卷或启动命令错误 | docker logs texlite查看退出前日志 | 按日志提示修正环境变量和挂载目录 |
| 前端页面 502 | Nginx 代理目标配置错误 | curl 127.0.0.1:8080确认后端存活 | 修改proxy_pass指向正确端口 |
| 多人同时编译资源不足 | 并发编译任务抢占 CPU | top观察多个 xelatex 进程 | 加任务队列,限制同时编译数量 |
| 服务频繁重启 | 内存不足触发 OOM | `dmesg | tail -20` 查看内核日志 |
8.1 编译日志怎么看
编译失败时,先做一件事:把编译日志完整看一遍。LaTeX 报错通常不会特别友好,但关键信息集中在两类。第一类是 “File not found”,说明缺文件或路径不对。第二类是 “Undefined control sequence”,说明宏包没加载或命令拼写错误。
查看日志时,搜索这些关键词有助于快速定位:
grep -n "^!" compile.log # 所有报错位置 grep -n "not found" compile.log grep -n "Error" compile.log8.2 权限问题的通用解法
容器部署最常见的权限问题是页面提示无法写入文件。原因是宿主机数据目录属于某个 UID,而容器内进程以另一个 UID 运行。解决方法是修改宿主机目录属主:
sudo chown -R 1000:1000 ./data如果不知道容器内用户 UID,可以在容器里执行:
docker exec -it texlite id然后按输出的 UID 调整宿主机目录权限。
8.3 中文字体问题的完整方案
在 Linux 服务器上部署 LaTeX 工作区,中文字体基本必踩。参考下面这套流程:
# 1. 安装中文相关宏包 sudo apt install -y texlive-lang-chinese # 2. 安装中文字体 sudo apt install -y fonts-noto-cjk # 3. 刷新字体缓存 fc-cache -fv # 4. 验证字体 fc-list :lang=zh | head -5如果装完字体后依然乱码,优先排查编译引擎。pdflatex对中文支持较差,统一改用xelatex编译中文文档。
8.4 端口冲突问题
服务无法启动,先查端口:
sudo ss -tlnp | grep 8080如果被占用,两种处理方式。第一种是换端口,修改服务配置。第二种是杀掉占用进程,但前提是你确认这个进程没用。
杀掉进程要谨慎:
sudo kill -9 <PID>9. 最佳实践与使用建议
9.1 第一次部署要做小规模验证
不要直接迁移大量历史文档。建议先建一个测试项目,只放一篇文章,跑通“编辑、编译、预览、下载”四个核心步骤后,再逐步迁移。这样能把环境问题隔离在最小范围,不会拿着几十篇文档排查环境。
9.2 数据目录与代码分离
把数据目录和代码目录分开管理。容器重建时,代码可以重新拉取,但数据目录必须持久化。建议目录结构:
/opt/texlite/ ├── data/ # 文档数据 ├── backups/ # 备份文件 ├── logs/ # 服务日志 └── docker-compose.yml这样升级版本、重装系统都不会丢文档。
9.3 定期备份
自托管服务的最大风险就是数据丢失。备份不需要太复杂,一个定时任务就够了:
30 2 * * * tar czf /backups/texlite-$(date +\%Y\%m\%d).tar.gz /opt/texlite/data你可以在 crontab 里加入类似任务,也可以直接配置备份工具。关键是两点:备份数据目录,定期验证备份文件可恢复。
9.4 认证与访问控制
自托管服务如果处于公网,必须启用认证。如果项目本身不带用户系统,一定要加反向代理层的认证。不要为了省事把端口直接暴露到公网。至少做三件事:
- 启用强制登录。
- 通过 HTTPS 访问。
- 对数据目录做服务账号隔离。
9.5 批量任务的工程化建议
如果你经常需要批量编译文档,建议把任务流程做成可重复的脚本,而不是每次手动点击界面。脚本要包含:
- 输入项目列表的配置文件。
- 每个项目编译结束后记录状态。
- 成功与失败分开归档。
- 日志带时间戳。
这样可以快速回溯“这一批文档哪些编译成功了,哪些失败了,失败原因是什么”。
9.6 合规声明
使用自托管 LaTeX 工作区处理文档时,要确保你拥有文档内容的合法上传和存储权限。涉及公司内部文件时,遵守公司保密要求。涉及他人论文、版权材料时,确认复制和二次分发是否合规。涉及人脸照片、身份证件号、手机号等敏感信息时,建议做脱敏处理再写入文档。自托管只是提供了网络层面的隔离,并不自动意味着合规和安全。
10. 总结与下一步
TexLite 这类轻量级自托管 LaTeX 工作区,最值得尝试的点在于:用很低的资源成本,把常用在线 LaTeX 写作体验搬回自己的服务器。如果你已经有了一台 Linux 服务器,部署一套并不会花太多时间,验证成本也很低。
最先应该验证的功能有三个:基础编译能不能跑通、中文文档能不能正常显示、文件保存和持久化是否正常。这三个点通过,日常写作就已经可以用了。
最容易踩的坑也很明确:中文支持、宏包缺失、数据目录权限、公网暴露问题。建议部署时直接参考文章第 8 节完整排查一遍,不要等出问题再回来查。
后续可以继续扩展的方向包括:接入 Git 做版本管理、配置 Webhook 实现提交后自动编译、对接文件同步工具、增加文档模板库。先把基础工作区用起来,再按实际需求逐步加功能。
部署时记得保留项目仓库链接和配置文件的备份。如果遇到环境相关的特殊问题,优先在项目 Issues 里搜索——很多坑别人已经在前面踩过了。