第一期:家庭自学打卡系统

- 家长手机号登录 + 孩子设备一次性激活(长期会话)
- 周模板自动生成每日任务快照,支持拍照凭证直传对象存储
- 连击计算(空白日自动达成)、家长补卡带标记
- 家长端三标签:今日概览 / 任务模板 / 设备管理
- Docker 独立输出,经 Traefik 接入 jump.hn12301.net

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jacobxu666
2026-08-02 23:19:13 +08:00
co-authored by Claude Opus 4.8
commit af7a144d58
57 changed files with 8875 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
# SuperJump 项目指南
> 本项目部署在「AI 实验场」服务器(47.98.16.70)。以下为该服务器的部署/运维上下文,
> 同步自部署手册:`~/Documents/obsidian/工作资料/47.98.16.70(Ai实验场)部署手册_2026-08-02.md`
> (手册内含全部凭据明文;本文件会进 git,故只记位置不记密码。)
## 一、目标服务器
- 阿里云 ECS:4 核 15G / Ubuntu 26.04 LTS / 99G 系统盘 / 公网 IP `47.98.16.70`
- 登录:`ssh aifield`(root,**仅密钥登录**,无密码)
- 私钥:本机 `~/.ssh/aifield_47.98.16.70_ed25519`,NAS 有备份
- ⚠️ 私钥丢失 = 失去服务器(只能走阿里云控制台 VNC)
- 代码托管:本项目 `https://git.hn12301.net/xuchao/SuperJump.git`(自建 Gitea,账号 `xuchao`)
## 二、架构
- 纯 Docker Compose 手工管理 + Traefik 自动反代 + Let's Encrypt 自动签发/续期证书
- 流量:`:80` 强制 301 → `:443`(Traefik)→ 各容器
- 已有域名:`git.hn12301.net`(Gitea)、`status.hn12301.net`(Uptime Kuma)、`traefik.hn12301.net`(Dashboard, Basic Auth);新项目用 `<项目>.hn12301.net`
- 两个内部网络:
- `proxy` — Traefik 与所有对外服务
- `data` — MySQL / Redis / Kuma(需连数据库的服务加入此网络)
- MySQL / Redis 宿主机**零端口暴露**,仅 data 内网可达(容器内用 `mysql:3306`、`redis:6379` 访问)
## 三、凭据获取(不进本文件)
| 服务 | 账号 | 密码在哪 |
| --- | --- | --- |
| Gitea | `xuchao` | 服务器 `/opt/services/gitea/.env`,或 Obsidian 手册 |
| MySQL | `root` | 服务器 `/opt/services/mysql/.env` |
| Redis | — | 服务器 `/opt/services/redis/.env` |
| Uptime Kuma | `admin` | 服务器 `/opt/services/uptime-kuma/`,或 Obsidian 手册 |
| Traefik Dashboard | `admin` | 服务器 `/opt/services/traefik/.env` |
- 服务器上各服务密码的权威来源:`/opt/services/*/.env`(权限 600)
- 完整凭据表与哈希备份:Obsidian 部署手册(路径见文首)
## 四、服务器目录结构
```
/opt/services/
├── traefik/ # 反向代理
├── gitea/ # Git 服务
├── gitea-runner/ # CI runner(默认基础镜像 node:24-slim)
├── mysql/ # 数据库
├── redis/ # 缓存
└── uptime-kuma/ # 监控(proxy + data 双网络)
```
数据卷:`mysql_mysql_data`、`redis_redis_data`、`gitea_gitea_data`、`kuma_data`、`runner_data`、`traefik_certs`(证书)。
## 五、日常运维速查
```bash
ssh aifield # 登录服务器
cd /opt/services/<服务> && docker compose ps / restart / logs -f --tail 50
docker ps # 全部容器
# MySQL / Redis 客户端(密码从 .env 现取,不要硬编码)
docker exec -it mysql mysql -uroot -p"$(grep MYSQL_ROOT_PASSWORD /opt/services/mysql/.env | cut -d= -f2)"
docker exec -it redis redis-cli -a "$(grep REDIS_PASSWORD /opt/services/redis/.env | cut -d= -f2)"
# 改某服务密码:更新对应 .env → docker compose up -d 重建容器
```
## 六、本项目部署接入步骤
域名:`superjump.hn12301.net`(或自定;若已有泛解析 `*` → `47.98.16.70` 则免加 DNS A 记录)。
1. 在 `/opt/services/superjump/` 建 `docker-compose.yml`:
```yaml
services:
superjump:
image: 你的镜像:tag
container_name: superjump
restart: unless-stopped
networks: [proxy, data] # data 仅在需要连 MySQL/Redis 时加
labels:
- traefik.enable=true
- traefik.docker.network=proxy
- traefik.http.routers.superjump.rule=Host(`superjump.hn12301.net`)
- traefik.http.routers.superjump.entrypoints=websecure
- traefik.http.routers.superjump.tls.certresolver=le
- traefik.http.services.superjump.loadbalancer.server.port=8080 # 改成容器内实际端口
networks:
proxy:
name: proxy
external: true
data:
name: data
external: true
```
2. `docker compose up -d` → 几十秒后 `https://superjump.hn12301.net` 自动可用(证书自动签发),**不用动 Traefik 任何配置**。
3. 需要数据库时建**专用账号**(勿用 root):
```sql
CREATE DATABASE superjump CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'superjump'@'%' IDENTIFIED BY '另起强密码';
GRANT ALL ON superjump.* TO 'superjump'@'%';
```
语言镜像映射:Java → JRE 镜像;.NET → `mcr.microsoft.com/dotnet/aspnet:9.0`;Python → uvicorn/gunicorn 镜像。需要构建的走 Gitea Actions。
## 七、CI(Gitea Actions)
- Runner 已注册,标签 `ubuntu-latest` / `ubuntu-24.04` / `ubuntu-22.04`,均映射轻量镜像 `node:24-slim`(含 bash/git/node)
- workflow 放仓库 `.gitea/workflows/*.yaml`,语法同 GitHub Actions
- 重型任务在 workflow 里用 `container:` 指定专用镜像,**不要改 runner 默认**(国内拉 docker.gitea.com 基础镜像极慢)
## 八、监控(Uptime Kuma)
- 5 个监控项(60s 间隔):Gitea(HTTP 2xx)、Traefik-Dashboard(HTTP 401 即存活)、MySQL(连接串探针)、Redis-TCP(端口探针,Kuma 1.x 的 redis 类型不支持密码)、Traefik-443-TCP
- 告警:QQ 邮箱 SMTP(`smtp.qq.com:465` SSL,`25260062@qq.com`),DOWN/恢复各发一封
- 改邮箱授权码:Kuma 网页 → Settings → Notifications → 编辑「邮件告警」
## 九、安全现状(2026-08-02 已加固验证)
- SSH 仅密钥登录(`PasswordAuthentication no` 在**主配置 + sshd_config.d/50-cloud-init.conf 两处**都改了)
- 阿里云安全组 + UFW:公网仅 22/80/443;fail2ban 运行中
- MySQL/Redis 架构级零暴露
- **换机/重装后必做**:阿里云重装会重置 sshd 配置,需重装公钥并再次执行两处 `PasswordAuthentication no`
- 备份:暂未设置(建议日后:阿里云自动快照 + `/opt/services` 与数据卷定期打包)
## 十、踩坑记录(务必先看)
1. **Docker 29 + Traefik v3.5 不兼容**:Docker 29 最低 API 1.44,须用 Traefik ≥ v3.6。
2. **docker exec 喂 SQL 必须加 `-i`**:否则 heredoc 内容不进容器且不报错。
3. **compose .env 里的 `$` 要写成 `$$`**:htpasswd 的 `$apr1$` 哈希不转义会被当变量,Basic Auth 永远 401。
4. **Let's Encrypt 失败重试**:Traefik 启动即尝试签发,DNS 未生效会失败;DNS 好后重启 Traefik 容器重新触发。
5. **Docker Hub 国内直连不通**:daemon.json 已配镜像源(docker.m.daocloud.io 等)。
6. **Gitea 禁止 root**:容器内执行 Gitea CLI 必须 `-u git`。
7. **本机代理 fake-ip 污染探测**:开发机 Clash 类代理会把域名解析成 198.18.x.x,导致 `nc -z` 显示所有端口 OPEN 的假象。判断真实暴露面必须**从服务器侧自探公网 IP**,不要信本机探测。
8. **远程 heredoc 里的反引号会被 shell 执行**:JS 模板字符串经 ssh 传输时反引号变命令替换;用 quoted heredoc('EOF')或先本地写文件再传。
9. **Kuma SQLite 是 WAL 模式**:拷库离线查询要同时拷 `kuma.db` + `kuma.db-wal` + `kuma.db-shm`。
10. **sshd_config.d 优先级高于主配置**:改 SSH 设置时主配置与 `50-cloud-init.conf` 两处都要查。
11. **Kuma 1.x socket.io API**:`addNotification` 第二参数是 notificationID(新建传 `null`);mysql 监控用 `database_connection_string`(无 password 字段);详见手册第九节第 8 条。
---
*手册验收记录:2026-08-02 全部完成 —— 6 容器全绿;三域名证书生效;Kuma 5 监控项全 UP;SSH 密码登录已关闭;全部凭据已轮换。*