diff --git a/apps/wizarr/2026.7.1/.env.sample b/apps/wizarr/2026.7.1/.env.sample new file mode 100644 index 000000000..4d1b8c68b --- /dev/null +++ b/apps/wizarr/2026.7.1/.env.sample @@ -0,0 +1,4 @@ +PANEL_APP_PORT_HTTP=5690 +TIME_ZONE=Etc/UTC +APP_DATA_DIR=./data +CONTAINER_NAME= diff --git a/apps/wizarr/2026.7.1/data.yml b/apps/wizarr/2026.7.1/data.yml new file mode 100644 index 000000000..6d0db3a18 --- /dev/null +++ b/apps/wizarr/2026.7.1/data.yml @@ -0,0 +1,51 @@ +additionalProperties: + formFields: + - default: 5690 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + label: + en: Port + zh: 端口 + zh-Hant: 埠 + ja: ポート + ko: 포트 + ru: Порт + ms: Port + pt-br: Porta + required: true + rule: paramPort + type: number + - default: Etc/UTC + edit: true + envKey: TIME_ZONE + labelEn: Time Zone + labelZh: 时区 + label: + en: Time Zone + zh: 时区 + zh-Hant: 時區 + ja: タイムゾーン + ko: 시간대 + ru: Часовой пояс + ms: Zon Masa + pt-br: Fuso Horario + required: true + type: text + - default: ./data + edit: true + envKey: APP_DATA_DIR + labelEn: Data Directory + labelZh: 数据目录 + label: + en: Data Directory + zh: 数据目录 + zh-Hant: 資料目錄 + ja: データディレクトリ + ko: 데이터 디렉터리 + ru: Каталог данных + ms: Direktori Data + pt-br: Diretorio de Dados + required: true + type: text diff --git a/apps/wizarr/2026.7.1/docker-compose.yml b/apps/wizarr/2026.7.1/docker-compose.yml new file mode 100644 index 000000000..6e67588e3 --- /dev/null +++ b/apps/wizarr/2026.7.1/docker-compose.yml @@ -0,0 +1,38 @@ +services: + wizarr: + image: "ghcr.io/wizarrrr/wizarr:v2026.7.1@sha256:606f9b88b0303daae11f595e424756b588d9365021c53dcb4d1369f2efc0543c" + container_name: ${CONTAINER_NAME} + restart: unless-stopped + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:5690" + environment: + - PUID=1000 + - PGID=1000 + - DISABLE_BUILTIN_AUTH=false + - PORT=5690 + - TZ=${TIME_ZONE} + security_opt: + - no-new-privileges:true + cap_drop: + - ALL + cap_add: + - CHOWN + - SETUID + - SETGID + - DAC_OVERRIDE + healthcheck: + test: ["CMD", "sh", "-c", "curl -fs http://localhost:5690/health || exit 1"] + interval: 30s + timeout: 5s + start_period: 60s + retries: 3 + volumes: + - "${APP_DATA_DIR}:/data/database" + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/wizarr/2026.7.1/scripts/init.sh b/apps/wizarr/2026.7.1/scripts/init.sh new file mode 100755 index 000000000..291e7954a --- /dev/null +++ b/apps/wizarr/2026.7.1/scripts/init.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}" + +read_env_value() { + local key="$1" + [[ -f "$ENV_FILE" ]] || return 0 + local value + value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" + case "$value" in + \"*\") value="${value#\"}"; value="${value%\"}" ;; + \'*\') value="${value#\'}"; value="${value%\'}" ;; + esac + printf '%s\n' "$value" +} + +prepare_data_directory() { + local raw path + raw="${APP_DATA_DIR:-}" + if [[ -z "$raw" ]]; then + raw="$(read_env_value APP_DATA_DIR)" + fi + raw="${raw:-./data}" + + [[ -n "$raw" ]] || { + printf '%s\n' 'APP_DATA_DIR must not be empty' >&2 + exit 1 + } + if [[ "$raw" = /* ]]; then + printf '%s\n' 'APP_DATA_DIR must be relative to the application version directory' >&2 + exit 1 + fi + + path="$(realpath -m -- "$ROOT_DIR/${raw#./}")" + case "$path" in + "$ROOT_DIR"/*) ;; + *) + printf '%s\n' 'APP_DATA_DIR must remain inside the application version directory' >&2 + exit 1 + ;; + esac + + install -d -m 0750 "$path" + path="$(realpath -e -- "$path")" + case "$path" in + "$ROOT_DIR"/*) ;; + *) + printf '%s\n' 'APP_DATA_DIR resolves outside the application version directory' >&2 + exit 1 + ;; + esac + + chmod 0750 "$path" +} + +prepare_data_directory diff --git a/apps/wizarr/2026.7.1/scripts/uninstall.sh b/apps/wizarr/2026.7.1/scripts/uninstall.sh new file mode 100755 index 000000000..6e877466e --- /dev/null +++ b/apps/wizarr/2026.7.1/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +set -euo pipefail diff --git a/apps/wizarr/2026.7.1/scripts/upgrade.sh b/apps/wizarr/2026.7.1/scripts/upgrade.sh new file mode 100755 index 000000000..692e341e2 --- /dev/null +++ b/apps/wizarr/2026.7.1/scripts/upgrade.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +"$(dirname "$0")/init.sh" diff --git a/apps/wizarr/README.md b/apps/wizarr/README.md new file mode 100644 index 000000000..5eda9c07d --- /dev/null +++ b/apps/wizarr/README.md @@ -0,0 +1,65 @@ +# Wizarr + +## 产品介绍 + +Wizarr 是 Plex、Jellyfin、Emby、Audiobookshelf、Romm、Komga 和 Kavita 的邀请与用户管理系统。管理员可以生成邀请链接,并为新用户提供分步骤的媒体应用配置引导。 + +## 主要功能 + +- 管理多个媒体服务器及其用户和媒体库权限 +- 创建限时、限次或分级邀请 +- 配置邀请前后引导步骤和应用下载说明 +- 集成 Overseerr、Ombi、Discord、LDAP、OIDC 和 WebAuthn +- 提供活动记录、通知和 REST API + +## 访问说明 + +安装后通过 `http://<服务器 IP>:<端口>` 访问,实际端口以 `PANEL_APP_PORT_HTTP` 为准。 + +首次访问会进入 `/setup/` 创建管理员。内置认证被强制保留,管理员密码至少 8 位并须包含大写字母、小写字母和数字。首次管理员创建前,任何能够访问该端口的人都可能抢先注册管理员;安装后应立即完成设置,并在此之前只允许可信管理网络访问。生产环境应使用带 HTTPS 和访问限制的反向代理。 + +## 数据持久化 + +`APP_DATA_DIR` 挂载到容器的 `/data/database`,保存 SQLite 数据库、会话和应用密钥。该路径必须位于应用版本目录内,默认 `./data`;安装脚本会拒绝绝对路径和目录逃逸。升级、迁移或卸载前请备份此目录,卸载不会删除绑定目录中的数据。 + +## 安全与漏洞警告 + +- 2026-07-28 对固定镜像的 Trivy 扫描结果为 `0 Critical / 10 High`,对应 8 个不同漏洞:pyasn1 `CVE-2026-59885`、`CVE-2026-59886`;Mako `CVE-2026-41205`、`CVE-2026-44307`;c-ares `CVE-2026-33630`;curl/libcurl `CVE-2026-5773`、`CVE-2026-6276`(各由两个包重复报告);PostCSS `GHSA-r28c-9q8g-f849`。 +- 默认网络服务不使用 Mako 生成模板,PostCSS 只用于上游镜像构建,curl/c-ares 只由固定的 `localhost` 健康检查使用;这些路径不接收用户文件、URL、Host、Cookie 或源映射。pyasn1 风险位于可选 LDAP 集成的 ASN.1 解析路径,默认未配置 LDAP,但恶意或失陷的 LDAP 端点可能触发拒绝服务。 +- 所有漏洞均已有上游修复版本。应只连接可信媒体、LDAP 和通知服务,限制管理端访问,并在 Wizarr 发布经过验证的更新镜像后尽快升级。 +- 容器入口仅为创建指定 UID/GID 和修正数据库目录属主而短暂使用 root;实际应用进程以 UID/GID `1000:1000` 运行。容器丢弃全部 capabilities,仅恢复入口所需的 `CHOWN`、`SETUID`、`SETGID` 和 `DAC_OVERRIDE`;最后一项用于重启时穿越已由 UID 1000 持有的 `0750` 数据目录。容器启用 `no-new-privileges`。 + +## Introduction + +Wizarr is an invitation and user management system for Plex, Jellyfin, Emby, Audiobookshelf, Romm, Komga, and Kavita. Administrators can create invitation links and guide new users through media application setup. + +## Features + +- Manage users and library permissions across multiple media servers +- Create expiring, limited-use, and tiered invitations +- Configure pre-invite and post-invite onboarding steps +- Integrate with Overseerr, Ombi, Discord, LDAP, OIDC, and WebAuthn +- Activity records, notifications, and a REST API + +## Usage Notes + +- Access the service at `http://:`. Built-in authentication is forced on. +- The first visit opens `/setup/` to create an administrator. Until that account exists, anyone who can reach the port could claim the first administrator. Complete setup immediately on a trusted management network, then use an access-controlled HTTPS reverse proxy for production. +- The administrator password must contain uppercase, lowercase, and numeric characters and be at least eight characters long. Login attempts are limited by the application. +- `APP_DATA_DIR` persists the SQLite database, sessions, and application keys at `/data/database`. It must remain inside the application version directory. Back it up before upgrades or migrations; uninstall does not delete it. + +## Security And Vulnerability Warning + +- A 2026-07-28 Trivy scan of the pinned image reports `0 Critical / 10 High`, covering eight distinct findings: pyasn1 `CVE-2026-59885` and `CVE-2026-59886`; Mako `CVE-2026-41205` and `CVE-2026-44307`; c-ares `CVE-2026-33630`; curl/libcurl `CVE-2026-5773` and `CVE-2026-6276`, each reported for both packages; and PostCSS `GHSA-r28c-9q8g-f849`. +- The default network service does not render Mako templates, PostCSS is build-time only, and curl/c-ares are used only by the fixed localhost health check. Those paths receive no user file, URL, Host, Cookie, or source-map input. The pyasn1 findings apply to the optional LDAP integration; LDAP is disabled by default, but a malicious or compromised LDAP endpoint could cause denial of service. +- Fixed upstream versions exist for every finding. Connect only trusted media, LDAP, and notification services, restrict management access, and upgrade promptly when Wizarr publishes a verified refreshed image. +- The entrypoint uses root briefly to create the configured UID/GID and fix database ownership. The application processes then run as UID/GID `1000:1000`. All capabilities are dropped except `CHOWN`, `SETUID`, `SETGID`, and `DAC_OVERRIDE`; the last capability lets the entrypoint traverse the UID-1000-owned `0750` data directory on restart. `no-new-privileges` is enabled. + +## References + +- Project: +- Installation: +- Reverse proxy: +- Release: +- License: (MIT) +- Logo: (official project asset from the MIT-licensed source tree) diff --git a/apps/wizarr/data.yml b/apps/wizarr/data.yml new file mode 100644 index 000000000..e328eec25 --- /dev/null +++ b/apps/wizarr/data.yml @@ -0,0 +1,30 @@ +name: Wizarr +tags: + - Media +title: 媒体服务器邀请与用户管理工具 +description: 媒体服务器邀请与用户管理工具 +additionalProperties: + key: wizarr + name: Wizarr + tags: + - Media + shortDescZh: 媒体服务器邀请与用户管理工具 + shortDescEn: Media server invitation and user management + description: + en: Media server invitation and user management + zh: 媒体服务器邀请与用户管理工具 + zh-Hant: 媒體伺服器邀請與使用者管理工具 + ja: メディアサーバーの招待およびユーザー管理ツール + ko: 미디어 서버 초대 및 사용자 관리 도구 + ru: Управление приглашениями и пользователями медиасервера + ms: Pengurusan jemputan dan pengguna pelayan media + pt-br: Gerenciamento de convites e usuarios de servidor de midia + type: website + crossVersionUpdate: true + limit: 0 + website: https://docs.wizarr.dev/ + github: https://github.com/wizarrrr/wizarr + document: https://docs.wizarr.dev/getting-started/installation + architectures: + - amd64 + - arm64 diff --git a/apps/wizarr/logo.png b/apps/wizarr/logo.png new file mode 100644 index 000000000..730414ada Binary files /dev/null and b/apps/wizarr/logo.png differ