From 3f2ecb89c093ee56e9b87bf30d3d92a6ae113571 Mon Sep 17 00:00:00 2001 From: chunzhimoe <60135925+chunzhimoe@users.noreply.github.com> Date: Sun, 12 Apr 2026 17:16:06 +0800 Subject: [PATCH] fix: SSH app filtering, auth secret, middleware, i18n typos, remove .env from tracking --- .env | 41 ------------------------------ .env.example | 47 +++++++++++++++++++++++++++++++++++ src/app/create/page.tsx | 26 +++++++++---------- src/app/page.tsx | 4 +-- src/app/tunnels/page.tsx | 4 +-- src/components/Dashboard.tsx | 15 ++++++----- src/components/TunnelList.tsx | 6 ++--- src/lib/authOptions.ts | 17 ++++++++++++- src/lib/cloudflare.ts | 22 ++++++++++++++-- src/middleware.ts | 11 ++++---- 10 files changed, 115 insertions(+), 78 deletions(-) delete mode 100644 .env create mode 100644 .env.example diff --git a/.env b/.env deleted file mode 100644 index 3eb6cf4..0000000 --- a/.env +++ /dev/null @@ -1,41 +0,0 @@ -# ═══════════════════════════════════════════════════════════════ -# SSH Launcher — Environment Variables -# Copy to .env.local for local dev, or paste into Vercel dashboard -# (Settings → Environment Variables → Import .env) -# ═══════════════════════════════════════════════════════════════ - -# ── GitHub OAuth ───────────────────────────────────────────── -# Create at https://github.com/settings/developers → New OAuth App -# Homepage URL: https://your-domain.vercel.app -# Callback URL: https://your-domain.vercel.app/api/auth/callback/github -GITHUB_CLIENT_ID=Ov23liBlDuiNR8E2ZmPR -GITHUB_CLIENT_SECRET=dfd1251347afb0fb09d0ceb97bd53de301b23768 - -# ── NextAuth ───────────────────────────────────────────────── -# Generate secret: openssl rand -base64 32 -NEXTAUTH_SECRET=N0yaiIpxiVxJrU+xG8cG1CWKRNQ2q3NYjLvd0eEMpic= -# Required only when self-hosting (Vercel sets this automatically) -# NEXTAUTH_URL=https://your-domain.vercel.app - -# ── Upstash Redis ───────────────────────────────────────────── -# Stores per-user Cloudflare credentials (multi-user) -# Create a free database at https://console.upstash.com -# Copy the REST API URL and Token from the database dashboard -UPSTASH_REDIS_URL=https://native-tadpole-80150.upstash.io -UPSTASH_REDIS_TOKEN=gQAAAAAAATkWAAIncDIzMWVkNTgxMDMzMzQ0OWVlYjRkY2RiOGM3NTlkYjdlNXAyODAxNTA - -# ── Cloudflare API (optional — can set per-user via /settings) ─ -# If set here, all users share these credentials (single-user mode) -# Required Token permissions: -# Account → Cloudflare Tunnel: Edit -# Account → Access: Apps and Policies: Edit -# Zone → DNS: Edit -# Zone → Zone: Read -CLOUDFLARE_ACCOUNT_ID=d6c7c05733970cca34c3f3a734195de0 -CLOUDFLARE_API_TOKEN=cfut_kNwpPHUr33ZZqvBl1WJpGA6bBiw5wpfTs8LW8kPAbf601ad8 - -# ── Cloudflare Access Service Token (optional) ─────────────── -# Used to fetch server metrics through Access-protected tunnels -# Create in Zero Trust → Access → Service Auth → Service Tokens -CF_SERVICE_CLIENT_ID= -CF_SERVICE_CLIENT_SECRET= diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..3b67b4f --- /dev/null +++ b/.env.example @@ -0,0 +1,47 @@ +# ═══════════════════════════════════════════════════════════════ +# SSH Console — 环境变量模板 +# 复制此文件为 .env.local 用于本地开发,或在 Vercel 控制台逐项填入 +# Vercel: Settings → Environment Variables → 按 Production / Preview 分别配置 +# ═══════════════════════════════════════════════════════════════ + +# ── GitHub OAuth ───────────────────────────────────────────── +# 创建地址: https://github.com/settings/developers → New OAuth App +# Homepage URL: https://your-domain.vercel.app +# Callback URL: https://your-domain.vercel.app/api/auth/callback/github +# 预览环境额外回调: https://-git--.vercel.app/api/auth/callback/github +GITHUB_CLIENT_ID= +GITHUB_CLIENT_SECRET= + +# ── NextAuth ───────────────────────────────────────────────── +# 必填!生产环境缺少此项会导致 NO_SECRET 错误和登录失败。 +# 生成命令: openssl rand -base64 32 +NEXTAUTH_SECRET= + +# 本地开发或自托管时需要填写;Vercel 部署通常不需要(会自动检测) +# NEXTAUTH_URL=https://your-domain.vercel.app + +# ── Upstash Redis ───────────────────────────────────────────── +# 存储每个用户的 Cloudflare 凭证(多用户模式) +# 免费数据库: https://console.upstash.com +UPSTASH_REDIS_URL= +UPSTASH_REDIS_TOKEN= + +# ── Cloudflare API(可选 — 也可以在 /settings 页面按用户配置)─ +# 如果在此处填写,所有用户共享同一套凭证(单用户模式) +# Token 所需权限: +# Account → Cloudflare Tunnel: Edit +# Account → Access: Apps and Policies: Edit +# Zone → DNS: Edit +# Zone → Zone: Read +CLOUDFLARE_ACCOUNT_ID= +CLOUDFLARE_API_TOKEN= + +# ── Cloudflare Access 服务令牌(可选)──────────────────────── +# 用于通过 Access 保护的隧道拉取服务器指标 +# 创建位置: Zero Trust → Access → Service Auth → Service Tokens +CF_SERVICE_CLIENT_ID= +CF_SERVICE_CLIENT_SECRET= + +# ── 允许登录的邮箱白名单(可选)────────────────────────────── +# 逗号分隔;留空表示所有通过 GitHub 认证的用户均可登录 +# ALLOWED_EMAILS=alice@example.com,bob@example.com diff --git a/src/app/create/page.tsx b/src/app/create/page.tsx index a952677..bbf1f33 100644 --- a/src/app/create/page.tsx +++ b/src/app/create/page.tsx @@ -40,12 +40,12 @@ interface Zone { const STEP_LABELS: Record = { find_zone: "查找 DNS Zone", - create_tunnel: "创建隆道", + create_tunnel: "创建隧道", configure_tunnel: "配置 Ingress", create_dns: "创建 DNS 记录", - create_access_app: "创建访问应用", + create_access_app: "创建 Access 应用", setup_ca: "配置短期证书", - get_token: "获取隆道 Token", + get_token: "获取隧道 Token", browser_rendering: "浏览器渲染提醒", }; @@ -78,11 +78,9 @@ export default function CreatePage() { try { const res = await fetch("/api/zones"); const data = await res.json(); - if (!res.ok) throw new Error(data.error || "Failed to load zones"); - setZones(data); - if (data.length === 1) setForm((f) => ({ ...f, zoneId: data[0].id })); + if (!res.ok) throw new Error(data.error || "加载 Zone 失败"); } catch (e) { - setZonesError(e instanceof Error ? e.message : "Failed to load zones"); + setZonesError(e instanceof Error ? e.message : "加载 Zone 失败"); } finally { setZonesLoading(false); } @@ -113,7 +111,7 @@ export default function CreatePage() { if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`); setResult(data); } catch (err) { - setError(err instanceof Error ? err.message : "Unknown error"); + setError(err instanceof Error ? err.message : "未知错误"); } finally { setLoading(false); } @@ -145,7 +143,7 @@ export default function CreatePage() {

部署 SSH 主机

- 一键完成 → 隆道 + DNS + 访问应用 + 安装命令 + 一键完成 → 隧道 + DNS + Access 应用 + 安装命令

@@ -212,14 +210,14 @@ export default function CreatePage() { placeholder="22" className="form-input w-28" /> - } label="SSO 邮筱" - hint="Cloudflare SSO 邮筱,前缀将作为 Linux 用户名"> + } label="SSO 邮箱" + hint="Cloudflare SSO 邮箱,前缀将作为 Linux 用户名"> - } label="允许访问的邮筱(可选)" - hint="多个邮筱用逗号分隔,留空表示所有已认证用户均可访问"> + } label="允许访问的邮箱(可选)" + hint="多个邮箱用逗号分隔,留空表示所有已认证用户均可访问">