[8] Hermes의 파일 생성 승인 문제 해결: write_file과 쓰기 허용 경로
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이나 셸 명령은 사용하지 마.
실제 결과:
- Hermes가
write_file로 Markdown 문서 생성을 완료했다. - Python·셸 실행에 대한
approval required요청이 나타나지 않았다. - 노트북 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 저장
- 기존 문서 변경을 위한 별도 승인 워크플로
- 정기 작업 예약, 실패 기록, 중복 생성 방지
이 항목들은 본 문서에서 구현·검증한 기능이 아니므로, 별도 후속편에서 다룬다.