Files
zhaoxi bfc83a2400 feat: 个人博客全栈实现(Rust/Axum + React/Tailwind + PostgreSQL)
后端(Axum + sqlx):
- GitHub OAuth 三层权限(管理员/用户/游客),MOCK_OAUTH 本地调试开关
- 文章 CRUD、草稿自动保存、发布/私有分离,发布时渲染 HTML
- 目录(folder 路径分层)、标签、评论、RSS、热门文章(按评论数)
- pages 表驱动动态内容:关于页、首页标题、个人名片
- S3 兼容对象存储图片上传接口(rust-s3,未配置时明确报错)
- 发布时自动提取正文首图作为封面 cover_url
- sqlx migrate 管理 5 个迁移

前端(React + Tailwind):
- 白天 Editorial / 黑夜星空双主题
- 首页(列表 + 热门侧栏 + 可编辑大标题)、文库(目录树+标签+搜索)
- Profile 页(GitHub 风格名片卡,全部字段后台可编辑)
- 后台:文件树文章管理、CodeMirror 编辑器(实时预览/自动保存/传图)
- Markdown 渲染:KaTeX 公式、代码块语言标注 + 双主题语法高亮
- 有封面的文章卡片自动整行展示,全局 ErrorBoundary

部署:
- docker-compose 本地三容器(postgres/backend/frontend)
- k8s manifests(适配 Caddy 终结 TLS → 隧道 → traefik 明文路由)
- 前端静态文件可由 Caddy 直接托管,集群只需 backend + postgres
- 可选 postgres 每日备份到 S3 的 CronJob
2026-07-18 19:15:49 +08:00

183 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Cosmos Blog
一个全栈个人博客系统,采用 **React + Tailwind CSS** 前端、**Rust + Axum** 后端、**PostgreSQL** 数据库,支持 **k3s/Kubernetes** 部署。
## 特性
- 🌌 星空暗色主题 + 杂志风排版
- 📝 CodeMirror 6 Markdown 编辑器,支持编辑/分屏/预览三种模式
- 💾 编辑器实时保存草稿
- 🔐 GitHub OAuth 登录,三层权限(guest / user / admin
- 💬 评论系统
- 🏷️ 标签云与搜索
- 📡 RSS 订阅
- 🐳 Docker / Docker Compose 一键运行
- ☸️ k3s + Traefik Ingress 部署配置
## 技术栈
### 后端
- [Axum](https://github.com/tokio-rs/axum) + Tokio
- [sqlx](https://github.com/launchbadge/sqlx)PostgreSQL
- [pulldown-cmark](https://github.com/pulldown-cmark/pulldown-cmark) 渲染 Markdown
- [jsonwebtoken](https://github.com/Keats/jsonwebtoken) 签发 JWT
- GitHub OAuth
### 前端
- React 19 + TypeScript + Vite
- Tailwind CSS + @tailwindcss/typography
- CodeMirror 6 Markdown 编辑器
- Framer Motion 动画
- TanStack Query 数据获取
- Zustand 状态管理
## 目录结构
```
.
├── backend/ # Rust + Axum 后端
│ ├── src/
│ ├── migrations/ # sqlx 数据库迁移
│ └── Dockerfile
├── frontend/ # React + Tailwind 前端
│ ├── src/
│ ├── Dockerfile
│ └── nginx.conf
├── k8s/ # Kubernetes manifests
│ ├── postgres/ # PostgreSQL StatefulSet
│ ├── backend/ # 后端 Deployment
│ ├── frontend/ # 前端 Deployment
│ ├── ingress.yaml # Traefik Ingress
│ └── kustomization.yaml
├── docker-compose.yml
└── .env.example
```
## 快速开始
### 1. 准备环境变量
```bash
cp .env.example .env
# 编辑 .env,填入 GitHub OAuth 参数和你的 GitHub 用户 ID
```
### 2. Docker Compose 一键启动
```bash
docker compose up --build
```
访问:http://localhost
后端 APIhttp://localhost:3000/api/health
### 3. 本地开发
启动 PostgreSQL
```bash
docker compose up postgres -d
```
启动后端:
```bash
cd backend
cargo run
```
启动前端:
```bash
cd frontend
npm install
npm run dev
```
## 权限模型
| 角色 | 权限 |
|------|------|
| guest | 浏览公开文章、评论、标签、RSS |
| user | guest 权限 + 发表评论 |
| admin | user 权限 + 文章 CRUD、发布/私有、删除任意评论 |
管理员通过 `GITHUB_ADMIN_ID` 环境变量指定,首次 GitHub 登录时自动赋予 `admin` 角色。
## 编辑器工作流
1. 管理员在 `/admin` 点击"新建文章"。
2. 编辑器默认分屏模式:左侧 CodeMirror 编辑 Markdown,右侧实时预览。
3. 输入停止 2 秒后自动保存草稿到后端 `drafts` 表。
4. 点击"发布":将草稿渲染为 HTML,状态变为 `public`
5. 已发布文章可转为 `private`(私有)或重新编辑。
## API 概览
### 公开接口
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/api/health` | 健康检查 |
| GET | `/api/posts?page=&tag=&q=` | 公开文章列表 |
| GET | `/api/posts/:slug` | 文章详情 |
| GET | `/api/posts/:slug/comments` | 文章评论列表 |
| GET | `/api/tags` | 标签云 |
| GET | `/api/rss.xml` | RSS Feed |
### 认证 / 用户 / 管理员接口
详见 `backend/README.md`
## 部署到 k3s
### 1. 构建并推送镜像
```bash
docker build -t your-registry/blog-backend:latest ./backend
docker build -t your-registry/blog-frontend:latest ./frontend
docker push your-registry/blog-backend:latest
docker push your-registry/blog-frontend:latest
```
### 2. 修改 K8s 配置
编辑以下文件中的占位符:
- `k8s/backend/secret.yaml`:数据库连接串、JWT 密钥、GitHub OAuth 参数、管理员 GitHub ID
- `k8s/postgres/secret.yaml`PostgreSQL 密码
- `k8s/backend/deployment.yaml``APP_URL``FRONTEND_URL`
- `k8s/ingress.yaml`:你的域名
- `k8s/kustomization.yaml`:镜像仓库地址
### 3. 应用配置
```bash
kubectl apply -k k8s/
```
### 4. 网络说明
你的场景是:**CaddyTLS 终止)→ k3s TraefikHTTP)→ frontend/backend**
- 集群内 Ingress 使用 `traefik.ingress.kubernetes.io/router.entrypoints: web`HTTP 80 端口)。
- Caddy 负责 HTTPS 证书和终止 TLS,反向代理到集群的 80 端口。
- 后端不做 TLS,不需要证书配置。
- Ingress 中 `/api` 路径转发到 backend,其余路径转发到 frontend。
## 安全注意事项
1. **JWT_SECRET** 生产环境必须替换为随机强密钥。
2. **GitHub OAuth state**:当前实现将前端 redirect URL 直接作为 state,存在开放重定向风险。后续建议对 state 做签名/加密。
3. **Secret 管理**:当前用 K8s Secret 明文存储,生产建议使用 Vault / Sealed Secrets / External Secrets Operator。
4. **PostgreSQL**k3s 内使用 StatefulSet + PVC,建议配置定期备份(如 pg_dump CronJob 或 Velero)。
## 后续可扩展
- 接入对象存储(如 MinIO/S3)保存图片/附件。
- 引入全文搜索(Meilisearch / Elasticsearch)。
- GitHub Actions CI/CD 自动构建推送镜像。
- 文章阅读量统计。
- 评论通知 / Webhook。