当前位置:首页>Linux>不会 Linux,也能用 Codex 搭后端服务器(中):从 SSH 加固到备案提交

不会 Linux,也能用 Codex 搭后端服务器(中):从 SSH 加固到备案提交

  • 2026-10-11 06:35:23
不会 Linux,也能用 Codex 搭后端服务器(中):从 SSH 加固到备案提交
这是“AI 时代独立开发者服务器实验”的第二篇实战记录。上篇让一台 68 元的阿里云轻量服务器跑通了 Docker;这一篇继续完成安全底座、后端骨架、域名和备案准备
不会Linux,也能用Codex搭后端服务器(上)结束时,Docker 能跑,但还不能放业务,只是解决了“服务器能不能用”的问题,但离“能不能长期放业务”还有一段距离

当时仍有四个明确待办:

    1. SSH 密钥已经验证,但密码登录和 root 登录还没有关闭
    2. 系统缺少持续跟踪安全更新的内核元包
    3. vm.swappiness 临时改成了 10,重启后却又恢复为 0
    4. “惜诗工具箱”和“汉字防线”都已经上架,但自己的后端代码、域名和备案还没有准备好

    所以这篇文章的目标不是急着开放网页,而是先把上线前最容易出问题的基础工作补齐

    我先给 Codex 定了一条规则:需要我操作时必须停下来

    本来计划让Codex直接操作浏览器完成接下来的设置:

    可以codex实在太慢了,我还是决定我和codex合作完成:

    修改 SSH、重启服务器、调整防火墙,都可能造成真实影响。特别是关闭 SSH 密码登录,如果密钥配置有误,人会直接被锁在服务器外面

    因此这次采用的协作方式是:

    • Codex 负责分析现状、生成命令、解释风险和判断返回结果
    • 我负责保管私钥和口令,确认主机指纹,并在独立终端测试登录
    • 每遇到一个高风险节点,Codex 必须停下来,等我完成后再继续
    • 所有操作写入日志,能重复的检查沉淀为脚本

    这会比“一次粘贴几十行命令”慢,但每一步都知道成功条件、失败影响和恢复方法

    对不会 Linux 的人来说,这种节奏比记住命令更重要

    1. 关闭 SSH 密码之前,先保留两条退路

    正式加固前,我同时保留了两种已经验证的连接方式:

    • Mac 上使用独立 ED25519 私钥建立的 SSH 会话
    • 阿里云 Workbench,以及服务器上原有的 Workbench 恢复公钥

    私钥只保存在 Mac 的~/.ssh/,没有上传到服务器,也没有交给 Codex

    配置写入独立文件:

    /etc/ssh/sshd_config.d/00-server-lab.conf

    核心设置如下:

    PubkeyAuthentication yesPasswordAuthentication noKbdInteractiveAuthentication noPermitEmptyPasswords noPermitRootLogin noMaxAuthTries 3LoginGraceTime 30X11Forwarding no

    这里使用00-前缀,是因为 Ubuntu 会按顺序读取sshd_config.d中的配置,而 OpenSSH 的不少选项采用“先读到的值生效”。云镜像可能已经带有自己的 SSH 配置,文件名排序会直接影响最终结果

    写完文件不等于完成。真正的验证顺序是:

    sudo sshd -tsudo systemctl reload sshsudo sshd -T | grep -E \  '^(pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitrootlogin) '

    其中:

    • sshd -t 检查配置语法
    • reload 平滑加载新配置,不主动中断已有连接
    • sshd -T 查看 OpenSSH 最终实际采用的值,而不是只看某一个文件

    最后必须从 Mac 新开一个终端,再用私钥登录一次。旧会话还在线,不能证明新连接一定成功

    最终复检结果是:

    permitrootlogin nopubkeyauthentication yespasswordauthentication nokbdinteractiveauthentication no

    新密钥会话可以登录,密码认证被拒绝,root 不能直接通过 SSH 登录,Workbench 恢复通道也仍然保留。到这一步,SSH 加固才算闭环

    2. 一个真实的坑:把 Mac 命令粘贴到了服务器

    测试过程中,我曾在 Workbench 里执行了本应在 Mac 终端运行的命令:

    ssh -i ~/.ssh/server_ed25519 admin@服务器地址

    服务器当然找不到只存在于 Mac 上的私钥,于是提示:

    Identity file ... not accessible: No such file or directory

    随后 SSH 退回密码认证,并连续失败

    判断自己在哪个终端,可以先看提示符:

    Mac 本地终端:通常以本地用户名开头,以 % 结束服务器终端:通常类似 user@host:~$

    解决方法不是把私钥复制到服务器,而是回到 Mac 终端执行登录命令。私钥应该始终留在本地可信设备。

    为什么 AI 运维的重点是“验证链”

    这次最有价值的不是 Codex 写出了 SSH 配置,而是它把高风险操作拆成了可以观察的状态:

    确认恢复通道  -> 验证独立密钥  -> 备份原配置  -> 写入候选配置  -> 检查语法  -> 平滑加载  -> 新终端密钥登录  -> 验证密码认证已关闭

    任何一步不符合预期,都停在原地,不继续收紧下一项

    不会 Linux 并不意味着可以跳过判断。更现实的方式是让 AI 告诉你:为什么执行、应该返回什么、返回不同结果时该怎么办

    小服务器也要控制维护成本

    SSH 加固完成后,我先创建了内核升级前的系统盘快照,再处理系统更新留下的问题

    Ubuntu 服务器如果只有一个固定版本的内核镜像,却没有内核元包,普通软件更新不一定会持续安装后续内核安全版本

    最初模拟安装linux-virtual时,会带入约 20 个包,包括头文件、编译和跟踪相关组件。它们不是坏东西,但当前机器只负责运行轻量后端,不需要在生产服务器编译内核模块

    继续模拟更精简的linux-image-virtual后,只需要新增 3 个包:

    linux-image-6.8.0-136-genericlinux-modules-6.8.0-136-genericlinux-image-virtual

    下载量约 54MB,磁盘增加约 54.5MB

    最终选择linux-image-virtual。它保留了后续内核镜像更新链路,又没有带入当前用不到的开发组件,更适合 2 核 2GB 的个人服务器

    这里的重点不是“装得越少越好”,而是让每个长期存在的软件包都有明确用途

    swappiness 明明改成 10,为什么重启后又变成 0

    这台服务器有 2GB Swap,但阿里云镜像原配置中存在:

    vm.swappiness = 0

    swappiness=0并不是禁用 Swap,但系统会尽量避免使用它。对只有约 2GB 内存、还要运行 Docker 的服务器,我希望保留更温和的缓冲,所以设为10

    问题是:运行时执行sysctl -w后显示为10,第一次重启却又回到了0

    检查后发现,/etc/sysctl.conf和多个 drop-in 中同时存在这个配置。与其继续增加一个“文件名排得更后”的配置文件,不如先备份,再把所有有效来源统一为同一个值

    验证时同时看持久化配置、当前运行值和 Swap 状态:

    sudo grep -nE '^[[:space:]]*vm\.swappiness[[:space:]]*=' \  /etc/sysctl.conf /etc/sysctl.d/*.conf 2>/dev/null || truesysctl vm.swappinessswapon --showfree -h

    维护重启后,结果稳定为:

    vm.swappiness = 10/swapfile file 2G

    这个问题给我的提醒是:

    命令当场成功,只能证明当前运行状态;涉及系统配置,必须再验证一次重启后的状态

    新内核安装成功,也不能马上重启

    安装完成时,新内核文件已经出现在/boot,但服务器当时仍运行旧内核。这是正常的,只有重启后才会切换

    重启前,Codex 又让我检查了四件事:

    1. GRUB 配置文件存在且非空
    2. 新内核和对应的 initrd 已写入启动菜单
    3. 默认启动项没有锁定到旧内核
    4. grub-script-check
      语法校验通过

    同时保留:

    • 阿里云控制台和 Workbench 恢复入口
    • 内核升级前快照
    • 旧内核文件
    • 已登录的密钥会话

    确认这些恢复路径后,我才单独批准维护重启

    服务器约两分钟后恢复,运行内核变为:

    6.8.0-136-generic

    随后又验证了内核元包、Swap、SSH、Docker、失败服务、监听端口和是否仍需重启。结果如下:

    底座验收通过后,我又创建了一份“首次服务部署前”快照。以后应用部署出问题,可以恢复到这一个干净、可登录、Docker 正常的基线,而不需要从头初始化

    两个产品都已上架,但我还没有自己的后端

    服务器底座完成后,才进入真正的应用部分

    我目前有两个同一个人主体下的微信产品:

    • 小程序“惜诗工具箱”
    • 小游戏“汉字防线”

    它们都已经上架,目前仍使用第三方接口。第一阶段并不迁移线上业务,也不安装数据库,只做自己的 API 连通测试

    后端技术一开始也没有确定。结合服务器配置和个人维护成本,最终先采用:

    TypeScript + Node.js 22 + Fastify 5 + Nginx + Docker Compose

    选择这套组合的原因很朴素:

    • 小程序前端本来就使用 JavaScript/TypeScript,减少一套语言切换
    • Fastify 启动快、资源开销较小,自带 Schema 和测试注入能力
    • Nginx 负责统一入口,API 容器不直接暴露到宿主机
    • Docker Compose 足够管理当前两三个轻量容器,不需要 Kubernetes

    Python + FastAPI 也很适合个人项目,后续如果增加 AI 或数据处理任务,可以单独增加 Python 服务。Java + Spring Boot 并非不能运行,但对现在的 2 核 2GB 和“只做连通测试”来说,学习与维护成本更高

    第一个后端不是业务系统,而是一个可验证的骨架

    Codex 在本地项目中创建了共享服务miniapps-api,先实现四个接口:

    GET /healthGET /api/v1/pingGET /api/v1/toolbox/pingGET /api/v1/game/ping

    其中:

    • /health 用于容器和反向代理健康检查
    • /api/v1/ping 验证通用 API 链路
    • /api/v1/toolbox/ping 对应惜诗工具箱
    • /api/v1/game/ping 对应汉字防线

    两个产品可以复用同一台服务器、同一个 API 域名和基础设施,但路由从第一天就分开。以后即使共用数据库,权限和数据表也不应该因为“省事”而混在一起

    当前本地验证结果是:

    • TypeScript 严格类型检查通过
    • 5 项接口测试通过
    • 生产构建通过
    • 生产依赖审计为 0 个已知漏洞
    • Fastify 服务在 Mac 回环地址实际启动并返回预期结果

    这里必须强调:

    后端骨架目前只在本地完成,尚未上传或启动到服务器,不能把它描述成线上服务

    为什么 Nginx 先只绑定 127.0.0.1:8080

    第一阶段设计的访问链路是:

    服务器本机 curl       |       v127.0.0.1:8080       |       vNginx 容器 :8080       |       vFastify API 容器 :3000

    API 容器不映射宿主机端口,Nginx 也只发布到:

    127.0.0.1:8080

    这样第一次部署时,可以先验证:

    • 镜像能否构建
    • 两个容器能否正常启动
    • 健康检查能否通过
    • Nginx 能否把请求代理到 Fastify
    • 重启策略、日志轮转和资源限制是否生效

    与此同时,阿里云防火墙不需要开放8080,公网仍然只有 SSH 的22端口

    容器还配置了非 root 用户、只读根文件系统、移除 Linux capabilities、进程数限制、CPU/内存限制和 Docker 日志轮转。对个人服务器来说,这些边界比安装一套复杂运维平台更实用

    为什么现在不安装数据库

    第一阶段只有 ping 和健康检查,数据库解决不了任何真实问题,却会立即带来备份、恢复、升级、密码和数据安全成本

    所以当前不安装 MySQL、PostgreSQL 或 Redis

    等第一个真实功能明确后,再根据数据类型选择:

    • 数据量很小、单机使用:可以先评估 SQLite
    • 需要并发写入、关系查询和长期演进:再使用 PostgreSQL 或 MySQL
    • 只是缓存、限流或短期状态:有明确需求后再增加 Redis

    数据库不会开放公网端口。即使以后运行在 Docker 中,也只允许应用容器通过内部网络访问,并单独设计备份和恢复验证

    15 元获得首年域名,但不能只看“便宜”

    域名方面,我原本看到一个.cn域名首年 38 元、正常续费 42 元的方案

    后来发现阿里云的一个建站体验活动:购买一个月 15 元的建站产品,可以获得一年域名权益。我的实际首年支出因此变成 15 元,建站系统本身不准备使用

    但这种优惠有三个必须核对的地方:

    1. 赠送域名是否真的包含自己选择的后缀和年限
    2. 退订或变更建站产品是否会影响已经获得的域名权益
    3. 建站产品和域名是否分别开启自动续费

    我最终确认建站产品自动续费处于关闭状态,域名以后按正常价格续费,目前显示为 42 元/年

    活动规则可能随时变化,这里记录的是一次真实购买经历,不代表所有账号、所有时间都能获得同样价格。购买前必须以结算页、服务协议和正常续费价为准

    域名不能买完就立刻备案

    这次还踩到了一个流程顺序问题

    .cn域名注册前,应该先创建个人域名持有人信息模板,并等待模板实名认证通过。否则即使优惠订单已经准备好,也可能因为没有可用模板而无法继续注册

    更稳妥的顺序是:

    创建个人信息模板  -> 模板实名认证通过  -> 注册域名  -> 域名实名认证完成  -> 等待备案系统同步  -> 提交个人 ICP 备案

    域名实名认证成功后,阿里云提示至少等待 3 天再进行备案。这个等待不是让域名“再审核一次”,而是让注册局、注册商和备案校验系统同步域名持有人与注册状态

    如果过早提交,备案系统可能暂时检索不到域名,或者提示实名信息不一致

    等待同步完成后,我通过“万小智·备案助手”提交了个人备案资料。当前进度已经进入:

    资料提交完成  -> 阿里云初审(当前)  -> 提交管局  -> 工信部短信核验  -> 管局审核

    当前只是阿里云初审,不等于备案已经通过。平台显示的预计初审时间也只是服务进度提示,最终仍要以实际审核状态为准

    创建个人信息模板 → 模板实名认证通过 → 注册域名→ 域名实名认证完成 → 等待备案系统同步(约3天) → 提交个人ICP备案

    小程序和小游戏共用域名,还需要分别配置

    “惜诗工具箱”和“汉字防线”属于同一个人主体,可以共用一个根域名,并使用统一的 API 子域名

    但共用服务器不等于微信后台只配置一次

    等备案完成、HTTPS 配置成功后,还要分别进入小程序和小游戏的管理后台,把同一个 HTTPS API 地址加入各自的服务器域名配置

    正式请求域名通常还需要满足:

    • 使用已经备案的域名,不能直接填写公网 IP
    • 使用有效的 HTTPS 证书
    • 不在域名中填写自定义端口
    • DNS 已正确解析到服务器
    • 服务端证书链完整,接口能稳定访问

    因为目前不使用微信支付,这一阶段不需要处理商户平台、支付回调域名和支付证书,范围可以保持很小

    到这里,服务器到底处于什么阶段

    当前真实状态如下:

    所以这篇完成的不是“正式上线”,而是把上线所需的安全、代码和合规前置条件准备好

    当前实际成本

    83 元只是第一年的已知现金成本。长期预算还必须考虑服务器正常续费、域名续费、对象存储、短信和第三方接口费用

    这次最值得记录的 10 个坑

    • 关闭密码登录前,必须先验证独立密钥并保留恢复通道
    • 已有 SSH 会话不断,不代表新连接还能成功
    • Mac 私钥找不到时,不要把私钥复制到服务器
    • 内核镜像安装成功,不代表 GRUB 一定会默认启动它
      sysctl -w 当场生效,不代表重启后仍然生效
    • ssh.service disabled 不一定是故障,还要检查ssh.socket
    • 小服务器安装软件要考虑后续更新和维护成本,而不只是磁盘占用
    • 没有业务需求时先别安装数据库
    • 域名购买前应先准备实名认证信息模板
    • 域名实名认证完成后,备案系统仍可能需要几天同步

    Codex 能做什么,不能替我做什么

    这一阶段,Codex 帮我完成了:

    • 分析 SSH 加固风险并生成可回滚脚本
    • 根据真实返回结果判断配置是否生效
    • 对比完整内核元包和精简镜像元包的依赖差异
    • 检查 GRUB、重启条件和重启后的系统状态
    • 生成可重复的服务器底座验收脚本
    • 设计适合 2 核 2GB 的 TypeScript/Fastify API
    • 编写测试、Dockerfile、Compose、Nginx 和部署检查脚本
    • 根据产品主体、域名成本和备案状态调整后续顺序
    • 把真实过程整理成操作日志和文章素材

    但它没有替我保管私钥、输入口令、确认高风险操作、决定备案内容或承担审核责任

    我越来越确定,AI 管服务器最合理的分工不是“把 root 权限交给它,然后等结果”,而是:

    人负责边界、身份、秘密和最终确认;Codex 负责分析、自动化、验证和记录

    下篇要真正把服务跑起来

    等阿里云初审、短信核验和管局审核继续推进时,服务器内部部署可以先独立进行

    下篇计划完成:

    1. 把 API 项目安全上传到服务器
    2. 在服务器构建并启动 Fastify 与 Nginx 容器
    3. 先通过127.0.0.1:8080完成内部连通验证
    4. 备案通过后配置 DNS 解析
    5. 开放公网80/443,不开放数据库和容器内部端口
    6. 申请并验证 HTTPS 证书
    7. 分别为惜诗工具箱和汉字防线配置微信合法请求域名
    8. 用两个产品完成第一次真实的 HTTPS API 连通测试

    到了那一步,这台 68 元服务器才会从“准备好”真正变成“提供服务”

    域名注册前,应先创建个人域名持有人信息模板并等待实名认证通过否则即使优惠订单已准备好,也可能因没有可用模板而无法继续注册

    最新文章

    随机文章