iOS에서 Self-Hosted Hermes Agent 실행하기: Cloudflare Tunnel + Access Service Tokens
요약
Cloudflare Tunnel과 Service Tokens를 활용하여 iOS 앱에서 셀프 호스팅된 Hermes Agent에 VPN 없이 안전하게 접속하는 방법을 설명합니다. OAuth 리다이렉트 문제를 커스텀 헤더 방식으로 해결하여 네이티브 앱 환경에서도 보안을 유지하며 에이전트를 사용할 수 있는 아키텍처를 제안합니다.
핵심 포인트
- Cloudflare Access Service Tokens를 사용하여 네이티브 앱의 OAuth 제한 해결
- Cloudflare Tunnel을 통한 보안 엣지 보호 및 VPN 없는 연결 구현
- Nginx Proxy Manager 또는 직접 연결을 통한 두 가지 아키텍처 경로 제시
- Hermes API 서버 활성화 및 커스텀 헤더 설정 방법 안내
iOS에서 Self-Hosted Hermes Agent 실행하기: Cloudflare Tunnel + Access Service Tokens + Hermex
릴레이 비용을 지불하지 않고, VPN 없이도, 완전한 Cloudflare 엣지 보호(edge protection)를 갖춘 상태로 iPhone에서 Hermes Agent를 사용해 보세요.
문제점 (The Problem)
VPS에서 Hermes Agent를 셀프 호스팅(self-hosted)하여 운영 중입니다. iPhone에서 이 에이전트와 채팅하고 싶습니다. 몇 가지 방법이 있습니다:
- HermesPilot P2P 릴레이 (relay) - 유료화되기 전까지는 아주 잘 작동합니다.
- Tailscale VPN - 작동하지만 매번 VPN을 연결해야 합니다.
- Cloudflare Tunnel + CF Access - 브라우저용으로는 훌륭하지만, iOS 앱은 OAuth 리다이렉트(redirects)를 처리할 수 없습니다.
마지막 옵션이 가장 흥미로운 이유는 Cloudflare의 엣지 보호, 본인 소유의 도메인, 그리고 기기별 VPN이 필요 없다는 장점 때문입니다. 문제는 Cloudflare Access가 보통 브라우저 로그인(Google, GitHub 등)으로 리다이렉트한다는 점이며, 이는 네이티브 앱(native app)에서는 작동하지 않습니다.
해결책: Cloudflare Access Service Tokens + 커스텀 헤더 (custom headers).
아키텍처 (The Architecture)
두 가지 일반적인 경로가 있으며, 둘 다 서비스 토큰(Service Tokens)으로 작동합니다:
경로 A: Cloudflare Tunnel → Nginx Proxy Manager (NPM)
Hermex iOS App
│ 커스텀 헤더: CF-Access-Client-Id, CF-Access-Client-Secret
▼ HTTPS (오렌지 클라우드)
...
NPM은 오리진 인증서(origin certs)를 사용하여 SSL 터미네이션(termination)을 처리하며, 프록시 호스트(proxy hosts) 관리를 위한 편리한 UI를 제공합니다.
경로 B: Cloudflare Tunnel → Hermes로 직접 연결
Hermex iOS App
│ 커스텀 헤더
▼ HTTPS
...
더 단순하며 리버스 프록시(reverse proxy)가 필요 없습니다. Cloudflare가 엣지에서 SSL을 처리합니다.
사전 요구 사항 (Prerequisites)
- Cloudflare에 등록된 도메인 (오렌지 클라우드 프록시 적용됨)
- API 서버가 활성화된 Hermes Agent
- iOS 기기 및 App Store의 Hermex 앱
1단계: Hermes API 서버 활성화
~/.hermes/.env 파일에서 다음과 같이 설정합니다:
API_SERVER_ENABLED=true
API_SERVER_KEY=강력한 무작위 키 생성
API_SERVER_HOST=127.0.0.1
API_SERVER_PORT=8642
재시작 및 확인:
hermes gateway restart
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8642/health
→ 200
Step 2: Cloudflare Tunnel 설치 및 구성
2a. cloudflared 설치
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared
chmod +x /usr/local/bin/cloudflared
또는 Debian/Ubuntu에서:
sudo apt install cloudflared
2b. 인증 및 터널 생성
cloudflared tunnel login
cloudflared tunnel create hermes-tunnel
2c. DNS 라우팅
cloudflared tunnel route dns hermes-tunnel hermes-api.yourdomain.com
2d. 터널 구성
~/.cloudflared/config.yml 파일을 생성합니다:
tunnel:
credentials-file: /home/ubuntu/.cloudflared/.json
ingress:
- hostname: hermes-api.yourdomain.com service: http://localhost:8642
- hostname: hermes-webui.yourdomain.com service: http://localhost:8787
- service: http_status:404
실행합니다:
cloudflared tunnel run hermes-tunnel
또는 systemd 서비스로 설치합니다:
sudo cloudflared service install
2e. 터널 → Nginx Proxy Manager
NPM을 사용하는 경우, 터널의 대상을 localhost:80으로 지정합니다:
ingress:
- hostname: hermes-api.yourdomain.com service: http://localhost:80
- service: http_status:404
그런 다음 NPM에서 프록시 호스트를 추가합니다:
- Domain: hermes-api.yourdomain.com
- Forward to: http://127.0.0.1:8642
- Websockets 활성화
- SSL 탭 → Cloudflare Origin Certificate
- Cloudflare SSL/TLS → Full (strict)
Step 3: Cloudflare Access - 서비스 토큰
| 모드 | 작동 방식 | 사용처 |
|---|---|---|
| Allow | OAuth(Google, GitHub 등)으로 리디렉션합니다. | 브라우저 사용자 |
| Service Auth | 정적 헤더를 검증합니다. | 앱, API, 스크립트 |
3a. 서비스 토큰 생성
Cloudflare Zero Trust 대시보드 → Access → Service Auth → Create Service Token
이름을 hermex-ios로 지정하고, Client ID와 Client Secret을 즉시 복사합니다.
3b. Access Application 생성하기
Access → Applications → Add an application → Self-hosted → 도메인 설정
다음 설정을 포함하여 정책(Policy)을 추가합니다:
- Action: Service Auth ← "Allow"가 아님에 주의
- 선택: hermex-ios 서비스 토큰 (service token)
저장합니다. 이제 Cloudflare는 올바른 헤더(headers)가 포함된 요청을 수락합니다.
단계 4: Hermex 설정하기
iPhone에서 다음을 설정합니다:
- Instance URL: https://hermes-api.yourdomain.com
- Custom Header 1: CF-Access-Client-Id:
- Custom Header 2: CF-Access-Client-Secret:
연결(connect)을 누릅니다.
작동 원리
서비스 토큰 (Service Tokens)은 머신 간 인증 (machine-to-machine auth)을 위해 설계되었습니다. Cloudflare의 에지 (edge)는 모든 요청에서 CF-Access-Client-Id 및 CF-Access-Client-Secret 헤더를 읽고, 요청이 터널 (tunnel)에 도달하기 전에 이를 검증합니다. 앱은 로그인 페이지를 전혀 보지 않습니다. CI/CD 파이프라인이나 Terraform과 동일한 패턴이며, iOS에서도 동일하게 작동합니다.
mTLS는 어떤가요?
mTLS가 이상적이겠지만, iOS 지원이 매우 까다롭습니다. 번거로운 우회 방법 없이는 네이티브 NSURLSession 지원이 되지 않으며, 인증서 배포는 사용자 경험 (UX) 측면에서 악몽과 같고, 갱신 및 폐기에는 커스텀 코드가 필요합니다.
서비스 토큰은 TLS 핸드셰이크 (handshakes) 대신 HTTP 헤더를 통해 동일한 "에지에서의 사전 공유 자격 증명 (pre-shared credential at the edge)" 모델을 제공합니다.
문제 해결 (Troubleshooting)
- Cloudflare 로그인 페이지가 나타남 → 정책 (Policy)이 Service Auth 대신 Allow로 설정됨
- 401 Unauthorized → 헤더 철자 오류 (대소문자 구분)
- 502 Bad Gateway → 터널 (tunnel) 또는 NPM이 백엔드 (backend)에 도달할 수 없음
- Connection timeout → 터널 (Tunnel)이 실행 중이 아니거나 DNS가 프록시 (proxied) 처리되지 않음
빠른 상태 점검:
systemctl status cloudflared
curl localhost:8642/health
dig hermes-api.yourdomain.com +short
대안: Tailscale
curl -fsSL [https://tailscale.com/install.sh](https://tailscale.com/install.sh) | sh
sudo tailscale up
hermeslink config set lanHost "100.x.x.x"
WireGuard를 통해 작동합니다. 단점은 매번 VPN이 필요하다는 것입니다.
결론
Cloudflare Access Service Tokens는 Cloudflare 뒤에 있는 네이티브 앱 (native apps)을 인증하기 위한 마지막 퍼즐 조각입니다. Hermex의 커스텀 헤더 (custom header) 지원 덕분에, 이미 터널 (tunnel)이 실행 중이라면 이 과정은 약 10분 정도 소요됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기