这是「把自己部署到互联网上」系列的第 17 篇。
从第 11 篇到第 16 篇,我一直在写服务器安全。这几篇没有部署成功截图,没有博客页面上线,也没有复杂架构图,讲的都是普通用户、root 登录、SSH、安全组、防火墙、数据库端口、服务器扫描、fail2ban、日志和健康检查。
这些内容不算新颖,但写完这一段后,我更确定了一件事:对一台准备长期暴露在公网的服务器来说,部署项目之前,必须先把基础安全边界建好。
这篇是服务器安全阶段的复盘,不包含太多操作,只是把前面几篇串起来,看看我为什么从“赶紧部署博客”,变成了“先把服务器边界理清楚”。
归档
第 10 篇之前,我主要解决的是动机问题:为什么做个人博客,为什么建设技术品牌,服务器怎么买,域名怎么选,备案怎么理解,ICP备案怎么填。那一阶段解决的是个人博客如何从一个想法,变成一个可以走向公网的入口。
从第 11 篇开始,视角转到服务器。服务器已经买了,也有公网 IP。按理说,下一步最自然的动作是部署项目。但我没有马上这么做,而是先处理安全。
这一阶段主要完成了几件事:明确公网服务器不是本地开发环境;创建普通用户,减少长期 root 操作;理解安全组和防火墙的关系;确认数据库端口不能随便暴露公网;通过扫描日志意识到公网风险是真实存在的;最后整理出个人服务器上线前的基础安全清单。
这些动作没有直接让博客上线,但它们让服务器从“刚买来的裸机”,变成了一个更适合承载项目的环境。
说实话,买完服务器后,我最想做的是部署项目。拉代码,装 Docker,起数据库,跑服务,配 Nginx,绑定域名,打开浏览器看到页面。这才是最直观的成就感。
安全初始化正好相反。创建普通用户,页面不会出现;配置安全组,文章不会发布;检查日志,博客也不会上线;整理健康检查命令,读者更看不到变化。从短期反馈看,它并不讨喜。
但个人博客不是学习用的Demo。它后面要承载文章、项目、作品站、公众号回流、Git 合集和个人品牌入口。如果它是长期项目,就不能只看第一天能不能访问,还要看它能不能稳定维护。稳定维护的前提,是不要把一台边界混乱的服务器直接放到公网。
调整顺序
这一阶段最重要的过程,是我调整了上线顺序。
以前
以前我可能会先部署项目顺序:
- 项目跑起来后再补安全;
- 出问题后再查日志;
- 需要远程连数据库时再开放端口;
- 发现登录尝试后再装
fail2ban。
这种做法上线项目很快,但项目长期稳定运行就容易埋坑。
现在
现在部署项目我更愿意按照下面的顺序:
- 确认服务器环境
- 创建普通用户
- 梳理
SSH - 安全组、防火墙
- 明确哪些端口不能开放
- 知道日志在哪里看
- 建立基础健康检查习惯
- 然后再部署项目
这个步骤看起来比较复杂,但后面排查问题会更清楚。项目真正跑起来后,我知道入口在哪里,权限边界在哪里,端口由谁控制,数据库有没有暴露,日志应该从哪里看。这比上线后再临时补救更稳。
思维改变
这一阶段带来三个关键认知变化。
个人小型服务器也会被扫描
以前我有个误判:个人项目很小,应该没人关注。看到服务器4个小时被扫 500 多次后,才意识到,扫描不是因为你重要,而是因为你在公网。只要有公网 IP,只要有端口开放,就可能被自动化脚本扫到。安全并不是大公司、有价值的业务才需要考虑的事。
端口不是越方便越好
以前部署项目时为了方便,端口访问规则比较宽泛:
-
SSH连不上,放开一点 -
数据库连不上,放开一点
- 项目调试不通,再放开一点
短期看问题解决了,长期看入口越来越多,边界越来越乱。所以经过这段时间,给自己的原则是:公网只开放必须开放的端口。博客真正应该对外的入口,主要是 Nginx 的 80、443,以及受控的 SSH 管理入口。数据库、内部服务、调试端口,不应该随意暴露在公网。
日志不是出事后才看
以前我查看日志比较被动,服务报错、部署失败、业务无法访问时才去查。但服务器暴露公网后,日志还能告诉你这台机器正在经历什么:SSH 登录失败、异常请求、服务重启、端口监听、资源变化。
小结
从表面看,这一阶段没有上线博客。但实际上,完成了几项基础能力。
第一是权限边界。普通用户和 root 分开,日常操作不再默认最高权限。
第二是入口边界。安全组和防火墙分层理解,知道公网流量从哪里进来。
第三是数据边界。数据库端口默认不暴露,内部服务尽量留在内部网络里。
第四是观察能力。知道如何看 SSH 日志、系统日志、服务状态、端口监听和资源占用。
第五是安全意识。不再用“个人项目没人看”安慰自己,而是按公网服务器的现实环境来处理。
这五件事加起来,感觉比单纯把项目跑起来更重要。因为它们决定后面部署项目时,我是不是在一个相对清晰、可控的环境里操作。
如何看待安全
当然,做完这一阶段不代表服务器就安全了。安全不是一次配置完就结束,它更像长期维护习惯。后面部署
Docker、Nginx、数据库、HTTPS、对象存储时,还会遇到新的安全问题:容器端口怎么映射,Nginx配置是否泄露路径,证书如何续期,数据库密码和环境变量怎么管理,上传资源如何控制访问,管理后台如何保护,日志和备份怎么处理。
所以这一阶段只是打底,不是终点。它的价值在于,先给后续部署提供一个清楚的起点。
这几篇看起来像运维笔记,但放到技术阵地建设里,它们也有明确意义。个人品牌不是只有表达,还需要稳定承载。如果博客经常打不开,服务器经常异常,数据库暴露公网,SSH 被持续尝试登录,日志从来没人看,那么这个入口就不可靠。
我想搭的不是临时页面,而是一个长期放文章、项目、复盘和作品的地方。安全不是额外工作,而是基础设施的一部分。
接下来,服务器安全阶段告一段落,下一阶段进入部署方案选择。也就是一个很现实的问题:生产环境到底该用 Conda 还是 Docker?
这个博客项目会涉及 Python 环境、数据库、依赖、服务启动、后续迁移和多项目部署。如果只在本地开发,Conda 可能很方便;但放到服务器长期运行时,还要考虑环境复现、依赖隔离、多项目共存、数据库管理、服务重启、迁移成本,以及全局 Nginx 统一代理。
前面安全阶段解决的是:这台服务器能不能更稳地承载项目。下一阶段要解决的是:项目应该以什么方式放到这台服务器上。
本文由 楸木 原创,转载请注明出处。