맥에서 EC2로 Hermes Agent 이사하기

작성일:2026.06.17|수정일:2026.07.07|조회수:1

맥에서 EC2로 Hermes Agent 이사하기

내가 Hermes Agent를 처음 Docker로 띄운 이유는 단순했다. 내 맥에서 돌아가게 만들고 싶었다. 그런데 막상 Discord까지 붙이고 나니 다른 문제가 생겼다. 노트북이 서버처럼 굴기 시작한 것이다.

잠깐 테스트할 때는 괜찮다. 하지만 개인 에이전트를 계속 켜두려면 이야기가 달라진다. 맥북은 닫고 싶을 때도 있고, 발열도 신경 쓰이고, 가끔은 그냥 노트북이 노트북답게 쉬었으면 좋겠다. 결국 Hermes는 로컬 앱이라기보다 작은 서버 프로세스에 가깝다. 그렇다면 EC2나 다른 VPS로 옮기는 편이 자연스럽다.

이 글은 Hermes Agent를 다른 컴퓨터나 서버로 이사시키는 방법을 정리한다. 핵심은 컨테이너를 옮기는 것이 아니다. Hermes의 상태 디렉터리를 옮기는 것이다. 컨테이너는 다시 만들 수 있다. Hermes의 정체성은 /opt/data에 mount한 디렉터리에 있다.

TXT
기존 컴퓨터의 ~/hermes-agents/personal
  -> 새 서버의 ~/hermes-agents/personal

personal 디렉터리 안에는 config.yaml, .env, 세션, 스킬, 메모리, 로그가 들어 있다. 이미지는 다시 받을 수 있고 컨테이너도 다시 만들 수 있지만, 이 디렉터리를 잃어버리면 내가 Hermes에게 쌓아둔 맥락을 잃어버린다. 조금 과장하면, 이 디렉터리가 Hermes의 몸통이다.

이사 전에 무엇을 옮길지 정한다

내가 쓰는 구조는 대략 이렇다.

TXT
~/hermes-agents/
  personal/       # Hermes 상태 디렉터리. 컨테이너의 /opt/data로 mount한다
  docker/         # docker-compose.yml 같은 운영 파일

반드시 옮겨야 하는 것은 personal이다. Docker Compose로 운영하고 있다면 docker도 같이 옮기는 편이 좋다. 그래야 새 서버에서 같은 명령으로 다시 띄울 수 있다.

personal 안에서 특히 중요한 파일은 다음과 같다.

TXT
config.yaml       # Hermes 설정
.env              # 모델 provider key, Discord token 같은 비밀값
skills/           # 누적된 스킬
sessions/         # 세션 관련 파일
state.db          # 세션/검색 상태
logs/             # 로그

여기서 .env가 가장 민감하다. 이사를 쉽게 하려면 그대로 옮기는 것이 편하지만, 그만큼 조심해야 한다. scp 대상을 잘못 치거나, 서버 권한을 대충 열어두면 API 키와 bot token을 통째로 넘기는 꼴이 된다. 이 글에서 하는 작업은 단순한 파일 복사가 아니라, 비밀값이 든 운영 상태를 옮기는 작업이다.

기존 컴퓨터에서 Hermes를 멈춘다

먼저 기존 컴퓨터에서 Hermes 컨테이너를 멈춘다.

SH
docker stop hermes-dev

이 단계가 중요한 이유는 두 가지다. 첫째, 복사하는 동안 세션 DB나 로그가 계속 바뀌는 일을 피할 수 있다. 둘째, 같은 Discord bot token이나 Telegram bot token을 가진 gateway가 두 군데에서 동시에 뜨는 일을 막을 수 있다.

특히 Discord나 Telegram처럼 하나의 bot token을 쓰는 gateway는 노트북과 EC2에서 동시에 켜지 않는 편이 좋다. 메시지가 어느 쪽으로 들어갈지 꼬이거나, 같은 요청을 서로 다른 프로세스가 처리하려고 할 수 있다. 이사는 “기존 것을 끄고, 복사하고, 새 것을 켠다”는 순서가 안전하다.

상태 디렉터리를 압축한다

이제 personaldocker 디렉터리를 묶는다.

SH
cd ~/hermes-agents

tar -czf ~/hermes-agents-backup-$(date +%Y%m%d-%H%M%S).tar.gz \
  personal \
  docker

Compose 파일을 쓰지 않는다면 docker는 빼도 된다.

SH
cd ~/hermes-agents

tar -czf ~/hermes-personal-$(date +%Y%m%d-%H%M%S).tar.gz \
  personal

압축 파일 안에는 .env가 들어 있다. 그러니 이 파일을 Slack에 올리거나, 아무 임시 저장소에 던져두면 안 된다. 잠깐 만들고, 새 서버로 옮긴 뒤 필요 없으면 지우는 편이 낫다.

새 서버를 준비한다

EC2를 예로 들면 처음 필요한 것은 많지 않다.

Discord나 Telegram gateway만 쓸 거라면 외부에 Hermes API 포트를 열 필요는 없다. gateway는 Discord/Telegram 쪽으로 나가는 연결만으로도 동작한다. 그래서 보안 그룹은 처음에 이렇게 작게 시작하는 편이 좋다.

TXT
Inbound
  SSH 22     내 IP만 허용
  8642       열지 않음
  9119       열지 않음

8642는 Hermes gateway의 OpenAI-compatible API server나 health endpoint를 외부에서 접근해야 할 때만 고민한다. dashboard를 쓸 때는 9119도 관련된다. 하지만 개인 Discord bot으로만 쓸 거라면 처음부터 열 이유가 없다. 포트를 열지 않는 것이 가장 단순한 보안 설정이다.

EC2에 Docker가 없다면 설치한다. Ubuntu 기준으로는 공식 설치 스크립트가 가장 빠르다.

SH
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

usermod 후에는 SSH를 다시 접속해야 권한이 반영된다.

SH
exit
ssh ubuntu@your-ec2-host

브라우저 기반 VPS 콘솔에서 긴 명령을 붙여넣는 것은 피하는 편이 좋다. Docker 명령에는 :, =, /, @ 같은 문자가 많이 들어가는데, 일부 콘솔은 이 문자들을 이상하게 전달한다. 가능하면 그냥 SSH로 들어가서 작업한다. 별것 아닌 것 같지만, -v ~/.hermes:/opt/data에서 : 하나가 깨지면 한참 헛돈다.

압축 파일을 새 서버로 복사한다

기존 컴퓨터에서 새 서버로 압축 파일을 보낸다.

SH
scp ~/hermes-agents-backup-20260707-120000.tar.gz \
  ubuntu@your-ec2-host:~

파일 이름은 실제로 만든 이름에 맞춘다. 매번 치기 귀찮으면 rsync를 써도 된다.

SH
rsync -avz ~/hermes-agents/ ubuntu@your-ec2-host:~/hermes-agents/

다만 처음 이사할 때는 tar가 더 명확하다. 한 덩어리로 묶고, 한 덩어리로 풀 수 있기 때문이다.

새 서버에서 압축을 푼다.

SH
ssh ubuntu@your-ec2-host
mkdir -p ~/hermes-agents

tar -xzf ~/hermes-agents-backup-20260707-120000.tar.gz \
  -C ~/hermes-agents

압축을 풀고 나면 구조가 이렇게 되어야 한다.

TXT
~/hermes-agents/
  personal/
    config.yaml
    .env
    skills/
    sessions/
  docker/
    docker-compose.yml

.env 권한도 한번 조여둔다.

SH
chmod 600 ~/hermes-agents/personal/.env

새 서버에서 Hermes를 띄운다

Compose를 쓰고 있다면 가장 단순하다.

SH
cd ~/hermes-agents/docker
docker compose up -d

Compose 파일은 대략 이런 모양이면 된다.

YAML
services:
  hermes-dev:
    image: nousresearch/hermes-agent:latest
    container_name: hermes-dev
    restart: unless-stopped
    volumes:
      - ../personal:/opt/data
    command: gateway run
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

여기서 중요한 줄은 역시 이것이다.

YAML
volumes:
  - ../personal:/opt/data

컨테이너 이름이 hermes-dev인지 hermes-personal인지는 본질이 아니다. Hermes가 어떤 /opt/data를 보고 있느냐가 중요하다.

Compose를 쓰지 않는다면 docker run으로 바로 띄울 수도 있다.

SH
docker run -d \
  --name hermes-dev \
  --restart unless-stopped \
  -v ~/hermes-agents/personal:/opt/data \
  nousresearch/hermes-agent:latest gateway run

공식 Docker 이미지는 gateway run을 supervised mode로 실행한다. gateway 프로세스가 죽으면 컨테이너 안에서 다시 올라오고, docker stop을 하면 정상적으로 내려간다. 개인 서버에 계속 켜두는 용도라면 이 기본 동작이 더 낫다.

로그와 실제 응답을 확인한다

컨테이너가 떴는지 먼저 본다.

SH
docker ps

로그를 확인한다.

SH
docker logs -f hermes-dev

Compose를 쓴다면 이렇게 봐도 된다.

SH
cd ~/hermes-agents/docker
docker compose ps
docker compose logs -f hermes-dev

로그에서 gateway가 올라왔고 Discord나 Telegram adapter가 연결된 것을 확인한 뒤, 실제로 메시지를 하나 보내본다. 여기서 중요한 확인은 “응답이 온다” 하나가 아니다.

이 확인이 끝나기 전까지는 기존 맥의 컨테이너를 다시 켜지 않는 편이 좋다. 새 서버가 제대로 뜨지 않았다면 원인은 대부분 셋 중 하나다.

TXT
1. /opt/data mount 경로가 잘못됐다
2. .env 또는 config.yaml이 빠졌다
3. Discord/Telegram token이나 권한 설정이 현재 서버에서 실패하고 있다

첫 번째가 가장 흔하다. 컨테이너 안에서 /opt/data를 못 보면 Hermes는 빈집에서 시작한다. 겉으로는 컨테이너가 멀쩡히 떠 있으니 더 헷갈린다.

API 포트는 필요할 때만 연다

이전 예제나 공식 문서에는 -p 8642:8642가 자주 나온다. 이 포트는 gateway의 API server나 health endpoint를 호스트 밖에서 접근할 때 필요하다. dashboard나 외부 도구를 붙일 계획이 있으면 써야 한다.

하지만 Discord bot만 운영한다면 굳이 열지 않아도 된다. EC2에서 포트를 연다는 것은 AWS 보안 그룹, 서버 방화벽, Hermes API key까지 같이 책임진다는 뜻이다. 처음에는 닫아두고, 필요해졌을 때 여는 쪽이 낫다.

만약 정말 외부 API 접근이 필요하다면 최소한 다음을 같이 본다.

SH
openssl rand -hex 32
YAML
services:
  hermes-dev:
    image: nousresearch/hermes-agent:latest
    container_name: hermes-dev
    restart: unless-stopped
    volumes:
      - ../personal:/opt/data
    command: gateway run
    ports:
      - "8642:8642"
    environment:
      API_SERVER_ENABLED: "true"
      API_SERVER_HOST: "0.0.0.0"
      API_SERVER_KEY: "여기에_긴_랜덤_문자열"

그리고 보안 그룹에서 8642를 전 세계에 열지 않는다. 가능하면 내 IP만 허용하거나, reverse proxy와 인증을 따로 둔다. 개인 에이전트는 내 일정, 메시지, 파일, 토큰과 연결될 수 있다. 그냥 장난감 서버처럼 열어두면 안 된다.

이전 맥으로 되돌리는 방법도 남겨둔다

이사는 항상 되돌릴 수 있어야 마음이 편하다. 새 서버에서 문제가 생기면 순서를 반대로 하면 된다.

SH
# EC2
docker stop hermes-dev

그리고 기존 맥에서 다시 켠다.

SH
# 기존 맥
docker start hermes-dev

다만 새 서버에서 Hermes를 한동안 사용한 뒤에는 상태가 새 서버 쪽에서 더 최신이 된다. 그 상태에서 맥으로 되돌리려면 EC2의 ~/hermes-agents/personal을 다시 맥으로 복사해야 한다. 그렇지 않으면 메모리, 세션, 스킬 변경분이 사라진 것처럼 보일 수 있다.

정리하면 active copy는 하나만 둔다.

TXT
운영 중인 쪽의 ~/hermes-agents/personal 이 최신 원본이다.

노트북과 EC2를 동시에 “둘 다 최신”으로 만들려고 하면 귀찮아진다. 데이터베이스 동기화나 파일 충돌까지 생각해야 한다. 개인용 Hermes 운영에서는 그럴 필요가 별로 없다. 한쪽을 끄고, 다른 쪽을 켠다. 단순한 방식이 오래 간다.

업데이트와 백업은 이사와 같은 원리다

이사를 이해하면 업데이트와 백업도 거의 같은 문제로 보인다. 이미지는 바꿔도 된다. 상태 디렉터리를 지키면 된다.

업데이트 전에는 백업을 하나 만든다.

SH
cd ~/hermes-agents

tar -czf ~/hermes-agents-backup-$(date +%Y%m%d-%H%M%S).tar.gz \
  personal \
  docker

그 다음 이미지를 갱신한다.

SH
cd ~/hermes-agents/docker
docker compose pull
docker compose up -d

컨테이너를 직접 띄운 경우라면 기존 컨테이너를 지우고 같은 mount로 다시 만들면 된다.

SH
docker rm -f hermes-dev

docker run -d \
  --name hermes-dev \
  --restart unless-stopped \
  -v ~/hermes-agents/personal:/opt/data \
  nousresearch/hermes-agent:latest gateway run

이 명령이 무섭지 않아야 한다. 컨테이너 삭제는 Hermes 상태 삭제가 아니다. 위험한 것은 이것이다.

SH
rm -rf ~/hermes-agents/personal

이건 컨테이너를 지우는 것이 아니라 Hermes의 상태 자체를 지우는 일이다. .env, config.yaml, 세션, 스킬, 메모리를 직접 삭제하는 것과 같다. 컨테이너는 cattle처럼 다뤄도 되지만, 상태 디렉터리는 아직 pet처럼 다루는 편이 맞다.

마무리

Hermes Agent를 서버로 옮기는 일은 생각보다 단순하다. 새 서버에 똑같은 이미지를 받고, 기존 상태 디렉터리를 /opt/data로 mount하면 된다. 복잡해 보이는 Docker 명령들은 결국 이 한 줄을 위한 주변 장치다.

TXT
~/hermes-agents/personal -> /opt/data

내 맥에서 돌아가던 Hermes를 EC2로 옮긴다는 것은, 맥에 있던 personal 디렉터리를 EC2로 옮기고 그 디렉터리를 다시 /opt/data로 연결한다는 뜻이다. Discord 설정도, 모델 설정도, 스킬도, 메모리도 그 안에 있다.

결국 중요한 것은 “어디서 실행하느냐”보다 “어떤 상태를 보고 실행하느냐”다. 노트북은 더 이상 서버 흉내를 내지 않아도 되고, Hermes는 EC2에서 계속 살아 있으면 된다. 지금 단계에서는 그 정도 분리만 해도 충분하다.

댓글

댓글을 불러오는 중...