ITADN
ajslater/codex
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

Codex

一款漫画归档浏览器和阅读器。

注意: Docker 镜像已迁移至 ghcr.io/ajslater/codex。 最后一个 docker.io 镜像已发布在 Docker Hub 上。

✨ 功能

📚 书库

  • 支持阅读 CBZ、CBR、CB7、CBT 和 PDF 格式的漫画。
  • 所有漫画服务器中最快的批量导入器
  • 监控文件系统,自动导入新增或变更的漫画。
  • 为文件夹、出版商、厂牌、系列和故事弧提供自定义封面

🔎 浏览与搜索

  • 浏览 出版商、厂牌、系列、卷 的树状结构,你的文件夹 层级,或按标签化的故事弧浏览。
  • 对漫画元数据和书签进行全文搜索
  • 按任意元数据字段进行筛选和排序,包括按用户划分的未读状态。
  • 提供多列可排序的元数据表格视图,用于高效浏览。
  • 保存和加载命名的视图和搜索条件。
  • 在出版商、系列、卷、文件夹、故事弧或单话 级别设置收藏夹 — 可按用户筛选。

🏷️ 编辑与标签

  • 编辑标签 直接在浏览器中为一个或多个漫画编辑标签——包括制作人员、故事弧、标识符等——并写回您的漫画文件。要求漫画目录以可写方式挂载,并具备文件系统写入权限。
  • 在线标签 从在线源查找并应用元数据,支持交互式匹配提示,并在“管理标签”选项卡中配置各源的凭据。
  • 重命名漫画文件 在编辑标签或进行在线标签时,根据标签生成的 comicbox 命名方案重命名漫画文件,并提供文件名预览和确认。

📖 阅读

  • 适应任何屏幕,支持多种宽高比和阅读方向
  • 每用户书签和阅读设置,即使没有账户也会保留。

👥 用户与访问

  • 匿名浏览 或需要注册的模式——由您选择。
  • 私有库 限制为特定用户组访问。
  • 可选的年龄限制,针对带有年龄标签的漫画。
  • 可选的自助密码重置,通过电子邮件(需要 SMTP 配置)。

🔌 集成

  • OPDS 1 & 2 联合分发,支持流式传输、搜索和身份验证。
  • OIDC 单点登录,支持 Authentik 和 Authelia 等身份提供商。
  • Remote-User HTTP 头 SSO,用于反向代理单点登录(tinyauth、Authelia、Authentik 代理模式)。
  • Fail2Ban 日志,用于封禁登录失败的 IP。

🪶 运维

  • 运行于 1 GB 内存(内存更多则更快)。
  • GPLv3 许可。

示例

  • 使用 Filter by Story Arc 和 Unread,Order by Publish Date 来创建一个事件 阅读列表。
  • 使用 Filter by Unread 和 Order by Added Time 来查看您最新的未读漫画。
  • 使用 Search by 您喜欢的角色来查找他们在不同 漫画中的出场。

👀 演示

您可以浏览 live demo server 来 了解 Codex。

📜 新闻

Codex 有一个 NEWS file 来总结影响用户的更改。

🕸️ HTML 文档

HTML formatted docs are available here

📦 安装

使用 Docker 安装并运行

运行官方 Docker Image 位于 ghcr.io/ajslater/codex。

阅读 Docker instructions

然后您需要阅读本文档的 Administration 部分。

在 HomeAssistant 服务器上安装并运行

如果您有一个 HomeAssistant 服务器,Codex 可以 通过以下步骤安装:

作为原生应用程序安装并运行

您也可以使用 pip 将 Codex 作为原生安装的 python 应用程序运行。

二进制依赖项

在安装 Codex 之前,您需要为平台安装相应的系统依赖项。

Linux 依赖项
Debian 依赖项

...以及 Ubuntu, Mint, MX, Window Subsystem for Linux 和其他。

apt install build-essential libimagequant0 libjpeg-turbo8 libopenjp2-7 libssl3 libyaml-0-2 libtiff6 libwebp7 python3-dev python3-pip sqlite3 unrar zlib1g

像 libjpeg、libssl、libtiff 这样的软件包版本,可能因发行版的不同风味和版本而异。如果上述示例中列出的软件包版本不可用,请尝试使用 apt-cacheaptitude 搜索可用的版本。

apt-cache search libjpeg-turbo
Alpine 依赖
apk add bsd-compat-headers build-base jpeg-dev libffi-dev libwebp openssl-dev sqlite yaml-dev zlib-dev
在非 Debian Linux 上安装 unrar 运行时依赖

Codex 需要 unrar 来读取 CBR 格式的漫画归档文件。Unrar 通常未为 Linux 提供软件包,但以下是一些说明: 如何在 Linux 中安装 unrar

Alpine Linux v3.14 中打包的 Unrar 似乎在 Alpine v3.15+ 上可以正常工作

macOS 依赖项

使用 Homebrew:

brew install jpeg libffi libyaml libzip openssl python sqlite unrar webp

Windows 安装

建议 Windows 用户使用 Docker 来运行 Codex,但它也可以在 Windows 子系统 for Linux 上原生运行。

安装说明位于 原生 Windows 依赖项安装文档

原生运行 Codex

安装 codex 后,codex 二进制文件应位于你的路径中。要启动 codex,请运行:

codex

使用 Codex

安装并运行后,您可以导航至 http://localhost:9810/

👑 管理

导航至管理面板

  • 点击汉堡菜单 ☰ 以打开浏览器设置抽屉。
  • 以 'admin' 用户身份登录。默认管理员密码也是 'admin'。
  • 登录后,点击浏览器设置抽屉中的链接,导航至管理面板。

更改管理员密码

您应该做的第一件事是以管理员用户身份登录并更改管理员 密码。

  • 如上所述导航至管理面板。
  • 选择 Users 选项卡。
  • 使用小锁按钮更改管理员用户的密码。
  • 您也可以使用编辑按钮更改管理员用户的名称。
  • 您可以创建其他用户并通过将其设为 staff 来授予他们管理员权限。

添加漫画库

您想要做的第二件事是以管理员身份登录并添加一个 或多个漫画库。

  • 如上所述导航至管理面板。
  • 在管理面板中选择 Libraries 选项卡
  • 使用左上角的 "+ LIBRARY" 按钮添加一个库。

重置管理员密码

如果您忘记了所有超级用户密码,您可以通过设置 CODEX_RESET_ADMIN 环境变量 并运行 codex 来恢复原始默认 管理员账户。

CODEX_RESET_ADMIN=1 codex

或者,如果使用 Docker:

docker run -e CODEX_RESET_ADMIN=1 -v host-parent-dir/config:/config ghcr.io/ajslater/codex

💾 备份与恢复用户数据

Codex 的主 SQLite 数据库(codex.sqlite3)包含两种截然不同的数据: 漫画元数据,始终可以通过重新扫描您的库来重建; 以及 用户 数据——账户、书签、收藏、浏览器设置、库 定义、管理员标志——这些数据无法重建。为了让第二类数据在 数据库丢失或重建后得以保留,Codex 会将所有与用户绑定的行快照到一个单独的 SQLite 文件中:用户数据伴随文件

它的位置

<CODEX_CONFIG_DIR>/user_data.sqlite

— 紧邻 codex.toml

包含内容

用户(含哈希密码)、组与权限、组成员关系、 书库及其访问列表、书签、收藏夹、每用户浏览器 设置、管理员标志、时间戳,以及在线标记默认值。

它刻意镜像任何可从文件系统 重新扫描中推导出的内容:漫画、出版商、系列、卷、文件夹、故事弧、标签、 演职员表、全文搜索索引。这些会在图书管理员 重新导入你的书库时自行重建。

创建快照

侧车文件会持续更新。快照会在以下时机创建:

  • 每晚自动执行,作为现有 Janitor 清理的一部分(紧随 数据库备份之后);以及
  • 按需执行,当你点击管理面板的 恢复 选项卡上的 立即快照,或从任务选项卡运行 Snapshot User Data Sidecar 时。

每个快照替换之前的内容——该文件始终是主数据库的 真实时间点镜像,而非部分日志。

异地备份

user_data.sqlite 复制到安全位置。该文件是一个自包含的 SQLite 数据库;从它恢复时不需要伴随文件( -wal/-shm 同级文件,如果存在,可以留在原地)。

你可以在 Codex 运行时复制它,但为了最干净的备份,请先 创建新快照(恢复选项卡 → 立即快照),然后复制该文件。

恢复

两条等效路径:

从管理面板: 打开 Restore 选项卡并点击 Restore Now。 dry-run 选项会报告 将会 发生什么,而不会写入。

从命令行:

codex restore_user_data            # default sidecar in CODEX_CONFIG_DIR
codex restore_user_data --dry-run  # report only
codex restore_user_data --from /path/to/another/user_data.sqlite

两条路径都是幂等的:在已恢复的数据库上重新执行恢复操作是安全的。目标无法解析的行(已删除的漫画、已重命名的标签)会被记录到配置目录中的 restore_user_data.log 并跳过——该操作绝不会中止。

迁移到新主机

  1. 在旧主机上,获取一个新的快照(恢复选项卡 → 立即快照)。
  2. 停止旧的 Codex。
  3. user_data.sqlite 复制到新主机的配置目录。
  4. 在新主机上启动 Codex,并将您的漫画挂载到相同的库路径。
  5. 让图书管理员完成初始文件系统扫描,然后运行 codex restore_user_data(或在管理面板中点击 立即恢复)。

书签通过漫画路径重新关联,收藏通过集合名称链(例如 出版社 → 印记 → 系列),标签过滤器通过标签名称。只要您的 库路径和标签名称匹配,所有内容都会重新关联。

私有库

在管理面板中,您可以配置仅特定组可访问的私有库。

没有 任何 组的库对所有用户(包括匿名 用户)可访问。

具有 任何 组的库仅对属于这些组的用户可访问。

使用组管理面板创建组,并使用用户管理面板将用户 添加到组中或从组中移除。

包含和排除组

Codex 可以为库创建组,以排除某些用户组,或排除 所有人并仅包含某些用户组。

PDF 元数据

Codex 从文件名、PDF 元数据字段以及嵌入在 PDF keywords 字段中的许多常见复杂漫画元数据格式中读取 PDF 元数据。

如果你决定在漫画库中包含 PDF,我建议花些时间重命名文件,以便 Codex 能够找到一些元数据。Codex 识别多种文件命名方案。以下方案效果良好:

{series} v{volume} #{issue} {title} ({year}) {ignored}.pdf

复杂的漫画元数据,例如 ComicInfo.xml,也可以通过 comicbox 命令行工具嵌入到 keywords 字段中。Codex 会读取这些数据,因为它内部依赖于 comicbox。 很少有人以这种方式使用 comicbox 或在 PDF 中嵌入元数据,因此除非您自己添加了它,否则您很可能找不到它。

🗝️ 带密钥访问的 API

Codex 提供有限数量的可通过 API 密钥访问的 API 端点。 API 密钥可在 admin/stats 选项卡上获取。

📧 电子邮件与密码重置

默认情况下,Codex 没有出站电子邮件,并且“忘记密码?”链接是 隐藏的。要启用自助密码重置,请在管理 面板的 Email 选项卡中配置 SMTP — 无需重启即可编辑。您必须至少设置一个主机 以及一个发件人地址或用户;在此之前,该功能保持关闭状态,并且 重置端点返回 404。

codex.toml 中的 [email] 部分(以及 CODEX_EMAIL_* 环境变量)已弃用:这些值仅在升级时导入一次, 否则仅用于初始化初始管理员设置。请参阅 下方的 完整 codex.toml 参考

特定提供商的注意事项:

  • Gmail:需要一个 16 位的应用密码(常规密码会被 Google 的 SMTP 拒绝)。账户 → 安全性 → 应用密码。使用 port = 587use_tls = true,并将 from_address 设置为与 user 相同的地址。
  • Amazon SESfrom_address 必须是已验证的 SES 身份(域名或 地址)。请使用 SES 控制台中的 SMTP 凭据,而不是直接使用 IAM 密钥。
  • Mailgun / SendGrid / 通用 SMTP 中继:通常接受 user 作为 经过身份验证的发件人;当 from_address 为空时,默认使用该值。

如果启用了 register_verification(管理 → 标志 → “验证新用户邮箱”), 新注册用户将收到一封激活邮件,并在点击链接之前保持未激活状态。在配置邮件(SMTP)之前,此功能不生效。

在此功能之前创建的现有用户没有记录邮箱地址,因此无法请求重置;管理员可以在用户管理选项卡中补填地址,或者用户 可以通过个人资料(用户菜单)自行设置。

🎛️ 配置

配置目录

默认配置目录是 config/,直接位于你运行 codex 的工作目录下。你可以使用 环境变量 CODEX_CONFIG_DIR 指定另一个配置目录。

配置目录中包含一个名为 codex.toml 的文件,你可以在其中指定 端口和绑定地址。如果不存在 codex.toml,Codex 会在启动时将该目录下的默认文件复制过去。例如:

[server]
host = "0.0.0.0"
port = 9810
url_path_prefix = ""

配置目录还包含主 sqlite 数据库、user_data.sqlite sidecar(参见 备份与恢复用户数据)、 Django 缓存以及漫画封面缩略图。

完整 codex.toml 参考

所有可用选项及其默认值。取消注释以进行覆盖。Codex 在首次启动时,如果该文件尚不存在, 会将其写入配置目录。

自 v2.0.0 起已弃用: [browser][throttle][email] 部分(及其对应的 CODEX_* 环境变量)现在由管理面板管理 —— 在 设置 选项卡中管理浏览器页面大小和速率限制,在 邮件 选项卡中管理 SMTP —— 并且可以在不重启的情况下进行编辑。此处 的值仅在升级时导入一次,否则仅用于初始化 Admin 设置。[server][logging][cache][auth] 部分 仍在此处配置。

# Codex Configuration File
# Copy to config/codex.toml and edit as needed.
# Environment variables override values in this file.
# See README.md for full documentation.

# [server]
# Granian ASGI server settings
# host = "0.0.0.0"
# port = 9810
# Number of worker processes. 1 is recommended for containerized environments.
# workers = 1
# HTTP version: "auto", "1", or "2"
# http = "auto"
# Enable websockets (required for Codex live updates)
# websockets = true
# HTTP path prefix for codex (e.g. "/codex" for reverse proxy sub-path)
# url_path_prefix = ""

# [logging]
# Log level: TRACE, DEBUG, INFO, SUCCESS, WARNING, ERROR, CRITICAL
# loglevel = "INFO"
# log_retention = "6 months"
# log_to_console = true
# log_to_file = true
# Directory for log files. Defaults to <config_dir>/logs.
# log_dir = ""

# [cache]
# Directory for the file-based cache (covers, query results, etc).
# Defaults to <config_dir>/cache.
# dir = ""

# [browser]
# Deprecated: now set on the Admin Settings tab (seeds the initial default).
# max_obj_per_page = 100

# [throttle]
# Deprecated: now set on the Admin Settings tab (seeds initial defaults).
# Rate limiting (requests per minute). 0 = disabled.
# anon = 0
# user = 0
# opds = 0
# opensearch = 0
# Password reset requests per hour, per IP. Defaults to 5.
# reset_password = 5

# [email]
# Deprecated: now set on the Admin Email tab (seeds initial defaults).
# SMTP configuration for outbound email. When unset, password-reset and
# email-verification features stay disabled and the related endpoints
# respond 404. Set `host` AND `from_address` (or `user`) to enable.
#
# IMPORTANT: codex.toml stores credentials in plain text. Restrict file
# permissions (chmod 600) and consider environment variable overrides
# (CODEX_EMAIL_PASSWORD) for secrets management systems.
#
# host = ""
# port = 587
# user = ""
# password = ""
# use_tls = true
# use_ssl = false
# timeout = 10
# Sender address. If blank, `user` is used as the From address. Many
# providers accept the auth user as sender; SES and similar require an
# explicit verified identity here.
# from_address = ""
# subject_prefix = "[Codex] "

# [auth]
# Allows authentication without authorization via the Remote-User header.
# Only enable if you have authorization in front of Codex. Dangerous.
# remote_user = false
# Log failed login attempts to a separate file. Useful as input for
# banning tools like fail2ban, CrowdSec, or sshguard.
# Line format: "<ISO timestamp> | Failed login from <ip> user=<username>"
# Example fail2ban failregex:
#   ^\s*\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \| Failed login from <HOST> user=.*$
# failed_login_log = false
# Path to the failed-login log. Defaults to <log_dir>/failed_logins.log.
# failed_login_log_path = ""
# When behind a reverse proxy, trust X-Forwarded-For for the client IP.
# Disable if Codex is exposed directly (otherwise clients can forge their IP).
# failed_login_log_trust_forwarded_for = true

环境变量

环境变量会覆盖 TOML 配置文件中设置的值。

通用

  • TIMEZONETZ 会以长格式显式设置时区(例如 "America/Los Angeles")。这在 Docker 内部很有用,因为 codex 无法 自动检测宿主机的时区。
  • DEBUG_TRANSFORM 将显示关于 comicbox 库如何 读取所有归档元数据源并将其转换为 comicbox 架构的详细信息。
  • CODEX_CONFIG_DIR 将设置 codex 配置目录的路径。默认为 $CWD/config
服务器
  • GRANIAN_HOST 用于提供 Codex 服务的 IP 或主机名。默认为 "0.0.0.0", 即所有接口。
  • GRANIAN_PORT 用于提供 Codex 服务的端口。默认为 9810。
  • GRANIAN_WORKERS 工作进程数量。建议容器化 环境使用 1。
  • GRANIAN_HTTP 要使用的 HTTP 协议。"auto"、"1" 或 "2"。默认为 "auto"。 通常你希望从 nginx 或 traefik 后面提供 codex 服务,由它们 处理协议,即使是 HTTP 3,因此此项应保持为 "auto"。
  • GRANIAN_WEBSOCKETS 启用 WebSocket。codex 实时更新所必需。 默认为 true。
  • GRANIAN_URL_PATH_PREFIX codex 的 HTTP 路径前缀(例如用于 反向代理子路径的 "/codex")。默认为 ""。
修复
  • CODEX_RESET_ADMIN=1 将在 codex 启动时将管理员用户及其密码重置为默认值。
  • CODEX_FIX_FOREIGN_KEYS=1 将在启动时检查并尝试修复非法的外键。
  • CODEX_INTEGRITY_CHECK=1 将在启动时执行数据库完整性检查。
  • CODEX_FTS_INTEGRITY_CHECK=1 将对全文 搜索索引执行完整性检查。
  • CODEX_FTS_REBUILD=1 将重建全文搜索索引。

日志

  • LOGLEVEL 将更改 codex 日志的详细程度。有效值为 CRITICALERRORWARNINGSUCCESSINFODEBUG 以及过于 嘈杂的 TRACE。默认值为 INFO
  • CODEX_LOG_DIR 设置用于保存日志文件的自定义目录。默认为 $CODEX_CONFIG_DIR/logs
  • CODEX_LOG_RETENTION 日志保留时长。默认为 "6 months"。
  • CODEX_LOG_TO_FILE=0 不记录到文件。
  • CODEX_LOG_TO_CONSOLE=0 不记录到控制台。

Cache

  • CODEX_CACHE_DIR 设置基于文件的缓存(Django 缓存条目和漫画封面缩略图)的自定义目录。默认为 $CODEX_CONFIG_DIR/cache。适用于将缓存放置在配置目录其余部分之外的独立(例如 更快或临时)卷上。
Browser

Deprecated: 请改为在 Admin Settings 选项卡中设置 Browser Page Size; 此设置仅用于初始化默认值。

  • CODEX_BROWSER_MAX_OBJ_PER_PAGE 每页的最大对象数量。 默认为 100。

Throttling

Deprecated: 请改为在 Admin Settings 选项卡中设置速率限制;这些 变量仅用于初始化默认值。

Codex 包含一些实验性的限流控制。提供给 这些变量的值将被解释为每分钟允许的最大请求 数。例如,以下设置将限制每个描述的组 为每秒 2 个查询。

  • CODEX_THROTTLE_ANON=30 匿名用户
  • CODEX_THROTTLE_USER=30 已认证用户
  • CODEX_THROTTLE_OPDS=30 OPDS v1 和 v2 API(Panels 使用此进行搜索)
  • CODEX_THROTTLE_OPENSEARCH=30 OPDS v1 Opensearch API

Authentication

  • CODEX_AUTH_REMOTE_USER 允许通过 Remote-User HTTP 头进行未认证登录。如果未正确配置,这可能会非常不安全。 请阅读下方专门介绍 Remote-User 的文档。
  • CODEX_AUTH_FAILED_LOGIN_LOG=1 会将每次失败的登录尝试(表单 登录和 OPDS Basic 认证)追加到一个单独的日志文件中,供 fail2ban、CrowdSec 或 sshguard 等封禁 工具使用。默认禁用。参见 Failed-Login Log 部分。
  • CODEX_AUTH_FAILED_LOGIN_LOG_PATH 覆盖失败登录日志的路径。 默认为 $CODEX_LOG_DIR/failed_logins.log
  • CODEX_AUTH_FAILED_LOGIN_LOG_TRUST_FORWARDED_FOR=0 使失败登录日志 使用 REMOTE_ADDR 而不是最左侧的 X-Forwarded-For 条目。默认值为 1(信任 XFF),当 Codex 位于反向代理后面时这是正确的。当 Codex 直接暴露时,请设置 为 0,以防止客户端伪造 X-Forwarded-For 来污染日志。
  • OIDC 单点登录没有环境变量或 TOML 键——它在 Admin UI 的 Auth 选项卡下配置。参见 OIDC Single Sign On 部分。

Reverse Proxy

nginx 常被用作 TLS 终结器和子路径代理。

以下是一个名为 '/codex' 的子路径的 nginx 配置示例。

# Only send "Connection: upgrade" for real WebSocket requests; plain HTTP
# requests get "Connection: close". This map must live in the http {} block.
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# Use "^~" so this prefix wins over any regex location (e.g. a shared
# "location ~* \.(js|css|...)$" or "/static" block common in multi-app /
# Organizr / SWAG setups). Without "^~", such a regex hijacks requests like
# /codex/static/assets/*.js and returns 404 even though Codex serves them
# correctly, giving a blank page with a working favicon. See GitHub #784.
location ^~ /codex {
    proxy_pass         http://codex:9810;
    # HTTP
    proxy_set_header   Host $http_host;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
    proxy_set_header   X-Forwarded-Port $server_port;
    proxy_set_header   X-Forwarded-Proto $scheme;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Scheme $scheme;
    # Websockets (Codex live updates)
    proxy_http_version 1.1;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Connection $connection_upgrade;
    # Codex reads http basic authentication.
    # If the nginx credentials are different than codex credentials use this line to
    #   not forward the authorization.
    proxy_set_header   Authorization "";
}

config/codex.toml 中指定反向代理子路径(如果有的话)

[server]
url_path_prefix = "/codex"

如果你在 /codex 位置前放置一个带身份验证的反向代理(Organizr、Authelia 等),并使用 auth_request,请按照 Codex 自身的示例那样豁免 API(location /codex/api { auth_request off; ... });上述的 ^~ 注释正是确保静态资源可访问的原因。

容器刷新时 Nginx 反向代理出现 502

当关联的 Docker 容器重新创建时,Nginx 需要一种特殊技巧来刷新 DNS。请参阅这篇 nginx with dynamix upstreams 文章。

单点登录和第三方身份验证

OAuth 和 OIDC

Codex 是一个原生 OIDC 客户端。将其指向一个身份提供商,例如 AuthentikAuthelia 登录对话框和未授权屏幕上会出现一个“使用 … 登录”按钮。(tinyauth 不是 OIDC 提供商——tinyauth 用户应改用下面的 Remote-User 方法。)

在管理 UI 的 Auth 选项卡下配置——OIDC 没有 TOML 键或环境变量。至少设置 Provider Name(登录按钮标签)、issuer Server URL(发现信息从 <server-url>/.well-known/openid-configuration 获取)以及 Client ID,然后打开启用开关;客户端密钥在静态存储时是加密的。Test Connection 按钮会获取提供者的发现文档,并在您提交配置之前报告其通告的端点。每次更改都会在下一个请求时生效——无需重启。该选项卡还包含用户映射设置(用户名声明、自动配置、电子邮件链接、组同步、管理员组)以及 RP 发起的注销,所有这些都已在行内文档中说明。

在您的身份提供者处注册此重定向 URI(如果您使用 url_path_prefix,请包含它):

https://your-host[/url_path_prefix]/sso/oidc/login/callback/

身份映射。 用户以稳定的 OIDC sub 声明作为键。在首次 登录时,Codex 会将该登录与具有相同用户名的现有本地用户关联 (如果启用了 Link by Email,则还会通过电子邮件关联);否则,如果启用了 Create Users on First Login,则创建新用户。启用 Sync Groups 后,身份 提供者的 groups 声明将在每次登录时替换用户的 Codex 组——仅匹配 现有的 Codex 组,绝不创建新组——因此 IdP 组可以驱动 Codex 库访问控制。 Admin Group 成员被授予(并在声明中不存在时 撤销)Codex 管理员权限。

⚠️ 用户名关联包括管理员账户:名为 admin 的身份提供者用户将关联到 Codex 内置的 admin 账户。仅针对 您控制其用户名命名空间的身份提供者启用 OIDC,并且无论如何都要更改默认 管理员密码。 ⚠️

提供者说明。

  • Authentik: 创建一个 OAuth2/OpenID 提供者 + 应用程序。默认 openid profile email 范围可直接使用;groups 包含在 profile 范围内。RP 发起的登出功能可用。
  • Authelia:identity_providers.oidc 中将 Codex 注册为客户端,并使用 哈希化的客户端密钥。保持 Fetch Userinfo 开启(Authelia 仅从 userinfo 端点提供用户名和 电子邮件声明),并为组同步在范围中添加 groups。Authelia 未实现 RP 发起的登出;请保持关闭。

须知。

  • 客户端密钥在管理界面中输入,并在静态存储时加密保存——它 绝不会出现在 codex.toml 或 API 响应中。
  • Codex 会话有效期为 60 天;在身份提供商处禁用用户 并不会结束其现有的 Codex 会话。请在 Codex 中也停用该用户,或 通过将其登出以降低 SESSION_COOKIE_AGE 等效暴露风险。
  • 通过 OIDC 创建的用户没有本地密码,因此 OPDS 阅读器无法 对他们使用 HTTP Basic 认证。请使用每用户 API 令牌(侧边栏中的用户资料) 用于 OPDS,或设置一个本地密码。
  • 升级后首次启动时,Codex 会应用几个用于 OIDC 账户关联 和设置单例的小型新数据库表。
  • 当启用时,OIDC 登录失败会记录在 Failed-Login Log 中。
Remote-User 认证

Remote-User 认证指示 Codex 接受来自 Web 服务器的用户名, 并假定认证已经完成。如果未在 Codex 前面配置认证反向代理, 这非常不安全。这是像 tinyauth 这样的 forward-auth 网关的正确方法,并且也适用于 Authelia 的 auth_request 模式和 Authentik 的 proxy outpost。

以下是针对 tinyauth 情况的完整 nginx location,假设 tinyauth 服务器本身已配置完成并可在 tinyauth:3000 处访问:

# In the http {} block (shared with the WebSocket map above).
# The internal auth endpoint nginx consults for every request.
location = /tinyauth {
    internal                ;
    proxy_pass              http://tinyauth:3000/api/auth/nginx;
    proxy_set_header        Host $host;
    proxy_set_header        X-Original-URL $scheme://$http_host$request_uri;
    proxy_pass_request_body off;
    proxy_set_header        Content-Length "";
}

location ^~ /codex {
    auth_request     /tinyauth;
    # Pass the authenticated username to Codex, OVERRIDING anything the
    # client sent. Never pass the client's own Remote-User through.
    auth_request_set $remote_user $upstream_http_remote_user;
    proxy_set_header Remote-User $remote_user;
    proxy_pass       http://codex:9810;
    # ... the same proxy_set_header / WebSocket lines as the
    # Reverse Proxy example above ...
}

等效的 Traefik 中间件(forwardAuth 配合 authResponseHeaders: [Remote-User])或 Caddy 指令(forward_auth 配合 copy_headers Remote-User)工作方式相同:代理进行身份验证,然后 向 Codex 注入 Remote-User

然后在 Codex 中通过 CODEX_AUTH_REMOTE_USER=1 或以下方式启用:

[auth]
remote_user = true

⚠️ 仅当你的 webserver 每次都会为 Codex 位置自行设置 Remote-User 头,从而覆盖任何可能自行设置该头的恶意客户端时,才开启 CODEX_AUTH_REMOTE_USER 环境变量。 ⚠️

forward-auth 部署检查清单:

  • 认证网关必须覆盖 Codex 位置的全部——包括 /opds/ 和 WebSocket 路径 /api/v4/ws——而不仅仅是 HTML 页面。如果你为阅读器应用豁免了 OPDS, 这些请求将回退到 Codex 自身的 Basic/token 认证,这是可以接受的。
  • 带有客户端伪造的 Remote-User 头且没有代理认证的请求必须被 拒绝或该头被覆盖(使用 curl -H "Remote-User: admin" 进行测试)。
  • Remote-User 和 OIDC 可以同时启用;它们是通往正常 Codex 会话的 独立路径。
HTTP Token Authentication

你也可以配置代理,在请求头中添加 token 认证。 Codex 会读取以 “Bearer” 为前缀的授权 token。该 token 对 每个用户都是唯一的,可以在侧边栏访问的用户资料中找到。你 必须配置代理或单点登录软件来发送此 token。

set              user_token 'user-token-taken-from-web-ui';
proxy_set_header Authorization "Bearer $user_token";

登录失败日志

Codex 可以将每次登录失败尝试以易于 IP 封禁工具(fail2ban、CrowdSec、sshguard 等)解析的格式追加到专用日志文件中。 该功能默认关闭。通过设置 CODEX_AUTH_FAILED_LOGIN_LOG=1 或在 codex.toml 中启用:

[auth]
failed_login_log = true
# failed_login_log_path = ""                       # defaults to <log_dir>/failed_logins.log
# failed_login_log_trust_forwarded_for = true      # set false if exposed directly

单个信号接收器同时覆盖 /api/v4/auth/login 处的表单登录和 OPDS HTTP Basic 认证——无需为每个端点单独配置。包含 IP 的行 写入 failed_logins.log;主 codex.log 仍会记录 Django 标准的 "Unauthorized: /api/v4/auth/login"(或 "Forbidden: ...") WARNING 日志,针对同一请求,因此即使主日志中不包含客户端 IP, 也能看到该失败。这使得 PII(IP + 用户名)集中存储在一个文件中, 你可以对其执行 chmod、转发到 SIEM,或按独立策略保留。

每行看起来像:

2026-05-10 12:34:56 | Failed login from 192.168.1.42 user=alice

X-Forwarded-For 信任

客户端 IP 取自最左侧的 X-Forwarded-For 条目(当 failed_login_log_trust_forwarded_for = true(默认值)时),否则回退到 REMOTE_ADDR。当 Codex 位于设置该请求头的反向代理之后时(典型的 Docker 部署),此行为是正确的。

如果 Codex 直接暴露在其端口上,请设置 failed_login_log_trust_forwarded_for = false — 否则客户端可以设置 自己的 X-Forwarded-For: 8.8.8.8,而您的封禁工具将会封禁该地址 而非真实的攻击者。

fail2ban 过滤器示例

/etc/fail2ban/filter.d/codex.conf:

[Definition]
failregex = ^\s*\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \| Failed login from <HOST> user=.*$
ignoreregex =

/etc/fail2ban/jail.d/codex.conf:

[codex]
enabled  = true
filter   = codex
logpath  = /path/to/codex/config/logs/failed_logins.log
maxretry = 5
findtime = 10m
bantime  = 1h

在启用 jail 之前,使用 fail2ban-regex 针对真实日志验证该过滤器:

fail2ban-regex /path/to/codex/config/logs/failed_logins.log /etc/fail2ban/filter.d/codex.conf

受限内存环境

Codex 可以在仅有 1GB 可用 RAM 的情况下运行。大型批处理任务——例如一次性导入和索引数万本漫画——在 Codex 可用内存越多时运行速度越快。当内存增加到约 6GB 时,速度提升最为显著。当 Codex 的内存超过 6GB 时,批处理任务速度仍会提升,但收益递减。

如果你必须在管理员受限的内存环境中运行 Codex,你可能希望暂时为 Codex 分配大量内存以运行非常大的导入任务,然后在正常操作时将其限制。

📖 使用

👤 会话与账户

一旦你的管理员添加了一些漫画库,你就可以浏览和阅读漫画。Codex 会在浏览器会话中记住你的偏好设置、书签和进度。Codex 会在 60 天后销毁匿名会话和书签。为了在浏览器之间以及会话过期后保留这些设置,你可以使用用户名和密码注册一个账户。如果你忘记了密码,你必须联系你的管理员来重置密码。

ᯤ OPDS

Codex 支持 OPDS 联合和 OPDS 流媒体。你可以在侧边抽屉中找到 OPDS url。它应该采用以下形式:

http(s)://host.tld(:9810)(/path_prefix)/opds/v1.2/

http(s)://host.tld(:9810)(/path_prefix)/opds/v2.0/

OPDS v1 客户端

Kybook 3 似乎不支持 http 基本身份验证,因此 Codex 用户 不受支持。

OPDS v2 客户端

  • iOS & macOS

    • Stump - 技术上是一个 Alpha 版本,但稳定且功能丰富。
  • 多平台移动 & 桌面

  • 桌面

OPDS 身份验证

OPDS 登录

少数实现了 OPDS 1.0 身份验证规范的客户端会向用户 展示一个登录界面以进行交互式身份验证。

HTTP Basic

一些 OPDS 客户端允许在其 OPDS 服务器设置中配置 HTTP Basic 身份验证。如果没有,您将不得不将用户名和密码 添加到 URL 中。在这种情况下,OPDS url 将如下所示:

http(s)://username:password@codex-server.tld(:9810)(/path_prefix)/opds/v1.2/

HTTP Token

某些客户端允许在 HTTP 请求头中添加唯一的登录令牌。Codex 将 读取带有 "Bearer" 前缀的授权令牌。该令牌对每个用户都是唯一的, 可以在 Web UI 侧边栏中找到。

支持的 OPDS 规范

OPDS v1
OPDS v2
OpenSearch v1

🩺 故障排查

📒 日志

Codex 将其日志收集在 config/logs 目录中。查看该目录以了解 服务器正在执行的操作。

您可以通过设置 LOGLEVEL 环境变量来更改 codex 的日志记录量。默认情况下,该级别为 INFO。要查看更详细的消息,请像这样运行 codex:

LOGLEVEL=DEBUG codex

使用 Docker 监听文件系统事件

Codex 会尝试监听文件系统事件,以便在磁盘上的漫画库发生变化时立即更新。但是,这些原生文件系统事件不会在 macOS 和 Windows 的 Docker 主机与 Docker Linux 容器之间进行转换。 如果您发现您的安装无法立即响应文件系统变化,您可以尝试为受影响的库启用轮询,并将管理控制台中的 poll_every 值降低到适合您的频率。

紧急数据库修复

如果数据库损坏,Codex 包含一个重建数据库的功能。请在您的 Codex 配置目录中放置一个名为 rebuild_db 的文件, 如下所示:

touch config/rebuild_db

关闭并重启 Codex。

下次 Codex 启动时,它将备份现有数据库并尝试 重建它。数据库位于配置目录中,文件名为 config/codex.sqlite3。如果此过程失败,您可以在 config/backups/codex.sqlite3.before-rebuild.bak 处恢复 原始数据库。Codex 将删除 rebuild_db 文件。

可忽略的警告

StreamingHttpResponse 迭代器警告

packages/django/http/response.py:517: Warning: StreamingHttpResponse must consume synchronous iterators in order to serve them asynchronously. Use an asynchronous iterator instead.

这是一个已知的警告,并不代表发生了任何不良情况。它是 Django 框架逐步支持异步服务器端点所带来的产物,目前尚不便于移除。

📚Codex 的替代方案

  • Kavita 具有轻量的元数据过滤/编辑功能, 支持漫画、电子书,并具备漫画(manga)相关功能。
  • Komga 具有轻量的元数据编辑和重复页面 消除功能。
  • Ubooquity 可以阅读漫画和电子书。

🔧 流行的漫画工具

  • Mylar 是最佳的漫画管理器, 并且内置了阅读器。
  • Comicbox 是一个强大的命令行漫画 元数据编辑器、多源在线标签工具和多元数据格式 合成器。它是 Codex 底层用于读取漫画元数据的工具。
  • Metron Tagger 是一个命令行 漫画元数据编辑器。它会从在线数据库 源为已识别的漫画添加标签。
  • Comictagger 是一个漫画元数据 编辑器。它附带命令行和桌面 GUI。它会从在线数据库源 为已识别的漫画添加标签。

🤝 贡献

🐛 错误报告

问题和功能请求最好在 Github issue tracker 上提交。

💬 支持

我和其他 Codex 用户会在 Codex Comic Server Discord 上回答问题

🛠 开发

Codex 的 git 仓库镜像在 Github

Codex 是一个带有 VueJS 前端的 Django Python Web 服务器。

/codex/codex/ 是提供 Web 服务器和 数据库的主 Django 应用。

/codex/frontend/ 是 vuejs 前端所在的位置。

目前 Codex 的大部分开发工作都通过 Makefile 进行控制。输入 make 可查看命令列表。

🔗 链接

🙏🏻 致谢

  • 感谢 Aurélien Mazurie 允许我 使用 PyPi 名称 'codex'。
  • 感谢 ProfessionalTart 提供 原生 Windows 安装说明。
  • 感谢 Mylar 的友好人士 持续提供反馈以及漫画生态系统教育。

😊 享受

These simple people have managed to tap into the spiritual forces that mystics and yogis spend literal lifetimes seeking. I feel... ...I feel...