Codex + SSH 远程运维实战:让 AI 管你的云服务器

从 Docker 部署到数据库调优,从日志排查到安全加固——用 Codex CLI 通过 SSH 管理云服务器的完整实战指南。


一、为什么用 Codex 做运维?

传统运维的痛点:

  • 半夜报警,睡眼惺忪敲命令,手滑 rm -rf 的恐惧
  • 排查问题要同时盯 5 个终端窗口
  • 不熟悉的中间件(如 pgvector)需要现查文档
  • 配置调优参数太多,试错成本高

Codex 做运维的天然优势:

  • 终端原生:SSH 过去就是它的家,不需要任何适配
  • 并行处理:同时 tail 3 个日志文件 + 检查进程状态 + 分析错误模式
  • 知识广度:Nginx、Docker、PostgreSQL、Redis、JVM……它都懂
  • 安全可控:所有命令先展示再执行(approval mode),AGENTS.md 禁止危险操作

二、环境准备

2.1 服务器配置(以 CentOS 7/Ubuntu 22.04 为例)

CPU: 4 核
内存: 8 GB
磁盘: 40 GB SSD
系统: Ubuntu 22.04 LTS

2.2 本地 Codex 连接

# 在 Codex CLI 中直接 SSH
ssh root@your-server-ip

# 或者用跳板机
ssh -J jump-user@jump-ip root@target-ip

2.3 先让 Codex 摸清服务器底细

连接后第一条指令非常重要——让 AI 先了解环境:

我:"检查当前服务器的操作系统、CPU、内存、磁盘、已安装的关键软件(Docker、Java、Node.js),生成一份环境报告"

Codex 会自主执行:

cat /etc/os-release
lscpu | head -15
free -h
df -h
docker --version 2>/dev/null
java -version 2>/dev/null
node --version 2>/dev/null

这样后续的所有操作,AI 都基于准确的环境信息做决策,而不是瞎猜。


三、Docker 环境部署

3.1 让 Codex 安装 Docker + Docker Compose

我:"在这台 Ubuntu 22.04 上安装 Docker CE 和 Docker Compose v2。
     使用官方源安装,不要用 snap。安装完成后启动 Docker 并设置开机自启。
     最后运行 docker run hello-world 验证。"

Codex 的执行流程:

# 1. 卸载旧版本
apt-get remove docker docker-engine docker.io containerd runc

# 2. 安装依赖
apt-get update && apt-get install -y ca-certificates curl gnupg

# 3. 添加 Docker 官方 GPG key
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 4. 添加仓库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
  tee /etc/apt/sources.list.d/docker.list

# 5. 安装
apt-get update && apt-get install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

# 6. 启动 + 验证
systemctl enable docker --now
docker run --rm hello-world

💡 为什么不用手敲:Docker 官方安装步骤在不同 Linux 发行版上命令不同。Codex 会自动检测系统版本(lsb_release -cs)并拼接正确的源地址。光这一步,省了 10 分钟查文档的时间。

3.2 编写 docker-compose.yml

AIGrader 项目需要 PostgreSQL + pgvector + Redis。让 Codex 生成编排文件:

我:"为 AIGrader 项目编写 docker-compose.yml,包含以下服务:
1. PostgreSQL 16 + pgvector 扩展,数据库名 ai_grader,用户 ai_grader,密码通过环境变量注入
2. Redis 7,选择 DB=2
3. 两个服务都配置健康检查
4. 数据卷挂载到 /data/postgres 和 /data/redis
5. 网络使用自定义 bridge 网络 aigrader-net"

Codex 生成的 docker-compose.yml

version: '3.8'

services:
  postgres:
    image: pgvector/pgvector:pg16
    container_name: aigrader-postgres
    environment:
      POSTGRES_DB: ${DB_NAME:-ai_grader}
      POSTGRES_USER: ${DB_USER:-ai_grader}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    ports:
      - "5432:5432"
    volumes:
      - /data/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-ai_grader} -d ${DB_NAME:-ai_grader}"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - aigrader-net

  redis:
    image: redis:7-alpine
    container_name: aigrader-redis
    command: redis-server --appendonly yes --databases 16
    volumes:
      - /data/redis:/data
    healthcheck:
      test: ["CMD", "redis-cli", "-n", "2", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - aigrader-net

networks:
  aigrader-net:
    driver: bridge

然后 Codex 会执行:

# 创建 .env 文件(敏感信息不提交)
cat > .env << 'EOF'
DB_NAME=ai_grader
DB_USER=ai_grader
DB_PASSWORD=ai_grader123
EOF

# 创建数据目录
mkdir -p /data/postgres /data/redis

# 启动
docker compose up -d

# 验证
docker compose ps
docker compose logs --tail=20

四、数据库部署与初始化

4.1 让 Codex 初始化数据库 Schema

AIGrader 用 JPA 的 ddl-auto: update 自动建表,但种子数据需要手动导入。

我:"连接到 PostgreSQL 容器,执行 backend/src/main/resources/seed.sql 中的种子数据。
     先检查 pgvector 扩展是否已启用,如果没有则 CREATE EXTENSION vector。
     导入后验证每张表的行数。"

Codex 实操:

# 进入容器
docker exec -it aigrader-postgres bash

# 验证 pgvector
psql -U ai_grader -d ai_grader -c "SELECT * FROM pg_extension WHERE extname='vector';"

# 如果没有,则创建
psql -U ai_grader -d ai_grader -c "CREATE EXTENSION IF NOT EXISTS vector;"

# 导入种子数据
psql -U ai_grader -d ai_grader -f /path/to/seed.sql

# 验证
psql -U ai_grader -d ai_grader -c "
SELECT 'users' as tbl, count(*) FROM users
UNION ALL SELECT 'questions', count(*) FROM questions
UNION ALL SELECT 'assignments', count(*) FROM assignments;
"

4.2 数据库连接池调优

我:"检查当前 PostgreSQL 的最大连接数配置,并根据 AIGrader 应用预计 20 并发来建议连接池参数。
     修改 Spring Boot 的 application.yml 中的 HikariCP 配置。"

Codex 分析并建议:

# 查看当前配置
docker exec aigrader-postgres psql -U ai_grader -d ai_grader -c "SHOW max_connections;"
# → 100

docker exec aigrader-postgres psql -U ai_grader -d ai_grader -c "
SELECT count(*) as active FROM pg_stat_activity WHERE state = 'active';
"

建议的 application.yml 配置:

spring:
  datasource:
    hikari:
      maximum-pool-size: 10        # 20 并发 × 0.5 = 10(经验公式)
      minimum-idle: 5              # 保持 5 个空闲连接
      idle-timeout: 300000         # 5 分钟空闲回收
      connection-timeout: 20000    # 20 秒超时
      max-lifetime: 1200000        # 20 分钟最大生命周期

五、项目部署(Spring Boot + React)

5.1 后端部署:Dockerfile + 构建

我:"为 AIGrader 后端编写多阶段 Dockerfile:
     第一阶段用 maven:3.9-eclipse-temurin-21 构建 JAR
     第二阶段用 eclipse-temurin:21-jre-alpine 运行
     构建后推送到 Docker Hub,在服务器上拉取并运行。"

Codex 编写的 Dockerfile

# 构建阶段
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn package -DskipTests -B

# 运行阶段
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD wget -qO- http://localhost:8080/actuator/health || exit 1

ENTRYPOINT ["java", "-jar", "app.jar"]

服务器上的部署流程:

# Codex 在服务器上执行
docker build -t aigrader-backend:latest .

# 在前面的 docker-compose.yml 中添加后端服务
cat >> docker-compose.yml << 'EOF'

  backend:
    image: aigrader-backend:latest
    container_name: aigrader-backend
    environment:
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/ai_grader
      SPRING_DATASOURCE_USERNAME: ${DB_USER}
      SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
      SPRING_DATA_REDIS_HOST: redis
      SPRING_DATA_REDIS_PORT: 6379
      DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY}
      JWT_SECRET: ${JWT_SECRET}
    ports:
      - "8080:8080"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: unless-stopped
    networks:
      - aigrader-net
EOF

docker compose up -d backend

5.2 前端部署:Nginx 静态托管

我:"前端是 React + Vite 构建的静态文件。编写 Nginx 配置:
     1. 静态文件从 /usr/share/nginx/html 提供
     2. /api/ 路径反向代理到后端 8080 端口
     3. SPA 路由 fallback 到 index.html
     4. 启用 gzip 压缩
     5. 设置 charset utf-8
     6. 配置 SSL(如果有证书)"

Codex 生成的 nginx.conf

server {
    listen 80;
    server_name your-domain.com;
    charset utf-8;

    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

    root /usr/share/nginx/html;
    index index.html;

    # API 反向代理
    location /api/ {
        proxy_pass http://backend:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 120s;
    }

    # SPA fallback
    location / {
        try_files $uri $uri/ /index.html;
    }
}

然后 Codex 会执行:

# 构建前端
cd frontend && pnpm build

# 用 Docker 运行 Nginx
docker run -d --name aigrader-frontend \
  -v $(pwd)/dist:/usr/share/nginx/html:ro \
  -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro \
  -p 80:80 \
  --network aigrader-net \
  nginx:alpine

六、日志检测与问题排查

这是 Codex 做运维最强的场景——AI 天生擅长从海量文本中提取异常模式。

6.1 多日志并行监控

我:"同时监控以下日志,发现 ERROR 或异常时立刻报告:
     1. Nginx 访问日志和错误日志
     2. Spring Boot 应用日志
     3. PostgreSQL 慢查询日志
     持续监控 3 分钟。"

Codex 会并行执行:

# 终端 1:Nginx 日志
tail -f /var/log/nginx/access.log /var/log/nginx/error.log | grep --color -E "ERROR|5[0-9]{2}|4[0-9]{2}"

# 终端 2:应用日志
docker logs -f aigrader-backend 2>&1 | grep --color -E "ERROR|Exception|WARN"

# 终端 3:数据库慢查询
docker exec aigrader-postgres psql -U ai_grader -d ai_grader -c "
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active' AND now() - pg_stat_activity.query_start > interval '1 seconds';
"

6.2 典型排查场景一:502 Bad Gateway

我:"Nginx 返回 502,帮我排查原因。"

Codex 排查路径:

# 1. 先看 Nginx 错误日志
tail -50 /var/log/nginx/error.log
# → "connect() failed (111: Connection refused) while connecting to upstream"

# 2. 检查后端是否存活
docker ps | grep backend
# → 没运行!

# 3. 查看后端退出原因
docker logs --tail=50 aigrader-backend
# → "Caused by: java.net.UnknownHostException: redis"

# 4. 检查 Redis
docker ps | grep redis
# → 也没运行!

# 5. 根因:Redis 和 PostgreSQL 先于后端崩溃
# 修复:重启全部服务
docker compose up -d

从发现 502 到定位根因,Codex 用了不到 30 秒。

6.3 典型排查场景二:AI 批改接口超时

我:"学生反映提交作业后一直转圈,检查 /api/submissions 接口为什么慢。"

Codex 排查路径:

# 1. 查看最近的请求日志
docker logs --since 5m aigrader-backend 2>&1 | grep "/api/submissions"

# 2. 发现 DeepSeek API 调用耗时 15 秒
# → "DeepSeek API response time: 15234ms"

# 3. 检查网络
curl -w "\ntime_total: %{time_total}\n" https://api.deepseek.com/v1/chat/completions

# 4. 建议:增加超时时间 + 添加重试机制

Codex 会直接修改配置并建议:

# application.yml
spring:
  ai:
    openai:
      chat:
        options:
          timeout: 30s    # 默认 10s → 30s

七、配置调优

7.1 JVM 参数调优

我:"服务器 8G 内存,只跑 AIGrader 后端这一个 Java 应用。请给出最优 JVM 参数。"

Codex 分析并给出:

# 在 Dockerfile 的 ENTRYPOINT 中:
java \
  -Xms2g -Xmx4g \                        # 初始 2G,最大 4G(留 4G 给 OS 和其他服务)
  -XX:+UseG1GC \                          # G1 垃圾回收器(适合 4G+ 堆)
  -XX:MaxGCPauseMillis=200 \              # 最大 GC 暂停 200ms
  -XX:+HeapDumpOnOutOfMemoryError \       # OOM 时 dump 堆
  -XX:HeapDumpPath=/tmp/heapdump.hprof \
  -jar app.jar

还会顺带检查当前 GC 情况:

docker exec aigrader-backend jstat -gcutil 1 1000 5
# → 显示各代使用率、GC 次数和耗时

7.2 Nginx 性能调优

我:"当前服务器 4 核,Nginx 作为前端反向代理。请优化 Nginx 配置。"

Codex 配置:

# /etc/nginx/nginx.conf

user nginx;
worker_processes auto;              # 自动匹配 CPU 核数
worker_rlimit_nofile 65535;         # 最大文件描述符

events {
    worker_connections 4096;        # 每个 worker 的连接数
    use epoll;                      # Linux 下高效事件模型
    multi_accept on;                # 一次接受多个连接
}

http {
    # 基础优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # 缓冲区
    client_body_buffer_size 128k;
    client_max_body_size 10m;       # 允许 10MB 上传(作业附件)

    # 连接池
    upstream backend {
        server backend:8080;
        keepalive 32;               # 保持 32 个长连接到后端
    }

    # Gzip
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 5;
    gzip_types text/plain text/css application/json application/javascript text/xml;
}

7.3 PostgreSQL 参数调优

我:"服务器 8G 内存,PostgreSQL 在 Docker 容器中运行。请调优 postgresql.conf。"

Codex 给出的关键参数:

# postgresql.conf(通过 Docker 环境变量设置)

shared_buffers = 2GB              # 25% 总内存
effective_cache_size = 6GB        # 75% 总内存
work_mem = 64MB                   # 单查询排序内存
maintenance_work_mem = 512MB      # VACUUM 维护内存
random_page_cost = 1.1            # SSD 环境降低随机读成本
effective_io_concurrency = 200    # SSD 并发 IO
max_connections = 50              # 限制连接数

Docker Compose 中添加:

postgres:
  command: >
    -c shared_buffers=2GB
    -c effective_cache_size=6GB
    -c work_mem=64MB
    -c maintenance_work_mem=512MB
    -c random_page_cost=1.1
    -c max_connections=50

八、安全加固

8.1 让 Codex 做安全审计

我:"对这台服务器进行基本的安全审计:检查 SSH 配置、防火墙状态、开放端口、Docker 安全配置。"

Codex 审计清单:

# SSH 配置
grep -E "^PermitRootLogin|^PasswordAuthentication|^Port" /etc/ssh/sshd_config
# 建议:PermitRootLogin no, PasswordAuthentication no(仅密钥登录)

# 防火墙
ufw status verbose
# 建议:只开放 22, 80, 443

# 开放端口
ss -tlnp
# 检查 Redis 是否绑定到 0.0.0.0(危险!)

# Docker 安全
docker info | grep -E "Root Dir|Cgroup"
docker run --rm aquasec/trivy image aigrader-backend:latest

8.2 一键生成安全配置

我:"生成 ufw 规则、SSH 加固配置、Redis 安全配置、Docker 非 root 运行配置。"

Codex 执行:

# UFW 防火墙
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp    # SSH
ufw allow 80/tcp    # HTTP
ufw allow 443/tcp   # HTTPS
ufw --force enable

# SSH 加固
cat >> /etc/ssh/sshd_config << 'EOF'
PermitRootLogin prohibit-password
PasswordAuthentication no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
EOF
systemctl reload sshd

# Redis 安全:绑定到 Docker 内部网络,不暴露外网
# docker-compose.yml 中去掉 ports,只保留内部网络通信

# Docker 非 root 用户(Dockerfile 中已添加 appuser)

九、运维 Checklist 模板

每次新项目部署时,直接把这个 Checklist 丢给 Codex:

帮我完成以下运维任务:

□ 检查系统环境(OS/CPU/内存/磁盘)
□ 安装 Docker + Docker Compose
□ 编写 docker-compose.yml(PostgreSQL + Redis + 应用)
□ 初始化数据库(建表 + 种子数据)
□ 构建后端 Docker 镜像并推送
□ 编写 Nginx 配置(反向代理 + SPA + gzip)
□ 启动全部服务
□ 配置防火墙规则
□ 进行基本安全审计
□ 配置日志轮转
□ 设置自动健康检查
□ 配置监控告警(CPU > 80% / 内存 > 90% / 磁盘 > 85%)

十、总结:Codex 运维的三个层次

层次一:命令执行者

我:"重启 Nginx"

Codex 就是个高级 systemctl,帮你敲命令。这层价值不大。

层次二:问题诊断者

我:"用户反馈访问慢,帮我查"

Codex 并行检查 CPU、内存、磁盘 IO、数据库慢查询、应用日志,综合诊断。这层已经超过大多数初级运维。

层次三:架构决策者

我:"我的应用日均 DAU 1000,现在一切正常。如果 DAU 涨到 10000,我需要做什么?"

Codex 从连接池、缓存策略、数据库索引、负载均衡、CDN 等多维度给出扩容方案。这层是真正的"AI 运维专家"。

关键心法:越模糊的问题,Codex 越能发挥价值——因为它可以自由收集信息、建立关联、给出方案。你给它的空间越大,它越能干。


下一篇预告:《约束即代码:AGENTS.md 深度设计指南》 — 三层约束体系的设计方法论,从行为边界到代码规范到任务调度,让你的 AI Agent 永远不跑偏。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐