双机开发环境搭建指南:Mac mini 负责 Apple 开发,13900K + RTX 4090 成为开发计算节点
如果你手里恰好有一台 Mac mini(Apple 平台开发)和一台 i9-13900K / 64GB RAM / RTX 4090 的高配 Linux 服务器,很容易陷入两种纠结:
- 把什么都塞在 Mac 上跑,结果内存、磁盘很快吃紧;
- 或者反过来,想让服务器”替代” Mac,却忘了 iOS 开发离不开 Xcode 与 Simulator。
这篇文章给出的是一个折中且务实的方案:让两台机器各司其职——Mac 只保留 Apple 平台不可替代的工作,后端、数据库、Docker、构建、测试和 GPU 工作负载全部迁到服务器上,日常统一通过 VS Code 的 Remote-SSH 与 Codex 插件开发前后端。
适用场景:
- Mac mini M2(约 256GB SSD)承担 Apple 平台开发;
- i9-13900K / 64GB RAM / 2.5TB SSD / RTX 4090 服务器承担后端、数据库、Docker、构建、测试和 GPU 工作负载;
- 日常使用 VS Code 中的 Codex 插件开发前后端;
- 使用 Codex 时需要 VPN / 代理网络;
- iOS 开发需要 Xcode 与 iOS Simulator。
全文按实施顺序展开,大体分为六大部分:
- 架构与目标(一 ~ 三)
- 服务器基础:系统、SSH、防火墙(六 ~ 八)
- VS Code + Codex Remote(九 ~ 十)
- 网络方案:VPN / Proxy 的三种选择(十一 ~ 十五)
- Docker 与服务迁移(十六 ~ 二十二)
- iOS 联调、日常维护与排查(二十三 ~ 四十二)
一、目标
这套方案的目标不是让高配服务器”替代 Mac”,而是让两台机器各自承担最适合自己的工作:
- Mac mini:Apple 开发终端
- Xcode
- Swift / SwiftUI
- iOS Simulator
- 真机调试
- 签名、Archive、发布
- 本地 VS Code + Codex(iOS 项目)
- VPN / 代理客户端
- 13900K + 4090 服务器:开发计算中心
- Linux
- VS Code Server / Remote-SSH
- Codex Remote 工作区
- 后端源码
- Web 前端源码
- Docker Engine
- PostgreSQL / MySQL / Redis / MinIO 等
- Node / Python / Java / Go 等运行环境
- 编译、测试、Lint、构建
- RTX 4090 AI / CUDA 工作负载
最终希望把 Mac 上最消耗资源的部分迁走,只保留 Xcode、Simulator 和必要的客户端界面。
二、推荐最终架构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Internet
│
VPN / Proxy 出口
│
┌────────────────────┴────────────────────┐
│ │
│ │
┌──────▼────────┐ ┌───────▼─────────┐
│ Mac mini M2 │ │ 13900K Server │
│ │ 1G / 2.5G LAN │ │
│ VS Code │◄──────────────────────►│ Ubuntu Linux │
│ Codex Local │ SSH │ VS Code Server │
│ Xcode │ │ Codex Remote │
│ Simulator │ │ Docker │
│ Git │ │ Backend / Web │
│ VPN / Proxy │ │ DB / Redis │
│ │ │ Build / Tests │
└───────────────┘ │ RTX 4090 │
└─────────────────┘
职责分配
| 工作 | Mac mini | 13900K Server |
|---|---|---|
| Xcode | ✅ | ❌ |
| iOS Simulator | ✅ | ❌ |
| Swift / SwiftUI | ✅ | 可存代码但不作为主运行环境 |
| Apple 签名 / Archive | ✅ | ❌ |
| VS Code 界面 | ✅ | VS Code Server |
| Codex iOS 开发 | ✅ 本地 | ❌ |
| Codex 后端 / Web 开发 | VS Code UI | ✅ Remote 工作区 |
| Docker | 尽量不跑 | ✅ |
| PostgreSQL / Redis | ❌ | ✅ |
| Node/Python/Java/Go 后端 | 尽量不跑 | ✅ |
| Web Build / Test | 尽量不跑 | ✅ |
| CUDA / AI | ❌ | ✅ RTX 4090 |
| Git | ✅ | ✅ |
三、一个关键事实:Codex 和 VPN 怎么处理
你使用的是 VS Code 中的 Codex 插件。
当 VS Code 使用 Remote-SSH 打开服务器目录时:
- Mac 上仍然显示 VS Code 界面;
- VS Code 会在 Linux 服务器安装 VS Code Server;
- Workspace 类型扩展通常会在远程 Extension Host 中运行;
- Codex IDE 扩展使用 Codex app-server;
- 因此,实际部署时必须验证:远程服务器侧是否能够完成 Codex 所需的网络访问和认证。
所以不要把下面两句话等同:
1
Mac 能使用 Codex
和:
1
Remote-SSH 服务器里的 Codex 也一定能使用
Mac 有 VPN,并不自动意味着服务器继承 Mac 的 VPN。这一条是整个方案里最容易被忽略、也最值得先验证的一点。
四、推荐实施顺序
不要一次迁移所有东西,建议按以下阶段推进:
1
2
3
4
5
6
7
8
Phase 1 Server 安装 Ubuntu
Phase 2 配好固定 IP / SSH
Phase 3 Mac VS Code Remote-SSH 成功
Phase 4 Server 解决 VPN / Proxy
Phase 5 Remote 工作区 Codex 验证
Phase 6 Docker / DB / Backend 迁移
Phase 7 iOS Simulator 联调 Server API
Phase 8 再考虑 RTX 4090 / AI
在 Phase 5 完成以前,不要大规模迁移代码。
五、准备变量
下面所有命令使用示例参数,请按自己的网络环境修改。
1
2
3
4
5
6
7
8
9
10
11
12
SERVER_USER=dev
SERVER_HOST=dev-server
SERVER_IP=192.168.10.20
MAC_IP=192.168.10.10
BACKEND_PORT=8080
POSTGRES_PORT=5432
REDIS_PORT=6379
# 如果让服务器通过 Mac 的代理上网:
MAC_PROXY_PORT=7890
建议在路由器上给两台机器做 DHCP Reservation:
1
2
3
4
5
Mac mini:
192.168.10.10
13900K:
192.168.10.20
优先推荐路由器 DHCP 固定地址,而不是一开始就手写 Linux 静态 IP。 这样以后换网卡、改网关、改 DNS 时更省事。
六、服务器安装 Ubuntu
推荐系统
优先选择:
1
Ubuntu Server 24.04 LTS
理由:
- 稳定;
- Docker 支持成熟;
- NVIDIA 驱动生态成熟;
- VS Code Remote SSH 支持良好;
- 不需要服务器桌面环境。
如果服务器同时还有其他虚拟化需求,再考虑 Proxmox。对于当前开发用途,直接 Ubuntu Server 更简单。
安装后的基础配置
登录服务器:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sudo apt update
sudo apt full-upgrade -y
sudo apt install -y \
openssh-server \
git \
curl \
wget \
ca-certificates \
gnupg \
jq \
htop \
tmux \
build-essential \
ufw
sudo systemctl enable --now ssh
顺便把主机名和时区设置好(时区对日志、测试、数据库时间都很有影响):
1
2
sudo hostnamectl set-hostname dev-server
sudo timedatectl set-timezone Asia/Shanghai
为服务器上的 Git 配置好身份(很多新手会漏掉,导致提交时报错):
1
2
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
检查:
1
2
3
hostname
ip addr
timedatectl
七、配置 SSH
Mac 生成独立 SSH Key
建议不要与 GitHub 共用同一把 key,为服务器单独生成一把:
1
2
3
ssh-keygen -t ed25519 \
-f ~/.ssh/id_ed25519_dev_server \
-C "macmini-to-dev-server"
复制公钥到服务器:
1
2
3
ssh-copy-id \
-i ~/.ssh/id_ed25519_dev_server.pub \
[email protected]
如果 macOS 没有 ssh-copy-id,可以手动追加:
1
2
3
cat ~/.ssh/id_ed25519_dev_server.pub | \
ssh [email protected] \
'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
验证登录(首次连接会提示确认 host key,确认无误后输入 yes):
1
ssh -i ~/.ssh/id_ed25519_dev_server [email protected]
Mac 配置 ~/.ssh/config
编辑:
1
nano ~/.ssh/config
增加:
Host dev-server
HostName 192.168.10.20
User dev
IdentityFile ~/.ssh/id_ed25519_dev_server
ServerAliveInterval 30
ServerAliveCountMax 3
ControlMaster auto
ControlPersist 10m
ControlPath ~/.ssh/cm-%C
配置完成后,直接:
1
ssh dev-server
即可连接。
ServerAliveInterval用于避免长时间无操作时连接被 NAT / 防火墙掐断;ControlMaster / ControlPersist让后续连接复用已有通道,重连和 Remote-SSH 都会更快。如果遇到”连接被复用但通道已死”的怪问题,可用ssh -O exit dev-server清理复用通道。
SSH 安全加固
一定先确认 SSH Key 登录成功,再禁止密码登录。
服务器:
1
sudo nano /etc/ssh/sshd_config.d/99-dev-server.conf
写入:
1
2
3
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
检查配置:
1
sudo sshd -t
如果没有输出错误:
1
sudo systemctl restart ssh
此时先不要关闭原 SSH 窗口。另开一个 Mac Terminal:
1
ssh dev-server
确认能正常登录后,再关闭旧连接。
八、防火墙
基础规则:
1
2
sudo ufw default deny incoming
sudo ufw default allow outgoing
只允许 Mac SSH:
1
sudo ufw allow from 192.168.10.10 to any port 22 proto tcp
如果需要 Mac / Simulator 访问后端:
1
sudo ufw allow from 192.168.10.10 to any port 8080 proto tcp
启用并查看状态:
1
2
sudo ufw enable
sudo ufw status verbose
注意:Docker 发布端口时存在绕过部分 UFW 规则的情况(Docker 直接操作 iptables)。因此后面 Docker Compose 中应尽量明确绑定服务器的 LAN IP,而不是简单写
0.0.0.0:端口。
九、VS Code Remote-SSH
Mac 安装扩展
在 Mac 的 VS Code 安装:
1
Remote - SSH
然后:
1
2
3
Command Palette
→ Remote-SSH: Connect to Host...
→ dev-server
第一次连接时 VS Code 会自动在远端安装 VS Code Server。连接成功后,左下角应显示类似:
1
SSH: dev-server
创建服务器项目目录
服务器:
1
2
mkdir -p ~/projects
cd ~/projects
例如:
1
2
git clone <YOUR_BACKEND_REPO>
cd your-backend
然后在 Remote VS Code:
1
2
3
File
→ Open Folder
→ /home/dev/projects/your-backend
十、VS Code + Codex Remote 验证
这是整个方案最重要的一步,请务必在迁移任何代码之前完成验证。
在 Remote SSH 窗口安装 / 启用 Codex
打开扩展页时,注意 VS Code 会区分:
1
2
LOCAL
SSH: dev-server
如果 Codex 提示:
1
Install in SSH: dev-server
则安装到远程环境。安装后打开 Codex Sidebar。
如果远程安装失败,先确认 Mac 端 VS Code 与远端 VS Code Server 版本匹配,再在 Remote Terminal 里检查网络,最后重试安装。
认证
正常情况下直接:
1
Sign in with ChatGPT
完成浏览器登录。
如果远程场景下登录出现问题,可把 Codex CLI 作为排障工具。在服务器安装当前官方 Codex CLI:
1
curl -fsSL https://chatgpt.com/codex/install.sh | sh
重新登录 Shell 后检查:
1
codex --version
检查认证状态:
1
codex login status
如果服务器是 headless 环境且浏览器回调有问题,可尝试:
1
codex login --device-auth
前提是对应账户 / Workspace 已允许 Device Code 登录。
Codex CLI 和 IDE Extension 会复用 Codex 的登录缓存,因此 CLI 很适合用来排查远程认证问题。
判断 Codex 到底运行在哪台机器
在 Remote VS Code 的 Codex 中输入:
1
2
3
4
5
不要修改任何文件。
请告诉我当前工作目录、hostname,
并读取当前项目的 README 或 package.json,
然后告诉我项目名称。
期望结果:
1
2
3
4
5
pwd:
/home/dev/projects/your-backend
hostname:
dev-server
而不是:
1
/Users/你的Mac用户名/...
同时可以打开 Remote Terminal 确认:
1
2
3
pwd
hostname
uname -a
这一步确认后,才算 Remote Codex 真正成功。
十一、VPN / Proxy 网络方案
共有三种方案,推荐优先级按”长期稳定性”排序:
1
2
3
4
5
方案 A:路由器 / 软路由统一处理
↓
方案 B:服务器自己运行 VPN / Proxy
↓
方案 C:服务器借 Mac 的代理出口
如果你想最快跑通,通常可以先用方案 C,跑通后再决定是否升级为 A / B。
十二、方案 A:路由器 / 软路由统一代理
长期最省事。
1
2
3
4
Mac ─────┐
Server ──┼── Router ─── Internet
iPhone ──┘ │
└── VPN / Proxy
优势:
- Mac 不需要给 Server 当网关;
- Mac 睡眠不会影响服务器;
- Docker / Git / npm / pip / Codex 都可以统一处理;
- 手机真机调试也方便;
- 规则统一维护。
理想的分流规则:
1
2
3
4
5
Apple / 国内服务 / LAN
→ DIRECT
需要代理的开发服务
→ PROXY
如果你已经有 OpenWrt / pfSense / OPNsense / 软路由环境,这通常是最终最佳方案。
十三、方案 B:Server 自己运行 VPN / Proxy
如果你的 VPN 服务提供 Linux 客户端,这是结构最清晰的方式。
1
2
3
Mac VPN → Internet
Server VPN → Internet
两台机器通过局域网互访:
1
2
3
Mac 192.168.10.10
│
└── 192.168.10.20 Server
局域网访问不需要绕 VPN。
服务器连接成功后测试:
1
curl -I https://chatgpt.com
以及:
1
curl -I https://github.com
然后测试:
1
codex login status
最后重新启动 VS Code Remote SSH 窗口,再测试 Codex。
十四、方案 C:Server 通过 Mac 的代理上网
这个方案特别适合:
- VPN 只有 macOS 客户端;
- 暂时不想动路由器;
- 想最快验证整个架构。
拓扑:
1
2
3
4
5
6
7
8
9
13900K Server
│
│ HTTP / SOCKS Proxy
▼
Mac mini
│
│ VPN
▼
Internet
Mac 代理软件配置
不同软件名称不同,但需要找到类似配置:
1
2
3
4
Allow LAN
允许局域网连接
Expose HTTP Proxy
Expose SOCKS Proxy
例如:
1
2
3
4
5
Mac IP:
192.168.10.10
HTTP Proxy:
192.168.10.10:7890
不要直接把代理端口暴露到公网。 如果软件允许设置 Allowed Clients,最好只允许:
1
192.168.10.20
即服务器 IP。
服务器临时测试代理
服务器:
1
2
3
4
5
export HTTP_PROXY=http://192.168.10.10:7890
export HTTPS_PROXY=http://192.168.10.10:7890
export http_proxy=$HTTP_PROXY
export https_proxy=$HTTPS_PROXY
测试:
1
curl -I https://chatgpt.com
测试 Git:
1
git ls-remote https://github.com/openai/codex.git HEAD
如果都能返回,说明基础代理路径正常。
NO_PROXY 很重要
一定排除局域网流量:
1
2
export NO_PROXY="localhost,127.0.0.1,::1,192.168.10.0/24"
export no_proxy="$NO_PROXY"
否则可能出现这种错误结构:
1
Server → Mac Proxy → VPN → 再绕回来访问 Server
导致:
- API 慢;
- Docker DB 连接异常;
- WebSocket 异常;
- 本地联调出现奇怪的超时。
持久化代理
先不要急着写全局配置,建议按以下顺序验证:
- 临时 export 验证;
- Codex 验证;
- Git / npm / Docker 验证;
- 最后再持久化。
如果决定持久化,可在服务器用户环境中配置,例如:
1
nano ~/.profile
加入:
1
2
3
4
5
6
7
8
export HTTP_PROXY=http://192.168.10.10:7890
export HTTPS_PROXY=http://192.168.10.10:7890
export http_proxy=$HTTP_PROXY
export https_proxy=$HTTPS_PROXY
export NO_PROXY="localhost,127.0.0.1,::1,192.168.10.0/24"
export no_proxy="$NO_PROXY"
重新登录:
1
2
exit
ssh dev-server
验证:
1
env | grep -i proxy
如果 VS Code Server 或某个扩展没有继承这些变量,不要盲目继续加代理层。先从 Remote Terminal 确认环境变量,再重新连接 Remote-SSH,并在 Codex 中重新验证网络。
十五、Codex 的两个”网络”不要混淆
Codex 涉及两类网络需求,排查问题时要先分清是哪一个出了问题。
Codex 自己连接服务
这是:
1
2
Codex Extension / app-server
→ OpenAI / ChatGPT
这决定 Codex 能不能回答和工作。
Codex 执行的命令访问网络
例如 Codex 执行:
1
2
3
4
npm install
pip install
git fetch
curl
这是另外一层网络权限。Codex 本地 / IDE 工作流具有 Sandbox 和网络权限控制。
所以可能出现:
1
2
Codex 聊天正常
但 npm install 被阻止
这不一定是 VPN 问题,也可能是 Codex 的 Sandbox / Network Permission。如果 Codex 执行命令需要联网,按实际需要开启网络权限,不要一上来就给整个 Agent 无限网络和系统权限。
十六、安装 Docker Engine
在服务器安装官方 Docker Engine。
先移除可能冲突的软件:
1
2
3
4
5
6
7
8
sudo apt remove -y \
docker.io \
docker-compose \
docker-compose-v2 \
docker-doc \
podman-docker \
containerd \
runc || true
添加官方仓库:
1
2
3
4
5
6
7
8
9
10
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL \
https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
增加 apt source(deb822 格式):
1
2
3
4
5
6
7
8
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
安装:
1
2
3
4
5
6
7
8
sudo apt update
sudo apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
测试:
1
sudo docker run hello-world
十七、让普通用户使用 Docker
1
sudo usermod -aG docker $USER
退出 SSH:
1
exit
重新登录:
1
ssh dev-server
测试:
1
2
docker ps
docker compose version
注意:加入
docker用户组等价于给该用户非常高的主机控制能力。开发机可以这样做,但不要随意给不可信用户加入 docker group。
十八、不要开放 Docker 2375
不推荐:
1
tcp://0.0.0.0:2375
特别不要:
1
2
3
Internet
→ 2375
→ Docker daemon
如果未来需要 Mac 上的 Docker CLI 管理 Server,优先走 SSH:
1
2
docker context create dev-server \
--docker host=ssh://[email protected]
使用:
1
2
docker context use dev-server
docker ps
切回:
1
docker context use default
不过对于当前架构,其实更简单:
1
2
Remote VS Code Terminal
→ 直接运行 Server 上的 docker compose
这样 Mac 连 Docker CLI 都可以不装。
十九、推荐开发服务目录
服务器:
1
2
3
4
5
/home/dev/
└── projects/
├── myapp-backend/
├── myapp-web/
└── infra/
例如:
1
mkdir -p ~/projects/infra
二十、一个可直接改的 Docker Compose 示例
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
services:
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_DB: myapp
POSTGRES_USER: myapp
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "${SERVER_BIND_IP}:5432:5432"
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
ports:
- "${SERVER_BIND_IP}:6379:6379"
api:
build:
context: ../myapp-backend
restart: unless-stopped
environment:
DATABASE_URL: postgresql://myapp:${POSTGRES_PASSWORD}@postgres:5432/myapp
REDIS_URL: redis://redis:6379
depends_on:
- postgres
- redis
ports:
- "${SERVER_BIND_IP}:8080:8080"
volumes:
postgres_data:
redis_data:
.env:
1
2
SERVER_BIND_IP=192.168.10.20
POSTGRES_PASSWORD=PLEASE_CHANGE_ME
不要提交 .env。
.gitignore:
.env
.env.local
提交:
1
.env.example
而不是实际 secret。
关于内存限制:老写法
mem_limit: 4g仍可用,但 Compose Spec 推荐在deploy.resources.limits下声明。具体写法见第 34 节。
二十一、Docker 网络建议
数据库通常不需要给 Mac 直接访问,更安全的结构是:
1
2
3
4
5
6
7
8
9
10
11
PostgreSQL
↑
Docker internal network
│
API
│
↓
192.168.10.20:8080
│
↓
Mac / Simulator
因此生产化一点可以删除:
1
2
postgres:
ports:
以及:
1
2
redis:
ports:
只保留 API 对 LAN 暴露。
这样:
1
2
3
4
Mac
只能直接访问 API
不能直接访问数据库
如果临时需要数据库 GUI,可使用 SSH Tunnel,而不是永久开放 DB:
1
ssh -L 15432:127.0.0.1:5432 dev-server
然后 Mac 数据库客户端连接:
1
127.0.0.1:15432
二十二、后端迁移原则
Mac 上尽量停止:
1
2
3
4
5
6
7
8
9
Docker Desktop
PostgreSQL
Redis
Elasticsearch
MinIO
后台 Node Server
后台 Python Server
大型测试
前端 production build
服务器承担:
1
2
3
4
5
6
7
8
9
10
docker compose up -d
npm / pnpm
pytest
gradle
maven
go test
eslint
tsc
vite build
next build
Mac 保留:
1
2
3
4
5
Xcode
Simulator
VS Code UI
浏览器
必要的轻量工具
二十三、iOS Simulator 连接 Server API
Server API:
1
192.168.10.20:8080
iOS 开发配置:
1
2
3
4
5
Development:
http://192.168.10.20:8080
Production:
https://api.example.com
不要把地址散落在代码中。例如 Swift 可以这样组织:
1
2
3
4
5
6
7
8
9
10
11
12
13
enum AppEnvironment {
case development
case production
var baseURL: URL {
switch self {
case .development:
return URL(string: "http://192.168.10.20:8080")!
case .production:
return URL(string: "https://api.example.com")!
}
}
}
更推荐使用:
1
xcconfig
或:
1
Build Configuration
管理不同环境,把地址集中在一处、并区分 Debug / Release。
二十四、HTTP / ATS 注意事项
iOS 对 HTTP 有 App Transport Security(ATS)限制。开发阶段有三种选择:
推荐
本地开发 API 也使用 HTTPS,例如:
1
2
3
Caddy / nginx
→ HTTPS
→ API
次选
仅 Debug 配置中增加开发例外。
不推荐
生产 App 里长期:
1
NSAllowsArbitraryLoads = YES
如果为了本地 HTTP 临时使用 ATS 例外,确保:
1
2
Debug 有
Release 没有
上线前必须检查。
二十五、真机调试
如果不是 Simulator,而是 iPhone:
1
2
3
4
5
6
7
iPhone
│ Wi-Fi
▼
Router / AP
│
▼
192.168.10.20:8080
需要满足:
- iPhone 与服务器在可互访的 LAN;
- Wi-Fi 不启用 Client Isolation;
- 后端端口允许 LAN 访问;
- App 根据 iOS 本地网络权限要求正确配置。
iOS 14+ 访问局域网设备会触发本地网络权限弹窗,需要在 Info.plist 中声明用途描述:
1
NSLocalNetworkUsageDescription
并建议开发网络不要使用访客 Wi-Fi。
二十六、推荐代码仓库结构
方案 1:分仓库(长期推荐)
1
2
3
4
myapp-ios/
myapp-backend/
myapp-web/
myapp-api-contract/
Mac:
1
myapp-ios
Server:
1
2
myapp-backend
myapp-web
优点:
- 职责清晰;
- Codex 上下文更小;
- Xcode 不碰 Remote FS;
- 后端完全 Server 化;
- CI 容易拆分。
方案 2:保留 Monorepo
如果现在已经是:
1
2
3
4
5
myapp/
├── ios/
├── backend/
├── web/
└── infra/
不需要为了迁移立刻重构。
可以:
Mac Clone:
1
~/Projects/myapp
主要打开:
1
ios/
Server Clone:
1
~/projects/myapp
主要打开:
1
2
3
backend/
web/
infra/
注意:两台机器不是自动同步文件系统的。
正确同步方式:
1
2
3
Git commit
Git push
Git pull
不要:
1
2
3
Mac 修改一半
Server 修改另一半
然后靠 rsync 强行互相覆盖
二十七、API 契约建议
iOS 与后端最好共享接口契约:
1
2
3
OpenAPI
JSON Schema
Protobuf
例如:
1
api/openapi.yaml
工作流:
1
2
3
4
5
6
7
Server Codex
→ 修改 Backend API
→ 更新 openapi.yaml
→ commit
Mac pull
→ Codex 根据 OpenAPI 修改 Swift API Client
这样前后端不会靠”聊天记忆”同步接口。
二十八、建议写一个 AGENTS.md
Codex 很适合通过项目规则固定工作方式。
Server 项目:
1
2
3
4
5
6
7
8
9
# Development Rules
- Backend runs on the Linux development server.
- Use Docker Compose for PostgreSQL and Redis.
- Never start PostgreSQL or Redis directly on the Mac.
- Run tests before finishing a backend task.
- Do not modify iOS files from this workspace.
- API contract lives in api/openapi.yaml.
- Do not commit .env or secrets.
iOS 项目:
1
2
3
4
5
6
7
8
# iOS Development Rules
- This workspace is for iOS code only.
- Build and test using Xcode on macOS.
- Development backend is configured through xcconfig.
- Do not hardcode production API URLs.
- Do not enable unrestricted ATS settings in Release.
- Update the API client from the shared OpenAPI contract.
这样 Codex 每次工作更容易遵循你的双机边界。
二十九、日常开发工作流
开始工作
Mac:
1
2
3
4
5
1. 启动 VPN
2. 打开 Xcode
3. 启动一个 Simulator
4. 打开 iOS VS Code / Codex
5. VS Code Remote-SSH → dev-server
Server Remote Terminal:
1
2
cd ~/projects/myapp
docker compose up -d
检查:
1
docker compose ps
后端日志:
1
docker compose logs -f api
开发后端
在:
1
2
VS Code
SSH: dev-server
给 Codex:
1
2
3
4
实现 refresh token。
修改数据库 migration。
运行相关测试。
最后给我列出修改文件、测试结果和 API 变化。
这些工作运行在:
1
13900K / 64G
而不是 Mac。
开发 iOS
Mac 本地 Codex:
1
2
3
4
根据最新 OpenAPI 更新 AuthService。
修改 LoginView。
不要改后端文件。
完成后告诉我需要在 Xcode 中运行哪些测试。
Xcode:
1
2
3
Build
→ Simulator
→ 调用 192.168.10.20:8080
三十、推荐的双窗口布局
1
2
3
4
5
6
7
8
9
10
11
12
┌─────────────────────┬──────────────────────┐
│ VS Code Remote │ Xcode │
│ SSH: dev-server │ │
│ │ Swift / SwiftUI │
│ Backend │ Simulator │
│ Web │ │
│ Codex Remote │ │
├─────────────────────┼──────────────────────┤
│ Remote Terminal │ Simulator │
│ docker compose │ │
│ logs │ App UI │
└─────────────────────┴──────────────────────┘
如果需要 iOS Codex:
1
2
3
第二个 VS Code 窗口
LOCAL
→ myapp-ios
三十一、Mac mini 资源优化
完成迁移后,Mac 上应该尽量不再运行:
1
2
3
4
5
6
7
Docker Desktop
Postgres.app
本地 Redis
大型 Node Server
大型 Java 服务
Elasticsearch
本地 AI 模型
检查:
1
2
3
Activity Monitor
→ Memory
→ Memory Pressure
理想状态:
1
2
3
4
5
Xcode
Simulator
VS Code
Codex
浏览器
同时运行时 Memory Pressure 仍能维持可接受范围。
三十二、Mac 256GB SSD 优化
iOS 开发特别容易消耗 SSD,重点检查:
1
2
3
4
5
6
7
Xcode
Simulator Runtime
DerivedData
Archives
DeviceSupport
项目 node_modules
Docker Desktop 数据
如果已经把 Docker 迁到服务器:Mac 可直接卸载 / 停用 Docker Desktop。
Xcode 可定期清理不可用的模拟器运行时:
1
xcrun simctl delete unavailable
清 DerivedData 前:先关闭 Xcode,再根据需要删除旧缓存。
不要把:
1
CoreSimulator 系统目录
随意用软链接迁到 NAS / 网络盘,稳定性没有保障。
如果需要扩容,优先给 Mac 增加高速 USB4 / Thunderbolt NVMe SSD,用于:
- 项目;
- 大型素材;
- Archives;
- 可迁移缓存。
三十三、RTX 4090:第二阶段再启用
先把:
1
2
3
4
5
Remote-SSH
Codex
Docker
Backend
iOS 联调
跑顺,然后再处理 GPU。
Linux 检查:
1
nvidia-smi
正常后再安装 NVIDIA Container Toolkit。示例流程:
1
2
3
4
5
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
ca-certificates \
curl \
gnupg2
增加 NVIDIA Container Toolkit 仓库后安装:
1
2
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
配置 Docker Runtime:
1
2
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
检查:
1
docker info | grep -i runtime
以后可以运行:
1
2
3
4
5
6
7
Ollama
vLLM
Embedding
RAG
Whisper
图像模型
CUDA 开发
此时 4090 才真正参与开发体系。
三十四、推荐 Server 的资源分配原则
64GB RAM 可以大致按逻辑分:
1
2
3
4
5
6
7
8
9
10
11
Host Linux:
4~8 GB
VS Code / Codex / 编译:
8~16 GB
Docker 开发服务:
16~32 GB
其余:
文件缓存 / GPU 工作流
不需要人工硬切,Linux 会自动使用空闲内存作为 Page Cache。真正需要防止的是单个容器无限吃内存。
Docker Compose 可以按需要设置(Compose Spec 推荐写法):
1
2
3
4
5
6
7
8
9
10
11
12
services:
api:
deploy:
resources:
limits:
memory: 4g
postgres:
deploy:
resources:
limits:
memory: 8g
仅在确实遇到资源争抢后再加,不必一开始过度限制。
兼容提示:
docker compose(v2)支持deploy.resources.limits.memory;老式的mem_limit也仍然可用,但新项目建议用前者。
三十五、安全原则
必须遵守:
- 不把 SSH 22 直接暴露到公网,除非你明确做好额外安全控制;
- 不公开暴露 Docker 2375;
- 不把 Codex app-server transport 暴露到公网;
- Remote 访问优先使用 SSH / VPN / Mesh Network;
.env不进 Git;- Codex 不需要时不要给无限网络 / 无限系统权限;
- Docker 数据库端口不要无脑
0.0.0.0; - SSH 禁止 root 登录;
- SSH Key 成功验证后再关闭密码登录;
- Mac 代理若允许 LAN,只允许可信 LAN / Server IP;
- 服务器不要使用与你日常个人账户相同的弱密码。
如果服务器后续暴露到公网,可以再考虑加装 fail2ban、限制 SSH 来源 IP、以及定期 apt upgrade。
三十六、验收 Checklist
Server 基础
- Ubuntu Server 安装完成
- Server IP 固定
hostname正确- SSH 服务启动
- Mac SSH Key 登录成功
- SSH 密码登录已关闭
- UFW 基础规则完成
VS Code
- Mac 安装 Remote-SSH
SSH: dev-server可连接- Remote Folder 可打开
- VS Code Terminal 中
hostname显示 Server - VS Code Server 工作正常
Codex
- Remote 环境 Codex 可打开
- ChatGPT 登录成功
- Codex 可读取 Remote 文件
- Codex 返回的
pwd是/home/dev/... - Codex 执行的
hostname是dev-server - Codex 能修改 Remote 文件
- Codex 能运行 Remote 测试
Network / VPN
- Server DNS 正常
- Server 可通过目标代理路径联网
curl -I https://chatgpt.com成功git fetch成功- npm / pip 等按需求成功
NO_PROXY包含 LAN
Docker
- Docker Engine 安装
docker ps无需 sudodocker compose version正常- Postgres 正常
- Redis 正常
- API 正常
- DB 端口没有不必要的公网暴露
iOS
- Simulator 能访问 Server IP
- Development API Base URL 已独立配置
- Debug / Release 环境分离
- ATS 例外不会进入 Release
- 真机在需要时也可访问开发 API
Mac 减负
- Docker Desktop 已停用或卸载
- 本地 PostgreSQL 已停用
- 本地 Redis 已停用
- Backend 默认不再运行在 Mac
- Web 大型构建默认在 Server
- Mac 主要资源留给 Xcode + Simulator
三十七、常见问题排查
1. Remote VS Code 能连接,但 Codex 一直转圈
先打开 Remote Terminal:
1
2
3
hostname
pwd
curl -I https://chatgpt.com
如果 curl 不通,说明是服务器网络问题,先解决 Server VPN / Proxy,不是 VS Code 的问题。
如果 curl 通:
1
codex login status
再:
1
codex --version
最后重新连接 Remote SSH。
2. Mac Codex 正常,Remote Codex 不正常
这是非常典型的现象:
1
2
3
Mac VPN
≠
Server VPN
检查:
1
2
3
4
ssh dev-server
env | grep -i proxy
curl -I https://chatgpt.com
3. Server 走 Mac Proxy,但突然 Codex 断了
检查:
1
2
3
4
5
6
Mac 是否睡眠
VPN 是否掉线
代理软件是否退出
Allow LAN 是否关闭
Mac IP 是否变化
代理端口是否变化
这也是为什么长期建议:
1
Router Proxy
或:
1
Server 自己的 VPN
4. Codex 能聊天,但 npm install 失败
可能是两类问题:
1
2
A. Server 网络问题
B. Codex Sandbox 网络权限
先在 Remote Terminal 手工验证:
1
npm ping
如果 Terminal 正常、Codex 命令失败,再检查 Codex Permissions / Network Access。
5. Simulator 调不到 Server API
Mac 先测试:
1
curl http://192.168.10.20:8080/health
如果 Mac 都不通,检查:
1
2
3
API listen address
Docker port
Server firewall
后端必须监听:
1
0.0.0.0
或服务器 LAN interface,不能只监听:
1
127.0.0.1
如果 Mac curl 正常、Simulator 不正常,检查:
1
2
3
ATS
App Environment URL
iOS Local Network 权限
6. Docker API 可访问,但数据库不应该暴露
检查监听端口:
1
ss -lntp
不需要从 LAN 访问 PostgreSQL 时,应避免:
1
0.0.0.0:5432
更推荐:
1
2
Postgres
仅 Docker internal network
需要 GUI 时用:
1
ssh -L
7. Remote-SSH 首次连接失败 / Permission denied
按顺序排查:
1
2
3
4
5
1. host key 确认:首次连接是否接受了正确的指纹
2. 公钥是否写入 authorized_keys,且权限为 600
3. ~/.ssh 目录权限是否为 700
4. 是否启用了 PasswordAuthentication no 但 key 还没配好
5. UFW 是否只允许了 Mac IP 的 22 端口
三十八、最推荐的第一天实施范围
第一天不要折腾 GPU,只完成下面 8 件事:
1
2
3
4
5
6
7
8
1. Ubuntu
2. 固定 IP
3. SSH Key
4. VS Code Remote SSH
5. Server VPN / Proxy
6. Remote Codex
7. Docker
8. 跑一个测试 Backend
测试项目甚至可以只是:
1
hello-api
Server:
1
2
GET /health
→ {"ok": true}
Mac:
1
curl http://192.168.10.20:8080/health
Simulator:请求同一个 API。
只要这一条链跑通:
1
2
3
4
5
6
7
8
9
10
11
12
13
Codex Remote
↓
修改 Backend
↓
13900K Build / Test
↓
Docker
↓
192.168.10.20:8080
↓
Mac
↓
iOS Simulator
整个架构就成立了。
三十九、最终日常状态
理想状态应该是:
1
2
3
4
5
6
7
8
9
Mac mini
CPU:
主要给 Xcode / Simulator
Memory:
主要给 Xcode / Simulator / VS Code
Disk:
不再被 Docker Images / DB 大量占用
Server:
1
2
3
4
5
6
7
8
9
10
11
13900K
→ 编译 / 测试 / Backend / Web
64GB
→ Docker / DB / Cache / Codex
2.5TB SSD
→ Repo / Docker Volume / Build Cache
4090
→ AI / CUDA
四十、最终建议
对于你的硬件,不建议:
1
把所有东西继续塞在 Mac
也不建议:
1
强行让 13900K 替代 macOS / iOS Simulator
最合理的是:
1
2
3
Mac = Apple Development Workstation
Server = Linux Development Compute Node
具体工作流:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
iOS:
Mac Local VS Code / Codex
+
Xcode
+
Simulator
Backend / Web:
Mac VS Code UI
+
Remote SSH
+
Server Codex
+
Server Docker
+
Server Tests
网络则保证:
1
2
Mac 可以访问 Codex
Server Remote Codex 也可以访问 Codex
最终得到:
1
2
3
4
5
6
7
8
9
10
11
Mac mini
Xcode / Simulator
│
│ LAN
▼
13900K / 64G Server
Codex / Docker / Backend
DB / Build / Test
│
▼
RTX4090
这套架构的重点不是”远程控制一台服务器”,而是让服务器真正成为你的 开发计算节点,Mac 只做 Apple 平台不可替代的工作。
四十一、官方技术依据
本文档在 2026-08-19 根据以下官方资料核对了关键行为:
- OpenAI — Codex IDE extension
- OpenAI — Codex Authentication
- OpenAI — Codex App Server
- OpenAI — Codex Remote Connections
- OpenAI — Codex Agent Approvals & Security / Network
- OpenAI — Codex CLI
- Microsoft — Visual Studio Code Remote Development using SSH
- Microsoft — Supporting Remote Development and Remote Extension Host
- Docker — Install Docker Engine on Ubuntu
- Docker — Protect the Docker daemon socket / SSH Context
- NVIDIA — NVIDIA Container Toolkit Installation Guide
参考地址可从以下官方站点查找:
1
2
3
4
5
https://developers.openai.com/
https://learn.chatgpt.com/docs/
https://code.visualstudio.com/docs/remote/ssh
https://docs.docker.com/
https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/
由于 Codex 与 VS Code 的版本迭代较快,实施时建议再查一遍上述官方文档的最新版本。
四十二、后续可继续细化的三个文档
在这份总方案跑通后,可以再单独整理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
01-network.md
Mac VPN / Clash / Surge / 具体代理软件
如何安全共享给 Ubuntu
02-server-bootstrap.md
一键安装 Ubuntu 开发环境
Docker / Git / Node / Python / CUDA
03-myapp-dev.md
针对你实际项目的目录
Docker Compose
环境变量
API
数据库
Codex AGENTS.md
iOS xcconfig
其中最值得优先继续细化的是:
1
01-network.md
因为你当前整个双机 Codex 架构能否成立,最关键的不是 13900K 或 4090,而是:
1
2
Remote Codex 所在的 Server
是否拥有稳定、可控的网络出口。