AWS에 Hermes Agent를 배포한 방법
요약
Nous Research의 오픈 소스 AI 에이전트인 Hermes Agent를 AWS EC2 환경에 효율적이고 안전하게 배포하는 방법을 설명합니다. 인바운드 포트를 전혀 열지 않고 텔레그램 롱 폴링 방식을 활용하여 보안을 강화하면서도 월 약 $35의 저렴한 비용으로 운영하는 아키텍처를 제안합니다.
핵심 포인트
- 텔레그램 롱 폴링을 활용해 인바운드 포트 개방 없이 외부 접속 구현
- EFS와 EBS 분리를 통해 I/O 부하를 줄이고 인프라 비용 최적화
- Amazon Bedrock과 IAM 역할을 연동하여 보안 및 인증 관리
- CDK를 이용한 VPC 및 네트워크 스택 자동화 구성
제 EC2 인스턴스는 퍼블릭 IP 주소를 가지고 있습니다. 인바운드 방화벽 규칙은 전혀 설정되어 있지 않습니다. 그럼에도 불구하고 저는 VPN이나 SSH 없이, 단 하나의 포트도 열지 않고 텔레그램(Telegram)에 있는 제 휴대폰에서 AI 에이전트에 접속하고, 브라우저에서 전체 웹 워크스페이스를 불러오며, 쉘(shell) 명령어를 실행할 수 있습니다.
최신 버전은 저장소를 의도적으로 분리했습니다. 지속적인 에이전트 데이터는 EFS에 유지되는 반면, Hermes 설치 파일과 Python 가상 환경(venv)은 루트 EBS 볼륨으로 이동했습니다. 이러한 변경을 통해 pip install / hermes update 시 발생하는 I/O 부하를 EFS에서 분리하였고, 상시 가동되는 인프라 비용을 매우 예측 가능한 수준인 월 약 $35로 유지할 수 있게 되었습니다.
이 포스트는 바로 그 설정에 관한 것입니다.
Hermes Agent란 무엇인가?
Hermes Agent는 Nous Research에서 만든 오픈 소스 AI 에이전트입니다. 단순한 챗봇 래퍼(wrapper)가 아닙니다. 지속적인 메모리, 기술(skills), 파일 시스템, 샌드박스화된 터미널 백엔드, 그리고 전체 웹 워크스페이스 UI를 갖추고 있습니다. 모델 제공자(model provider)를 지정하면 hermes-gateway라는 데몬(daemon)으로 실행되어 OpenAI 호환 API를 제공합니다.
웹 워크스페이스는 채팅 패널, 파일 브라우저, 터미널, 작업 큐(job queue)를 갖춘 제대로 된 IDE처럼 보입니다. 텔레그램(Telegram) 연동은 동일한 게이트웨이에 연결되는 롱 폴링(long-polling) 방식의 봇으로 작동합니다. 별도의 서버, 웹훅(webhook), 또는 퍼블릭 URL이 필요하지 않습니다.
저는 이 에이전트가 Amazon Bedrock을 기반으로 AWS에서 실행되기를 원했습니다(API 키 교체가 필요 없고, IAM 역할이 인증을 처리함). 또한 인스턴스를 교체하더라도 에이전트의 메모리가 유지되기를 바랐습니다.
아키텍처
사용자 휴대폰 (Telegram)
└─► Telegram 서버 ──► hermes-gateway 롱 폴링 (아웃바운드 HTTPS만 허용)
...
순서대로 배포되는 세 개의 CDK 스택:
| 스택 | 프로비저닝 항목 |
|---|---|
HermesNetworkStack | VPC (1 AZ), 퍼블릭 서브넷, IGW, S3 게이트웨이 엔드포인트, 보안 그룹 |
| ... |
보안 트릭: 인바운드 규칙 제로
AWS에 무언가를 배포할 때 본능적으로 프라이빗 서브넷(private subnet), NAT 게이트웨이(NAT Gateway), 그리고 VPC 인터페이스 엔드포인트(VPC interface endpoints)를 찾게 됩니다. 그것이 기업형 태세(enterprise posture)입니다. 하지만 이는 인스턴스가 시작되기도 전에 엔드포인트 비용만으로 월 약 $88가 소요됩니다.
개인적인 배포(personal deployment)의 경우, 실제 보안 경계(security boundary)는 서브넷(subnet) 유형이 아니라 인스턴스에서 무엇이 리스닝(listening)하고 있느냐입니다.
세 서비스 모두 127.0.0.1에만 바인딩(bind)됩니다. 보안 그룹(Security Group)에는 인바운드(inbound) 규칙이 전혀 없습니다. 인스턴스의 퍼블릭 IP(public IP)는 그 뒤에 아무것도 없기 때문에 모든 연결 시도를 거부합니다.
# network_stack.py — 인스턴스의 전체 인바운드 표면(inbound surface)
self.instance_security_group = ec2.SecurityGroup(
self,
...
관리자 액세스(Admin access)는 AWS Systems Manager Session Manager를 통해 이루어집니다. 이는 SSM 서비스 엔드포인트(endpoint)로의 아웃바운드(outbound) HTTPS 연결이며, 인바운드 포트(inbound port)는 필요하지 않습니다. SSM은 포트 포워딩(port-forwarding)도 처리하며, 이를 통해 워크스페이스(workspace)가 브라우저에 도달합니다.
텔레그램(Telegram)은 롱 폴링(long-polling) 방식을 사용합니다. 게이트웨이(gateway)가 텔레그램 서버로 아웃바운드 연결을 열고 이를 유지합니다. 텔레그램은 해당 연결을 통해 메시지를 푸시(push)합니다. 다시 말하지만, 인바운드는 전혀 없습니다.
결과적으로, 퍼블릭 IP에는 공격 표면(attack surface)이 존재하지 않습니다. Shodan이 하루 종일 스캔하더라도 말이죠.
메모리 트릭: 데이터는 EFS, 코드는 EBS
지속적인 에이전트 데이터(agent data) — SOUL.md, 기술(skills), 세션 히스토리(session history), 상태 DB(state DBs), 모든 비밀 정보가 담긴 .env, config.yaml — 는 /mnt/efs/hermes에 마운트(mount)된 EFS 볼륨에 저장됩니다. 대신 hermes 바이너리(binary) 및 venv는 /opt/hermes-agent에 있는 루트 EBS 볼륨에 저장됩니다.
왜 분리할까요? EFS 탄력적 처리량(Elastic Throughput)은 액세스한 GB당 비용이 부과됩니다. venv를 EBS로 옮기면 의존성 업데이트 시 발생하는 heavy throughput 비용을 EFS에서 제거할 수 있어, 의존성 업데이트 중에 높은 처리량 비용을 지불하는 대신 정상 상태(steady-state)의 EFS I/O 비용을 월 약 $1 정도로 유지할 수 있습니다. 전체 참조는 docs/STORAGE.md를 확인하세요.
EFS에는 RemovalPolicy.RETAIN이 설정되어 있습니다. 액세스 포인트(access point)는 해당 경로를 UID 10000으로 잠급니다. 35일의 보관 기간을 가진 자동 백업(automatic backups)이 활성화되어 있습니다.
# storage_stack.py — 영속성 계층(persistence layer)
self.file_system = efs.FileSystem(
self,
...
이것이 실제 환경에서 의미하는 바는 다음과 같습니다: 만약 EC2 인스턴스에 문제가 발생하면, cdd deploy를 실행하여 새로운 인스턴스를 생성하면 됩니다. 새 인스턴스는 동일한 EFS를 마운트하고, 동일한 .env 파일을 읽으며, user-data를 통해 EBS에 venv를 재설치합니다. 그러면 세 가지 systemd 서비스가 에이전트의 모든 메모리를 온전하게 유지한 채 시작됩니다. 수동 데이터 마이그레이션이나 재설정은 필요하지 않습니다.
EC2 루트 EBS는 delete_on_termination=True로 설정되어 있습니다. 에이전트 데이터는 EFS(RETAIN)에 있으며, EBS에 있는 설치 아티팩트(install artifacts)는 배포할 때마다 자동으로 재생성됩니다.
Bedrock: API 키 불필요, IAM Role이 처리
Hermes는 Hermes Bedrock 가이드를 통해 Bedrock에 연결됩니다. EC2 인스턴스는 특정 추론 프로필(inference-profile) 및 파운데이션 모델(foundation-model) ARN에 대해서만 bedrock:InvokeModel, bedrock:Converse 및 스트리밍 변형(streaming variants) 권한이 부여된 IAM 역할(IAM role)을 가집니다.
어디에도 API 키가 없습니다. 키 로테이션(key rotation)도 필요 없습니다. 만약 인스턴스가 침해되더라도, 피해 범위(blast radius)는 두 가지 특정 모델에 대한 Bedrock 추론으로 제한됩니다. 이 역할은 S3, DynamoDB, 다른 계정 또는 그 외 어떤 것에도 접근할 수 없습니다.
이 스택에서는 두 가지 모델이 실행됩니다:
| 모델 | 역할 | 이유 |
|---|---|---|
us.anthropic.claude-sonnet-4-6 | 기본 (모든 주요 에이전트 작업) | Bedrock에서 가격 대비 최고의 추론 능력 |
us.amazon.nova-lite-v1:0 | 보조 (5개의 백그라운드 슬롯) | 웹 추출, 비전, 요약 작업 시 Sonnet보다 약 85배 저렴 |
us. 접두사는 교차 리전 추론 프로필(cross-region inference profile)입니다. Bedrock은 처리량(throughput)을 위해 us-east-1, us-east-2 또는 us-west-2로 자동으로 라우팅합니다. Bedrock Model Access 콘솔에서 두 모델을 한 번 활성화해 두면 다시는 건드릴 필요가 없습니다.
비용 상세 내역
인프라 (항상 켜져 있음, us-east-1)
| 구성 요소 (Component) | 상세 내용 (Detail) | ≈ 월간 비용 (Monthly) |
|---|---|---|
EC2 m7g.medium (Graviton, 2 vCPU / 4 GiB) | 730 hrs × $0.0404/hr | ~$29.50 |
| ... |
NAT Gateway를 사용하지 않았습니다. 인터페이스 VPC 엔드포인트 (interface VPC endpoints)도 사용하지 않았습니다. EC2는 인터넷 게이트웨이 (Internet Gateway)를 통해 아웃바운드 트래픽을 직접 라우팅합니다. 퍼블릭 서브넷 (public subnet)을 사용하고, 프라이빗 서브넷 (private subnet) + NAT 조합 대신 인바운드 허용이 없는 보안 그룹 (zero-inbound SG)을 선택한 이 단 하나의 아키텍처 결정이, 6개의 VPC 엔드포인트를 사용하는 동일한 프라이빗 서브넷 설정보다 58% 더 저렴합니다.
사용하지 않을 때는 중지하세요
aws ec2 stop-instances --instance-ids <InstanceId> --region us-east-1
EC2 컴퓨팅 비용 청구는 즉시 중단되며, 대부분의 EFS 데이터 액세스 I/O도 서비스와 함께 중단됩니다. EFS 스토리지 (storage), EBS, Secrets Manager, 그리고 CloudWatch는 월 약 $8 정도의 비용이 계속 청구됩니다. 다시 시작하면 SSM은 약 60초 내에 준비되며, 세 가지 hermes-* systemd 유닛이 자동으로 재시작됩니다. 재부팅(re-bootstrapping)이나 재설정 (re-configuration)이 필요 없으며, 에이전트의 메모리는 완전히 유지됩니다.
최저 비용: 꺼져 있을 때 약 $8/월. 항상 켜져 있을 때 약 $35/월.
Bedrock 토큰 (가변적, 인프라 비용 외 별도)
| 모델 (Model) | 요율 (Rate) | 일반적인 개인 사용량 |
|---|---|---|
| Claude Sonnet 4.x | 입력(in) ~$3/M · 출력(out) ~$15/M | $10–50/mo |
| Nova Lite (보조 슬롯) | 입력(in) ~$0.06/M · 출력(out) ~$0.24/M | < $2/mo |
대안과의 비교
ChatGPT Plus는 월 $20입니다. 하지만 여기에는 지속적인 에이전트 파일 시스템 (filesystem), 터미널 백엔드 (terminal backend), Telegram 롱 폴링 (long-polling)이 없으며, 메모리와 로그가 저장되는 위치에 대한 제어권도 훨씬 적습니다.
Hermes 설정은 직접 관리해야 할 인프라가 더 많지만, 그것이 핵심입니다. 여러분이 메모리, 기술, 에이전트의 페르소나를 형성하는 SOUL.md, 로그, 그리고 대화 기록을 직접 소유하게 됩니다. 오늘 인스턴스를 중지했다가 6개월 후에 다시 배포하더라도, 에이전트는 EFS 기반의 동일한 상태에서 작업을 이어갑니다.
설정 요약
- Bedrock 모델 액세스 활성화 (Enable Bedrock model access) — 콘솔에서 한 번만 수행, 두 개의 모델
cdk deploy --all— 세 개의 스택을 모두 프로비저닝합니다. 첫 부팅에는 5~8분이 소요됩니다 (패키지 설치 + 워크스페이스 빌드).- @BotFather를 통해 Telegram 봇 생성, @userinfobot을 통해 사용자 ID(user ID) 획득
- 봇 토큰(bot token) + 사용자 ID를 Secrets Manager (
hermes/runtime)에 추가, EFS로 동기화, 게이트웨이 재시작 - 노트북에서 웹 워크스페이스에 접속하기 위해 SSM을 통해
:3000포트 포워딩 (Port-forward) 수행
# 노트북에서 워크스페이스 접속
aws ssm start-session --target <InstanceId> \
--document-name AWS-StartPortForwardingSession \
...
4단계를 마친 후에는 Telegram이 즉시 작동합니다. 봇에게 메시지를 보내면 답장을 받을 수 있습니다. 추가 설정은 필요 없습니다.
놀라웠던 점
저는 프라이빗 서브넷 (private subnet), NAT 게이트웨이 (NAT Gateway), 그리고 SSM, Bedrock, Secrets Manager, EFS, CloudWatch를 위한 VPC 인터페이스 엔드포인트 (VPC interface endpoints)로 시작했습니다. 이는 모든 AWS 보안 가이드에서 권장하는 방식입니다. 하지만 단 하나의 토큰도 처리하기 전에 엔드포인트 비용만 월 약 $88가 발생합니다.
이 아키텍처를 가능하게 한 통찰은 다음과 같습니다: 개인용 에이전트의 보안 경계는 서브넷이 아니라, 인스턴스에서 도달 가능한 범위입니다. 인바운드 보안 그룹 (inbound SG) 규칙을 전혀 설정하지 않고 모든 서비스를 루프백 (loopback)에 바인딩하면, 퍼블릭 IP (public IP)는 아무런 역할도 하지 못합니다. SSM과 Telegram의 롱 폴링 (long-polling) 방식이 아웃바운드 HTTPS를 통해 두 가지 액세스 패턴 (관리자 셸 / 봇 메시지)을 처리합니다. VPN도, 배스천 호스트 (bastion)도, 열린 포트도 필요 없습니다.
이 유스케이스(use case)를 위한 가장 안전한 설계는 결국 가장 단순한 설계였습니다.
Built with Hermes Agent · AWS CDK (Python) · Amazon Bedrock · SSM Session Manager
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기