Guides (Simplified Chinese): 安装、使用与插件开发
# LANrurugi 文档
> 以漫画为主、也能读 PDF / EPUB 等电子书的自托管书库,以 LANraragi 为起点、用 Rust + React 大幅改造与强化——现有 LANraragi 部署的数据与 API 直接可用。
## 这个站点里有什么 [Section titled “这个站点里有什么”](#这个站点里有什么) * **[安装(Docker / NAS)](guide/install/)**——把 LANrurugi 跑起来,并让它读到你已有的库。 * **[原生安装](guide/install-native/)**——不用容器,直接在 Linux、Apple Silicon Mac 或 FreeBSD 上运行。 * **[快速开始](guide/quickstart/)**——首次登录、扫描库、导入旧数据。 * **[支持的格式](guide/formats/)**——能放进书库的压缩包和电子书(PDF、EPUB、MOBI/AZW3、DjVu、FB2、TXT),以及各自怎么显示。 * **[用文档站测试 API](guide/api-testing/)**——在浏览器里直接对**你自己的实例**发请求,以及它不生效时的处理方式。 * **[插件开发入门](plugin/getting-started/)**——写一个元数据/登录/下载插件。 * **[API 参考](api/)**——完整的 HTTP API:每个端点、参数、响应,以及可直接复制的命令行。 ## 关于 API 参考 [Section titled “关于 API 参考”](#关于-api-参考) API 参考**不是手写的**。它由 `crates/lanrurugi-api-docgen` 从服务端自己的路由注册里生成,因此: * 服务端提供的每个端点都在里面,**不会**出现“代码里有、文档里没有”; * 它**不会**列出服务端其实不提供的端点; * 与 LANraragi 共有的端点,直接沿用 LANraragi 官方 OpenAPI 文档的字段级描述(路径前缀与鉴权部分除外); * 尚未写清请求/响应结构的端点会被明确标出,而不是被编造出一份看起来很像真的 schema。 CI 会在生成结果与代码不一致时直接失败,所以这份参考不会像手写文档那样慢慢过期。
# 用文档站测试 API
> 在浏览器里直接对你自己正在运行的 LANrurugi 实例发请求——前置条件、安全边界,以及它不生效时怎么办。
[API 参考](../../api/) 里每个端点都有一个请求面板:填服务器地址、填令牌、点发送。这一页说明它到底 把请求发到哪里、需要什么前置条件,以及浏览器拦下来的时候怎么继续。 ## 请求发到哪里 [Section titled “请求发到哪里”](#请求发到哪里) **从你的浏览器,直接发到你在面板里填的那个地址。** * 你在下面填的地址与令牌,只存在你浏览器的本地存储里,也只发往那个地址。 * 本项目**没有**中间服务器、**没有**代理。绝不会有一条路径把用户的令牌或内网地址送到本项目的基础设施。 * 唯一的例外是页面本身:API 描述文档(`openapi.json`)和 Scalar 的运行时都由文档站同源提供,不走外部 CDN。 因此这个功能不需要任何“公开 demo 实例”——它的目标从来就是你自己的实例。 ## 前置条件 [Section titled “前置条件”](#前置条件) ### 1. 你的实例要对这个浏览器可达 [Section titled “1. 你的实例要对这个浏览器可达”](#1-你的实例要对这个浏览器可达) 面板里填的地址必须是**当前浏览器**能访问到的。你在这台机器上跑文档站、实例在另一台机器上,那么 `localhost` 指的是浏览器所在的机器,不是实例所在的机器。 ### 2. 在实例上打开跨源访问 [Section titled “2. 在实例上打开跨源访问”](#2-在实例上打开跨源访问) 设置页面里的 **「为客户端 API 启用 CORS」** 必须打开。默认是关闭的,此时浏览器会拒绝跨源请求。 打开之后,实例会允许浏览器预检所需的头——包括带 JSON 请求体时必需的 `Content-Type`。如果你的实例版本较 旧、带请求体的调用总是失败,多半就是这一项没有覆盖到。 ### 3. HTTPS 页面只能调用 HTTPS 实例和 `http://localhost` [Section titled “3. HTTPS 页面只能调用 HTTPS 实例和 http://localhost”](#3-https-页面只能调用-https-实例和-httplocalhost) 这是浏览器强制执行的规则,和 LANrurugi 无关: | 文档站 | 你填的实例地址 | 结果 | | ----------- | -------------------------- | ----------------------------- | | `https://…` | `https://lrr.example.com` | ✅ 可用 | | `https://…` | `http://localhost:3000` | ✅ 可用(浏览器把 `localhost` 当作可信来源) | | `https://…` | `http://192.168.1.10:3000` | ❌ 被当作混合内容拦掉 | | `http://…` | 任意 | ✅ 可用(站点本身也是 HTTP) | 局域网 IP **不**享受 `localhost` 那个豁免。想在 HTTPS 文档站上测试局域网里的实例,两条路: * **给实例配 HTTPS**:反向代理(Caddy / Traefik / nginx)、Cloudflare Tunnel,或者 VPN 里带证书的入口。 * **把端口转发到 localhost**:
```sh
ssh -L 3000:127.0.0.1:3000 <跑着实例的机器>
```
然后在面板里填 `http://localhost:3000`。浏览器把它当作可信来源,直接可用。 ## 浏览器不允许的时候:用命令行 [Section titled “浏览器不允许的时候:用命令行”](#浏览器不允许的时候用命令行) **每个端点都有一份可直接复制的命令行(cURL)**,在代码示例面板里。它由端点本身生成,不依赖浏览器、 不依赖 CORS、不依赖 HTTPS,永远可用——面板里发送失败时,用它。
```sh
curl -H "Authorization: Bearer <你的令牌>" \
"http://192.168.1.10:3000/api/archives?start=0&count=10"
```
## 面板报错时怎么读 [Section titled “面板报错时怎么读”](#面板报错时怎么读) * **网络错误 / failed to fetch**:先看上面三条前置条件。最常见的是 CORS 没开、地址填错,或者那份「 混合内容」的组合。 * **401**:令牌不对,或者令牌没有这个端点的权限。 * **403**:令牌是访客类型的,而这个端点只允许管理员。 * **404**:路径或档案 ID 不对。 ## 令牌 [Section titled “令牌”](#令牌) 在设置页面的令牌管理里创建。面板里的令牌字段只是把它放进 `Authorization: Bearer ` 头,存在你 浏览器的本地存储里,也只会发往你填的那个地址。 别在别人的文档站上填令牌 这一页的前提是文档站只是个静态页面。但“静态页面”不等于“可信页面”——对你信任的部署再填令牌。如果你不 确定某个文档站是不是官方部署,直接用 cURL。
# 支持的格式
> 能放进书库的压缩包与电子书格式,以及每种格式怎么显示、目录从哪里来。
书库里的每个文件都是一本「档案」,在同一个阅读器里一页一页地读。除了装着图片的压缩包,PDF、EPUB 等 电子书也可以直接放进书库目录或通过上传页加入,不需要先转换。 ## 压缩包 [Section titled “压缩包”](#压缩包) | 格式 | 扩展名 | | ----------- | ----------------------------------------------------------------------------- | | ZIP | `.zip` `.cbz` | | RAR(含 RAR5) | `.rar` `.cbr` | | 7-Zip | `.7z` `.cb7` | | TAR | `.tar` `.cbt`,以及 gzip / bzip2 / xz / lzma 压缩的 tar(`.gz` `.bz2` `.xz` `.lzma`) | | LZH | `.lzh` `.lha` | 压缩包里能作为页面的图片:PNG、JPEG(`.jpg` `.jpeg` `.jfif`)、GIF、BMP、WebP、AVIF、JPEG XL、HEIF/HEIC。 浏览器显示不了的格式(例如部分浏览器上的 AVIF、JPEG XL 和动画图)会由服务端转换后再显示;HEIF/HEIC 目前 无法转换,只有原生支持它的浏览器(例如 Safari)能显示。 用 zstd 压缩的文件(`.zst`)目前不支持,不会被收录。 ## 电子书 [Section titled “电子书”](#电子书) | 格式 | 扩展名 | 页面怎么显示 | 目录从哪里来 | | ----------------- | ----------------------------- | ------------------------------ | ----------------------------------- | | PDF | `.pdf` | 扫描页直接输出 PDF 里存的原图;文字页、矢量页渲染成图片 | PDF 书签 | | EPUB(固定版式) | `.epub` | 每一页输出书里存的原图 | 书自带的目录(nav / NCX) | | EPUB(流式文字) | `.epub` | 服务端排版成页,插图随文排入 | 书自带的目录,精确到章节所在的位置 | | MOBI / AZW / AZW3 | `.mobi` `.azw` `.azw3` `.prc` | 漫画:每页输出原图;文字书:服务端排版 | 书里的目录页或章节标题 | | DjVu | `.djvu` `.djv` | 渲染成图片 | DjVu 书签 | | FB2 | `.fb2` | 服务端排版,插图随文排入 | 书的章节结构 | | 纯文本 | `.txt` | 服务端排版 | 自动识别「第一章」「第十二回」「序章」「Chapter 3」这类章节行 | 几点说明: * **原图不重新压缩。** 书里存的是图片的页面(扫描版 PDF、固定版式 EPUB、漫画 MOBI/AZW3、FB2 插图), 阅读器拿到的就是书里那张图本身。 * **文字书由服务端排版。** 正文按书的语言选用简体中文、日文或韩文字体,标题、段落、插图都会排进页面; 目前只支持横排。 * **目录只在首次入库时导入**,而且只在档案还没有章节目录时才导入,不会覆盖你手动编辑过的目录。书自带的 目录缺失或只有一两条(比如只有封面、版权页)时,会从正文里的标题和章节行补全。 * **TXT 只收录 8 KB 以上的文件**,避免把书库里的说明文件、备注当成书。编码自动识别(UTF-8、UTF-16、 GBK/GB18030、Big5、Shift_JIS、EUC-JP、EUC-KR 等);按固定宽度折行的文本会重新拼回段落。 * **书库里会标出格式。** 电子书在标题旁显示 `PDF`、`EPUB` 之类的小标签;PDF 还可以在阅读页里直接用浏览器 打开原文件。 * 拆包建议只对压缩包有意义,电子书不提供。 * 文字书和 PDF 文字页渲染出的页面会缓存起来,与阅读器的其它缓存一起受 「设置 → 档案文件 → 最大阅读缓存大小」限制。 ## 不支持的情况 [Section titled “不支持的情况”](#不支持的情况) * **带 DRM 或密码保护的书**(例如从商店购买、未去除保护的 Kindle 书,或加了打开密码的 PDF)无法读取。 这类文件仍会出现在书库里(0 页),打开时阅读器会显示无法读取的原因(受 DRM 或密码保护),服务端日志里也会 记录。 * **损坏或不完整的文件**同样会提示具体原因,不影响书库里的其它书。 * Kindle 的 KFX 格式,以及使用 HUFF/CDIC 压缩的 MOBI(多见于 Kindle 词典)暂不支持。
# 安装(Docker / NAS)
> 用 Docker 或 Compose 在服务器/NAS 上部署 LANrurugi。
LANrurugi 的服务端是一个常驻进程,前端静态资源、HTTP API、文件监视器和后台任务都在里面;插件、电子书解析和 AI 推理在按需启动的子进程里运行。它有自己的数据库,不读取也不改动 LANraragi 的数据库,两者可以同时运行。 不想用容器的话,也可以用 Linux、macOS(Apple Silicon)和 FreeBSD 的[原生安装包](../install-native/)。 ## 用 Compose 部署(推荐) [Section titled “用 Compose 部署(推荐)”](#用-compose-部署推荐) 把下面这段保存为 `compose.yaml`,按注释把左侧的宿主机目录改成你自己的,然后启动:
```yaml
services:
lanrurugi:
image: ghcr.io/thelastfantasy/lanrurugi:latest
container_name: lanrurugi
ports:
- "3000:3000"
volumes:
# 书库,可以直接指向旧版 LANraragi 的 content 目录
- ./data/manga:/home/koyomi/lanrurugi/content
# 缩略图缓存
- ./data/thumb:/home/koyomi/lanrurugi/thumb
# Redis 数据,LANrurugi 专用;LANraragi 的元数据通过备份 JSON 导入
- ./data/database:/home/koyomi/lanrurugi/database
# 推荐功能的嵌入模型,首次用到时自动下载
- ./data/models:/home/koyomi/lanrurugi/models
environment:
# 经 HTTPS 反向代理访问时改为 true
- LANRURUGI_FORCE_SECURE_COOKIES=false
restart: unless-stopped
```
```sh
docker compose up -d # 或 podman compose up -d
```
NAS 上(群晖 Container Manager、Portainer 等)新建一个 compose 项目,粘贴同一段文本即可。 启动后在浏览器打开 `http://<服务器地址>:3000`。镜像自带 Redis,不需要额外的数据库容器。四个挂载目录: | 宿主机路径 | 容器内路径 | 用途 | | ----------------- | --------------------------------- | ---------------------- | | `./data/manga` | `/home/koyomi/lanrurugi/content` | 你的档案库 | | `./data/thumb` | `/home/koyomi/lanrurugi/thumb` | 缩略图缓存 | | `./data/database` | `/home/koyomi/lanrurugi/database` | Redis 数据(LANrurugi 专用) | | `./data/models` | `/home/koyomi/lanrurugi/models` | 推荐功能的嵌入模型缓存 | 要通过域名和 HTTPS 访问,见[反向代理](../reverse-proxy/)。 ## 直接用 Docker 运行 [Section titled “直接用 Docker 运行”](#直接用-docker-运行)
```sh
docker run -d --name lanrurugi -p 3000:3000 \
-v /path/to/library:/home/koyomi/lanrurugi/content \
-v /path/to/thumb:/home/koyomi/lanrurugi/thumb \
-v /path/to/database:/home/koyomi/lanrurugi/database \
ghcr.io/thelastfantasy/lanrurugi:latest
```
## 镜像来源 [Section titled “镜像来源”](#镜像来源) 同一个镜像同时发布在两个仓库,内容完全相同,都包含 amd64 和 arm64 两种架构: | 仓库 | 镜像名 | | ----------------------------- | ---------------------------------- | | GitHub Container Registry(推荐) | `ghcr.io/thelastfantasy/lanrurugi` | | Docker Hub | `jade913/lanrurugi` | 上面的示例用的是 GitHub 的仓库。Docker Hub 对未登录用户有拉取次数限制;如果你的 NAS 面板只能从 Docker Hub 搜索镜像,或者你更习惯用它,把镜像名换成 `jade913/lanrurugi` 即可。`latest` 指向最新的正式版本, 也可以写具体的版本号。 ## 从源码构建镜像 [Section titled “从源码构建镜像”](#从源码构建镜像) 仓库根目录的 `compose.yaml` 用于从源码构建并试运行(`network_mode: host`,监听 3000 端口):
```sh
podman compose up -d --build # 或 docker compose up -d --build
```
## 首次登录 [Section titled “首次登录”](#首次登录) 首次打开时会出现首次运行向导:修改管理员密码、填写 AI 功能用的 DeepSeek API 密钥、从 LANraragi 备份导入 数据,每一步都可以跳过,之后也能在设置页面重新运行。 一个全新实例——或者从一个从未修改过密码的旧版安装迁移过来的实例——使用的是旧版 LANraragi 自身的默认 管理员密码 **`kamimamita`**。 第一件事就是改密码 登录后请立刻在设置页面修改密码。不要让一个还在用默认密码的实例可以从本地网络之外访问。 ## 离线阅读本文档 [Section titled “离线阅读本文档”](#离线阅读本文档) 文档站、API 正文参考、Swagger UI 和插件 SDK 参考都打包在镜像里,由实例自己在 `/docs` 下提供:
```text
http://<你的实例地址>:3000/docs/ 指南与按分组的 API 正文参考(中文)
http://<你的实例地址>:3000/docs/en/ 同上,英文版
http://<你的实例地址>:3000/docs/swagger/ Swagger UI,中文内容(可看 schema,可试发请求)
http://<你的实例地址>:3000/docs/swagger/en/ Swagger UI,英文内容
http://<你的实例地址>:3000/docs/sdk/ 插件 SDK 参考
```
不需要外网:连 Swagger UI 的 JS 打包和 SDK 的搜索索引都在镜像里,没有任何资源来自 CDN。 ## 工具链(从源码构建) [Section titled “工具链(从源码构建)”](#工具链从源码构建) 版本固定在 `.mise.toml` 里,`mise install` 会精确复现它们(Rust、Node、Deno、pnpm,以及 `sccache`/`mold`)。
```sh
# 后端
cargo build --release -p lanrurugi-server
./target/release/lanrurugi-server serve --redis-url redis://127.0.0.1:6379 \
--library-path /path/to/existing/library
# 前端开发服务器(把 /api 代理到上面的后端)
pnpm --filter lanrurugi-frontend run dev
```
### CLI 子命令 [Section titled “CLI 子命令”](#cli-子命令) * `lanrurugi serve`——在同一个进程里运行 HTTP API、静态前端、文件监视器与插件池。 * `lanrurugi rebuild-index`——用大小感知算法重新计算每个档案的 ID,并发现历史上曾被误判合并而隐藏的 文件。 * `lanrurugi bench`——生成合成库,并针对一个正在运行的旧版实例做并发/吞吐量对比。 ## 下一步 [Section titled “下一步”](#下一步) * [快速开始](../quickstart/) * [用文档站测试 API](../api-testing/)
# 原生安装(Linux / macOS / FreeBSD)
> 不用容器,直接在 Linux、Apple Silicon Mac 或 FreeBSD 上运行 LANrurugi。
除了 [Docker 镜像](../install/),每个版本还提供以下平台的原生安装包: | 安装包 | 适用系统 | | -------------------------------------- | ------------------------------------------------------------------ | | `lanrurugi-<版本>-linux-x86_64.tar.gz` | 64 位 Linux(glibc 2.35 及以上:Debian 12、Ubuntu 22.04、Fedora 36、Arch 等) | | `lanrurugi-<版本>-linux-aarch64.tar.gz` | ARM64 Linux(同上,例如树莓派 5、ARM 服务器) | | `lanrurugi-<版本>-macos-arm64.tar.gz` | Apple Silicon Mac(macOS 13 及以上) | | `lanrurugi-<版本>-freebsd-x86_64.tar.gz` | FreeBSD 14 | 安装包在 GitHub 的 [Releases](https://github.com/thelastfantasy/LANrurugi/releases) 页面,`SHA256SUMS` 里有每个文件的校验值。 不想管理依赖的话,Docker 仍然是最省事的方式;Windows 用户请使用 Docker Desktop。 ## 1. 安装依赖 [Section titled “1. 安装依赖”](#1-安装依赖) 数据库、插件运行环境、DjVu 工具和字体由系统的包管理器安装,安装包里不附带: | | Debian / Ubuntu | Fedora | Arch | macOS(Homebrew) | FreeBSD | | ---------------- | ------------------------------------ | -------------------------------------------------------------------- | ---------------------------- | -------------------------- | ------------------------------------------------------------------- | | Redis 7.4 及以上 | `apt install redis-server` ¹ | `dnf install redis` ² | `pacman -S redis` | `brew install redis` | `pkg install redis` | | Deno(插件) | [官方安装脚本](https://deno.com) | [官方安装脚本](https://deno.com) | `pacman -S deno` | `brew install deno` | `pkg install deno` | | DjVu 阅读 | `apt install djvulibre-bin` | `dnf install djvulibre` | `pacman -S djvulibre` | `brew install djvulibre` | `pkg install djvulibre` | | 中日韩字体(文字书) | `apt install fonts-noto-cjk` | `dnf install google-noto-serif-cjk-fonts google-noto-sans-cjk-fonts` | `pacman -S noto-fonts-cjk` | 系统自带,无需安装 | `pkg install noto-serif-sc noto-sans-sc noto-serif-jp noto-sans-jp` | | 彩色 emoji 字体(文字书) | `apt install fonts-noto-color-emoji` | `dnf install google-noto-color-emoji-fonts` | `pacman -S noto-fonts-emoji` | 系统自带,无需安装 | `pkg install noto-emoji` | | 压缩包解码库 | 系统自带 | 系统自带 | 系统自带 | `brew install xz lz4 zstd` | `pkg install lz4 zstd` | | PDF 阅读 | 安装包自带 | 安装包自带 | 安装包自带 | 安装包自带 | `pkg install pdfium` | | OCR、翻译、推荐 | 安装包自带 | 安装包自带 | 安装包自带 | 安装包自带 | `pkg install onnxruntime` | | CA 证书(HTTPS) | `apt install ca-certificates` ³ | 系统自带 | 系统自带 | 系统自带 | `pkg install ca_root_nss` | ¹ Debian 12 自带的是 Redis 7.0,用于新书库没有问题;要沿用 Docker 部署留下的数据,需要 7.4 及以上(可使用 redis.io 的软件源)。 ² 较新的 Fedora 实际安装的是兼容 Redis 的 Valkey,用于新书库没有问题,但它读不了 Redis 7.4 写出的数据文件。 ³ 精简系统(最小化容器、虚拟机)可能没有装。不装也能运行:程序找不到系统证书时,HTTPS 会改用内置的 Mozilla 根证书,启动日志里的 `tls_roots=bundled` 表示这种情况。装上系统证书则跟随系统更新,也能识别你自己添加的证书。 ## 2. 解压并启动 [Section titled “2. 解压并启动”](#2-解压并启动)
```sh
tar -xzf lanrurugi-<版本>-<平台>.tar.gz
cd lanrurugi-<版本>-<平台>
redis-server --daemonize yes # 或启用系统自带的 Redis 服务
./bin/lanrurugi-server serve \
--library-path ~/manga \
--thumb-dir ~/.local/share/lanrurugi/thumb \
--temp-dir ~/.local/share/lanrurugi/temp \
--log-dir ~/.local/share/lanrurugi/log
```
然后打开 `http://<你的机器>:3000`,首次运行向导会引导你修改默认密码、填写 AI 功能用的 API 密钥、导入 LANraragi 备份。 前端、插件、文档、自带的原生库和模型都按程序自己的位置查找,解压到哪里都可以,不需要再设置其它路径。 默认连接 `redis://127.0.0.1:6379`,用 `--redis-url` 或环境变量 `LANRURUGI_REDIS_URL` 修改。 ## 3. 下载翻译模型(可选) [Section titled “3. 下载翻译模型(可选)”](#3-下载翻译模型可选)
```sh
./fetch-models.sh # 文字识别与擦除模型,几百 MB
./fetch-models.sh --with-bubbles # 另外生成对话框分割模型(需要 uv)
```
不下载也能正常使用书库和阅读器;没有对话框分割模型时,翻译用矩形框擦除原文。 ## 4. 作为系统服务运行 [Section titled “4. 作为系统服务运行”](#4-作为系统服务运行)
```sh
sudo ./install-service.sh /var/lib/lanrurugi # Linux(systemd)、FreeBSD(rc.d)
./install-service.sh ~/LANrurugi # macOS(launchd,当前用户)
```
脚本会创建数据目录和 `lanrurugi.env`(书库位置、Redis 地址、监听端口),并为当前系统安装服务定义,最后提示启动命令。 只想看生成的服务文件而不安装,加 `--print`。 ## 从 Docker 部署迁移 [Section titled “从 Docker 部署迁移”](#从-docker-部署迁移) 把容器挂载的三个目录直接拿过来用:`content` 作为书库,`thumb` 作为缩略图目录。`database` 目录交给一个按 `service/redis.conf.example` 配置的 Redis(7.4 及以上),它的 `dir` 指向这个目录,端口 16379;再把 `LANRURUGI_REDIS_URL` 设为 `redis://127.0.0.1:16379`。 ## 各平台功能 [Section titled “各平台功能”](#各平台功能) | 功能 | Linux | macOS | FreeBSD | | ------------------------------------ | ---------------- | ------ | ------------------------ | | 书库、阅读、搜索、压缩包 | ✓ | ✓ | ✓ | | PDF / DjVu / EPUB / MOBI / FB2 / TXT | ✓ | ✓ | ✓(PDF 需 `pdfium` 包) | | 插件、下载、订阅 | ✓ | ✓ | ✓ | | 推荐、OCR、页面翻译 | ✓ | ✓(CPU) | ✓(CPU,需 `onnxruntime` 包) | | GPU 加速推理 | ✓(与 Docker 镜像相同) | — | — | 缺少某个可选组件时服务照常启动,启动日志会列出 `optional components` 和 `some features are unavailable on this system`,说明缺了什么、影响哪些功能;用到这些功能时也会显示原因。 ## 尚未支持的平台 [Section titled “尚未支持的平台”](#尚未支持的平台) * **Windows**:请使用 Docker Desktop。 * **Intel Mac、其它 BSD、musl 发行版(如 Alpine)**:没有提供安装包;musl 发行版请使用 Docker 镜像。 * **鸿蒙(HarmonyOS / OpenHarmony)**:暂不支持。鸿蒙系统上的应用运行在沙箱里,不支持长期在后台运行的 服务端程序,LANrurugi 依赖的 Redis、Deno、PDFium、ONNX Runtime 也都没有鸿蒙版本。可行的方向是另做 一个连接现有 LANrurugi 服务端的鸿蒙阅读客户端,而不是在设备上运行服务端。
# 给 AI 工具用的 llms.txt
> 项目主页和文档站提供的 llms.txt 系列文件各自包含什么,以及让 AI 助手了解 LANrurugi 时该给它哪一份。
[llms.txt](https://llmstxt.org/) 是一种约定:在站点根目录放一份 Markdown 文件,告诉 AI 工具这个项目是什么、 更详细的内容去哪里读。LANrurugi 的项目主页和文档站都提供了这类文件。把对应的地址交给 AI 助手, 它就能按文档回答问题、帮你部署、写调用 API 的脚本或者写插件,而不必只凭训练时的印象猜。 ## 文件一览 [Section titled “文件一览”](#文件一览) | 地址 | 内容 | 大小(约) | | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------ | | [`lrrg.dev/llms.txt`](https://lrrg.dev/llms.txt) | 入口:项目简介、HTTP API 与插件 SDK 的说明,以及主要文档的链接 | 3.5 KB | | [`docs.lrrg.dev/llms.txt`](https://docs.lrrg.dev/llms.txt) | 文档站目录:下面各文件的链接,以及 API 与 SDK 的说明 | 3 KB | | [`docs.lrrg.dev/llms-full.txt`](https://docs.lrrg.dev/llms-full.txt) | 全部文档页,中英两种语言,合成一个 Markdown 文件 | 800 KB | | [`docs.lrrg.dev/llms-small.txt`](https://docs.lrrg.dev/llms-small.txt) | 精简版:只含指南和插件开发,去掉 API 参考页与提示框 | 80 KB | | [`…/_llms-txt/guides-simplified-chinese.txt`](https://docs.lrrg.dev/_llms-txt/guides-simplified-chinese.txt) | 只含中文的指南与插件开发 | 40 KB | | [`…/_llms-txt/guides-english.txt`](https://docs.lrrg.dev/_llms-txt/guides-english.txt) | 同上,英文 | 40 KB | | [`…/_llms-txt/api-reference-simplified-chinese.txt`](https://docs.lrrg.dev/_llms-txt/api-reference-simplified-chinese.txt) | 只含中文的 API 参考,每组一节 | 300 KB | | [`…/_llms-txt/api-reference-english.txt`](https://docs.lrrg.dev/_llms-txt/api-reference-english.txt) | 同上,英文 | 300 KB | 另有两份结构化数据,llms.txt 里也有链接: * [`docs.lrrg.dev/openapi.json`](https://docs.lrrg.dev/openapi.json):完整的 HTTP API,OpenAPI 3.1 格式。它由服务器 自己注册的路由生成,列出的正是服务器实际提供的全部端点。 * [`sdk.lrrg.dev/plugin-sdk.json`](https://sdk.lrrg.dev/plugin-sdk.json):插件 SDK 参考的 JSON 版,由 `deno doc` 从插件运行时实际加载的 TypeScript 生成。 这些文件在每次发布文档时与网页一同重新生成,内容和网页同源,不会各自过时。 ## 该给 AI 哪一份 [Section titled “该给 AI 哪一份”](#该给-ai-哪一份) | 你想让 AI 做什么 | 给它 | | ---------------- | ------------------------------------------------------------ | | 介绍这个项目、回答一般问题 | `lrrg.dev/llms.txt` | | 帮你部署、排查安装与反向代理问题 | 一种语言的指南(`guides-*.txt`)或 `llms-small.txt` | | 写调用 API 的脚本或客户端 | `openapi.json`:比 API 参考页的 Markdown 更精确,也更省 token | | 写插件 | [插件开发入门](../../plugin/getting-started/) 加上 `plugin-sdk.json` | | 需要全部背景、上下文足够大 | `llms-full.txt` | 如果只是想为某个站点生成元数据、登录或下载插件,实例里自带的 **「AI 创建插件」** 会直接抓取目标页面、 生成代码并试运行,通常比让外部 AI 助手从零写更省事。 ## 怎么交给 AI [Section titled “怎么交给 AI”](#怎么交给-ai) * **能联网的 AI 工具**(带网页读取的聊天助手、编程代理等):直接把地址发给它,例如 「先读 `https://lrrg.dev/llms.txt`,再回答……」。它会按里面的链接继续读需要的部分。 * **不能联网的工具**:先下载需要的文件,再作为附件上传或粘贴进对话。 * **编程代理**(在代码仓库里工作的 AI):把 `openapi.json` 或 `plugin-sdk.json` 下载进项目目录,比每次 联网读取更稳定。
# 快速开始
> 首次登录、建立 API 令牌、扫描库、导入旧数据。
## 1. 登录 [Section titled “1. 登录”](#1-登录) 打开 `http://<你的实例地址>:3000`,用默认密码 `kamimamita` 登录,然后**立刻在设置页面改掉它**。 ## 2. 指向你的库 [Section titled “2. 指向你的库”](#2-指向你的库) `--library-path`(或 `LANRURUGI_LIBRARY_PATH`)指向放档案的目录。默认是 `./library`;Compose 部署里 对应容器的 `/home/koyomi/lanrurugi/content`。 ## 3. 扫描 [Section titled “3. 扫描”](#3-扫描) 在设置页面触发一次全量扫描。扫描是并发的(Rayon),并且**不会**自动删除档案记录——「扫描时发现文件消失」 只会清理路径簿记,档案记录本身归「数据库清理」管,是一个独立的、需要你明确触发的操作。 ## 4. 建立 API 令牌 [Section titled “4. 建立 API 令牌”](#4-建立-api-令牌) API 参考里的「Test it」面板需要令牌。在设置页面的令牌管理里创建一个,然后:
```sh
curl -H "Authorization: Bearer <你的令牌>" http://localhost:3000/api/archives
```
令牌按权限分为管理员与访客两类;访客令牌只能读取。 ## 5. 从旧版 LANraragi 迁移 [Section titled “5. 从旧版 LANraragi 迁移”](#5-从旧版-lanraragi-迁移) LANrurugi 用自己的数据库,不读取也不改动 LANraragi 的数据,两边可以同时运行。步骤见[安装](../install/)页的 「从 LANraragi 迁移」:书库挂载同一个漫画目录,缩略图和数据库用新的目录,再在首次运行向导里导入 LANraragi 的 备份 JSON。 导入按文件名把备份里的档案对应到 LANrurugi 扫描到的档案,不比较档案 ID:LANrurugi 用大小感知指纹 (`hash(前 512KB ++ 大端 u64 文件大小)`)作为 ID,和 LANraragi 的 `SHA-1(前 512KB)` 不同。同名文件有多个时 不会猜测,计入「匹配不唯一」。导入前请等书库扫描完成,还没扫描到的档案会被算作「无匹配而跳过」。 LANraragi 曾把开头字节相同的不同文件误判为重复并合并,这些文件在 LANrurugi 里会各自出现。 ## 6. 试试 API [Section titled “6. 试试 API”](#6-试试-api) 打开 [API 参考](../../api/),在请求面板里把服务器地址改成你自己的实例(默认已经是 `http://localhost:3000`),填上令牌,然后直接发请求。请求从你的浏览器直接到你的实例,不经过本项目。 浏览器不允许的时候(例如文档站是 HTTPS 而你的实例是局域网里的纯 HTTP),每个端点都提供了一份可直接 复制的命令行。 细节见[用文档站测试 API](../api-testing/)。
# 反向代理
> 用 Nginx、Caddy、Traefik、Apache 或 Nginx Proxy Manager 为 LANrurugi 配置域名与 HTTPS。
LANrurugi 本身只提供 HTTP(默认 `0.0.0.0:3000`)。要通过域名和 HTTPS 访问,在它前面放一个反向代理。 无论用哪一种代理,都要满足下面几条。 ## 代理需要满足的条件 [Section titled “代理需要满足的条件”](#代理需要满足的条件) * **挂在域名根路径下。** 前端以绝对路径 `/api/...` 请求接口,不支持挂在子路径(如 `example.com/lanrurugi/`)下。请用独立的域名或子域名,例如 `manga.example.com`。 * **转发三个请求头。** `X-Forwarded-Proto`(判断是否走 HTTPS)、`X-Forwarded-Host`(跨域登录交接与 OpenSearch 生成正确的地址)、`X-Forwarded-For`(活动记录里显示真实客户端 IP)。同时保留原始 `Host`。 * **不要缓冲 SSE。** 下载队列进度、AI 插件向导与拆包建议使用 Server-Sent Events 实时推送。代理一旦缓冲 响应,这些界面就会卡住、直到请求结束才一次性刷新。服务端每 15 秒发送一次心跳,所以默认的读超时 (通常 60 秒)够用,但缓冲必须关闭。 * **放开上传大小。** 档案上传以每片最多 64 MB 分片发送,旧版数据导入单次最多 100 MB。代理的请求体 上限要不小于这个值,最简单的做法是不设上限。 * **走 HTTPS 后打开安全 Cookie。** 在 compose 里设置 `LANRURUGI_FORCE_SECURE_COOKIES=true`。服务端不会 根据 `X-Forwarded-Proto` 自动推断这一项——那个请求头可以被伪造,而本服务没有可信代理白名单。只走 HTTP 时**不要**打开它,否则浏览器会丢弃登录 Cookie,导致无法登录。 不需要 WebSocket。 下面的示例都假设 LANrurugi 与代理在同一台机器上,监听 `127.0.0.1:3000`;如果代理和 LANrurugi 在同一个 compose 网络里,把地址换成 `lanrurugi:3000`。 ## Nginx [Section titled “Nginx”](#nginx)
```nginx
server {
listen 443 ssl;
http2 on;
server_name manga.example.com;
ssl_certificate /etc/ssl/manga.example.com/fullchain.pem;
ssl_certificate_key /etc/ssl/manga.example.com/privkey.pem;
# 不限制上传大小(分片上传每片最多 64 MB)
client_max_body_size 0;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
# SSE:不缓冲,长连接不超时
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 1h;
proxy_request_buffering off;
}
}
server {
listen 80;
server_name manga.example.com;
return 301 https://$host$request_uri;
}
```
## Caddy [Section titled “Caddy”](#caddy) Caddy 自动申请证书、默认转发 `X-Forwarded-*`,并且会立即刷新 `text/event-stream` 响应,所以配置最短:
```caddyfile
manga.example.com {
reverse_proxy 127.0.0.1:3000
}
```
## Traefik [Section titled “Traefik”](#traefik) 在 LANrurugi 的 compose 服务上加 labels(假设 Traefik 已经有名为 `websecure` 的 entrypoint 与名为 `letsencrypt` 的证书解析器,且两者在同一个 Docker 网络里):
```yaml
services:
lanrurugi:
image: ghcr.io/thelastfantasy/lanrurugi:latest
# 由 Traefik 对外提供服务时,不需要再发布 3000 端口
volumes:
- ./data/manga:/home/koyomi/lanrurugi/content
- ./data/thumb:/home/koyomi/lanrurugi/thumb
- ./data/database:/home/koyomi/lanrurugi/database
- ./data/models:/home/koyomi/lanrurugi/models
environment:
- LANRURUGI_FORCE_SECURE_COOKIES=true
labels:
- traefik.enable=true
- traefik.http.routers.lanrurugi.rule=Host(`manga.example.com`)
- traefik.http.routers.lanrurugi.entrypoints=websecure
- traefik.http.routers.lanrurugi.tls.certresolver=letsencrypt
- traefik.http.services.lanrurugi.loadbalancer.server.port=3000
restart: unless-stopped
```
Traefik 默认转发 `X-Forwarded-*`、不缓冲响应、不限制请求体大小,无需额外中间件。 ## Apache httpd [Section titled “Apache httpd”](#apache-httpd) 需要启用 `mod_proxy`、`mod_proxy_http`、`mod_headers` 与 `mod_ssl`:
```apache
ServerName manga.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/manga.example.com/fullchain.pem
SSLCertificateKeyFile /etc/ssl/manga.example.com/privkey.pem
ProxyPreserveHost On
# mod_proxy 会自动设置 X-Forwarded-For 与 X-Forwarded-Host
RequestHeader set X-Forwarded-Proto "https"
# flushpackets=on 让 SSE 事件立即送达浏览器
ProxyPass / http://127.0.0.1:3000/ flushpackets=on timeout=3600
ProxyPassReverse / http://127.0.0.1:3000/
# 不限制上传大小
LimitRequestBody 0
```
## Nginx Proxy Manager [Section titled “Nginx Proxy Manager”](#nginx-proxy-manager) 许多 NAS 用户用它管理证书。新建一个 Proxy Host: * **Details**:Domain 填 `manga.example.com`,Scheme 选 `http`,Forward Hostname / IP 与 Port 填 LANrurugi 的地址和 `3000`。 * **SSL**:申请证书,勾选 *Force SSL*。 * **Advanced** 中粘贴:
```nginx
client_max_body_size 0;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 1h;
proxy_set_header X-Forwarded-Host $host;
```
Nginx Proxy Manager 默认已经转发 `Host`、`X-Forwarded-Proto` 与 `X-Forwarded-For`。 ## 检查是否配置正确 [Section titled “检查是否配置正确”](#检查是否配置正确) 1. 打开 `https://manga.example.com`,能正常登录且刷新后仍保持登录。 2. 在下载队列里添加一个任务,进度条应当连续推进,而不是在结束时才一次跳到 100%。 3. 活动记录页(`/activity`)里,登录记录显示的是你的客户端 IP,而不是代理的地址。
# 插件开发入门
> 用 TypeScript 写 LANrurugi 的元数据 / 登录 / 下载插件。
LANrurugi 的插件是**单个 `.ts` 文件**,放在 `plugins/<类别>/` 下,或者通过设置页面/`POST /api/plugins/upload` 上传(会上传到 `plugins/custom/<类别>/`)。它在**独立的 Deno 子进程**里运行,只带插件自己声明的权限 (`--allow-net` / `--allow-read` 等),拿不到宿主进程的任何东西。 ## 最小插件 [Section titled “最小插件”](#最小插件) 一个插件文件必须导出恰好两样东西: 1. `pluginInfo()`——同步、无副作用,只返回插件自己的元数据:命名空间、名称、参数、声明的权限。 宿主会用一个**零权限**的一次性子进程调用它,就为了读元数据,然后再按声明去申请真正的权限。 2. 对应类型的执行函数——`execMetadata`(元数据抓取)、`execLogin`(登录)、`execDownload`(下载)。 具体签名、类型与每个字段的含义,见 **[SDK 参考](../sdk/)**:它由 `deno doc` 直接从运行时会加载的那份 TypeScript 源码生成,所以不会和实际行为脱节。 ## 权限 [Section titled “权限”](#权限) 插件必须**预先声明**它需要什么,宿主才会授予什么。这是为了让一个行为异常或者恶意的插件没法拖垮宿主进程, 也没法读它不该读的文件。声明之外的任何网络/文件访问都会失败。 ## 调试 [Section titled “调试”](#调试) * 设置页面的插件列表会显示每个插件的 `pluginInfo()` 结果,包括它声明的权限。 * 插件调用失败时,宿主会把子进程的 stderr 一并记录;日志页面按类别可查。 * HTTP 请求走宿主中继,并按需最小化——插件发出的请求由宿主代理,因此插件不需要 `--allow-net` 之外的东西, 也能被统一限流与记录。 ## 下一步 [Section titled “下一步”](#下一步) * [SDK 参考](../sdk/)——所有导出类型与函数,含文档注释。 * [API 参考](../../api/)——`/api/plugins*` 下的端点(列表、上传、执行、导出)。
# SDK 参考
> 插件运行时实际加载的那份 TypeScript 的 API 参考。
插件作者可用的每个类型与函数,都由 `deno doc` 直接从**插件运行时实际加载的那份 TypeScript** (`crates/lanrurugi-plugin/dispatcher/` 下的 `plugin-sdk.ts`、`dispatcher.ts`,以及 `plugins/legacy-globals.d.ts`)生成,所以它不会和真实行为脱节。 [打开 SDK 参考 →](https://sdk.lrrg.dev/) 那份参考里可以搜索符号、按类型/接口/函数分组浏览,也能看到每个符号自身的文档注释。同一份内容还有一个 机器可读的 JSON 版本(`plugin-sdk.json`),便于工具消费。 ## 相关 [Section titled “相关”](#相关) * [插件开发入门](../getting-started/)——最小插件、权限模型、调试。 * [API 参考](../../api/)——`/api/plugins*` 下的端点。