Skip to content

Sena Repo 服务端部署说明书 ​

CAUTION

Sena Repo 由 AI 辅助开发,安全性未经过专业审计。强烈建议仅在 VPN 或家庭内网环境中使用,不建议直接暴露到公网。

目录 ​


部署前准备 ​

目录结构 ​

Sena Repo 按固定层级扫描游戏文件,部署前请先整理好文件:

游戏目录/
  ├── 会社A/
  │   ├── 游戏1/
  │   │   ├── [PC]游戏1.rar
  │   │   └── [KRKR]游戏1_v2.zip
  │   └── 游戏2/
  │       └── [Ty]游戏2.7z
  └── 会社B/
      └── 游戏3/
          └── 直装_游戏3.apk
层级内容
第一级会社文件夹(文件夹名即会社名)
第二级游戏文件夹(文件夹名即游戏名)
第三级压缩包(.rar .zip .7z .tar .gz .xz .apk)
  • 平台标记:[PC] [KRKR] [Ty] [ONS] 直装_,无标记默认 PC
  • 压缩包直接放在会社目录下也可以,自动视为独立游戏

文件不按规则整理则扫不出来。也可以在设置中调整目录结构为"仅游戏"或"扁平"模式。

如果游戏库和 Steam 补丁库都使用 OpenList 作为文件来源,服务端本地无需挂载实际的 /games 和补丁文件目录。补丁索引与关键词配置都写在数据目录下的 steam_patch_index/,只要 /data 是持久化挂载即可。

Steam 补丁目录结构 ​

steam_patch/                      ← 补丁压缩包目录(本地类型的补丁库)
├── 游戏1_Steam_Chinese_Patch.7z
└── 游戏2_Steam_Voice_Patch.rar

data/steam_patch_index/           ← 索引目录,位于数据目录内
├── patches.json                  ← 自动生成,记录所有补丁与匹配规则
└── patch_type_keywords.json      ← 补丁类型识别关键词配置

服务端部署 ​

方式一:Docker 拉取(推荐) ​

Release 发布时镜像自动推送到 DockerHub 和 GHCR,同时支持 amd64 和 arm64。

bash
# DockerHub(推荐)
docker pull 404gcross/sena-repo:latest

# GHCR(备用)
docker pull ghcr.io/404-gcross/sena-repo:latest

# Pre-release 预发布版(发布 beta / rc 时更新)
docker pull 404gcross/sena-repo:pre-release

# Dev 开发版
docker pull 404gcross/sena-repo:dev

基础启动:

bash
docker run -d \
  --name sena-repo \
  -p 11451:11451 \
  -v /path/to/games:/games \
  -v /path/to/data:/data \
  -v /path/to/steam_patches:/steam_patch \
  --restart unless-stopped \
  404gcross/sena-repo:latest

纯 OpenList 启动(游戏文件全在 OpenList 上):

bash
docker run -d \
  --name sena-repo \
  -p 11451:11451 \
  -v /path/to/data:/data \
  -e SENA_PATCH_DIR=/data/steam_patch \
  --restart unless-stopped \
  404gcross/sena-repo:latest

完整启动(含刮削 API Key 与代理):

bash
docker run -d \
  --name sena-repo \
  -p 11451:11451 \
  -v /path/to/games:/games \
  -v /path/to/data:/data \
  -v /path/to/steam_patches:/steam_patch \
  -e SENA_BANGUMI_TOKEN="your_token" \
  -e SENA_VNDB_TOKEN="your_token" \
  -e SENA_PROXY="http://127.0.0.1:7890" \
  --restart unless-stopped \
  404gcross/sena-repo:latest

Docker Compose:

yaml
services:
  sena-repo:
    image: 404gcross/sena-repo:latest
    container_name: sena-repo
    ports:
      - "11451:11451"
    volumes:
      - /path/to/games:/games
      - /path/to/data:/data
      - /path/to/steam_patches:/steam_patch
    environment:
      - SENA_BANGUMI_TOKEN=your_token      # 可选
      - SENA_VNDB_TOKEN=your_token         # 可选
      - SENA_PROXY=http://127.0.0.1:7890   # 可选,刮削代理
    restart: unless-stopped

纯 OpenList Docker Compose:

yaml
services:
  sena-repo:
    image: 404gcross/sena-repo:latest
    container_name: sena-repo
    ports:
      - "11451:11451"
    volumes:
      - /path/to/data:/data
    environment:
      - SENA_PATCH_DIR=/data/steam_patch
    restart: unless-stopped

Docker 镜像内置 senacli,可以直接在容器里执行本地维护命令:

bash
docker exec -it sena-repo senacli status
docker exec -it sena-repo senacli scan --scrape missing
docker exec -it sena-repo senacli useradd

Docker 部署的升级和卸载仍应在宿主机通过重新拉取镜像、停止旧容器、重建容器完成;容器内的 senacli update / senacli uninstall 只会给出操作提示,不会尝试修改宿主机。

方式二:Tarball 加载 ​

从 Releases 下载对应架构的 Sena-Repo_Server_*.tar.gz:

架构文件名
x86_64 / amd64Sena-Repo_Server_amd64_v*.tar.gz
ARM64Sena-Repo_Server_arm64_v*.tar.gz
bash
docker load < Sena-Repo_Server_amd64_v0.1.0.tar.gz
docker run -d \
  --name sena-repo \
  -p 11451:11451 \
  -v /path/to/games:/games \
  -v /path/to/data:/data \
  -v /path/to/steam_patches:/steam_patch \
  sena-repo:latest

方式三:安装脚本直接部署 ​

适合没有 Docker 的设备,例如部分 arm32 NAS、盒子或 Armbian 设备。amd64 / arm64 仍建议优先使用 Docker。

一键安装(交互式会让你选版本通道,默认开发版):

bash
# 直连
curl -fsSL https://raw.githubusercontent.com/404-GCross/Sena-Repo/main/server/install.sh | sudo bash

# 国内镜像(只在脚本地址前加前缀;源码拉取会自动跟随,直连失败时也会自动回退到镜像)
curl -fsSL https://gh-proxy.com/https://raw.githubusercontent.com/404-GCross/Sena-Repo/main/server/install.sh | sudo bash

安装时会让你选择:

  • 稳定版:最新正式版 tag
  • 测试版:最新预发布(beta / rc)tag
  • 开发版:main 分支,滚动最新(默认,直接回车)

非交互环境用 --channel 指定,例如 ... | sudo bash -s -- --channel beta;固定某个版本用 --ref(如 --ref v0.2.0)。选择结果会记入 /opt/sena-repo/.version,之后 --update / senacli update 继续沿用。

安装结束时会检测 firewalld / ufw:如果端口未放行会询问是否放行(非交互时打印手动命令)。

如果需要指定端口、数据目录或 Python 路径,可以把环境变量放到 sudo 后面:

bash
curl -fsSL https://raw.githubusercontent.com/404-GCross/Sena-Repo/main/server/install.sh | sudo SENA_PORT=11451 SENA_DATA_PATH=/var/lib/sena-repo bash

如果希望先查看脚本内容再执行:

bash
curl -fsSLO https://raw.githubusercontent.com/404-GCross/Sena-Repo/main/server/install.sh
sudo bash install.sh

也可以手动 clone 稳定版源码后运行本地脚本:

bash
git clone https://github.com/404-GCross/Sena-Repo.git
cd Sena-Repo/server
sudo bash install.sh

国内网络同样给地址加 https://gh-proxy.com/ 前缀即可,例如 git clone https://gh-proxy.com/https://github.com/404-GCross/Sena-Repo.git;先下载脚本再执行、以及带环境变量的命令也同理。

如需固定某个分支或 tag 的源码,把上面命令的 -b 与 SENA_REPO_REF 换成对应 ref 即可(例如滚动开发标签 dev-release,或正式版发布后的 v0.2.0)。

脚本当前支持带 systemd 的常见 Linux 发行版,会自动识别 apt-get、dnf、yum、zypper 或 pacman 安装 Python 编译依赖、创建 venv、写入 systemd 服务并启动服务。已覆盖 Debian / Ubuntu / Armbian、Fedora / RHEL / Rocky / AlmaLinux / openEuler、openSUSE、Arch / Manjaro 等发行版。

如果发行版不在上述包管理器范围内,脚本不会立即退出;只要系统已经手动准备好依赖,仍会继续尝试创建 venv 和安装服务。

如果系统默认 python3 低于 3.10,可以通过环境变量指定 Python:

bash
sudo SENA_PYTHON_BIN=/usr/bin/python3.11 bash install.sh

Steam 补丁压缩包探测需要 7z / 7zz / 7za。RPM 系发行版如果没有直接安装到 7z,通常需要先启用 EPEL 或手动安装 7zip / p7zip。

如果服务端已经安装,再次直接运行安装脚本时会先检查远程提交版本与本地组件:源码已是最新且组件齐全时才会跳过;检测到新提交、或发现组件缺失(例如 senacli、venv、systemd 单元)时会重新安装并重启服务。需要强制更新可使用 --update,只检查而不更新可使用 --check。

安装完成后会注册本地维护命令 senacli,常用命令如下:

bash
senacli status --roots
senacli scan
senacli scan --scrape missing
senacli clear
senacli backup
senacli backup /path/to/backup-dir
senacli backup -o /path/to/backup.zip
senacli backup --json-only
senacli restore sena-backup-20260915-153000.zip
senacli update
senacli update --channel beta
senacli update --channel release
senacli uninstall

用户管理命令:

bash
senacli users
senacli useradd
senacli username
senacli passwd
senacli useradmin
senacli userdel

useradd 在数据库没有任何用户时会创建首个服主;已有用户后默认创建普通用户,加 --admin 可创建管理员。username、passwd、useradmin 会让目标用户现有登录态失效,用户需要重新登录。clear 只清空游戏、版本和游戏标签关联,目录配置、用户、OpenList 与刮削配置会保留,然后重新扫描。

连不上怎么排查 ​

按顺序检查(把 <服务器IP> 换成实际地址)。

1. 服务在跑吗

bash
senacli status        # 确认 Service active、Bind 是 0.0.0.0:<端口>

2. 本机连通性

bash
curl -fsS http://127.0.0.1:11451/api/health    # 期望 {"status":"ok","version":"..."}
ss -tlnp | grep 11451                          # 期望 0.0.0.0:11451 LISTEN

3. 从客户端所在设备测

bash
curl -v http://<服务器IP>:11451/api/health
nc -vz <服务器IP> 11451

4. 本机能通、外面不通 → 基本都是防火墙

bash
# firewalld(Fedora / RHEL / openEuler)
sudo firewall-cmd --permanent --add-port=11451/tcp && sudo firewall-cmd --reload
# ufw(Ubuntu / Debian)
sudo ufw allow 11451/tcp

云主机还要在服务商控制台的安全组放行对应端口;局域网内注意路由器的 AP 隔离或 VLAN 隔离。

5. 客户端设置

地址要带 scheme,例如 http://<服务器IP>:11451(只有走 HTTPS 反代时才勾选 HTTPS);新服务器第一次连接会提示「服务器需要初始化」,跟着向导创建服主账号即可。

备份与恢复 ​

senacli backup / senacli restore 用于在换机、重装前导出服务端数据。默认导出成单个 zip:

sena-backup-<时间戳>.zip
├── backup.json          # 结构化数据
└── media/
    ├── covers/          # 封面
    ├── backgrounds/     # 横版背景
    └── avatars/         # 用户头像

backup.json 包含五块:

区块内容
steam_patch补丁匹配规则(AppID、游戏名、标签、类型、patch_dir、target_dir、清单确认状态)、补丁类型关键词与补丁库目录(含来源类型/来源名/分析模式)
library目录库(含来源类型/来源名/OpenList 子路径)、文件源(OpenList 地址、账号、密码、启用状态)、会社、游戏(含封面/背景路径、NSFW、VNDB/Steam/Bangumi/Hikarinagi/NextMoe ID、简介等)、版本(含平台、解压密码、校验值)、标签与关联、忽略列表
accounts用户(用户名、角色、状态、密码哈希与 salt、头像路径,以及 鲲Galgame 绑定字段与是否设置过本地密码)
settings扫描设置(自动扫描、间隔、目录结构)与刮削设置(启用的源、NextMoe 模式、各站 token / NextMoe API Key、代理)
mediazip 里包含的图片文件名清单

不含游戏文件本体和用户登录态(user_sessions);安装路径、端口、/etc/sena-repo/sena-repo.env 里的机器配置也不会跟着走,换机后需要重新设置。

备份文件里有密码哈希、解压密码、OpenList 密码与各站 token(导出时解密、导入时按目标机器的密钥重新加密),请当作敏感文件保管。

恢复时的几点行为:

  • 文件源按名字匹配:目标服务器已有同名源就复用(合并模式保留本机配置,清空重建模式按备份覆盖),缺失的会自动创建,所以目录库能被正确接回
  • 刮削/扫描设置写入后会提示重启服务端生效
  • 旧版本的备份(缺少 settings / 文件源 / 绑定字段)依然可以导入,且不会清空目标机器已有的绑定或配置
bash
# 备份到数据目录下的 backups/sena-backup/
senacli backup

# 换目录,或指定文件名
senacli backup /path/to/backup-dir
senacli backup -o /path/to/backup.zip

# 只要 JSON,不带图片和头像
senacli backup --json-only

# 只备份一部分(all 默认:游戏库 + 补丁)
senacli backup --scope library     # 仅游戏库、文件源、设置与账号
senacli backup --scope patch       # 仅补丁匹配规则与类型关键词

# 恢复(会依次询问恢复范围、已存在条目怎么处理、同名图片怎么处理)
senacli restore sena-backup-20260915-153000.zip

# 全部按默认值(全部恢复 / 合并更新 / 跳过同名图片),脚本化用
senacli restore sena-backup-20260915-153000.zip -y

恢复时的三个选择:

  1. 恢复范围:全部 / 仅补丁规则 / 仅游戏库与账号(备份里两块都有时才问)
  2. 已存在的条目:合并更新(按路径匹配,保留现有)或清空重建(先删除现有游戏库、账号与忽略列表)
  3. 同名图片:跳过已有文件或全部覆盖

恢复前会打印备份内容概览,并先把现有的 patches.json、patch_type_keywords.json 备份到 backups/sena-backup/。游戏、版本、标签按路径或名称匹配(目录库按 path、游戏按 folder_path、版本按 file_path、标签按 name),id 会重新分配;OpenList 目录库按文件源名称重新绑定,找不到同名源时跳过该目录库及其游戏并提示。

旧的 steam_patch_rules 备份(.json,只有补丁规则和关键词)仍然可以恢复。

从备份重建服务端 ​

新装一台服务端后,有两种方式导入备份:

  1. 客户端向导:连接到未初始化的服务端时,向导第一页选「导入备份」,直接上传 zip。服务端只在还没有服主时接受这种导入(POST /api/setup/import),导入完成后用备份里的账号登录。
  2. senacli:把 zip 放到服务端(或挂载目录)后执行 senacli restore <zip>,先 senacli restore <zip> -y 也可以用默认选项一把过。这条路同样适用于已完成初始化的服务端。

上传的 zip 会保留在 <data>/backups/ 下,名字形如 uploaded-<时间戳>-<随机>.zip。

已初始化的服务端还可以在客户端「设置 → 服务端 → 备份与恢复」里导出、下载和恢复备份,走的是同一套逻辑(/api/backup/*,仅管理员):导出会在 <data>/backups/sena-backup/ 生成 zip 并列在页面里,导入时可直接选恢复范围、合并或清空重建、同名图片跳过或覆盖。

默认路径:

路径说明
/opt/sena-repo/server服务端程序
/opt/sena-repo/venvPython 虚拟环境
/etc/sena-repo/sena-repo.env服务端环境变量
/var/lib/sena-repo数据库、封面、配置数据
/srv/sena-repo/games本地游戏库目录
/srv/sena-repo/steam_patchSteam 补丁目录

更新:

bash
sudo bash /opt/sena-repo/install.sh --update

更新会从配置的远程仓库和分支拉取最新服务端代码,不使用当前目录中的旧代码;数据库、游戏目录、补丁目录和环境配置会保留。

只检查是否有更新、不执行安装:

bash
sudo bash /opt/sena-repo/install.sh --check

安装脚本会记录上次使用的仓库地址和分支;未显式设置 SENA_REPO_URL / SENA_REPO_REF 时,后续检查会继续使用该记录。

卸载程序文件:

bash
sudo bash /opt/sena-repo/uninstall.sh

默认卸载会保留 /var/lib/sena-repo 和 /etc/sena-repo/sena-repo.env,避免误删数据库和配置。需要连数据库与配置一起清除时:

bash
sudo bash /opt/sena-repo/uninstall.sh --purge-data

也可以明确保留数据:

bash
sudo bash /opt/sena-repo/uninstall.sh --keep-data

不带选项且在交互终端执行时,脚本会询问是否删除;如果程序目录已经被删除但数据库或配置仍在,也会先询问。非交互执行默认保留数据,并提示使用 --purge-data。


配置参考 ​

环境变量 ​

变量说明默认值
SENA_GAMES_PATH游戏文件目录/games
SENA_DATA_PATH数据目录(数据库、封面等)/data
SENA_PATCH_DIRSteam 补丁目录/steam_patch
SENA_HOST监听地址0.0.0.0
SENA_PORT监听端口11451
SENA_PROXY刮削代理(http/socks5)空
SENA_BANGUMI_TOKENBangumi API Token空
SENA_VNDB_TOKENVNDB API Token空
SENA_NEXTMOE_API_KEYNextMoe 应用密钥(nmk_live_…)空

config.yaml(可选) ​

/data/config.yaml 可覆盖部分配置(环境变量优先级更高):

yaml
server:
  host: 0.0.0.0
  port: 11451

games_path: /games
data_path: /data
patch_dir: /steam_patch
steam_dir: ""
proxy: ""

scrapers:
  bangumi_token: ""
  vndb_token: ""
  hikarinagi_client_id: ""
  hikarinagi_client_secret: ""
  nextmoe_api_key: ""

数据目录结构 ​

/data/
├── sena_repo.db          ← SQLite 数据库
├── covers/               ← 游戏封面图
├── backgrounds/          ← 游戏背景图
├── avatars/              ← 用户头像
├── scan_settings.json    ← 扫描配置持久化
└── scraper_config.json   ← 刮削配置持久化

刮削源 ​

刮削源认证要求说明
VNDB可选 Token含游戏时长数据
Bangumi可选 Token中文元数据丰富
Steam免认证封面、背景、简介
HikarinagiClient ID / Secret中文 Galgame 资料站
NextMoe应用密钥聚合六源;独立模式,开启后禁用其他刮削源;含游戏时长(仅详情)

NextMoe 是独立的刮削模式:在客户端「扫描设置 → 刮削源」中开启 NextMoe 后,其余刮削源会自动关闭并禁用,单条目和批量刮削都只走 NextMoe。密钥在 https://developer.nextmoe.dev 控制台自助创建应用并勾选 catalog:read,免费额度为每分钟 60 次、每天 50000 次。关闭 NextMoe 后其余刮削源恢复可选。

游戏时长来自 NextMoe 详情接口的 playtimes 块(多上游并列,服务端优先取 nextmoe 聚合行、否则取票数最多的行)。由于列表接口不返回该字段,只有单条目刮削(详情)会写入平均时长,批量刮削不会写入,也不额外请求详情。

别名自动填充:VNDB(aliases)、Bangumi(infobox「别名」)、Hikarinagi(aliases)和 NextMoe(titles 中 title_kind=alias,不收缩写,机器翻译保留但排最后)会在刮削时提取别名,去重后以「、」拼接写入游戏别名(最多 5 条、200 字符)。「补全缺失」只填空,「覆盖」会替换已有别名;Steam 无别名数据。


OpenList 文件源 ​

Sena Repo 支持将 OpenList 作为游戏库或 Steam 补丁库的文件来源,添加分两步:

第一步:添加 OpenList 服务器

在「扫描设置」→「OpenList 服务器」中添加,填写:

  • OpenList 地址(客户端和服务端都能访问的地址,如 http://192.168.1.100:5244)
  • 用户名和密码(留空则使用 OpenList 访客模式)

第二步:添加目录

在「游戏库目录」或「Steam 补丁目录」中选择该 OpenList 服务器,填写 OpenList 内部路径,例如 /115/Games/GalGame/Library。目录内仍需遵守 Sena Repo 的目录结构规则。

下载链路:

客户端 → Sena /api/download/{id}
  → 302 → OpenList /d/文件路径?sign=...
  → 302 → 网盘/CDN 直链
  → 客户端直接从网盘/CDN 下载

Sena 服务端只生成跳转,不代理大文件流量。OpenList 地址必须从客户端设备可访问。


Steam 补丁 ​

工作原理 ​

补丁文件(.7z/.rar/.zip 等)
    │
扫描 → patches.json(记录 AppID、文件路径、类型等)
    │
客户端扫描本地 steamapps → 匹配 AppID → 下载注入

AppID 识别规则(优先级从高到低) ​

  1. 文件名中的纯数字(123456.zip → 123456)
  2. 父目录名中的纯数字(123456/patch.zip → 123456)
  3. 从文件名提取游戏名 → Steam Store API 搜索
  4. 都失败则 app_id: null,可手动在客户端填写

补丁类型识别关键词 ​

类型默认关键词
translation(汉化)_Steam_Chinese_Patch
voice(音声)_Steam_Voice_Patch
story(剧情)_Steam_Story_Patch
extra(额外)_Steam_Extra_Patch
misc(其他)无关键词匹配时

关键词文件位于数据目录的 steam_patch_index/patch_type_keywords.json,可在客户端 Steam 补丁页的「关键词匹配」里编辑,也可以直接改这个文件。文件名(统一转小写)包含任一关键词即归为该类型,按类型顺序取第一个命中的;misc 不参与匹配。

这份文件只在不存在时才会写入上面的默认值,之后以文件内容为准——也就是说修改过关键词后,升级服务端不会覆盖你改过的词。它会被 senacli backup 一起导出,senacli restore 默认一起恢复(加 --skip-keywords 可保留服务器上的现有词表)。

patches.json 字段说明 ​

字段说明
app_idSteam AppID
file压缩包相对补丁目录的路径
patch_dir解压后取哪个子目录的内容(空=自动选)
target_dir复制到游戏目录的哪个子路径(空=根目录)
label界面显示名称
type补丁类型
game_nameSteam 游戏中文名

附录 ​

支持的压缩格式 ​

.zip .rar .7z .tar .gz .xz .apk

平台标识 ​

标识平台
[PC]Windows PC
[KRKR]Kirikiri
[Ty]Tyranor
[ONS]ONScripter
直装_ / .apkAndroid 直装

默认端口 ​

11451 — 服务端 HTTP API

相关文档 ​

Released under the AGPL v3 License.