Home / Blog / AI
Tech · AI · Claude Code · Codex

Happy Coder 自托管:把 Claude Code / Codex 装进手机的最优解

国内 iPhone 上用 Claude Code / Codex 又不想挂 VPN,可以试试 Happy Coder。把本地 AI 会话同步到自己国内的服务器,手机端走国内线路。本文是我的选型理由 + 自托管全套部署步骤。

Haofly by Haofly
· 2026-05-23 · 3 views

我手机上想用 Claude Code 这事折腾了半年。

说白了 5 件事得满足:Claude Code 和 Codex 都得能用、Mac 和手机的会话要连得上、服务端得自己说了算、别让我在手机上敲 terminal、相册里的图能直接发。

我把 GitHub 翻了一圈,能全做到的就一个:slopus/happy

为啥国内用户我会特意推荐这个。Claude 官方的 iOS app、Codex 官方 app 都是直连 Anthropic 和 OpenAI 的,手机上不挂 VPN 根本打不开。Happy 不一样,手机只跟你自己的服务器说话,服务器放国内(阿里云、腾讯云、家里 NAS 走公网穿透都行),跨境那一段是 Mac 帮你扛了。所以手机上你什么也不用做,地铁里掏出来就能用。

选型

我对比过这几个:

项目我的 5 项StarsE2E 加密备注
slopus/happy5/520.9kAES-256-GCMiOS 原生 + CLI + Web
siteboon/claudecodeui4/511.1k100% 自托管 PWA,跨设备要自己解决
amantus-ai/vibetunnel3/54.5k终端转发,UI 还是 terminal
JessyTsui/Claude-Code-Remote2/51.2k邮件/IM 桥,异步模式

Happy 还有一个我比较在乎的点是 E2E 加密。message 和 file 在客户端 AES-256-GCM 加密好了才上传,服务端拿到的就是它自己也解不开的密文。所以即便你暂时还没自托管,先用官方的服务也不慌。

架构

┌─────────────┐         ┌──────────────────┐         ┌─────────────┐
│  iOS App    │◀───WSS──│   happy-server   │──WSS───▶│  Mac daemon │
│             │   E2E   │  + PG + Redis    │   E2E   │  + CC/Codex │
└─────────────┘         └──────────────────┘         └─────────────┘
                          你自己的 VPS

Mac 上 happy daemon start-sync 这个常驻进程盯着本地的 Claude Code / Codex session,加密之后推到服务器。iOS 端从服务器拉密文回来本地解密渲染。服务器本身根本不知道你们在聊啥。

部署同步服务器

一台 2GB 的 VPS 就够,我自己跑下来内存稳定在 80MB 以内。前置假设你有 Ubuntu 22.04+,装好了 PostgreSQL、Redis、nginx、Node 20+。

1. 拉源码 + 建 PG

cd ~
git clone https://github.com/slopus/happy.git happy-server

sudo -u postgres psql <<'SQL'
CREATE USER happy_user WITH PASSWORD '<强密码>';
CREATE DATABASE happy_db OWNER happy_user;
SQL

happy 仓库是 monorepo,我们要的服务端在 packages/happy-server/ 这个子包里。

2. 写 .env.production

packages/happy-server/.env.production

NODE_ENV=production
PORT=3005
DB_PROVIDER=postgres
DATABASE_URL=postgresql://happy_user:<密码>@127.0.0.1:5432/happy_db
REDIS_URL=redis://:<redis密码>@127.0.0.1:6379/3
HANDY_MASTER_SECRET=<openssl rand -hex 32>
PUBLIC_URL=https://happy.example.com

说明一下:HANDY_MASTER_SECRET 是服务端自己签 token 用的密钥,不是用来加解密用户数据的。用户数据该怎么加密还是怎么加密。

3. 装依赖 + 跑 migration

cd ~/happy-server
pnpm install
cd packages/happy-server
pnpm prisma migrate deploy

4. systemd 单元

/etc/systemd/system/happy-server.service

[Unit]
Description=happy-server (Happy Coder sync server, E2E encrypted)
After=network.target postgresql.service redis-server.service

[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/home/deploy/happy-server/packages/happy-server
EnvironmentFile=/home/deploy/happy-server/packages/happy-server/.env.production
Environment="PATH=/home/deploy/.nvm/versions/node/v20.20.2/bin:/usr/local/bin:/usr/bin:/bin"
ExecStart=/home/deploy/.nvm/versions/node/v20.20.2/bin/pnpm start
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/deploy/happy-server
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictNamespaces=true
LockPersonality=true
RestrictRealtime=true
RestrictSUIDSGID=true

MemoryMax=256M

[Install]
WantedBy=multi-user.target

5. nginx vhost(WebSocket 反代)

server {
    server_name happy.example.com;

    location /.well-known/acme-challenge/ { root /var/www/html; }

    location / {
        proxy_pass http://127.0.0.1:3005;
        proxy_http_version 1.1;
        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_set_header X-Forwarded-Proto $scheme;

        # WebSocket upgrade(Happy 的实时同步走 WS)
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_buffering off;

        client_max_body_size 100M;
    }

    listen 80;
}

这里 WS upgrade header 千万别漏。漏了的话表现特别迷惑:连接是上的,消息就是不来,也不报错。我第一次部署就在这卡了半小时。

6. 起服务 + 上证书

sudo systemctl daemon-reload
sudo systemctl enable --now happy-server
sudo certbot --nginx -d happy.example.com

# 验证
curl -sI https://happy.example.com | head -1
sudo systemctl status happy-server

Mac 端:CLI + LaunchAgent 开机自启

npm install -g happy-coder
export HAPPY_SERVER_URL=https://happy.example.com   # 写进 ~/.zshrc
happy   # 第一次会弹 QR,用 iOS app 扫码配对

每次开机都要手动跑一遍太烦了,封成 LaunchAgent 让它自己跑。~/Library/LaunchAgents/net.example.happy-daemon.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key><string>net.example.happy-daemon</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/yourname/.nvm/versions/node/v22.15.1/bin/happy</string>
        <string>daemon</string>
        <string>start-sync</string>
    </array>
    <key>RunAtLoad</key><true/>
    <key>KeepAlive</key><true/>
    <key>ThrottleInterval</key><integer>10</integer>
    <key>EnvironmentVariables</key>
    <dict>
        <key>HAPPY_SERVER_URL</key><string>https://happy.example.com</string>
        <key>PATH</key><string>/Users/yourname/.nvm/versions/node/v22.15.1/bin:/usr/local/bin:/usr/bin:/bin</string>
        <key>HOME</key><string>/Users/yourname</string>
    </dict>
    <key>StandardOutPath</key><string>/Users/yourname/.happy/logs/launchagent-stdout.log</string>
    <key>StandardErrorPath</key><string>/Users/yourname/.happy/logs/launchagent-stderr.log</string>
    <key>WorkingDirectory</key><string>/Users/yourname</string>
    <key>ProcessType</key><string>Background</string>
</dict>
</plist>
launchctl load ~/Library/LaunchAgents/net.example.happy-daemon.plist
launchctl list | grep happy

ProgramArguments 第一个值一定要写 happy 的绝对路径。LaunchAgent 是不读 ~/.zshrc 的,PATH 默认是空的。如果你用 nvm,每次升 Node 版本这条路径就废了,记得回来改一下 plist。

iOS 端

App Store 搜 “Happy Coder”。注意国区还没上架,得切到美区或港区 Apple ID 才下得到(顺便说一句,Claude 和 Codex 官方 app 国区下不到,也是因为这个)。

装好后进 Settings,找到 “Relay Server URL” 这一项(app 里写的是这个英文,意思就是你刚搭的同步服务器),填上 https://happy.example.com。然后在 Mac 上跑 happy auth 会弹个二维码,30 秒内扫掉就配上了。

配好之后 iOS 里就能直接看到 Mac 上正在跑的会话,续聊、传图、传文件都行。

维护

更新我一般一两周做一次:

cd ~/happy-server && git pull
pnpm install
cd packages/happy-server && pnpm prisma migrate deploy
sudo systemctl restart happy-server

备份的话,所有用户数据(虽然都是加密的)都在 happy_db 这个数据库里,我自己已经有 pg_dumpall 的 cron,加一个不加一个都一样,自动备进去了。

要看日志:

sudo journalctl -u happy-server -f
tail -f ~/.happy/logs/launchagent-stderr.log   # Mac 端

用了一阵之后

「手机上用 AI Coding」这件事其实有好几条路,我都试过:

方案手机要挂 VPN?手机端 UX
Claude 官方 iOS app只能聊 claude.ai 本身,没法接本地工程
Codex 官方 iOS app同上
Termius / Blink SSH 进 Mac不要在手机上敲 terminal,传图传文件很别扭
Tailscale + web IDE不要浏览器里凑合用,不是原生 app
Happy Coder + 国内服务器不要iOS 原生 chat,接本地 CC/Codex,相册直传

Happy 比较合我胃口的地方是,本地 AI 工具的能力没缩水,手机上又不用挂 VPN,UX 还是 iOS 原生 app 的感觉。这三件事我之前一直没找到能同时给齐的方案。

什么人适合用:你本来就在 Mac 上跑 Claude Code 或 Codex CLI,想多设备切来切去;或者你不想把代码会话过第三方 SaaS;又或者你想给团队几个人搭一台共享的同步服务器,每人独立账号互相看不到。一台便宜的国内 VPS(2 核 2G 那种最低配)就够了。

什么人不适合:你从来只在 Mac 前面用,那 Happy 对你就是多余的一层;你想要的是浏览器里写代码跑命令那种 web IDE,可以看看 siteboon/claudecodeui;你既不想自托管又对官方服务不放心,那干脆别用更省事。

最后说一句心里话。我本来是想自己做一个翻译层 + 移动端 chat UI 的小产品,调研完才发现,认真做出一个能用的东西要 2 个月起,而 Happy 已经有 20.9k stars 在那里了,我做不到比它更好。后来把那两个月省下来,自己的服务器 10 分钟就搭好了,每个月也基本不用维护。

相关:

评论 · Comments

评论由 Giscus 提供,需用 GitHub 账号登录;留言会同步到这个仓库的 Discussions 里。