diff --git a/.env.example b/.env.example index 7753735..2ef6237 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,8 @@ # Server -SERVER_PORT=3001 -SERVER_BASE_URL=http://localhost:3001 +SERVER_PORT=6667 +SERVER_BASE_URL=http://mark.cloud-xl.top:6667 +# CORS (comma-separated) +CORS_ORIGINS=http://mark.cloud-xl.top:6666 # Postgres (server-side only) DATABASE_HOST=127.0.0.1 diff --git a/README.md b/README.md index 583b9a5..c7e35e7 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,155 @@ ## 配置 - 复制 `.env.example` 为 `.env` 并填写数据库与密钥。 + +## 发布(NAS / SSH / x86 Linux) + +以下步骤适用于你描述的环境:x86 Linux NAS + SSH 部署,已安装 Node.js 24 与 pm2。 + +### 0) 本地已执行的命令(在本机开发环境) + +- 路径:仓库根目录 +- 已执行: + - `npm install` + - `npm run build` + +这会生成下列产物: +- Web 构建产物:`apps/web/dist/` +- 扩展构建产物:`apps/extension/dist/` +- 后端为 Node 直接运行源代码(`apps/server/src/`) + +### 1) 服务器目录建议(NAS) + +建议在 NAS 上建立如下目录结构(可按需调整): + +``` +/opt/browser-bookmark/ +├── server/ # 后端源码与依赖 +├── web/ # Web 静态站点 +└── extension/ # 扩展构建产物(用于打包/发布或本地加载) +``` + +### 2) 通过 SSH 上传文件 + +以下是需要上传的内容与目标路径: + +1. 后端(运行源码) + - 本地:`apps/server/` + - 服务器:`/opt/browser-bookmark/server/` + +2. Web 前端(静态产物) + - 本地:`apps/web/dist/` + - 服务器:`/opt/browser-bookmark/web/` + +3. 扩展产物(打包或本地加载) + - 本地:`apps/extension/dist/` + - 服务器:`/opt/browser-bookmark/extension/` + +4. 部署配置文件 + - 本地:`deploy/` + - 服务器:`/opt/browser-bookmark/deploy/` + +你可以使用 `scp` 或 `rsync`(示例命令需替换服务器地址与用户名): + +```bash +# 后端源码 +rsync -avz ./apps/server/ user@YOUR_NAS:/opt/browser-bookmark/server/ + +# Web 构建产物 +rsync -avz ./apps/web/dist/ user@YOUR_NAS:/opt/browser-bookmark/web/ + +# 扩展构建产物 +rsync -avz ./apps/extension/dist/ user@YOUR_NAS:/opt/browser-bookmark/extension/ + +# 部署配置 +rsync -avz ./deploy/ user@YOUR_NAS:/opt/browser-bookmark/deploy/ +``` + +### 3) 服务器端安装依赖 + +登录到 NAS: + +```bash +ssh user@YOUR_NAS +``` + +在服务器的后端目录安装依赖: + +```bash +cd /opt/browser-bookmark/server +npm install --omit=dev +``` + +### 4) 配置环境变量 + +在服务器 `server` 目录准备 `.env`: + +```bash +cd /opt/browser-bookmark/server +cp .env.example .env +``` + +根据你的数据库与密钥填写 `.env`。 + +### 5) 初始化数据库(首次部署必做) + +```bash +cd /opt/browser-bookmark/server +npm run db:migrate +``` + +### 6) 使用 systemd 启动后端 + +本仓库已生成 systemd 服务文件:`deploy/systemd/browser-bookmark-server.service`。 + +将其复制到服务器并启用: + +```bash +sudo cp /opt/browser-bookmark/deploy/systemd/browser-bookmark-server.service /etc/systemd/system/browser-bookmark-server.service +sudo systemctl daemon-reload +sudo systemctl enable browser-bookmark-server +sudo systemctl start browser-bookmark-server +``` + +查看服务状态: + +```bash +sudo systemctl status browser-bookmark-server +``` + +### 7) 配置 Nginx(端口 6666) + +本仓库已生成 Nginx 配置文件:`deploy/nginx/mark.cloud-xl.top.conf`。 + +将其复制到服务器并启用: + +```bash +sudo cp /opt/browser-bookmark/deploy/nginx/mark.cloud-xl.top.conf /etc/nginx/conf.d/mark.cloud-xl.top.conf +sudo nginx -t +sudo systemctl reload nginx +``` + +该配置将 `mark.cloud-xl.top:6666` 指向 `/opt/browser-bookmark/web/`。 + +### 8) 扩展发布/加载 + +扩展产物位于服务器:`/opt/browser-bookmark/extension/`。 + +- 如需本地加载:将该目录下载到你的桌面浏览器,用“加载已解压扩展”指向该目录。 +- 如需打包发布到商店:以该目录为基础打包(按平台要求)。 + +### 9) 验证与排查 + +- 后端日志: + ```bash + sudo journalctl -u browser-bookmark-server -f + ``` +- Web 是否可访问(浏览器访问你的域名/端口)。 +- 扩展是否能正常登录与同步。 + +### 10) 版本更新流程(建议) + +1. 本地执行:`npm install` 与 `npm run build` +2. 重新上传:`apps/server/`、`apps/web/dist/`、`apps/extension/dist/` +3. 服务器端:`npm install --omit=dev`(如依赖变更) +4. 重启服务:`sudo systemctl restart browser-bookmark-server` diff --git a/apps/extension/.env.example b/apps/extension/.env.example index 879d175..aad4711 100644 --- a/apps/extension/.env.example +++ b/apps/extension/.env.example @@ -1,5 +1,5 @@ # Extension API base (Fastify server) -VITE_SERVER_BASE_URL=http://localhost:3001 +VITE_SERVER_BASE_URL=http://mark.cloud-xl.top:6667 # Web app base (used by Options -> 跳转 Web) -VITE_WEB_BASE_URL=http://localhost:5173 +VITE_WEB_BASE_URL=http://mark.cloud-xl.top:6666 diff --git a/apps/server/src/config.js b/apps/server/src/config.js index 98bcc11..1ea8127 100644 --- a/apps/server/src/config.js +++ b/apps/server/src/config.js @@ -23,10 +23,15 @@ loadEnv(); export function getConfig() { const serverPort = Number(process.env.SERVER_PORT || 3001); const adminEmail = String(process.env.ADMIN_EMAIL || "").trim().toLowerCase(); + const corsOriginsRaw = String(process.env.CORS_ORIGINS || "").trim(); + const corsOrigins = corsOriginsRaw + ? corsOriginsRaw.split(",").map((item) => item.trim()).filter(Boolean) + : true; return { serverPort, adminEmail, + corsOrigins, database: { host: process.env.DATABASE_HOST || "127.0.0.1", port: Number(process.env.DATABASE_PORT || 5432), diff --git a/apps/server/src/index.js b/apps/server/src/index.js index 3849e17..2b3b170 100644 --- a/apps/server/src/index.js +++ b/apps/server/src/index.js @@ -14,8 +14,9 @@ import { syncRoutes } from "./routes/sync.routes.js"; const app = Fastify({ logger: true }); // Plugins +const config = getConfig(); await app.register(cors, { - origin: true, + origin: config.corsOrigins, credentials: true, methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "Accept"] @@ -69,7 +70,6 @@ app.setErrorHandler((err, _req, reply) => { app.get("/health", async () => ({ ok: true })); // Routes -const config = getConfig(); app.decorate("config", config); await authRoutes(app); diff --git a/apps/web/src/App.vue b/apps/web/src/App.vue index 8602ae9..bf44b73 100644 --- a/apps/web/src/App.vue +++ b/apps/web/src/App.vue @@ -95,8 +95,8 @@ router.afterEach(() => {