From b282c846fe29d688fe0d23f31c98243ffc2cfa0a Mon Sep 17 00:00:00 2001 From: Meng Sen Date: Wed, 25 Jun 2025 13:21:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83=E5=BA=94=E7=94=A8=20NodePass?= =?UTF-8?q?Dash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Meng Sen --- .github/README.md | 1 + README.md | 1 + apps/nodepassdash/2.0.2/data.yml | 33 +++++++++++++++ apps/nodepassdash/2.0.2/docker-compose.yml | 23 +++++++++++ apps/nodepassdash/2.0.2/envs/default.env | 2 + apps/nodepassdash/2.0.2/envs/global.env | 2 + apps/nodepassdash/2.0.2/scripts/init.sh | 17 ++++++++ apps/nodepassdash/2.0.2/scripts/uninstall.sh | 10 +++++ apps/nodepassdash/2.0.2/scripts/upgrade.sh | 17 ++++++++ apps/nodepassdash/README.md | 41 +++++++++++++++++++ apps/nodepassdash/data.yml | 14 +++++++ apps/nodepassdash/logo.png | Bin 0 -> 16486 bytes apps/nodepassdash/logo.svg | 12 ++++++ 13 files changed, 173 insertions(+) create mode 100644 apps/nodepassdash/2.0.2/data.yml create mode 100644 apps/nodepassdash/2.0.2/docker-compose.yml create mode 100644 apps/nodepassdash/2.0.2/envs/default.env create mode 100644 apps/nodepassdash/2.0.2/envs/global.env create mode 100644 apps/nodepassdash/2.0.2/scripts/init.sh create mode 100644 apps/nodepassdash/2.0.2/scripts/uninstall.sh create mode 100644 apps/nodepassdash/2.0.2/scripts/upgrade.sh create mode 100644 apps/nodepassdash/README.md create mode 100644 apps/nodepassdash/data.yml create mode 100644 apps/nodepassdash/logo.png create mode 100644 apps/nodepassdash/logo.svg diff --git a/.github/README.md b/.github/README.md index ba063d12a..f3ca1b0c1 100644 --- a/.github/README.md +++ b/.github/README.md @@ -121,6 +121,7 @@ | 🟢 | | Nginx UI | https://nginxui.com/ | 全新的 Nginx 网络管理界面,旨在简化 Nginx 服务器的管理和配置 | | | 🟢 | | NocoDB | https://nocodb.com/ | 无代码数据库平台 | | | 🟢 | | NodeBB | https://nodebb.org/ | 一个更适合现代网络的社会平台 | | +| 🟢 | | NodePassDash | https://github.com/NodePassProject/NodePassDash/ | 现代化的 NodePass 管理界面 | | | 🟢 | | Ollama | https://ollama.com/ | 一站式大模型部署平台 | | | 🟢 | | OneDev | https://onedev.io/ | DevOps 平台、带有 CI/CD、看板和软件包的 Git 服务器 | | | 🟢 | | Open Webui | https://openwebui.com/ | 用户友好的 AI 界面 | | diff --git a/README.md b/README.md index e24ca1022..16f58be87 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ | 🟢 | | Nginx UI | https://nginxui.com/ | 全新的 Nginx 网络管理界面,旨在简化 Nginx 服务器的管理和配置 | | | 🟢 | | NocoDB | https://nocodb.com/ | 无代码数据库平台 | | | 🟢 | | NodeBB | https://nodebb.org/ | 一个更适合现代网络的社会平台 | | +| 🟢 | | NodePassDash | https://github.com/NodePassProject/NodePassDash/ | 现代化的 NodePass 管理界面 | | | 🟢 | | Ollama | https://ollama.com/ | 一站式大模型部署平台 | | | 🟢 | | OneDev | https://onedev.io/ | DevOps 平台、带有 CI/CD、看板和软件包的 Git 服务器 | | | 🟢 | | Open Webui | https://openwebui.com/ | 用户友好的 AI 界面 | | diff --git a/apps/nodepassdash/2.0.2/data.yml b/apps/nodepassdash/2.0.2/data.yml new file mode 100644 index 000000000..ad4bc5870 --- /dev/null +++ b/apps/nodepassdash/2.0.2/data.yml @@ -0,0 +1,33 @@ +additionalProperties: + formFields: + - default: "host" + edit: true + envKey: NETWORK_MODE + labelZh: 网络模式 + labelEn: Network mode + required: true + type: select + values: + - label: 主机网络模式 + value: "host" + - label: 桥接网络模式 + value: "bridge" + - label: 无网络模式 + value: "none" + - label: 1panel-network + value: "1panel-network" + - default: "/home/nodepassdash" + edit: true + envKey: NODEPASSDASH_ROOT_PATH + labelZh: 数据持久化路径 + labelEn: Data persistence path + required: true + type: text + - default: 3000 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelZh: WebUI 端口 + labelEn: WebUI port + required: true + rule: paramPort + type: number diff --git a/apps/nodepassdash/2.0.2/docker-compose.yml b/apps/nodepassdash/2.0.2/docker-compose.yml new file mode 100644 index 000000000..7c8f507a0 --- /dev/null +++ b/apps/nodepassdash/2.0.2/docker-compose.yml @@ -0,0 +1,23 @@ +networks: + 1panel-network: + external: true + +services: + nodepassdash: + image: ghcr.io/nodepassproject/nodepassdash:2.0.2 + container_name: ${CONTAINER_NAME} + labels: + createdBy: "Apps" + restart: always + network_mode: ${NETWORK_MODE} + ports: + - ${PANEL_APP_PORT_HTTP}:${PANEL_APP_PORT_HTTP} + env_file: + - ${GLOBAL_ENV_FILE:-/etc/1panel/envs/global.env} + - ${ENV_FILE:-/etc/1panel/envs/default.env} + volumes: + - ${NODEPASSDASH_ROOT_PATH}/logs:/app/logs + - ${NODEPASSDASH_ROOT_PATH}/public:/app/public + environment: + - TZ=Asia/Shanghai + - PORT=${PANEL_APP_PORT_HTTP} diff --git a/apps/nodepassdash/2.0.2/envs/default.env b/apps/nodepassdash/2.0.2/envs/default.env new file mode 100644 index 000000000..cd05f46e6 --- /dev/null +++ b/apps/nodepassdash/2.0.2/envs/default.env @@ -0,0 +1,2 @@ +# copyright© 2024 XinJiang Ms Studio +ENV_FILE=.env diff --git a/apps/nodepassdash/2.0.2/envs/global.env b/apps/nodepassdash/2.0.2/envs/global.env new file mode 100644 index 000000000..e10989fe4 --- /dev/null +++ b/apps/nodepassdash/2.0.2/envs/global.env @@ -0,0 +1,2 @@ +# copyright© 2024 XinJiang Ms Studio +TZ=Asia/Shanghai diff --git a/apps/nodepassdash/2.0.2/scripts/init.sh b/apps/nodepassdash/2.0.2/scripts/init.sh new file mode 100644 index 000000000..07fb8c3fe --- /dev/null +++ b/apps/nodepassdash/2.0.2/scripts/init.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +if [ -f .env ]; then + source .env + + # setup-1 add default values + CURRENT_DIR=$(pwd) + sed -i '/^ENV_FILE=/d' .env + sed -i '/^GLOBAL_ENV_FILE=/d' .env + echo "ENV_FILE=${CURRENT_DIR}/.env" >> .env + echo "GLOBAL_ENV_FILE=${CURRENT_DIR}/envs/global.env" >> .env + + echo "Check Finish." + +else + echo "Error: .env file not found." +fi diff --git a/apps/nodepassdash/2.0.2/scripts/uninstall.sh b/apps/nodepassdash/2.0.2/scripts/uninstall.sh new file mode 100644 index 000000000..c86c4fbca --- /dev/null +++ b/apps/nodepassdash/2.0.2/scripts/uninstall.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ -f .env ]; then + source .env + + echo "Check Finish." + +else + echo "Error: .env file not found." +fi diff --git a/apps/nodepassdash/2.0.2/scripts/upgrade.sh b/apps/nodepassdash/2.0.2/scripts/upgrade.sh new file mode 100644 index 000000000..07fb8c3fe --- /dev/null +++ b/apps/nodepassdash/2.0.2/scripts/upgrade.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +if [ -f .env ]; then + source .env + + # setup-1 add default values + CURRENT_DIR=$(pwd) + sed -i '/^ENV_FILE=/d' .env + sed -i '/^GLOBAL_ENV_FILE=/d' .env + echo "ENV_FILE=${CURRENT_DIR}/.env" >> .env + echo "GLOBAL_ENV_FILE=${CURRENT_DIR}/envs/global.env" >> .env + + echo "Check Finish." + +else + echo "Error: .env file not found." +fi diff --git a/apps/nodepassdash/README.md b/apps/nodepassdash/README.md new file mode 100644 index 000000000..7d91e87f3 --- /dev/null +++ b/apps/nodepassdash/README.md @@ -0,0 +1,41 @@ +# NodePassDash + +NodePassDash是一个现代化的 NodePass 管理界面,基于 Go 后端 + Next.js 14、HeroUI 和 TypeScript 构建。提供实时隧道监控、流量统计和端点管理功能。 + +![NodePassDash](https://file.lifebus.top/imgs/nodepassdash_cover.png) + +![](https://img.shields.io/badge/%E6%96%B0%E7%96%86%E8%90%8C%E6%A3%AE%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91%E5%B7%A5%E4%BD%9C%E5%AE%A4-%E6%8F%90%E4%BE%9B%E6%8A%80%E6%9C%AF%E6%94%AF%E6%8C%81-blue) + +## 初始化 + +通过日志获取 + +## 特性 + +🚀 高性能 Go 后端: 完全重构的 Go 后端,性能提升 300%+,内存占用降低 60% + +🎯 实时监控: 通过 Server-Sent Events (SSE) 实现实时隧道状态更新 + +📊 流量统计: 可视化显示隧道流量数据和性能指标 + +🎨 现代UI: 基于 HeroUI 的响应式设计,支持深色/浅色主题 + +📱 移动适配: 完整的移动端响应式布局,支持各种设备访问 + +🐳 容器化: 开箱即用的 Docker 部署方案 + +🔧 命令行工具: 支持密码重置和自定义端口等管理功能 + +## 快捷操作 + +以下命令行均在容器中执行 + +### 密码重置 + +```shell +./nodepassdash --reset-pwd +``` + +--- + +![Ms Studio](https://file.lifebus.top/imgs/ms_blank_001.png) diff --git a/apps/nodepassdash/data.yml b/apps/nodepassdash/data.yml new file mode 100644 index 000000000..4ad377a81 --- /dev/null +++ b/apps/nodepassdash/data.yml @@ -0,0 +1,14 @@ +additionalProperties: + key: nodepassdash + name: NodePassDash + tags: + - WebSite + - Local + shortDescZh: 现代化的 NodePass 管理界面 + shortDescEn: NodePass Dashboard + type: website + crossVersionUpdate: true + limit: 0 + website: https://github.com/NodePassProject/NodePassDash/ + github: https://github.com/NodePassProject/NodePassDash/ + document: https://github.com/NodePassProject/NodePassDash/ diff --git a/apps/nodepassdash/logo.png b/apps/nodepassdash/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e3c0a9a7c04fdc4370ee92857bf02a468107b92e GIT binary patch literal 16486 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 + + + + + + + + + +