feat: 更新环境配置,添加 CORS 支持并修改服务器地址
This commit is contained in:
@@ -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
|
||||
|
||||
152
README.md
152
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`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -95,8 +95,8 @@ router.afterEach(() => {
|
||||
</RouterLink>
|
||||
|
||||
<nav class="links">
|
||||
<RouterLink to="/" class="link">首页</RouterLink>
|
||||
<RouterLink to="/my" class="link">我的</RouterLink>
|
||||
<RouterLink to="/" class="link">公开</RouterLink>
|
||||
<RouterLink to="/my" class="link">个人</RouterLink>
|
||||
|
||||
<RouterLink v-if="!loggedIn" to="/login" class="link primary">登录</RouterLink>
|
||||
|
||||
@@ -142,7 +142,12 @@ router.afterEach(() => {
|
||||
.links { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
|
||||
.link { color: var(--bb-text); text-decoration: none; padding: 9px 12px; border-radius: 14px; transition: transform 120ms ease, box-shadow 120ms ease, background 150ms, color 150ms; background: rgba(255,255,255,0.25); border: 1px solid rgba(255,255,255,0.45); }
|
||||
.link:hover { box-shadow: 0 10px 30px rgba(15, 23, 42, 0.10); transform: translateY(-1px); }
|
||||
.link.router-link-active { background: rgba(255,255,255,0.55); }
|
||||
.link.router-link-active {
|
||||
background: linear-gradient(135deg, var(--bb-primary), var(--bb-cta));
|
||||
color: white;
|
||||
border-color: rgba(255,255,255,0.25);
|
||||
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.18);
|
||||
}
|
||||
.primary { background: linear-gradient(135deg, var(--bb-primary), var(--bb-primary-weak)); color: white; border-color: rgba(255,255,255,0.25); }
|
||||
.primary:hover { filter: brightness(1.03); }
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ async function exportLocal() {
|
||||
<p v-if="error" class="bb-alert bb-alert--error" style="margin-top: 12px;">{{ error }}</p>
|
||||
|
||||
<p class="bb-muted" style="margin-top: 10px;">
|
||||
未登录:导入写入本机 localStorage,并使用 urlNormalized/urlHash 自动去重;登录:导入写入数据库并自动去重合并。
|
||||
未登录:导入写入本机 localStorage,并自动去重;登录:导入写入数据库并自动去重合并。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -608,7 +608,7 @@ onBeforeUnmount(() => {
|
||||
<div class="bb-row" style="justify-content: space-between; align-items: flex-end; gap: 12px; flex-wrap: wrap;">
|
||||
<div>
|
||||
<h1 style="margin: 0;">我的书签</h1>
|
||||
<div class="bb-muted" style="margin-top: 4px;">像课程进度一样管理你的链接:分组、搜索、可公开。</div>
|
||||
<div class="bb-muted" style="margin-top: 4px;">轻松管理你的书签:分组、搜索、可公开。</div>
|
||||
</div>
|
||||
|
||||
<div class="bb-row" style="gap: 10px; flex-wrap: wrap;">
|
||||
|
||||
@@ -111,7 +111,7 @@ onMounted(loadFolders);
|
||||
<div class="bb-row" style="justify-content: space-between; align-items: flex-end; gap: 12px; flex-wrap: wrap;">
|
||||
<div>
|
||||
<h1 style="margin: 0;">公开书签</h1>
|
||||
<div class="bb-muted" style="margin-top: 4px;">无需登录即可浏览:来自用户设置为“公开”的书签。</div>
|
||||
<div class="bb-muted" style="margin-top: 4px;">无需登录即可浏览本页面书签。</div>
|
||||
</div>
|
||||
|
||||
<div v-if="loggedIn" class="bb-row" style="gap: 10px; flex-wrap: wrap;">
|
||||
|
||||
@@ -256,7 +256,8 @@ input:focus-visible {
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: auto;
|
||||
z-index: 2147483000;
|
||||
/* Must be above BbModal overlay (2147483500) */
|
||||
z-index: 2147483600;
|
||||
}
|
||||
|
||||
.bb-selectOption {
|
||||
|
||||
14
deploy/nginx/mark.cloud-xl.top.conf
Normal file
14
deploy/nginx/mark.cloud-xl.top.conf
Normal file
@@ -0,0 +1,14 @@
|
||||
server {
|
||||
listen 6666;
|
||||
server_name mark.cloud-xl.top;
|
||||
|
||||
root /opt/browser-bookmark/web;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/mark.cloud-xl.top.access.log;
|
||||
error_log /var/log/nginx/mark.cloud-xl.top.error.log;
|
||||
}
|
||||
16
deploy/systemd/browser-bookmark-server.service
Normal file
16
deploy/systemd/browser-bookmark-server.service
Normal file
@@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=Browser Bookmark Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/browser-bookmark/server
|
||||
EnvironmentFile=/opt/browser-bookmark/server/.env
|
||||
ExecStart=/usr/bin/node src/index.js
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
User=root
|
||||
Group=root
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user