From 781cf0e87cc3adf07d4a7c19744fa9ca2e95fc46 Mon Sep 17 00:00:00 2001 From: okxlin <61420215+okxlin@users.noreply.github.com> Date: Fri, 26 Jun 2026 01:01:28 +0800 Subject: [PATCH] Add LibreSpeed LinuxServer app --- apps/librespeed-linuxserver/6.1.0/.env.sample | 8 ++ apps/librespeed-linuxserver/6.1.0/data.yml | 107 ++++++++++++++++++ .../6.1.0/docker-compose.yml | 25 ++++ .../6.1.0/scripts/init.sh | 14 +++ .../6.1.0/scripts/uninstall.sh | 3 + .../6.1.0/scripts/upgrade.sh | 5 + apps/librespeed-linuxserver/README.md | 61 ++++++++++ apps/librespeed-linuxserver/data.yml | 31 +++++ .../librespeed-linuxserver/latest/.env.sample | 8 ++ apps/librespeed-linuxserver/latest/data.yml | 107 ++++++++++++++++++ .../latest/docker-compose.yml | 25 ++++ .../latest/scripts/init.sh | 14 +++ .../latest/scripts/uninstall.sh | 3 + .../latest/scripts/upgrade.sh | 5 + apps/librespeed-linuxserver/logo.png | Bin 0 -> 5975 bytes 15 files changed, 416 insertions(+) create mode 100644 apps/librespeed-linuxserver/6.1.0/.env.sample create mode 100644 apps/librespeed-linuxserver/6.1.0/data.yml create mode 100644 apps/librespeed-linuxserver/6.1.0/docker-compose.yml create mode 100755 apps/librespeed-linuxserver/6.1.0/scripts/init.sh create mode 100755 apps/librespeed-linuxserver/6.1.0/scripts/uninstall.sh create mode 100755 apps/librespeed-linuxserver/6.1.0/scripts/upgrade.sh create mode 100644 apps/librespeed-linuxserver/README.md create mode 100644 apps/librespeed-linuxserver/data.yml create mode 100644 apps/librespeed-linuxserver/latest/.env.sample create mode 100644 apps/librespeed-linuxserver/latest/data.yml create mode 100644 apps/librespeed-linuxserver/latest/docker-compose.yml create mode 100755 apps/librespeed-linuxserver/latest/scripts/init.sh create mode 100755 apps/librespeed-linuxserver/latest/scripts/uninstall.sh create mode 100755 apps/librespeed-linuxserver/latest/scripts/upgrade.sh create mode 100644 apps/librespeed-linuxserver/logo.png diff --git a/apps/librespeed-linuxserver/6.1.0/.env.sample b/apps/librespeed-linuxserver/6.1.0/.env.sample new file mode 100644 index 000000000..144ff9b4c --- /dev/null +++ b/apps/librespeed-linuxserver/6.1.0/.env.sample @@ -0,0 +1,8 @@ +CONTAINER_NAME= +PANEL_APP_PORT_HTTP=80 +CONFIG_PATH=./data/config +TIME_ZONE=Asia/Shanghai +PASSWORD=linuxserver-change-me +CUSTOM_RESULTS=false +IPINFO_APIKEY= + diff --git a/apps/librespeed-linuxserver/6.1.0/data.yml b/apps/librespeed-linuxserver/6.1.0/data.yml new file mode 100644 index 000000000..1a0d3a048 --- /dev/null +++ b/apps/librespeed-linuxserver/6.1.0/data.yml @@ -0,0 +1,107 @@ +additionalProperties: + formFields: + - default: 80 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: HTTP Port + labelZh: HTTP 端口 + label: + en: HTTP Port + zh: HTTP 端口 + zh-Hant: HTTP 連接埠 + ja: HTTP ポート + ko: HTTP 포트 + ru: HTTP-порт + ms: Port HTTP + pt-br: Porta HTTP + required: true + type: number + rule: paramPort + - default: ./data/config + edit: true + envKey: CONFIG_PATH + labelEn: Config folder path + labelZh: 配置文件路径 + label: + en: Config folder path + zh: 配置文件路径 + zh-Hant: 設定檔資料夾路徑 + ja: 設定フォルダーのパス + ko: 설정 폴더 경로 + ru: Путь к папке конфигурации + ms: Laluan folder konfigurasi + pt-br: Caminho da pasta de configuração + required: true + type: text + - default: Asia/Shanghai + edit: true + envKey: TIME_ZONE + labelEn: Time zone + labelZh: 时区 + label: + en: Time zone + zh: 时区 + zh-Hant: 時區 + ja: タイムゾーン + ko: 시간대 + ru: Часовой пояс + ms: Zon waktu + pt-br: Fuso horário + required: true + type: text + - default: linuxserver-change-me + edit: true + envKey: PASSWORD + labelEn: Results database password + labelZh: 结果数据库密码 + label: + en: Results database password + zh: 结果数据库密码 + zh-Hant: 結果資料庫密碼 + ja: 結果データベースのパスワード + ko: 결과 데이터베이스 비밀번호 + ru: Пароль базы данных результатов + ms: Kata laluan pangkalan data keputusan + pt-br: Senha do banco de dados de resultados + random: true + required: true + rule: paramComplexity + type: password + - default: "false" + edit: true + envKey: CUSTOM_RESULTS + labelEn: Custom results page + labelZh: 自定义结果页 + label: + en: Custom results page + zh: 自定义结果页 + zh-Hant: 自訂結果頁 + ja: カスタム結果ページ + ko: 사용자 지정 결과 페이지 + ru: Пользовательская страница результатов + ms: Halaman keputusan tersuai + pt-br: Pagina de resultados personalizada + required: true + type: select + values: + - label: "false" + value: "false" + - label: "true" + value: "true" + - default: "" + edit: true + envKey: IPINFO_APIKEY + labelEn: IPInfo access token + labelZh: IPInfo 访问令牌 + label: + en: IPInfo access token + zh: IPInfo 访问令牌 + zh-Hant: IPInfo 存取權杖 + ja: IPInfo アクセストークン + ko: IPInfo 액세스 토큰 + ru: Токен доступа IPInfo + ms: Token akses IPInfo + pt-br: Token de acesso IPInfo + required: false + type: password + diff --git a/apps/librespeed-linuxserver/6.1.0/docker-compose.yml b/apps/librespeed-linuxserver/6.1.0/docker-compose.yml new file mode 100644 index 000000000..20bcf467d --- /dev/null +++ b/apps/librespeed-linuxserver/6.1.0/docker-compose.yml @@ -0,0 +1,25 @@ +networks: + 1panel-network: + external: true +services: + librespeed: + image: "linuxserver/librespeed:6.1.0" + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:80" + volumes: + - "${CONFIG_PATH}:/config" + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TIME_ZONE} + - PASSWORD=${PASSWORD} + - CUSTOM_RESULTS=${CUSTOM_RESULTS} + - DB_TYPE=sqlite + - IPINFO_APIKEY=${IPINFO_APIKEY:-} + labels: + createdBy: "Apps" + diff --git a/apps/librespeed-linuxserver/6.1.0/scripts/init.sh b/apps/librespeed-linuxserver/6.1.0/scripts/init.sh new file mode 100755 index 000000000..8a929d096 --- /dev/null +++ b/apps/librespeed-linuxserver/6.1.0/scripts/init.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail + +paths=( + "${CONFIG_PATH:-./data/config}" +) + +mkdir -p "${paths[@]}" +for path in "${paths[@]}"; do + case "$path" in + ./*|../*) chown -R 1000:1000 "$path" 2>/dev/null || true ;; + esac +done + diff --git a/apps/librespeed-linuxserver/6.1.0/scripts/uninstall.sh b/apps/librespeed-linuxserver/6.1.0/scripts/uninstall.sh new file mode 100755 index 000000000..accdccd70 --- /dev/null +++ b/apps/librespeed-linuxserver/6.1.0/scripts/uninstall.sh @@ -0,0 +1,3 @@ +#!/bin/bash +docker-compose down --volumes + diff --git a/apps/librespeed-linuxserver/6.1.0/scripts/upgrade.sh b/apps/librespeed-linuxserver/6.1.0/scripts/upgrade.sh new file mode 100755 index 000000000..a6eb46bac --- /dev/null +++ b/apps/librespeed-linuxserver/6.1.0/scripts/upgrade.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail + +: + diff --git a/apps/librespeed-linuxserver/README.md b/apps/librespeed-linuxserver/README.md new file mode 100644 index 000000000..74202660b --- /dev/null +++ b/apps/librespeed-linuxserver/README.md @@ -0,0 +1,61 @@ +# LibreSpeed + +## 产品介绍 +LibreSpeed 是一个自托管网络速度测试服务,本应用使用 LinuxServer.io 镜像部署。 + +## 主要功能 +- 在浏览器中进行下载、上传、延迟和抖动测试。 +- 使用 `/config` 持久化配置和结果数据库。 +- 默认使用 sqlite 结果数据库,便于单容器部署和迁移。 + +## 访问说明 +安装完成后,通过应用表单中的 HTTP 端口访问 Web UI。 + +## Introduction +LibreSpeed is a self-hosted network speed test service. This app deploys the LinuxServer.io image. + +## Features +- Run download, upload, latency, and jitter tests from a browser. +- Persist configuration and the results database under `/config`. +- Use sqlite by default for a simple single-container deployment. + +## 应用简介 +LibreSpeed 测速服务。 + +英文说明:Network speed test service maintained by LinuxServer.io. + +## 部署说明 +- 本应用使用 Docker Compose 在 1Panel 中部署。 +- 应用分类:工具。 +- 支持架构:amd64、arm64。 +- 可选版本:`latest`、`6.1.0`。 + +## 端口 +| 变量 | 说明 | 默认值 | 必填 | +| --- | --- | --- | --- | +| PANEL_APP_PORT_HTTP | HTTP 端口 | 80 | 是 | + +## 数据持久化 +| 变量 | 说明 | 默认值 | 必填 | +| --- | --- | --- | --- | +| CONFIG_PATH | 配置文件路径 | ./data/config | 是 | + +升级或迁移前,请在 1Panel 中备份上述数据目录。 + +## 配置项 +| 变量 | 说明 | 默认值 | 必填 | +| --- | --- | --- | --- | +| TIME_ZONE | 时区 | Asia/Shanghai | 是 | +| PASSWORD | 结果数据库密码 | 随机生成 | 是 | +| CUSTOM_RESULTS | 启用自定义结果页 | false | 是 | +| IPINFO_APIKEY | IPInfo 访问令牌 | 空 | 否 | + +## 使用说明 +- 默认结果数据库类型固定为 sqlite,不需要外部数据库。 +- 如需对外开放访问,请同步检查防火墙、安全组和反向代理配置。 + +## 参考资料 +- 官网: +- 文档: +- 源码: + diff --git a/apps/librespeed-linuxserver/data.yml b/apps/librespeed-linuxserver/data.yml new file mode 100644 index 000000000..4aa2179ed --- /dev/null +++ b/apps/librespeed-linuxserver/data.yml @@ -0,0 +1,31 @@ +name: LibreSpeed +tags: +- Tool +title: LibreSpeed 测速服务 +description: LibreSpeed 测速服务 +additionalProperties: + key: librespeed-linuxserver + name: LibreSpeed + tags: + - Tool + shortDescZh: LibreSpeed 测速服务 + shortDescEn: Network speed test service maintained by LinuxServer.io + description: + en: Network speed test service maintained by LinuxServer.io + zh: LibreSpeed 测速服务 + zh-Hant: LibreSpeed 測速服務 + ja: LinuxServer.io が保守するネットワーク速度テストサービス + ko: LinuxServer.io에서 유지 관리하는 네트워크 속도 테스트 서비스 + ru: Сервис проверки скорости сети, поддерживаемый LinuxServer.io + ms: Perkhidmatan ujian kelajuan rangkaian yang diselenggara oleh LinuxServer.io + pt-br: Servico de teste de velocidade de rede mantido pela LinuxServer.io + type: tool + crossVersionUpdate: true + limit: 0 + website: https://librespeed.org/ + github: https://github.com/linuxserver/docker-librespeed + document: https://docs.linuxserver.io/images/docker-librespeed/ + architectures: + - amd64 + - arm64 + diff --git a/apps/librespeed-linuxserver/latest/.env.sample b/apps/librespeed-linuxserver/latest/.env.sample new file mode 100644 index 000000000..144ff9b4c --- /dev/null +++ b/apps/librespeed-linuxserver/latest/.env.sample @@ -0,0 +1,8 @@ +CONTAINER_NAME= +PANEL_APP_PORT_HTTP=80 +CONFIG_PATH=./data/config +TIME_ZONE=Asia/Shanghai +PASSWORD=linuxserver-change-me +CUSTOM_RESULTS=false +IPINFO_APIKEY= + diff --git a/apps/librespeed-linuxserver/latest/data.yml b/apps/librespeed-linuxserver/latest/data.yml new file mode 100644 index 000000000..1a0d3a048 --- /dev/null +++ b/apps/librespeed-linuxserver/latest/data.yml @@ -0,0 +1,107 @@ +additionalProperties: + formFields: + - default: 80 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: HTTP Port + labelZh: HTTP 端口 + label: + en: HTTP Port + zh: HTTP 端口 + zh-Hant: HTTP 連接埠 + ja: HTTP ポート + ko: HTTP 포트 + ru: HTTP-порт + ms: Port HTTP + pt-br: Porta HTTP + required: true + type: number + rule: paramPort + - default: ./data/config + edit: true + envKey: CONFIG_PATH + labelEn: Config folder path + labelZh: 配置文件路径 + label: + en: Config folder path + zh: 配置文件路径 + zh-Hant: 設定檔資料夾路徑 + ja: 設定フォルダーのパス + ko: 설정 폴더 경로 + ru: Путь к папке конфигурации + ms: Laluan folder konfigurasi + pt-br: Caminho da pasta de configuração + required: true + type: text + - default: Asia/Shanghai + edit: true + envKey: TIME_ZONE + labelEn: Time zone + labelZh: 时区 + label: + en: Time zone + zh: 时区 + zh-Hant: 時區 + ja: タイムゾーン + ko: 시간대 + ru: Часовой пояс + ms: Zon waktu + pt-br: Fuso horário + required: true + type: text + - default: linuxserver-change-me + edit: true + envKey: PASSWORD + labelEn: Results database password + labelZh: 结果数据库密码 + label: + en: Results database password + zh: 结果数据库密码 + zh-Hant: 結果資料庫密碼 + ja: 結果データベースのパスワード + ko: 결과 데이터베이스 비밀번호 + ru: Пароль базы данных результатов + ms: Kata laluan pangkalan data keputusan + pt-br: Senha do banco de dados de resultados + random: true + required: true + rule: paramComplexity + type: password + - default: "false" + edit: true + envKey: CUSTOM_RESULTS + labelEn: Custom results page + labelZh: 自定义结果页 + label: + en: Custom results page + zh: 自定义结果页 + zh-Hant: 自訂結果頁 + ja: カスタム結果ページ + ko: 사용자 지정 결과 페이지 + ru: Пользовательская страница результатов + ms: Halaman keputusan tersuai + pt-br: Pagina de resultados personalizada + required: true + type: select + values: + - label: "false" + value: "false" + - label: "true" + value: "true" + - default: "" + edit: true + envKey: IPINFO_APIKEY + labelEn: IPInfo access token + labelZh: IPInfo 访问令牌 + label: + en: IPInfo access token + zh: IPInfo 访问令牌 + zh-Hant: IPInfo 存取權杖 + ja: IPInfo アクセストークン + ko: IPInfo 액세스 토큰 + ru: Токен доступа IPInfo + ms: Token akses IPInfo + pt-br: Token de acesso IPInfo + required: false + type: password + diff --git a/apps/librespeed-linuxserver/latest/docker-compose.yml b/apps/librespeed-linuxserver/latest/docker-compose.yml new file mode 100644 index 000000000..ff8d8fa50 --- /dev/null +++ b/apps/librespeed-linuxserver/latest/docker-compose.yml @@ -0,0 +1,25 @@ +networks: + 1panel-network: + external: true +services: + librespeed: + image: "linuxserver/librespeed:latest" + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:80" + volumes: + - "${CONFIG_PATH}:/config" + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TIME_ZONE} + - PASSWORD=${PASSWORD} + - CUSTOM_RESULTS=${CUSTOM_RESULTS} + - DB_TYPE=sqlite + - IPINFO_APIKEY=${IPINFO_APIKEY:-} + labels: + createdBy: "Apps" + diff --git a/apps/librespeed-linuxserver/latest/scripts/init.sh b/apps/librespeed-linuxserver/latest/scripts/init.sh new file mode 100755 index 000000000..8a929d096 --- /dev/null +++ b/apps/librespeed-linuxserver/latest/scripts/init.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail + +paths=( + "${CONFIG_PATH:-./data/config}" +) + +mkdir -p "${paths[@]}" +for path in "${paths[@]}"; do + case "$path" in + ./*|../*) chown -R 1000:1000 "$path" 2>/dev/null || true ;; + esac +done + diff --git a/apps/librespeed-linuxserver/latest/scripts/uninstall.sh b/apps/librespeed-linuxserver/latest/scripts/uninstall.sh new file mode 100755 index 000000000..accdccd70 --- /dev/null +++ b/apps/librespeed-linuxserver/latest/scripts/uninstall.sh @@ -0,0 +1,3 @@ +#!/bin/bash +docker-compose down --volumes + diff --git a/apps/librespeed-linuxserver/latest/scripts/upgrade.sh b/apps/librespeed-linuxserver/latest/scripts/upgrade.sh new file mode 100755 index 000000000..a6eb46bac --- /dev/null +++ b/apps/librespeed-linuxserver/latest/scripts/upgrade.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -euo pipefail + +: + diff --git a/apps/librespeed-linuxserver/logo.png b/apps/librespeed-linuxserver/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..153102dd7e8396e56609cf7f8478c3778fe60fdf GIT binary patch literal 5975 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