计算机协会主页的 Hugo 静态站点仓库,保存主页源码、主题配置、自动发布流程,以及服务器使用的 Docker Compose 部署配置与脚本。
当前已是使用真实计协品牌和资料的可浏览主页,不再是 Gentoo 社区示例首页。活动排期和成员档案等未确认内容仍明确标为占位,不能视为正式通知或真实成员名单。
- 使用 gentoozh-theme
v0.3.23,在 Hextra 之上提供 Gentoo 风格、Bento 首页及文章/贡献者页面模板。当前锁定的 Hextra 版本为v0.13.0。 - 沿用 Gentoo 原生 Bento 网格、文章卡片、共建方向卡片、文档侧栏和搜索,不重写页面结构;明暗配色采用从计协 Logo 蓝绿主色生成的 Material 3 色板。
- 已有首页、协会介绍、加入与交流、Touranki 项目展台、文章与活动、共学手册、四个共建方向及网站共建指南;文章标签、RSS、手机导航、群号复制和 404 页面均有对应入口。
- 使用本机提供的原版 CA Logo、两张最新招新海报及对应二维码、历史义务维修招牌裁图,以及 Touranki 项目既有背景。来源、裁剪方法和公开范围记录在
data/materials.yaml;未发布人脸合照、旧二维码、私人表单或原始 PPT。 - 协会介绍与参与方向依据已有公开资料整理。
content/posts/activity-example/是明确标注的活动文案示例;content/contributors/展示软件、硬件、内容设计和活动运营方向,成员档案待补充,不虚构人物或提交次数。 - 首页中的入口来自
data/home.yaml,最新文章从content/posts/读取;QQ 群号为1071797934与695523861。交流入口集中在content/join/index.md,二维码链接是否继续可用以 QQ 客户端为准。
主页域名为 hustca.cn,当前临时 HTTPS 入口为 https://hustca.cn:404/。入口可访问不表示占位内容已获确认,也不表示备案要求已满足。
| 路径 | 用途 |
|---|---|
hugo.yaml |
域名、语言、主题导入和页面参数 |
go.mod、go.sum |
Hugo Module 依赖及版本锁定 |
content/ |
首页与各栏目 Markdown 内容 |
archetypes/ |
新内容的默认前置元数据 |
assets/、static/ |
站点资源与原样发布的静态文件 |
layouts/、i18n/ |
主题允许的站点级适配与翻译,不修改下载的模块文件 |
data/home.yaml |
首页入口、社区链接、素材卡片与共建方向 |
data/materials.yaml |
素材来源、处理记录、使用限制及未发布材料说明 |
public/ |
本地或 CI 生成的静态站点,不纳入 Git |
deploy/ |
非敏感编排配置、Caddy 配置、镜像定义及发布脚本 |
.github/workflows/mainpage.yml |
PR 构建检查与 main 分支自动发布 |
.github/CODEOWNERS |
发布流程、主题配置和部署代码的维护者审查范围 |
Touranki 的游戏源码不在本仓库:分别由 touranki-web、touranki-server 与 touranki-core 管理。招新密码小游戏由独立的 password-game 私有仓库管理。deploy/ 保存这三个站点共享的服务器部署配置,不包含小游戏源码。
需要 Hugo extended 与 Go;CI 固定使用 Go 1.27.3,并用该工具链从源码编译 Hugo extended 0.154.5,避免沿用旧 Go 编译的构建工具。首次运行会拉取 go.mod、go.sum 锁定的主题模块。安装同版本 Hugo 需要 C/C++ 编译器:GOTOOLCHAIN=go1.27.3 CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@v0.154.5,并将 Go 的 bin 目录加入 PATH。
在仓库根目录执行:
# 本地预览,默认地址为 http://localhost:1313/
hugo server
# 生产构建,输出到 public/
hugo --environment production --minify --cleanDestinationDir --gc编辑首页文案从 content/_index.md 开始,入口配置在 data/home.yaml;菜单、Logo、搜索等参数在 hugo.yaml。文章放在 content/posts/<slug>/index.md,栏目已经设置 type: blog;共学手册在 content/docs/,方向档案在 content/contributors/。正式活动确认前,保留标题、摘要与正文中的占位标记。draft: true 的内容默认不进入生产构建。
layouts/shortcodes/home-bento.html保留原生 Bento 类名,改用计协数据,去掉 Gentoo 专属的固定社交链接与运行天数。layouts/contributors/list.html复用原生卡片,展示参与方向,不套用上游由权重推算提交次数的逻辑。layouts/_partials/通过主题扩展点替换站点身份、图标、元信息与页脚;layouts/404.html沿用主题错误页样式。- 原主题
assets/css/custom.css未覆盖;assets/css/site.css经custom/head-end加载,承载站点配色、导航适配、媒体尺寸与标题换行。 - 色板使用 Material 官方
material-color-utilities的 Tonal Spot/标准对比度方案:Logo 蓝#0ea1d7生成主色及中性表面,绿#32b76c生成辅助色。明暗语义色固化在 CSS 中,浏览器不加载配色库;按钮、标签、搜索弹窗与页面表面共用这些变量。 - 导航 Logo 在
hugo.yaml中设为28 × 28;搜索文字与快捷键保持单行、不参与挤压,低于64rem时显示带无障碍名称的搜索图标,点击仍打开完整搜索弹窗。 - Hugo Module 版本继续由
go.mod、go.sum锁定。主题许可位于static/licenses/;素材没有因此统一改授 MIT 或 CC 许可。
只提交源码和资源,不提交 public/、resources/ 或 .hugo_build.lock。 PR 的 Hugo build 检查会运行发布器边界测试并构建完整站点;合并到 main 后,GitHub Actions 自动构建、发布到 https://hustca.cn:404/,再通过受限命令请求官网 HTTPS 首页,核验本次发布版本与响应的 SHA256。
- 没有写权限的成员可以 Fork 本仓库,在自己的分支修改,再向
main提交 PR;无需服务器账号。已有写权限的成员也通过分支和 PR 提交,不直接推送main。 - 合并要求
Hugo build通过、分支与main同步,以及至少一位有写权限的维护者批准。.github/、deploy/、主题依赖、布局与样式配置还须由CODEOWNERS指定的维护者批准;新提交会撤销过时的批准。 - 仓库管理员保留紧急绕过权限;正常协作不绕过检查和审核。部署不再增加一次人工审批,合并后自动执行。
- 在 Actions → Mainpage 查看发布结果。外部贡献者的首次运行可能需要维护者批准;
draft: true的文章不会进入生产构建。
production环境只允许main分支部署。PR 构建没有生产密钥;部署 job 不检出源码,只接收同一次运行的静态归档并校验摘要。Actions 固定完整提交 SHA,主题模块只读,不在发布时更新依赖。- 环境 Secret
DEPLOY_SSH_KEY使用独立账号hustca-deploy的密钥,不能复用管理员私钥。环境 Variables 为DEPLOY_HOST、DEPLOY_PORT、DEPLOY_USER、SSH_KNOWN_HOSTS、SITE_URL;当前分别指向服务器、SSH 22、发布账号、经可信 SSH 会话核对的主机公钥、上述 HTTPS 入口。不能临时扫描主机公钥代替身份核验,也不能关闭 SSH 或 HTTPS 校验。 - 发布器源码为
deploy/scripts/publish-mainpage.py,服务器安装位置为/usr/local/libexec/hustca-publish.py,由 root 拥有。发布账号没有 sudo/Docker 权限,账号的家目录和公钥文件由 root 管理;公钥使用restrict,command="/usr/local/libexec/hustca-publish.py",只允许status、publish、verify,不允许 shell、SFTP 或端口转发。 verify在服务器上通过 HTTPS 请求官网,只接受hustca.cn的 404/443 端口首页。证书与域名校验开启,不跟随重定向;当前提交、运行编号、HTTP 200 和响应 SHA256 必须与本次构建一致。初始化时,GitHub 海外 runner 到hustca.cn及其子域在 TLS 握手阶段被重置,同 IP 的 Touranki 域名正常;因此由服务器执行 HTTPS 验收,不降低 TLS 安全要求。这不代表海外链路已经恢复,也不替代异地可达性检查。- 发布文件位于
/srv/hustca/releases/<run_id>-<run_attempt>-<commit_sha>/。完整上传、摘要与归档安全检查成功后,原子切换相对软链接current;上传或归档检查失败不会替换现有站点。并发发布加锁,旧运行不能覆盖新运行;归档上限为压缩后 64 MiB、展开后 128 MiB、10,000 个成员,禁止路径穿越、链接及特殊文件。 - Caddy 挂载父目录
/srv/hustca:/srv/mainpage:ro,根目录为/srv/mainpage/current。不能直接挂载current软链接,否则切换版本后容器可能继续读取旧目录。正常官网发布不重启 Caddy、Touranki 或密码小游戏。 - 最近五个已发布版本保留供恢复,发布记录保存在不对外提供的
receipts/中;GitHub 静态归档保留七天。
- 回滚通过撤销问题提交并提交 PR 完成,产生新的发布运行。不要重新运行旧提交的部署任务:旧提交和旧运行会被拒绝或跳过。仅需重发当前版本时,在
Mainpage中选择main手动运行。 - 发布后 HTTPS 验收失败会使 Actions 失败,但不会自动回滚已切换的版本。先根据日志和服务器发布记录判断故障位置,再决定是否回滚,不应仅凭网络探测失败覆盖已发布内容。
- 紧急恢复可由服务器维护者将
current原子切回releases/中已有版本,随后仍需撤销 Git 中的问题提交,避免下一次发布重新引入问题。 - 修改发布器后,由维护者审查、运行
python3 -m unittest discover -s deploy/tests -v,再以 root 更新服务器安装副本;CI 发布账号不能改写自身程序。公钥轮换也由维护者同时更新 root 管理的authorized_keys与 GitHub 环境 Secret。 deploy/scripts/deploy.sh是维护者在具备构建工具、Docker、密钥 SSH 和游戏源码仓库的发布环境使用的基础设施入口,不是服务器一键安装脚本。它只更新网关与游戏服务,不再读取或覆盖官网生成目录;运行时可能重建 Touranki 后端并丢失内存中的房间、会话与对局,不能拿来发布文章。- 服务器运行配置位于
/root/cateam,版本化副本位于本仓库deploy/。基础设施变更仍需单独维护;自动发布官网不意味着修改 Compose 或 Caddy 配置也会自动生效。 - 自定义错误页仍返回原 404 状态,域名及 404/443 端口映射保持不变。密码、私钥、面板凭据和其他秘密不得提交到仓库。
- PHP2Shell 公告对应 CVE-2026-109618/109619。服务器宿主机和四个生产容器均未部署 PHP、FPM、mod_php 或 FastCGI 路由,不受这两个漏洞影响;不要为此安装 PHP。
- eMudhra 中间 CA 事件对应 CVE-2026-111943 / GO-2026-6809。Go 的修复是拒绝八个受损中间证书的公钥,不是更换网站自己的证书。现有站点使用 Let's Encrypt;证书及私钥继续保存在原 Caddy 数据卷中。
- 网关镜像为
cateam/caddy:2.11.7-go1.27.3,由deploy/caddy.Dockerfile使用锁定摘要的官方 builder、Go 1.27.3 和 Caddy 2.11.7 源码构建。官方 Caddy 2.11.7 运行镜像的二进制仍由 Go 1.26.8 编译,不能只更新官方镜像标签就认为完成修复。构建使用goproxy.cn,保留 Go 校验数据库及 TLS 验证;可通过 Docker 的--build-arg GOPROXY=...指定其他模块代理。 - 面板使用 Portainer CE 2.45.3,官方修复包含 Go 1.26.10,并移除了镜像中的 emSign 根证书。升级前应检查外接的 SSO、LDAP、镜像仓库和 Git 服务是否使用 emSign 证书;当前面板使用本地账号认证。
- 宿主机的 CA 库不含此次受影响的 G3/AAA 信任锚,但容器信任库彼此独立,不能以宿主机更新代替容器修复。离线验证使用 Mozilla 提供的八个公开中间证书:显式加入测试信任池后,旧 Go 1.27.1 接受八个,Go 1.27.3 全部拒绝;未使用私钥或对线上服务运行漏洞利用。
- Touranki 和密码小游戏没有出站 HTTPS 或 mTLS 验证路径。Touranki 构建脚本已固定 Go 1.27.3,供下次正常发布使用;此次不重启在线 Touranki,以保留内存中的房间和会话。小游戏仅发布交流入口调整,规则和数据库版本不变。
安全更新应先备份面板数据卷、校验并加载镜像,再分别定向更新 gateway 和独立面板项目中的 portainer,使用 up -d --no-deps --no-build --pull never --wait;不要运行全项目 up 或重启 Docker 守护进程。网关更换会短暂中断连接,面板更换不影响游戏后端。
- 入口为 https://pg.hustca.cn:404/,DNS A 记录指向
121.40.128.93。404 端口直接提供 HTTPS 页面,不是跳转到 80 端口;备案及后续端口调整仍由服务器维护者处理。 - 题库融合同学提供的 30 条规则方案,当前共 43 个候选题;每局无放回抽取 10 题,按「易、易、中、易、中、中、难、中、难、难」排列,即简单 3、中等 4、困难 3。第四题固定从校园候选中抽取,包含
CAteam、1037、绝望坡、野猪、电动车、百团大战、武汉、华科、喻家山、东湖、东九、西十二、cateam、hustca;其他题位也有替换题。 - 每局题组在开始时抽好,输入不会换题,重新开始会重新抽取;当前已显示题目全部通过后自动解锁下一题,已解锁题目不会收回。密码不再有全局字符数上下限,仍须满足本局十条规则。需要汉字的题面加粗提示「请输入汉字,不是拼音」,输入框明确一个汉字算一个字符。罗马数字题已移除,题面只保留判定条件和必要的实时统计,不提供直接答案示例。
1037分支不抽「数字唯一」和「数字符号」,避免与连续门牌号及其他位置条件冲突。每个校园分支的整个可选题池都有通过规则引擎检验的共同解,因此其任意合法十题组合均可解;验证用答案仅在不对外发布的测试中,不提供自动填答或预置公开记录。- 前端使用原生 HTML/CSS/ES Module,服务端使用 Node.js 24+ 与内置 SQLite,不依赖 Hugo,也不复刻 Gentoo 模板。复用计协 Logo 与蓝绿 Material 配色,适配手机和系统暗色模式;灵感来自 The Password Game,不是原作官方版本。
- 普通游玩、通关、填写寄语和勾选同意都不会上传输入。只有通关后明确勾选公开同意,再点击「公开分享」,完整游戏密码、选填寄语和本轮题组才会上传、保存并向所有访客公开;页面禁止使用真实密码或个人信息。刷新和重新开始只清空本地游戏,不删除公开记录;当前没有玩家自助撤回接口。通关后仍提供招新页入口。
- 「查看大家的答案」位于通关后的按钮列表,未通关时不显示入口或列表;通关后无需先上传即可浏览。此限制用于避免剧透,不是访问授权,分享数据及读取接口仍是公开的。支持刷新、每页 12 条的游标分页、空列表及失败重试;每条记录可展开查看上传时的题面,旧版未存题组的记录有明确标识。密码、寄语和题面均仅作为文字渲染,不执行其中的 HTML。
- 浏览器需要支持
Intl.Segmenter;汉字和完整表情按用户感知的字符计数。开发需要 Node.js 24+,无 npm 依赖;在 password-game 仓库运行npm test、npm run build,再用npm run preview在http://127.0.0.1:18405/预览真实页面与 API。本地数据在被 Git 和 Docker 构建忽略的.data/shares.sqlite。 - 前后端共同使用
src/rules.js抽题、检查题号/题位及判定规则,避免浏览器伪造通关结果;交互在src/app.js、src/shares.js,共享题面渲染在src/rule-view.js,分享限制在src/share-policy.js,HTTP/SQLite 服务在server/。题目语义或抽取协议变化时应递增RULES_VERSION并同步前后端;已公开题面使用数据库快照展示,不按新题面重新解释。升级前已打开的旧页面须刷新后重新挑战。scripts/build.mjs只复制必要前端文件到public/;测试、数据库、服务端源码及 Git 文件不对外提供,构建产物不纳入小游戏 Git 仓库。 - v1.2.1 精简了游戏、分享和公开答案的文案,删除重复指导、字节数、规则版本号及多余说明区,保留必要的题面、安全告知和操作反馈,不用新文案填充留白;当时的规则与数据库版本均为 2。
- v1.3.0 移除游戏与分享的字符数门槛,并加入汉字输入提示。规则版本更新为 3;数据库仍为 2,无需迁移。此前公开的版本 1/2 记录及题面保持不变,可继续浏览。
服务器源码在 /root/password-game,生产前端和 API 一同构建进 cateam/password-game:local 镜像。Compose 的 password-game 服务以非 root 用户运行,只读根文件系统,不新增宿主机端口;现有网关通过 Compose 内网反向代理,复用 404/443 端口。静态页面使用 no-cache,API 使用 no-store;CSP 仅允许同源连接,仍禁止表单外送。Caddy 覆盖 X-Game-Client-IP,服务端仅在启用 TRUST_PROXY=1 时信任该值,避免客户端伪造限流来源。
分享数据位于命名卷 cateam_password_game_data 内的 /data/shares.sqlite,开启 WAL 与同步持久化;重启或更换容器不清空记录。v1.2.0 会在事务中将原三列分享表迁移到数据库版本 2,保留旧记录、ID、首次时间和已删除记录的自增高水位;不导入同学压缩包中的 .data、.git 或 public。升级前应备份生产数据库。不要执行 docker compose down -v,不要将数据库或 WAL 文件提交到 Git 或放进 public/。 备份应使用 SQLite 备份接口、VACUUM INTO,或只停止小游戏后备份完整数据卷,不能只复制运行中的主数据库文件而忽略 WAL。需要移除公开内容时,由服务器维护者在数据库中按记录 ID 处理。
POST /api/shares 接受本站来源的 JSON:password、显式 consent: true、rulesVersion: 3、按题位排列的十个 ruleIds,以及选填的 message。服务端验证版本、题位、难度、去重及冲突约束,再独立校验答案;不会信任客户端提供的通过标记或题面。按「完整密码+规则版本+有序题号」去重,同题组重复上传保留首次寄语和题面,不允许覆盖别人的内容。不同题组可分别分享同一字符串。
密码通关不设全局字符数上下限,公开分享也不再限制字符数,但仍保留 4096 个 UTF-8 字节的数据大小上限;超过该大小的答案可以通关,但不能上传。寄语去除首尾空白后最多 120 个字素簇、2048 个 UTF-8 字节,可留空。请求体最多 16 KiB。每个客户端每分钟最多 60 次提交尝试,限流地址只保存在有界内存中,不写入数据库;最多保存 10000 条记录,满后拒绝新增但仍可浏览、识别重复,不静默删除旧记录。GET /api/shares 支持 before 游标,返回密码、寄语、版本、题号和当时题面;GET /healthz 检查服务和数据库可读性。
小游戏源码修改后先提交、推送 GitHub,并将对应提交同步至服务器源码仓库。SSH 与 GitHub 各自需要有效的密钥或认证;发布脚本不保存 GitHub 凭据,也不自动执行 git pull。在具有 Docker、rsync 和密钥 SSH 的部署工作机上运行:
# 在本仓库运行;默认 SSH 别名为 cateam
bash deploy/scripts/deploy-password-game.sh该脚本通过 build-password-game.sh 归档服务器已提交 HEAD,使用锁定摘要的 Node 24 Alpine 基础镜像在工作机构建完整镜像,再通过 SSH 传给服务器;不发布未提交改动,也不依赖服务器访问 Docker Hub。它只更新小游戏容器、保留 SQLite 数据卷,验证并热加载 Caddy,不重建网关或 Touranki 后端。仅更新小游戏时,不要改用完整 deploy.sh。
如 SSH 不可达,可通过已经固定证书身份的 Portainer Docker API 传输 Git bundle、已构建镜像及这份版本化配置,再执行同样的限定操作:docker compose --project-directory /root/cateam up -d --no-deps --no-build --pull never --wait password-game,随后在 gateway 内运行 caddy validate 和 caddy reload。先确保源码与镜像来自同一提交;临时维护容器用后删除,凭据不得写入仓库。旧的宿主机 /root/password-game/public 静态挂载已退出生产发布流程。
主题与首页示例分别来自 Gentoo 主题仓库和 Gentoo 官网源码。使用或改写上游资源时,应遵守其原有许可证并保留必要署名。