From f26e6258071c59de262ad58fc59bdfc4299657aa Mon Sep 17 00:00:00 2001 From: zhongkunming <73384930+zhongkunming@users.noreply.github.com> Date: Sat, 24 May 2025 12:17:09 +0800 Subject: [PATCH] =?UTF-8?q?feat(localApps):=20=E6=B7=BB=E5=8A=A0=E8=BF=85?= =?UTF-8?q?=E9=9B=B7=E8=BF=9C=E7=A8=8B=E4=B8=8B=E8=BD=BD=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=BA=94=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增迅雷远程下载服务应用配置和文档 - 添加 3.20.2 和 latest 版本的 Docker Compose 文件 - 创建 README.md 文件,详细介绍迅雷远程下载服务的使用方法和环境变量参数 - 在 data.yml 中配置应用的基本信息、标签和环境变量 --- xunlei/3.20.2/data.yml | 27 ++++++++++ xunlei/3.20.2/docker-compose.yml | 30 +++++++++++ xunlei/README.md | 86 +++++++++++++++++++++++++++++++ xunlei/data.yml | 19 +++++++ xunlei/latest/data.yml | 27 ++++++++++ xunlei/latest/docker-compose.yml | 30 +++++++++++ xunlei/logo.png | Bin 0 -> 7710 bytes 7 files changed, 219 insertions(+) create mode 100644 xunlei/3.20.2/data.yml create mode 100644 xunlei/3.20.2/docker-compose.yml create mode 100644 xunlei/README.md create mode 100644 xunlei/data.yml create mode 100644 xunlei/latest/data.yml create mode 100644 xunlei/latest/docker-compose.yml create mode 100644 xunlei/logo.png diff --git a/xunlei/3.20.2/data.yml b/xunlei/3.20.2/data.yml new file mode 100644 index 000000000..4b3110e7e --- /dev/null +++ b/xunlei/3.20.2/data.yml @@ -0,0 +1,27 @@ +additionalProperties: + formFields: + - default: "40163" + edit: true + envKey: PANEL_APP_PORT_HTTP + labelZh: WebUI 端口 + labelEn: WebUI port + required: true + rule: paramPort + type: number + + - default: "xunlei" + edit: true + envKey: XL_DASHBOARD_USERNAME + labelZh: 控制台用户名 + labelEn: Dashboard Username + required: true + type: text + + - default: "xunlei" + edit: true + envKey: XL_DASHBOARD_PASSWORD + labelZh: 控制台密码 + labelEn: Dashboard Password + required: true + rule: paramComplexity + type: password diff --git a/xunlei/3.20.2/docker-compose.yml b/xunlei/3.20.2/docker-compose.yml new file mode 100644 index 000000000..52ad30da5 --- /dev/null +++ b/xunlei/3.20.2/docker-compose.yml @@ -0,0 +1,30 @@ +networks: + 1panel-network: + external: true + +services: + xunlei: + container_name: ${CONTAINER_NAME} + environment: + - XL_DASHBOARD_PORT=${PANEL_APP_PORT_HTTP} + - XL_DASHBOARD_IP=0.0.0.0 + - XL_DASHBOARD_USERNAME=${XL_DASHBOARD_USERNAME} + - XL_DASHBOARD_PASSWORD=${XL_DASHBOARD_PASSWORD} + - XL_DIR_DOWNLOAD=/xunlei/downloads + - XL_DIR_DATA=/xunlei/data + - XL_UID=0 + - XL_GID=0 + - XL_PREVENT_UPDATE=true + - XL_DEBUG=false + image: cnk3x/xunlei:v3.20.2 + labels: + createdBy: "Apps" + networks: + - 1panel-network + ports: + - ${PANEL_APP_PORT_HTTP}:${PANEL_APP_PORT_HTTP} + privileged: true + restart: always + volumes: + - ./data/data:/xunlei/data + - ./data/downloads:/xunlei/downloads diff --git a/xunlei/README.md b/xunlei/README.md new file mode 100644 index 000000000..aefc0d58c --- /dev/null +++ b/xunlei/README.md @@ -0,0 +1,86 @@ +# 迅雷远程下载服务(非官方) + +[![GitHub Stars][1]][2] [![Docker Pulls][3]][5] [![Docker Version][4]][5] + +[1]: https://img.shields.io/github/stars/cnk3x/xunlei?style=flat +[2]: https://star-history.com/#cnk3x/xunlei&Date +[3]: https://img.shields.io/docker/pulls/cnk3x/xunlei.svg +[4]: https://img.shields.io/docker/v/cnk3x/xunlei +[5]: https://hub.docker.com/r/cnk3x/xunlei + +从迅雷群晖套件中提取出来用于其他设备的迅雷远程下载服务程序。仅供研究学习测试。 \ +本程序仅提供 Linux 模拟和容器化运行环境,未对原版迅雷程序进行任何修改。 + +## 使用 + +### Docker + +#### 镜像 + +```plain +cnk3x/xunlei:latest +registry.cn-shenzhen.aliyuncs.com/cnk3x/xunlei:latest +ghcr.io/cnk3x/xunlei:latest +``` + +**常规**的容器,还是要在特权模式下运行。 + +如果 docker 的存储驱动如果是 btrfs 或者 overlayfs,可以支持的非特权运行。 + +#### 环境变量参数 + +```bash +XL_DASHBOARD_PORT #网页访问的端口,默认 2345 +XL_DASHBOARD_IP #网页访问的端口,默认 0.0.0.0(代表所有IP) +XL_DASHBOARD_USERNAME #网页访问的用户名 +XL_DASHBOARD_PASSWORD #网页访问的密码 +XL_DIR_DOWNLOAD #下载保存默认文件夹,默认 /xunlei/downloads,多个文件夹用冒号:分隔 +XL_DIR_DATA #程序数据保存文件夹,默认 /xunlei/data +XL_UID #运行迅雷的用户ID +XL_GID #运行迅雷的用户组ID +XL_PREVENT_UPDATE #是否阻止更新,默认 true, 可选值 true/false, 1/0 +XL_CHROOT #隔离运行主目录, 指定该值且不为`/`则以隔离模式运行, 用于在容器内隔离环境,容器内默认为 /xunlei,隔离模式运行需要特权模式(--privileged),可以将该值设置为`/`来以非特权模式运行。非特权模式运行有条件,可以尝试失败后使用特权模式重新运行。 +XL_DEBUG #调试模式, 可选值 true/false, 1/0 +``` + +#### 在容器中运行 + +```bash +# docker run -d \ +# -v <数据目录>:/xunlei/data \ +# -v <默认下载保存目录>:/xunlei/downloads \ +# -p <访问端口>:2345 \ +# --privileged \ +# cnk3x/xunlei + +# example +docker run --privileged -v /mnt/sdb1/configs/xunlei:/xunlei/data -v /mnt/sdb1/downloads:/xunlei/downloads -p 2345:2345 cnk3x/xunlei + +# 如果你的docker存储驱动是 overlayfs 或者 btrfs等, 可以不用特权运行 +docker run -e XL_CHROOT=/ -v /mnt/sdb1/configs/xunlei:/xunlei/data -v /mnt/sdb1/downloads:/xunlei/downloads -p 2345:2345 cnk3x/xunlei + +``` + +也可以直接运行 + +```plain +$ bin/xlp-amd64 --help + +Flags: + -p, --dashboard_port 网页访问的端口 (env: XL_DASHBOARD_PORT) (default 2345) + -i, --dashboard_ip 网页访问绑定IP,默认绑定所有IP (env: XL_DASHBOARD_IP) + -u, --dashboard_username 网页访问的用户名 (env: XL_DASHBOARD_USERNAME) + -k, --dashboard_password 网页访问的密码 (env: XL_DASHBOARD_PASSWORD) + --dir_download 下载保存文件夹,可多次指定,需确保有权限访问 (env: XL_DIR_DOWNLOAD) (default [/xunlei/downloads]) + --dir_data 程序数据保存文件夹,其下'.drive'文件夹中,存储了登录的账号,下载进度等信息 (env: XL_DIR_DATA) (default "/xunlei/data") + --uid 运行迅雷的用户ID (env: XL_UID, UID) + --gid 运行迅雷的用户组ID (env: XL_GID, GID) + --prevent_update 阻止更新 (env: XL_PREVENT_UPDATE) (default true) + -r, --chroot CHROOT主目录, 指定该值且不为/则以chroot模式运行, 用于在容器内隔离环境 (env: XL_CHROOT) (default "/") + --debug 是否开启调试日志 (env: XL_DEBUG) + -v, --version 显示版本信息 +``` + +## Used By + +[kubespider](https://github.com/opennaslab/kubespider/blob/main/docs/zh/user_guide/thunder_install_config/README.md) \ No newline at end of file diff --git a/xunlei/data.yml b/xunlei/data.yml new file mode 100644 index 000000000..45842f6e2 --- /dev/null +++ b/xunlei/data.yml @@ -0,0 +1,19 @@ +name: 迅雷 +tags: + - 实用工具 +title: 提取自群晖平台的迅雷下载套件 +description: 提取自群晖平台的迅雷下载套件 +additionalProperties: + key: xunlei + name: 迅雷 + tags: + - Tool + shortDescZh: 提取自群晖平台的迅雷下载套件 + shortDescEn: Thunder download kit extracted from Synology platform + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://www.xunlei.com + github: https://github.com/cnk3x/xunlei/tree/docker + document: https://github.com/cnk3x/xunlei/tree/docker diff --git a/xunlei/latest/data.yml b/xunlei/latest/data.yml new file mode 100644 index 000000000..4f6015888 --- /dev/null +++ b/xunlei/latest/data.yml @@ -0,0 +1,27 @@ +additionalProperties: + formFields: + - default: "40163" + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number + + - default: "xunlei" + edit: true + envKey: XL_DASHBOARD_USERNAME + labelEn: Dashboard Username + labelZh: 控制台用户名 + required: true + type: text + + - default: "xunlei" + edit: true + envKey: XL_DASHBOARD_PASSWORD + labelEn: Dashboard Password + labelZh: 控制台密码 + required: true + rule: paramComplexity + type: password diff --git a/xunlei/latest/docker-compose.yml b/xunlei/latest/docker-compose.yml new file mode 100644 index 000000000..1d054bd4c --- /dev/null +++ b/xunlei/latest/docker-compose.yml @@ -0,0 +1,30 @@ +networks: + 1panel-network: + external: true + +services: + xunlei: + container_name: ${CONTAINER_NAME} + environment: + - XL_DASHBOARD_PORT=${PANEL_APP_PORT_HTTP} + - XL_DASHBOARD_IP=0.0.0.0 + - XL_DASHBOARD_USERNAME=${XL_DASHBOARD_USERNAME} + - XL_DASHBOARD_PASSWORD=${XL_DASHBOARD_PASSWORD} + - XL_DIR_DOWNLOAD=/xunlei/downloads + - XL_DIR_DATA=/xunlei/data + - XL_UID=0 + - XL_GID=0 + - XL_PREVENT_UPDATE=true + - XL_DEBUG=false + image: cnk3x/xunlei:latest + labels: + createdBy: "Apps" + networks: + - 1panel-network + ports: + - ${PANEL_APP_PORT_HTTP}:${PANEL_APP_PORT_HTTP} + privileged: true + restart: always + volumes: + - ./data/data:/xunlei/data + - ./data/downloads:/xunlei/downloads diff --git a/xunlei/logo.png b/xunlei/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4d35c4e89313c620f38ae86bc1ddcc83cf56c6d5 GIT binary patch literal 7710 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