“运维与审计控制台”。

主要能力:
SuperAdmin 专用入口:组织与权限 → 运维与审计。
操作日志分页查询,支持时间、账号、路径、方法和状态码筛选。
汇总自动排课、课表发布、补考安排三类失败后台任务。
实时检查数据库、缓存、任务通道及积压状态。
聚合 5xx、失败/重试任务、健康探针和备份时效告警。
SQLite 在线备份;MySQL 调用原生客户端备份。
SHA-256 校验及隔离数据库恢复演练,不覆盖业务库。
MySQL 强制使用独立运维连接,容器增加持久化备份卷与数据库客户端。
This commit is contained in:
biss committed 2026-07-27 16:37:45 +08:00
1 parent 14ac49115c
commit 4d8de1e4ae
15 files changed
+2687 -4

No files matched your search

+13
View File
@@ -6,6 +6,9 @@ Database__Provider=MySql
Database__ApplyMigrationsOnStartup=false Database__ApplyMigrationsOnStartup=false
Database__CommandTimeoutSeconds=30 Database__CommandTimeoutSeconds=30
ConnectionStrings__MySql="Server=db.example.edu.cn;Port=3306;Database=jiaowu;User=APP_USER;Password=REPLACE_WITH_A_STRONG_PASSWORD;SslMode=VerifyFull;SslCa=/etc/jiaowu/mysql-ca.pem;" ConnectionStrings__MySql="Server=db.example.edu.cn;Port=3306;Database=jiaowu;User=APP_USER;Password=REPLACE_WITH_A_STRONG_PASSWORD;SslMode=VerifyFull;SslCa=/etc/jiaowu/mysql-ca.pem;"
# 仅供备份与隔离恢复演练使用。该账号需要读取业务库,并仅能创建/删除
# jiaowu_restore_drill_* 临时库;不要在此复用日常业务账号。
# ConnectionStrings__OperationsMySql="Server=db.example.edu.cn;Port=3306;Database=jiaowu;User=OPS_USER;Password=REPLACE_WITH_A_STRONG_PASSWORD;SslMode=VerifyFull;SslCa=/etc/jiaowu/mysql-ca.pem;"
# Redis 是可选加速器;留空时应用仅使用进程内缓存。 # Redis 是可选加速器;留空时应用仅使用进程内缓存。
# ConnectionStrings__Redis="redis.example.edu.cn:6380,user=jiaowu,password=REPLACE_WITH_A_STRONG_PASSWORD,ssl=true,abortConnect=false" # ConnectionStrings__Redis="redis.example.edu.cn:6380,user=jiaowu,password=REPLACE_WITH_A_STRONG_PASSWORD,ssl=true,abortConnect=false"
@@ -32,6 +35,16 @@ Cache__AnalyticsExpirationMinutes=3
Cache__AnalyticsLocalExpirationSeconds=30 Cache__AnalyticsLocalExpirationSeconds=30
Cache__MaximumPayloadKilobytes=2048 Cache__MaximumPayloadKilobytes=2048
# 运维控制台备份目录必须位于持久化、仅服务账号可写的位置。
Operations__BackupDirectory=/var/lib/jiaowu/backups
Operations__BackupWarningHours=24
Operations__ToolTimeoutMinutes=30
Operations__MySqlDumpPath=mysqldump
Operations__MySqlClientPath=mysql
# 按实际客户端补充 TLS 参数;Oracle MySQL 客户端示例:
# Operations__MySqlAdditionalArguments__0=--ssl-mode=VERIFY_IDENTITY
# Operations__MySqlAdditionalArguments__1=--ssl-ca=/etc/jiaowu/mysql-ca.pem
Jwt__Issuer=Jiaowu.Api Jwt__Issuer=Jiaowu.Api
Jwt__Audience=Jiaowu.Web Jwt__Audience=Jiaowu.Web
Jwt__Key=REPLACE_WITH_AT_LEAST_32_RANDOM_BYTES Jwt__Key=REPLACE_WITH_AT_LEAST_32_RANDOM_BYTES
+9 -2
View File
@@ -30,11 +30,14 @@ FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
WORKDIR /app WORKDIR /app
ENV ASPNETCORE_ENVIRONMENT=Production \ ENV ASPNETCORE_ENVIRONMENT=Production \
ASPNETCORE_HTTP_PORTS=8080 \ ASPNETCORE_HTTP_PORTS=8080 \
DOTNET_EnableDiagnostics=0 DOTNET_EnableDiagnostics=0 \
Operations__BackupDirectory=/var/lib/jiaowu/backups \
Operations__MySqlDumpPath=mariadb-dump \
Operations__MySqlClientPath=mariadb
EXPOSE 8080 EXPOSE 8080
COPY --from=build /app/publish/ ./ COPY --from=build /app/publish/ ./
ARG UID=10001 ARG UID=10001
RUN apk add --no-cache font-noto-cjk RUN apk add --no-cache font-noto-cjk mariadb-client
RUN adduser \ RUN adduser \
--disabled-password \ --disabled-password \
--gecos "" \ --gecos "" \
@@ -43,5 +46,9 @@ RUN adduser \
--no-create-home \ --no-create-home \
--uid "${UID}" \ --uid "${UID}" \
appuser appuser
RUN mkdir -p /var/lib/jiaowu/backups \
&& chown appuser:appuser /var/lib/jiaowu/backups \
&& chmod 700 /var/lib/jiaowu/backups
VOLUME ["/var/lib/jiaowu/backups"]
USER appuser USER appuser
ENTRYPOINT ["dotnet", "Jiaowu.Api.dll"] ENTRYPOINT ["dotnet", "Jiaowu.Api.dll"]
+25
View File
@@ -101,6 +101,12 @@ sudo chown -R root:jiaowu /opt/jiaowu
sudo chmod 0750 /opt/jiaowu sudo chmod 0750 /opt/jiaowu
sudo chmod 0750 /opt/jiaowu/Jiaowu.Api sudo chmod 0750 /opt/jiaowu/Jiaowu.Api
sudo chmod 0640 /opt/jiaowu/.env sudo chmod 0640 /opt/jiaowu/.env
sudo install -d \
--owner=jiaowu \
--group=jiaowu \
--mode=0700 \
/var/lib/jiaowu/backups
sudo apt-get install default-mysql-client
``` ```
如果账号已存在,`useradd` 会报错,可以跳过该命令。RHEL 系发行版的 `nologin` 通常 如果账号已存在,`useradd` 会报错,可以跳过该命令。RHEL 系发行版的 `nologin` 通常
@@ -297,6 +303,25 @@ Outbox 租约恢复改为按维护周期执行,避免积压发布时每条消
消息会根据 Outbox 状态和租约继续补投。迁移服务应先应用 消息会根据 Outbox 状态和租约继续补投。迁移服务应先应用
`BackgroundJobOutbox` 数据库迁移,再启动应用实例。 `BackgroundJobOutbox` 数据库迁移,再启动应用实例。
### 运维与审计控制台
超级管理员可从“组织与权限 → 运维与审计”查询写操作日志、三类失败后台任务、数据库、
缓存与任务通道健康状态,并查看由 5xx、失败/重试任务、健康探针和备份时效汇总出的异常
告警。查询接口和备份操作均在后端强制要求 `SuperAdmin`,不能只依赖前端菜单隐藏。
SQLite 开发环境直接使用在线备份 API。MySQL 环境需要在服务器安装 `mysqldump` 与
`mysql`(容器镜像已包含对应的 `mariadb-dump` 与 `mariadb` 客户端),并配置独立的
`ConnectionStrings__OperationsMySql`。该账号不得复用日常业务账号:它需要读取业务库,
并只应被授权创建和删除名称为 `jiaowu_restore_drill_*` 的临时演练库。恢复演练不会覆盖
当前业务库,流程是“校验 SHA-256 → 恢复到随机临时库 → 检查表结构 → 删除临时库”。
备份目录必须是仅服务账号可写的持久化目录。示例配置使用
`/var/lib/jiaowu/backups`;Compose 已挂载独立命名卷。启用 MySQL TLS 时,还要通过
`Operations__MySqlAdditionalArguments__N` 传入与所选命令行客户端匹配的 CA 与主机名
校验参数。例如 Oracle MySQL 客户端使用 `--ssl-mode=VERIFY_IDENTITY` 和
`--ssl-ca=/etc/jiaowu/mysql-ca.pem`,容器内 MariaDB 客户端使用 `--ssl`、
`--ssl-ca=...` 与 `--ssl-verify-server-cert`。
## 跨平台发布与 Docker ## 跨平台发布与 Docker
`.gitea/workflows/publish.yml` 只在推送 `v*` 标签或手动运行时执行,普通分支 push `.gitea/workflows/publish.yml` 只在推送 `v*` 标签或手动运行时执行,普通分支 push
Loaded 3 of 15 files, more files were not shown because too many files have changed in this diff. Show more