2026-06-22 14:04:35 +08:00
|
|
|
|
# Write Server
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
Hugo 博客的本地管理后台,基于 Next.js 16 + Tailwind CSS 4,Docker 容器化部署。
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
域名:`https://post.usj.cc`
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
## 功能模块
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
| 模块 | 路径 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| 文章管理 | `/` | 列表、搜索、编辑、删除、预览 |
|
|
|
|
|
|
| 撰写文章 | `/edit` | Markdown 编辑器,图片上传 |
|
|
|
|
|
|
| 评论管理 | `/comments` | Artalk 评论回复、删除 |
|
|
|
|
|
|
| 订阅源 | `/feeds` | RSS 订阅源管理 |
|
|
|
|
|
|
| 友链管理 | `/links` | 友链增删改查 |
|
|
|
|
|
|
| 图片管理 | `/images` | 图片上传管理 |
|
|
|
|
|
|
| 公众号 | `/wechat` | 微信公众号发布(自包含) |
|
|
|
|
|
|
| 回收站 | `/recycle` | 已删文章恢复 |
|
|
|
|
|
|
| Bot 管理 | `/bot` | Telegram Bot / Hugo 状态 |
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
## 技术栈
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
- **框架**: Next.js 16 (Turbopack, standalone 输出)
|
|
|
|
|
|
- **样式**: Tailwind CSS 4, SEN 暖色系
|
|
|
|
|
|
- **数据**: 直接读写 Hugo Markdown 文件,无数据库
|
|
|
|
|
|
- **评论**: Artalk API v2
|
|
|
|
|
|
- **Bot**: Telegram Bot (长轮询)
|
|
|
|
|
|
- **公众号**: 微信 API 直连(不依赖外部服务)
|
|
|
|
|
|
- **反向代理**: Nginx + Basic Auth + Service Worker
|
|
|
|
|
|
- **Hugo 预览**: 独立端口 1313,HTTPS 访问
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
|
|
|
|
|
## 目录结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
write-server/
|
2026-06-22 14:04:35 +08:00
|
|
|
|
├── src/ # 源代码
|
|
|
|
|
|
│ ├── app/ # Next.js 页面和 API
|
|
|
|
|
|
│ ├── components/ # React 组件
|
|
|
|
|
|
│ └── lib/ # 核心库(posts, recycle, bot, wechat, hugo)
|
|
|
|
|
|
├── nginx/ # Nginx 配置
|
|
|
|
|
|
│ ├── conf.d/ # 站点配置(主站 + Hugo 预览)
|
|
|
|
|
|
│ ├── login.html # 登录页面
|
|
|
|
|
|
│ └── sw.js # Service Worker(认证)
|
|
|
|
|
|
├── entrypoint.sh # Docker 入口脚本(权限修复)
|
|
|
|
|
|
├── Dockerfile # Docker 镜像
|
|
|
|
|
|
├── docker-compose.yml # Docker Compose
|
|
|
|
|
|
├── .env.example # 环境变量模板
|
|
|
|
|
|
└── .htpasswd # Basic Auth 密码文件
|
2026-06-21 20:42:44 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
## 端口说明
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
| 端口 | 用途 | 协议 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| 80 | HTTP → HTTPS 重定向 | HTTP |
|
|
|
|
|
|
| 443 | 写作后台(nginx 代理 → 8016) | HTTPS |
|
|
|
|
|
|
| 1313 | Hugo 预览(nginx 代理 → 容器内 1313) | HTTPS |
|
|
|
|
|
|
| 8016 | write-server(仅容器内部) | - |
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
## 环境变量 (.env)
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 评论系统
|
|
|
|
|
|
ARTALK_SERVER=https://artalk.usj.cc
|
|
|
|
|
|
ARTALK_SITE=优世界
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# Telegram Bot
|
2026-06-21 20:42:44 +08:00
|
|
|
|
TG_BOT_TOKEN=your-bot-token
|
|
|
|
|
|
TG_ALLOWED_CHAT_IDS=your-chat-id
|
|
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 微信公众号(自包含,直连微信 API)
|
2026-06-21 20:42:44 +08:00
|
|
|
|
WECHAT_APP_ID=your-app-id
|
|
|
|
|
|
WECHAT_APP_SECRET=your-app-secret
|
|
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# RSS/友链 API
|
|
|
|
|
|
RSS_API_BASE=https://api.usj.cc
|
|
|
|
|
|
RSS_API_TOKEN=your-token
|
|
|
|
|
|
|
|
|
|
|
|
# AI
|
|
|
|
|
|
DEEPSEEK_API_KEY=your-key
|
2026-06-21 20:42:44 +08:00
|
|
|
|
DEEPSEEK_BASE_URL=https://api.deepseek.com
|
|
|
|
|
|
DEEPSEEK_MODEL=deepseek-chat
|
2026-06-22 14:04:35 +08:00
|
|
|
|
|
|
|
|
|
|
# 其他
|
|
|
|
|
|
DEFAULT_AUTHOR=小赵
|
|
|
|
|
|
PREFER_IFACE=eth0
|
2026-06-21 20:42:44 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
## 常用命令
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 启动
|
|
|
|
|
|
docker compose up -d
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 停止
|
|
|
|
|
|
docker compose down
|
|
|
|
|
|
|
|
|
|
|
|
# 重建(代码/Dockerfile 变更后)
|
|
|
|
|
|
docker compose down
|
|
|
|
|
|
docker compose build --no-cache
|
|
|
|
|
|
docker compose up -d
|
|
|
|
|
|
|
|
|
|
|
|
# 查看日志
|
|
|
|
|
|
docker logs write-server -f
|
|
|
|
|
|
docker logs write-nginx -f
|
|
|
|
|
|
|
|
|
|
|
|
# 重启单个服务
|
|
|
|
|
|
docker compose restart write-server
|
|
|
|
|
|
docker compose restart nginx
|
2026-06-21 20:42:44 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 迁移到新服务器
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 新服务器准备
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 安装 Docker
|
|
|
|
|
|
curl -fsSL https://get.docker.com | sh
|
|
|
|
|
|
systemctl enable docker
|
|
|
|
|
|
systemctl start docker
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 安装 docker compose 插件
|
|
|
|
|
|
apt install -y docker-compose-plugin git
|
2026-06-21 20:42:44 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
### 2. 克隆项目
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-22 14:04:35 +08:00
|
|
|
|
cd ~
|
|
|
|
|
|
mkdir -p hugo && cd hugo
|
|
|
|
|
|
git clone <your-repo-url> blog
|
|
|
|
|
|
cd blog/write-server
|
2026-06-21 20:42:44 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
### 3. 配置环境变量
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-22 14:04:35 +08:00
|
|
|
|
cp .env.example .env
|
|
|
|
|
|
nano .env
|
2026-06-21 20:42:44 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
填写所有必要的 Token 和 API Key。
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
### 4. 生成 Basic Auth 密码
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
```bash
|
|
|
|
|
|
docker run --rm httpd:alpine htpasswd -nbB admin "your-password" > .htpasswd
|
|
|
|
|
|
```
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
### 5. 配置域名 DNS
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
添加 A 记录指向新服务器 IP:
|
|
|
|
|
|
```
|
|
|
|
|
|
post.usj.cc → 新服务器IP
|
|
|
|
|
|
```
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
### 6. 申请 SSL 证书
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
```bash
|
|
|
|
|
|
apt install -y certbot
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 先启动 nginx(HTTP 模式)
|
|
|
|
|
|
docker compose up -d nginx
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 停 nginx 释放 80 端口
|
|
|
|
|
|
docker compose stop nginx
|
2026-06-21 20:42:44 +08:00
|
|
|
|
|
2026-06-22 14:04:35 +08:00
|
|
|
|
# 申请证书
|
|
|
|
|
|
certbot certonly --standalone -d post.usj.cc --agree-tos --email your@email.com
|
|
|
|
|
|
|
|
|
|
|
|
# 复制证书
|
|
|
|
|
|
mkdir -p nginx/ssl
|
|
|
|
|
|
cp /etc/letsencrypt/live/post.usj.cc/fullchain.pem nginx/ssl/
|
|
|
|
|
|
cp /etc/letsencrypt/live/post.usj.cc/privkey.pem nginx/ssl/
|
|
|
|
|
|
|
|
|
|
|
|
# 启动所有服务
|
|
|
|
|
|
docker compose up -d
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7. 配置防火墙
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
ufw allow 22/tcp
|
|
|
|
|
|
ufw allow 80/tcp
|
|
|
|
|
|
ufw allow 443/tcp
|
|
|
|
|
|
ufw allow 1313/tcp
|
|
|
|
|
|
ufw enable
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 8. 配置 Git
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 博客目录需要 git 可写
|
|
|
|
|
|
git config --global --add safe.directory /root/hugo/blog
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 9. 验证
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 检查容器状态
|
|
|
|
|
|
docker ps
|
|
|
|
|
|
|
|
|
|
|
|
# 检查 API
|
|
|
|
|
|
curl -s https://post.usj.cc/api/stats
|
|
|
|
|
|
|
|
|
|
|
|
# 检查 Hugo 预览
|
|
|
|
|
|
curl -s https://post.usj.cc:1313/ | head -5
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 10. 自动续期 SSL 证书
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 添加 crontab
|
|
|
|
|
|
crontab -e
|
|
|
|
|
|
|
|
|
|
|
|
# 添加:
|
|
|
|
|
|
0 3 1 * * certbot renew --quiet && docker compose restart nginx
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 迁移清单
|
|
|
|
|
|
|
|
|
|
|
|
换服务器时需要迁移的内容:
|
|
|
|
|
|
|
|
|
|
|
|
### 必须迁移
|
|
|
|
|
|
|
|
|
|
|
|
| 内容 | 位置 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| 博客源码 | `~/hugo/blog/` | git clone 即可 |
|
|
|
|
|
|
| write-server 代码 | `~/hugo/blog/write-server/` | git clone 即可 |
|
|
|
|
|
|
| .env 文件 | `write-server/.env` | 手动创建,填写 Token |
|
|
|
|
|
|
| .htpasswd 文件 | `write-server/.htpasswd` | 重新生成 |
|
|
|
|
|
|
| SSL 证书 | `nginx/ssl/` | 重新申请 |
|
|
|
|
|
|
|
|
|
|
|
|
### 可选迁移
|
|
|
|
|
|
|
|
|
|
|
|
| 内容 | 位置 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| 回收站数据 | `write-server/recycle/` | 30 天自动过期,可不迁移 |
|
|
|
|
|
|
| 日志 | `write-server/logs/` | 可不迁移 |
|
|
|
|
|
|
|
|
|
|
|
|
### 需要在新服务器操作
|
|
|
|
|
|
|
|
|
|
|
|
| 操作 | 说明 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| DNS 解析 | 把 post.usj.cc 指向新 IP |
|
|
|
|
|
|
| SSL 证书 | 在新服务器重新申请 |
|
|
|
|
|
|
| 防火墙 | 放行 80, 443, 1313 端口 |
|
|
|
|
|
|
| git safe.directory | 新服务器执行 `git config --global --add safe.directory ...` |
|
|
|
|
|
|
| 微信 IP 白名单 | 如果用公众号功能,新服务器 IP 需加入微信白名单 |
|
|
|
|
|
|
|
|
|
|
|
|
### 不需要迁移
|
|
|
|
|
|
|
|
|
|
|
|
| 内容 | 原因 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| Docker 镜像 | 新服务器重新构建 |
|
|
|
|
|
|
| node_modules | Docker 构建时自动安装 |
|
|
|
|
|
|
| .next 目录 | Docker 构建时自动生成 |
|
|
|
|
|
|
| Hugo 二进制 | Dockerfile 自动安装 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 已知限制
|
|
|
|
|
|
|
|
|
|
|
|
- Hugo 预览和写作后台共用域名,Hugo 导航链接只在 1313 端口有效
|
|
|
|
|
|
- Telegram Bot 通过 Docker 挂载的 SSH 密钥进行 git push
|
|
|
|
|
|
- 博客目录 owner 会被 entrypoint 改为 uid 1001(nextjs 用户)
|
|
|
|
|
|
- 3 小时登录过期(localStorage + Service Worker 双重检查)
|
|
|
|
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
|
|
|
|
MIT
|