MQTT Broker Setup Guide
공개 PoC 브로커에서 내부 TLS 및 ACL 통제 브로커로의 컷오버 셋업 가이드
1. PoC vs Production broker
자율 에이전트 위임 스킬(delegate-job)의 모든 연결 설정은 환경변수 및 레지스트리 레코드의 broker 블록 정보로부터 유도됩니다. 코드를 일체 변경하지 않고 설정 조율만으로 자체 사내망 브로커로 안전하게 컷오버(Cut-over)할 수 있도록 추상화되어 있습니다.
PoC 환경 (Public HiveMQ)
장점: 제로 셋업, 외부 접근성 완비, 빠른 프로토타입 작성 및 timeout/state-machine 로직 결선용에 최적화.
단점 및 수용 제약: 암호화 전송 없음(Plaintext), 임의의 제3자가 동일 토픽 메시지를 엿보거나 주입 가능, 민감 정보(패스워드, 소스 경로 등) 적재 절대 금지. 또한 비영속(Non-retained) 모드 구동 시 신호 수신기(Subscriber) 기동 전에 발행된 이벤트 및 재구독(Re-subscribing) 클라이언트의 과거 이벤트 유실을 수용해야 함.
Production 환경 (사설 Mosquitto)
장점: TLS 전송 암호화, ID/Password 기반 클라이언트 인증, 토픽 레벨의 세분화된 ACL 인가 통제(Publish/Subscribe 권한 분리), 영속성 보장(QoS 1 + Retained).
단점 및 관리 요소: 전용 사설 인프라 및 자체 CA/인증서 키 체인 수명 관리 셋업 비용 발생.
2. 환경변수로 broker config
공통 모듈 mqtt_common.py는 다음 환경변수를 우선 로드하여 접속 설정을 결정합니다. 코드를 일체 변경하지 않고 매개변수 설정만으로도 브로커를 즉각 대체할 수 있도록 추상화되어 있습니다.
| 환경변수 | 의미 | PoC 기본 설정값 | 운영(Production) 구성 예시 |
|---|---|---|---|
MQTT_BROKER |
브로커 서버 IP / 도메인 호스트명 | "broker.hivemq.com" |
"mqtt.internal.example.com" |
MQTT_PORT |
브로커 접속 포트 번호 | 1883 (Plaintext TCP) |
8883 (TLS TCP) |
MQTT_TLS |
TLS 암호화 채널 기동 옵션 (1/0) |
0 (미기동) |
1 (기동 활성화) |
MQTT_USERNAME |
접속 인증 계정 사용자명 | None |
"hermes-delegator" |
MQTT_PASSWORD |
접속 인증 계정 비밀번호 | None |
"secure_broker_password" |
MQTT_CA_CERTS |
검증용 사설 CA 인증서 묶음 파일 경로 | None |
"/etc/ssl/certs/internal-ca.pem" |
MQTT_CERTFILE |
mTLS 대응용 클라이언트 공개 인증서 경로 | None |
"/path/to/client.crt" |
MQTT_KEYFILE |
mTLS 대응용 클라이언트 개인 키 경로 | None |
"/path/to/client.key" |
MQTT_CLIENT_ID_PREFIX |
식별 접두사 (충돌 방지용 임의 접미사 결합) | "hermes" |
"hermes-prod" |
3. 운영 broker 설정 체크리스트 (Mosquitto/EMQX)
영속성 구성 및 TLS 암호화 채널, ACL 인가 제어를 위해 구성 정보를 셋업합니다. 다음 체크리스트를 준수하십시오.
- 영속성(Persistence) 보장: 브로커 재기동 시에도 이전 retained 메시지가 유지되도록 설정
- 익명 접속 금지:
allow_anonymous false설정으로 허가된 계정만 연결 허용 - 전용 포트 매핑: TLS 전용
8883포트 리스너 바인딩 - 인증 및 인가 분리: 비밀번호 파일 및 ACL 규칙 파일 경로 정의
3.1 Mosquitto 패키지 설치
# macOS 환경인 경우 Homebrew로 설치
brew install mosquitto
# Debian / Ubuntu 리눅스 환경인 경우
sudo apt-get update && sudo apt-get install -y mosquitto mosquitto-clients
# Docker 컨테이너 가상 머신으로 가동하는 경우
docker run -d --name mosquitto -p 8883:8883 \
-v "$PWD/mosquitto.conf:/mosquitto/config/mosquitto.conf" \
-v "$PWD/certs:/mosquitto/certs" \
-v "$PWD/auth:/mosquitto/auth" \
eclipse-mosquitto:2
3.2 `mosquitto.conf` 주요 설정 명세
persistence true
persistence_location /mosquitto/data/
password_file /mosquitto/auth/passwd
acl_file /mosquitto/auth/acl
allow_anonymous false
listener 8883
cafile /mosquitto/certs/ca.crt
certfile /mosquitto/certs/server.crt
keyfile /mosquitto/certs/server.key
3.3 사용자 크레덴셜 생성 (`mosquitto_passwd`)
인증된 클라이언트만 통신할 수 있도록 사용자 해시 패스워드 파일을 생성합니다.
# 최초 사용자(hermes) 등록 (-c 옵션은 기존 파일 초기화 및 재생성하므로 최초 1회만 사용)
mosquitto_passwd -c /mosquitto/auth/passwd hermes
# 추가 에이전트 전용 계정 등록 (-c를 붙이면 기존 패스워드 목록이 휘발되므로 제외)
mosquitto_passwd /mosquitto/auth/passwd claude-worker
4. TLS / 인증서 설정
전송 구간 암호화 및 도청 방지를 위해 TLS 인증체계를 갖춥니다. 사설 환경 구축 시 다음 명령어를 참조하여 인증서 세트를 준비하십시오.
4.1 간이 검증용 자체 서명 인증서 세트 (단일 호스트 테스트용)
mkdir -p certs && cd certs
openssl req -x509 -newkey rsa:2048 -nodes -days 825 \
-keyout server.key -out server.crt \
-subj "/CN=mqtt.internal"
cp server.crt ca.crt # 클라이언트는 동일 인증서를 루트 CA 신뢰용 인증서로 복사하여 참조
4.2 사내 전용 루트 CA 기반 발급 구조 (권장 체계)
# 1) 사내 최상위 루트 CA 키 및 인증서 생성 (10년 보존 기한)
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -days 3650 -out ca.crt -subj "/CN=Hermes-CA"
# 2) 브로커용 개인키 및 CSR 발급 신청 파일 생성
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=mqtt.internal"
# 3) 루트 CA 개인키 서명을 통해 최종 브로커용 인증서 생성 (825일 유효)
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 825
클라이언트는 환경변수 MQTT_CA_CERTS=/path/to/ca.crt를 설정함으로써 해당 사설 CA를 신뢰하게 됩니다.
5. ACL (claude worker / Hermes reader 권한 분리)
최소 권한의 법칙(Least Privilege)에 입각하여 퍼블리셔(에이전트 Worker)와 서브스크라이버(Hermes 모니터)의 토픽 읽기/쓰기 권한을 명확히 분리합니다. 이를 통해 타사 또는 다른 권한 영역의 에이전트가 허가되지 않은 작업 이벤트를 스푸핑하거나 발행하는 것을 완벽히 방지합니다.
5.1 ACL 규칙 파일 명세 (`/mosquitto/auth/acl`)
# claude-worker: 지정한 JID의 하위 이벤트 토픽에 메시지를 '발행'할 권한만 소유
user claude-worker
topic write python/mqtt/jobs/+/events
# hermes: 모든 작업 식별자 토픽으로부터 이벤트를 '구독'할 권한만 소유
user hermes
topic read python/mqtt/jobs/+/events
# 호환성 검증용 샘플 토픽 권한 공유
pattern readwrite python/mqtt/sample
6. Cut-over 절차 + precedence 함정 + 검증
환경 구성 이관 준비가 완료되었다면, 오직 주입 설정 정보만으로 올바르게 컷오버가 체결되는지 점검합니다.
우선순위 역전 장애 (Broker Precedence Pitfall) 주의
공통 모듈 broker_config_from_job()는 환경 변수보다 Job 레지스트리 레코드 내부의 broker.* 설정값을 최종 우선(Overriding)하여 병합합니다.
쉘 터미널에 신규 프로덕션 브로커 환경변수(MQTT_BROKER=mqtt.internal 등)를 정상 주입하였더라도, 과거에 이미 생성되어 대기 중이던 레지스트리 JSON 파일이 있다면 기존 PoC 주소(broker.hivemq.com)가 우선 적용되게 됩니다.
반드시 신규 작업을 다시 등록(register)하거나, 레코드 JSON 파일(.hermes/jobs/<id>.json)을 수동 편집하여 broker.host 항목을 수동 업데이트한 후 실행하십시오.
6.1 컷오버 통합 검증 명령어 시나리오
# 1) 쉘 환경에 신규 브로커 접속 매개변수 바인딩
export MQTT_BROKER=mqtt.internal
export MQTT_PORT=8883
export MQTT_TLS=1
export MQTT_CA_CERTS=$PWD/certs/ca.crt
export MQTT_USERNAME=hermes
export MQTT_PASSWORD=secure_hermes_password
# 2) mosquitto CLI 유틸리티를 활용한 선 구독 점검
mosquitto_sub -h "$MQTT_BROKER" -p 8883 --cafile "$MQTT_CA_CERTS" \
-u hermes -P "$MQTT_PASSWORD" -t 'python/mqtt/jobs/+/events' -v &
# 3) 작업 위임 스크립트를 변경 없이 실행
PY=.venv/bin/python
JID=$($PY scripts/registry.py register --prompt "broker cutover smoke test")
$PY scripts/job_subscriber.py --job "$JID" --timeout 30 &
sleep 3
$PY scripts/publish_event.py --job "$JID" --event started
$PY scripts/publish_event.py --job "$JID" --event completed
6.2 성공 판정 체크리스트
job_subscriber.py가completed최종 수신 감지 즉시 exit code 0으로 반환 종료mosquitto_sub백그라운드 수신 터미널 창에 발행된 JSON 이벤트 페이로드가 정상 검출됨- 인가되지 않은(허가 받지 않은) 크레덴셜 계정으로 publish 시도 시 브로커 ACL에 의해 즉각 거절 차단
- 작업 종료 시그널 발송 완료 후 늦게 접속한(late joined) 신규 구독자도 retained terminal 이벤트 정상 수신
검증이 완료되면, publish_event.py 및 에이전트 구동 시 로컬 Registry 정보를 통해 신규 브로커 정보로 자동 접속할 수 있도록 각 작업 레코드 JSON의 broker 블록을 다음과 같이 지속(Persist) 정의해 주십시오.
"broker": {
"host": "mqtt.internal",
"port": 8883,
"tls": true,
"username": "claude-worker",
"password": "…"
}