본문으로 건너뛰기

[8] Hermes의 파일 생성 승인 문제 해결: write_file과 쓰기 허용 경로

· 약 7분

Python이나 셸 명령은

검증 범위 — 2026-10-09, Windows 농장 PC + WSL2 Ubuntu + Docker의 Hermes 환경에서 write_file로 garden/inbox/에 문서를 생성하고 Obsidian 동기화를 확인했다. 설치 버전마다 메뉴·경로·도구 정책이 달라질 수 있다.

1. 목표와 전제 조건​

목표: Hermes가 별도의 Python 또는 셸 실행 승인 없이 Markdown 파일을 생성하도록 설정한다. 허용 위치는 기존 Hermes 데이터 영역인 /opt/data와 Digital Garden의 /workspace/garden/inbox로 제한한다.

사전 조건:

  • Hermes가 Docker Compose로 실행 중이다.
  • 호스트의 garden/은 컨테이너의 /workspace/garden에 읽기 전용으로 연결되어 있다.
  • garden/inbox/만 별도로 읽기·쓰기 연결되어 있다.
  • Syncthing으로 농장 PC와 노트북 Obsidian의 garden/ 양방향 동기화가 검증되어 있다.

중요: Docker 마운트의 :rw와 Hermes 파일 도구의 쓰기 허용 정책은 별개의 제어 장치다. 둘 다 충족해야 write_file이 파일을 만들 수 있다.

2. 최초 증상: 파일 하나 만들 때도 승인 요청​

Hermes에게 다음과 같이 요청했다.

/workspace/garden/inbox/에 hermes-first-note.md 파일을 생성해 줘.

Hermes는 파일 작성 전용 도구 대신 Python 스크립트를 실행하려 했고, 다음 승인을 요구했다.

approval required · script execution via -e/-c flag
python3 -c "..."

1. Allow once
2. Allow this session
3. Always allow
4. Deny

당시에는 2번 Allow this session으로 작업을 완료했지만, 반복적인 문서 생성에 적합한 운영 방식은 아니었다.

설계 결정: python3 -c를 광범위하게 자동 허용하지 않는다. 임의 코드 실행은 문서 작성 외에도 많은 작업을 할 수 있기 때문이다. 파일 생성 전용 도구의 정책을 먼저 확인한다.

3. 승인 관리 기능 확인​

3.1 명령어 메뉴 확인​

Hermes는 대화형 명령에 TTY가 필요하다. 실제로 다음 명령은 오류가 발생했다.

docker exec hermes hermes tools
Error: 'hermes tools' requires an interactive terminal.

-it로 다시 실행했다.

docker exec -it hermes hermes tools

이 메뉴는 CLI 도구 활성화 등을 설정하는 기능이므로, 승인 정책 자체를 바꾸지는 않았다.

전체 명령 목록을 확인했다.

docker exec -it hermes hermes --help

여기서 approvals 명령을 확인했다.

docker exec -it hermes hermes approvals --help

당시 확인된 하위 명령:

  • suggest: 과거 승인 이력에서 자동 허용 후보 제안
  • test: 명령을 실제 실행하지 않고 승인 판정 검사

기록에 따라 후보를 조사했다.

docker exec -it hermes hermes approvals suggest

결과:

No allowlist candidates found in approval history (last 90 days).
Either nothing dangerous was approved often enough (see --min-count/--days),
or the approved classes are excluded for safety.

결론: 실제 기록에서 자동 허용 후보가 나오지 않았다. 후보가 없는 정확한 이유는 단정할 수 없다. 승인 정책을 무조건 우회하는 --yolo 옵션은 사용하지 않았다.

4. 원인 발견: write_file은 있지만 허용 경로가 다름​

Hermes 채팅에 다음 요청을 보냈다.

/workspace/garden/inbox/에 file-tool-test.md 파일을 생성해 줘.
단, Python이나 셸 명령은 사용하지 말고
파일 작성 전용 도구가 있다면 사용해 줘.
없다면 실행하지 말고 이유를 알려줘.

Hermes는 Write File 도구를 호출했지만 작업은 실패했다.

Write denied: '/workspace/garden/inbox/file-tool-test.md'
is outside HERMES_WRITE_SAFE_ROOT (/opt/data).

원인: 도구가 없어서가 아니라, Hermes의 쓰기 안전 경로가 /opt/data로 제한되어 있었다.

호스트 터미널에서 실제 환경변수를 확인했다.

docker exec hermes printenv HERMES_WRITE_SAFE_ROOT

결과:

/opt/data

5. 다중 경로 지원 확인: 설정값을 추측하지 않기​

문자열을 쉼표로 합치는 등 임의의 설정을 만들지 않고, 컨테이너에 포함된 설치 코드와 설명을 확인했다.

docker exec hermes sh -c \
'grep -R -n -m 3 "HERMES_WRITE_SAFE_ROOT" /opt/hermes 2>/dev/null | head -20'

실제 발견한 관련 소스는 다음 위치였다.

/opt/hermes/agent/file_safety.py

해당 코드에서는 경로 목록을 os.pathsep 기준으로 분할했다.

os.getenv("HERMES_WRITE_SAFE_ROOT", "").split(os.pathsep)

즉, Linux에서는 콜론(:)으로 여러 허용 경로를 지정할 수 있다.

/opt/data:/workspace/garden/inbox

Windows에서 직접 실행하는 Hermes라면 경로 구분자가 다를 수 있다. 이 매뉴얼의 설정은 Linux 컨테이너 내부를 기준으로 한다.

6. Docker Compose 수정과 적용​

기존 파일: /home/<USER>/docker/hermes/compose.yaml

기존 Hermes 설정과 Dashboard, 볼륨을 그대로 유지하면서 environment에 다음 항목을 추가했다.

services:
hermes:
image: nousresearch/hermes-agent:latest
container_name: hermes
restart: unless-stopped
command: gateway run
environment:
HERMES_DASHBOARD: "1"
HERMES_WRITE_SAFE_ROOT: "/opt/data:/workspace/garden/inbox"
volumes:
- /home/<USER>/.hermes:/opt/data
- /mnt/c/works/abulafium/garden:/workspace/garden:ro
- /mnt/c/works/abulafium/garden/inbox:/workspace/garden/inbox:rw
ports:
- "127.0.0.1:8642:8642"
- "127.0.0.1:9119:9119"

<USER>와 Windows 드라이브 경로는 사용자 환경에 맞게 바꾼다. 위 예시에서 두 중첩 볼륨 마운트는 이전 편에서 설정 완료된 상태였다. 이번 단계의 실질적인 변경점은 HERMES_WRITE_SAFE_ROOT 한 줄이다.

6.1 문법 검사​

docker compose -f /home/<USER>/docker/hermes/compose.yaml config --quiet

실제 검사 결과: 오류 없음.

6.2 컨테이너 재생성​

cd /home/<USER>/docker/hermes
docker compose up -d --force-recreate hermes

기존 .hermes 데이터 디렉터리를 삭제하지 않는다. 컨테이너 재생성 중에는 Gateway와 Dashboard 연결이 잠시 끊길 수 있다.

6.3 적용 결과 확인​

docker exec hermes printenv HERMES_WRITE_SAFE_ROOT

실제 출력:

/opt/data:/workspace/garden/inbox

7. 에이전트 동작 검증: 승인 없는 문서 생성​

Hermes 채팅에 아래 내용을 보냈다.

파일 작성 전용 도구 write_file을 사용해서
/workspace/garden/inbox/write-test.md 파일을 생성해 줘.

내용:
# Hermes 파일 작성 테스트

write_file 도구를 사용해 승인 없이 생성한 문서입니다.

Python이나 셸 명령은 사용하지 마.

실제 결과:

  1. Hermes가 write_file로 Markdown 문서 생성을 완료했다.
  2. Python·셸 실행에 대한 approval required 요청이 나타나지 않았다.
  3. 노트북 Obsidian에서도 생성된 파일을 확인했다.

따라서 다음 경로의 작업을 검증했다.

Hermes 채팅
→ write_file
→ /workspace/garden/inbox/write-test.md
→ 농장 PC의 garden/inbox/
→ Syncthing 양방향 동기화
→ 노트북 Obsidian

완료 판정: 일반적인 Markdown 파일 생성은 별도의 임의 코드 실행 승인 없이 가능해졌다.

8. 보안 범위와 제한 사항​

제어 계층적용 상태의미
Docker garden:ro적용Garden의 일반 영역을 컨테이너에 읽기 전용으로 제공
Docker inbox:rw적용inbox/에 파일 시스템 쓰기 허용
HERMES_WRITE_SAFE_ROOT적용write_file 및 관련 파일 도구의 허용 경로 제한
셸·Python 실행 승인유지위험한 실행 요청에 대한 별도 승인 정책 유지
기존 문서 수정 승인 워크플로미구현새 문서 생성과 별개로 추후 설계 필요

주의:

  • write_file의 경로 제한이 모든 도구·셸 명령을 통제하는 것은 아니다. 컨테이너에서 직접 실행하는 프로그램은 별도의 권한 및 승인 정책의 영향을 받는다.
  • inbox/를 쓰기 허용했다는 것은 새 파일 생성만 가능하다는 뜻은 아니다. 같은 폴더 안의 기존 파일 수정·덮어쓰기·삭제도 별도 정책 없이는 가능할 수 있다.
  • :ro와 :rw는 기존 자료 보호 범위를 줄이는 데 도움이 되지만, 이것만으로 완전한 권한 분리나 악성 명령 격리를 보장하지 않는다.
  • Syncthing으로 inbox/에 생성된 파일이 여러 장치에 전파되므로 중요한 자료는 백업하고, 자동 생성 파일은 출판 전에 검토해야 한다.

9. 문제 발생 시 점검 순서​

증상 A: Write denied ... outside HERMES_WRITE_SAFE_ROOT

docker exec hermes printenv HERMES_WRITE_SAFE_ROOT
  • 두 경로가 모두 보이는지 확인한다.
  • Compose를 수정만 하고 재생성하지 않은 상태인지 확인한다.
  • 요청한 저장 경로가 /workspace/garden/inbox/ 아래인지 확인한다.

증상 B: Permission denied / 파일 생성 실패

docker inspect hermes --format '{{range .Mounts}}{{println .Source "->" .Destination "(" .RW ")"}}{{end}}'
  • inbox 마운트가 읽기·쓰기로 연결됐는지 확인한다.
  • 호스트 디렉터리의 실제 권한과 Docker 프로세스 사용자를 확인한다.

증상 C: Hermes는 작성했는데 Obsidian에 안 보임

  • 농장 PC 호스트의 garden/inbox/에 실제 파일이 있는지 먼저 확인한다.
  • Syncthing 양쪽 장치의 폴더 상태를 확인한다.
  • Windows → WSL2 → Docker 구성에서는 파일 감시가 지연될 수 있다. 실제 구축 시 60초 재탐색 간격을 적용했으며, 완전한 즉시 감지 문제는 해결하지 않았다.

증상 D: 또 python3 -c 승인을 요구함

  • Hermes에게 write_file을 사용하고 Python·셸 명령은 사용하지 말라고 명시해 본다.
  • write_file 도구가 활성화되어 있는지 확인한다.
  • --yolo 등 전체 실행 승인을 무조건 우회하는 옵션으로 문제를 덮지 않는다.

10. 이번 단계의 설계 결정 요약​

판단채택한 방법이유
반복 승인 제거파일 작성 전용 write_file파일 생성에 일반 코드 실행 불필요
승인 자동 허용 범위python3 -c 전체 허용 안 함임의 코드 실행 권한이 지나치게 큼
파일 쓰기 허용 범위/opt/data + inbox/기존 Hermes 데이터 기능 유지, Garden의 다른 폴더 보호
설정 변경 방법Compose 환경변수 추가 + 재생성Docker 실행 설정으로 재현 가능
성공 검증Agent 작성 + Obsidian 표시설정값 확인에서 끝내지 않고 전체 데이터 흐름 검증

11. 다음 단계​

이제 Hermes가 요청받은 문서를 안전한 지정 폴더에 저장하는 기본 경로는 확보했다. 후속 작업은 다음과 같이 구분한다.

  • 관심 분야 자료 수집 → 출처 확인 → Markdown 생성 → inbox/ 저장
  • 이메일 요약 → 개인정보·민감정보 검토 → Markdown 저장
  • 기존 문서 변경을 위한 별도 승인 워크플로
  • 정기 작업 예약, 실패 기록, 중복 생성 방지

이 항목들은 본 문서에서 구현·검증한 기능이 아니므로, 별도 후속편에서 다룬다.