第 18 课:完成正式环境安全加固
第五阶段 · 正式生产环境 · 面向 Docker 初学者
本课完成标准
你能够用“只开放必要端口”的原则检查 ECS;保护 .env、宝塔密码、SSH 私钥和 JWT 密钥;限制 SSH 与宝塔访问来源;避免日志泄露密码和 Token;完成上线前安全清单。
1. 先理解安全边界
正式环境像一栋办公楼:安全组是大门,Nginx 是前台,FastAPI 是办公室,MySQL 是档案室。大门只打开必要入口,数据库和内部端口不应对陌生人开放。
2. 最小化公网端口
| 端口 | 用途 | 建议 |
|---|---|---|
| 22 | SSH | 只允许固定 IP,或使用密钥登录 |
| 80 | HTTP 跳转和证书验证 | 开放 |
| 443 | HTTPS | 开放 |
| 8000 | FastAPI 内部 | 不开放,绑定 127.0.0.1 |
| 3306 | 宝塔 MySQL | 不开放公网 |
| 8888 | 宝塔面板 | 限制来源 IP,修改默认入口 |
在阿里云安全组和宝塔防火墙都检查一次。两边都要遵循最小权限。
3. 保护环境变量和密钥
.env 可能包含 DB_PASSWORD、JWT 密钥和管理员账号,只能留在 ECS,不应提交 GitHub。
cd /www/wwwroot/student-management-api; git status; git ls-files .env; chmod 600 .env
如果 git ls-files .env 有输出,说明它已经被 Git 跟踪:先从版本控制中移除,再轮换已经暴露的密码和密钥。.gitignore 只能阻止未来新增,不会自动删除历史提交。
不要在 Dockerfile 中写密码,也不要把真实密钥写进前端 JavaScript。
4. SSH 和宝塔账号
- 使用 SSH 密钥,禁用密码登录前先确认密钥可用;
- 不使用 root 运行日常命令,按需使用
sudo; - 宝塔使用强密码和二次验证(如果版本支持);
- 宝塔面板端口和入口只允许自己的管理 IP;
- 私钥只保存在自己的电脑,不能上传网盘或 GitHub。
修改 SSH 配置前保持当前 SSH 会话,先开第二个会话测试新配置,避免把自己锁在服务器外。
5. 日志和错误信息
生产日志应帮助排查,但不能暴露密码、Token、Cookie、Authorization 请求头或完整数据库连接串。
docker compose logs --tail=100 api
分享日志前替换:password=真实密码 → password=***,Authorization: Bearer … → Authorization: Bearer ***,mysql://user:pass@… → mysql://user:***@…。生产 API 不要开启调试模式,不要把 traceback 直接返回用户。
6. 数据库和文件权限
- MySQL 用户只授予项目数据库需要的权限,不用 root 连接应用;
- 宝塔 MySQL 只监听本机或受控内网;
- 静态资源目录允许 Nginx 读取,但不能执行上传脚本;
- 上传文件设置大小限制和类型校验;
- 备份文件不要放在可被 Nginx 下载的静态目录。
7. 上线前安全清单
- 8000、3306 没有公网访问;
- 安全组只开放 22(受限)、80、443;
- 宝塔入口已限制来源并启用强密码;
-
.env没有提交 GitHub,权限为600; - 数据库不是 root 用户;
- JWT、数据库和管理员密码不是默认值;
- HTTPS 有效并设置自动续期;
- 日志没有密码、Token 和 Cookie;
- 数据库和静态资源有备份方案;
- 已记录 Git 提交和 Alembic 迁移版本。
8. 一分钟自测
.gitignore 的作用是什么?
- A. 阻止指定文件被 Git 继续追踪或新增提交
- B. 自动加密
.env - C. 自动删除 GitHub 历史中的密码
答案:A。若密码已经提交过,必须移除历史并立即更换密码。
本课通关证据
git ls-files .env; docker compose ps; docker compose logs --tail=100 api
保存安全组截图、端口检查结果、.env 未被跟踪的证明和清单。不要上传真实密钥。
完成后进入第 19 课:发布、升级与回滚。遇到安全问题时,请先隐藏敏感值再提问。
想系统学习这门课程?
你已阅读完本文。需要更完整的知识体系,可以继续了解「Vibe Coding 实战课程」。
查看课程详情