diff --git a/README.md b/README.md index a4fb6fc..a538be5 100644 --- a/README.md +++ b/README.md @@ -177,3 +177,29 @@ npm run test:e2e 升级时保留原 `.env`、`DATABASE_PATH`、`SESSION_SECRET` 和管理员配置。尤其不能更换 `SESSION_SECRET`,现有 HY2 用户凭据依赖它解密。发布前应停服务并通过 SQLite backup API 备份数据库(包含 WAL 中已提交的数据),不要仅复制正在写入的 `.db` 文件。随后更新代码、安装锁定依赖、构建并启动;无需导出导入业务数据,也无需手工执行 `ALTER TABLE`。 `tests/fixtures/remote-v4-schema.sql` 是从服务器只读获取的实际表结构,不含生产数据。`npm test` 使用该结构和模拟业务数据验证兼容性、重复迁移、失败回滚、原始 YAML 保留、订阅生成,以及自定义节点不参与鉴权和轮询。`npm run test:e2e` 验证新版 UI 的新增、校验、编辑、分组、禁用和删除流程。 + +## 证书托管与服务器自动安装 + +管理员进入「证书与安装」,上传 PEM 完整证书链(CRT)和未加密私钥(KEY)。证书私钥使用 `SESSION_SECRET` 派生密钥加密保存,不在页面回显;请保留原有 `SESSION_SECRET` 并备份数据库。本功能使用覆盖 `*.p.xn--876a.net` 的通配符证书;只管理上传的证书,不申请或自动续期,也不会自动更新已安装服务器的文件。 + +选择证书、填写节点名称与 Slug,生成并下载安装脚本。每份脚本限一个节点,有效期 24 小时,可在平台撤销。脚本不内嵌证书私钥,运行时通过 HTTPS 获取配置和证书,安装完成后凭据不能再次获取私钥。 + +在使用 systemd 的 Linux 服务器上以 root 运行(支持 x86_64、ARM64、ARMv7): + +```bash +sudo bash install-jp1.sh +# 或显式指定参数;jp1 可替换为任意合法的单级子域名前缀: +sudo bash install-jp1.sh --domain jp1 --hy2-port 23456 --stats-port 23457 +# NAT 内外端口不同: +sudo bash install-jp1.sh --domain jp1.p.xn--876a.net \ + --hy2-port 23456 --stats-port 23457 \ + --hy2-listen-port 443 --stats-listen-port 9999 +``` + +无参数时交互输入域名和两个端口。短域名自动补全 `.p.xn--876a.net`;完整域名用作订阅地址和 SNI。请提前将域名解析至服务器公网 IP,在 NAT / 云防火墙设置 UDP 的 HY2 映射和 TCP 的统计 API 映射。脚本不能代替云厂商配置端口转发或 DNS。统计 API 使用随机密钥,建议将其 TCP 端口限制为仅面板 IP 可访问。 + +脚本安装 curl/jq/openssl 等依赖,从 Hysteria 官方下载入口下载服务端,保存 `/etc/hysteria/config.yaml`、`server.crt`、`server.key`,创建 `hy2-panel-node.service` 并设置开机启动。先以禁用状态注册,检查本机统计 API 健康后启用节点。公网 NAT 连通性请通过平台的节点同步状态确认。 + +重复执行仅允许同一安装记录、同一域名和端口,不覆盖其他已有 HY2 配置。失败后修复问题,在凭据有效期内重试;已启用的节点不因删除安装记录而删除。凭据过期且已有部分安装时,请先检查并清理对应的禁用节点和服务器配置,再生成新的安装记录。 + +平台 `APP_URL` 必须是服务器能访问的公网 HTTPS 地址(本地测试允许 localhost HTTP)。新迁移使用数据库版本 5,只新增 `managed_certificates` / `node_installations` 表,兼容现有 v4 节点、用户和订阅数据。部署前仍应备份数据库;不要用旧版本程序打开已升级的数据库。 diff --git a/app/admin/admin-nav.tsx b/app/admin/admin-nav.tsx index d54d03a..af2c389 100644 --- a/app/admin/admin-nav.tsx +++ b/app/admin/admin-nav.tsx @@ -6,6 +6,7 @@ import { Server, Radio, ScrollText, + ShieldCheck, } from "lucide-react"; import Link from "next/link"; import { usePathname } from "next/navigation"; @@ -17,12 +18,19 @@ type NavItem = { export function AdminNav({ items }: { items: NavItem[] }) { const pathname = usePathname(); - const icons = [LayoutDashboard, Users, Server, Radio, ScrollText]; + const icons: Record = { + "/admin/dashboard": LayoutDashboard, + "/admin/users": Users, + "/admin/nodes": Server, + "/admin/certificates": ShieldCheck, + "/admin/subscriptions": Radio, + "/admin/audits": ScrollText, + }; return (