OpenClaw 보안 강화: Traefik으로 Basic Auth 구축하기

🔐 OpenClaw Gateway에 Traefik 리버스 프록시와 Basic Authentication을 적용하여 보안을 한층 강화하는 방법을 알아봅니다.
왜 Basic Auth가 필요한가?
OpenClaw Gateway는 기본적으로 로컬호스트에서만 접근 가능하지만, 다음과 같은 상황에서는 추가 보안이 필요합니다:
🚨 보안이 필요한 시나리오
- 원격 접속: VPN이나 공개 네트워크를 통한 접근
- VPS 배포: 클라우드 서버에서 실행할 때
- 네트워크 노출: LAN 환경에서 다른 기기의 접근 허용
✅ Basic Auth의 장점
- 🔒 간단한 구현: 복잡한 OAuth 없이 빠른 구축
- 🎯 효과적인 방어: 무단 접근 차단
- 🔄 표준 프로토콜: 모든 브라우저와 호환
- 📦 경량: 추가 리소스 거의 없음
Traefik 소개
Traefik은 현대적인 리버스 프록시이자 로드 밸런서입니다. Docker와의 완벽한 통합으로 마이크로서비스 환경에서 널리 사용됩니다.
🌟 Traefik의 주요 특징
- 🐳 Docker 네이티브: 라벨 기반 자동 설정
- 🔄 자동 디스커버리: 컨테이너 시작/종료 시 자동 반영
- 🛡️ 미들웨어 지원: Basic Auth, HTTPS, 압축 등
사전 준비
시스템 요구사항
1. Docker 환경 확인
# Docker 버전 확인
docker --version
# Docker version 24.0.0 이상
# Docker Compose 확인
docker compose version
# Docker Compose version v2.0.0 이상
2. OpenClaw 이미지 준비
# OpenClaw 리포지토리에서
cd openclaw
# 이미지 빌드
docker build -t openclaw:local -f Dockerfile .
3. 디렉토리 구조 준비
# 프로젝트 디렉토리 생성
mkdir -p ~/openclaw-docker
cd ~/openclaw-docker
# 데이터 디렉토리 생성
mkdir -p data
# 디렉토리 구조 확인
tree -L 2
예상 구조:
~/openclaw-docker/
├── compose.yml # Docker Compose 설정
├── .htpasswd # Basic Auth 인증 파일
├── .env # 환경 변수
└── data/ # OpenClaw 데이터
└── .openclaw/
└── workspace/
htpasswd 파일 생성
방법 1: htpasswd 명령어 사용 (권장)
macOS에서 htpasswd 설치
# Apache 도구 설치 (htpasswd 포함)
brew install httpd
인증 파일 생성
# 첫 번째 사용자 생성 (-c: 파일 생성)
htpasswd -c .htpasswd admin
프롬프트에서 비밀번호 입력:
New password: ********
Re-type new password: ********
Adding password for user admin
추가 사용자 생성
# 두 번째 사용자 추가 (-c 옵션 제거!)
htpasswd .htpasswd user2
⚠️ 주의: 두 번째 사용자부터는-c옵션을 빼야 합니다.-c를 사용하면 파일이 새로 생성되어 기존 사용자가 삭제됩니다!
방법 2: 온라인 생성기 (비권장)
보안상 로컬에서 생성하는 것을 권장하지만, 테스트 목적으로는:
- https://hostingcanada.org/htpasswd-generator/
- https://www.web2generators.com/apache-tools/htpasswd-generator
🔐 보안 팁: 프로덕션 환경에서는 반드시 로컬에서 생성하세요!
생성된 파일 확인
# .htpasswd 내용 확인
cat .htpasswd
출력 예시:
admin:$2y$05$EIBak0g7V8bQPjC9bLCJe.eXXRlMCDEXAMPLEHASH
user2:$2y$05$JDFak0g7V8bQPjC9bLCJe.eXXRlMEXAMPLEHASH2
Docker Compose 설정
compose.yml 수정
프로젝트 디렉토리의 docker-compose.yml 파일을 아래와 같이 수정합니다:
services:
# OpenClaw Gateway 서비스
openclaw-gateway:
image: openclaw:local
environment:
TZ: ${TZ}
HOME: /home/node
TERM: xterm-256color
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN}
volumes:
- ./data:/home/node
expose:
- "18789"
labels:
# Traefik 활성화
traefik.enable: "true"
# Basic Auth 미들웨어 정의
traefik.http.middlewares.auth.basicauth.realm: "chat"
traefik.http.middlewares.auth.basicauth.usersfile: "/auth/.htpasswd"
# 라우팅 규칙
traefik.http.routers.gateway.rule: "Host(`${GW_HOST}`)"
traefik.http.routers.gateway.middlewares: "auth"
traefik.http.routers.gateway.entrypoints: "web"
networks:
- openclaw
init: true
restart: unless-stopped
command:
[
"node",
"dist/index.js",
"gateway",
"--bind",
"lan",
"--port",
"18789",
]
# Traefik 리버스 프록시
openclaw-proxy:
image: traefik:v3.6
restart: unless-stopped
command:
# 익명 사용 통계 비활성화
- "--global.sendAnonymousUsage=false"
# 액세스 로그 활성화
- "--accesslog"
- "--accesslog.fields.names.StartUTC=drop"
# Docker 프로바이더 설정
- "--providers.docker"
- "--providers.docker.exposedByDefault=false"
- "--providers.docker.network=openclaw"
# HTTP 엔트리포인트 (포트 80)
- "--entrypoints.web.address=:80"
- "--entrypoints.web.forwardedHeaders.insecure=true"
environment:
- TZ=${TZ}
ports:
# 로컬호스트에만 포트 바인딩
- "127.0.0.1:18789:80"
volumes:
# htpasswd 파일 마운트
- ./.htpasswd:/auth/.htpasswd
# Docker 소켓 (읽기 전용)
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- openclaw
# OpenClaw CLI (선택사항)
openclaw-cli:
image: openclaw:local
environment:
HOME: /home/node
TERM: xterm-256color
BROWSER: echo
OPENCLAW_GATEWAY_TOKEN: ${OPENCLAW_GATEWAY_TOKEN}
volumes:
- ./data:/home/node
profiles:
- manual
network_mode: "service:openclaw-gateway"
stdin_open: true
tty: true
init: true
entrypoint: ["node", "dist/index.js"]
depends_on:
- openclaw-gateway
networks:
openclaw:
설정 상세 분석
1. OpenClaw Gateway 설정
포트 노출:
expose:
- "18789"
expose는 내부 네트워크에만 포트 공개- 외부에서 직접 접근 불가 (Traefik을 통해서만)
Traefik 라벨:
labels:
traefik.enable: "true"
traefik.http.middlewares.auth.basicauth.realm: "chat"
traefik.http.middlewares.auth.basicauth.usersfile: "/auth/.htpasswd"
traefik.http.routers.gateway.rule: "Host(`${GW_HOST}`)"
traefik.http.routers.gateway.middlewares: "auth"
라벨 설명:
traefik.enable: Traefik에서 이 컨테이너 관리 활성화basicauth.realm: 인증 창에 표시될 영역 이름basicauth.usersfile: htpasswd 파일 경로 (Traefik 컨테이너 내부 경로)router.rule: 라우팅 조건 (호스트명 매칭)router.middlewares: 적용할 미들웨어 (여기서는 auth)
2. Traefik 프록시 설정
포트 바인딩:
ports:
- "127.0.0.1:18789:80"
- 로컬호스트에만 바인딩 (외부 접근 허용시에는 삭제)
- 호스트 포트 18789 → 컨테이너 포트 80
볼륨 마운트:
volumes:
- ./.htpasswd:/auth/.htpasswd
- /var/run/docker.sock:/var/run/docker.sock:ro
.htpasswd: 인증 파일 (읽기/쓰기)docker.sock: Docker API 접근 (읽기 전용)
⚠️ 보안 참고: Docker 소켓을 마운트하면 컨테이너가 호스트의 Docker를 제어할 수 있습니다. Traefik은 컨테이너 정보를 읽기 위해 필요하며, :ro 플래그로 읽기 전용으로 제한했습니다.3. 네트워크 설정
networks:
openclaw:
모든 서비스가 openclaw 네트워크에 연결되어 내부 통신이 가능합니다.
환경 변수 설정
기존 .env 파일에 환경 변수를 추가합니다:
# 타임존 설정
TZ=Asia/Seoul
# Gateway 도메인
GW_HOST=localhost
# 기타 openclaw 설정...실행 및 테스트
1. 파일 확인
시작하기 전에 모든 파일이 준비되었는지 확인:
# 현재 디렉토리 구조
ls -la
필수 파일:
- ✅
compose.yml - ✅
.htpasswd - ✅
.env - ✅
data/디렉토리
2. 서비스 시작
# 백그라운드로 서비스 시작
docker compose up -d
# 또는 로그를 보면서 시작
docker compose up
3. 상태 확인
# 실행 중인 컨테이너 확인
docker compose ps
정상 출력:
NAME IMAGE STATUS
openclaw-gateway openclaw:local Up 30 seconds
openclaw-proxy traefik:v3.6 Up 30 seconds
4. 로그 확인
# Gateway 로그
docker compose logs -f openclaw-gateway
# Traefik 로그
docker compose logs -f openclaw-proxy
# 모든 로그
docker compose logs -f
5. 웹 브라우저 테스트
브라우저에서 다음 주소로 접속하면 인증창이 표시됩니다:
http://localhost:18789
6. CLI 테스트 (선택사항)
Basic Auth가 적용되어도 CLI는 Gateway 네트워크를 직접 사용하므로 인증 없이 작동합니다:
# CLI 컨테이너 실행
docker compose run --rm openclaw-cli status
# 채널 목록 확인
docker compose run --rm openclaw-cli channels list
문제 해결
1. 인증 창이 나타나지 않음
증상: 브라우저에서 바로 접속되거나 502 에러
확인 사항:
# Traefik 로그 확인
docker compose logs openclaw-proxy | grep -i auth
# htpasswd 파일이 제대로 마운트되었는지 확인
docker compose exec openclaw-proxy cat /auth/.htpasswd
해결책:
# 서비스 재시작
docker compose restart openclaw-proxy
# 캐시 문제라면 완전 재시작
docker compose down
docker compose up -d
2. 401 Unauthorized (인증 실패)
증상: 비밀번호를 입력해도 계속 인증 창이 나타남
원인:
- 비밀번호가 틀림
- htpasswd 형식 오류
해결:
# 새로운 htpasswd 파일 생성
rm .htpasswd
htpasswd -c .htpasswd admin
# 서비스 재시작
docker compose restart openclaw-proxy
3. 502 Bad Gateway
증상: Traefik은 작동하지만 Gateway에 연결 불가
원인:
- Gateway 컨테이너가 실행되지 않음
- 네트워크 문제
확인:
# Gateway 상태 확인
docker compose ps openclaw-gateway
# Gateway 로그 확인
docker compose logs openclaw-gateway
# 네트워크 확인
docker network inspect openclaw_openclaw
해결:
# Gateway 재시작
docker compose restart openclaw-gateway
# 전체 재시작
docker compose down && docker compose up -d
4. 포트 충돌
증상: Error: port 18789 is already in use
해결:
# 사용 중인 프로세스 확인
lsof -i :18789
# 또는 compose.yml에서 포트 변경
ports:
- "127.0.0.1:19000:80" # 다른 포트 사용
5. Permission Denied (htpasswd 접근 오류)
증상: Error: cannot access /auth/.htpasswd: Permission denied
해결:
# htpasswd 파일 권한 수정
chmod 644 .htpasswd
# 재시작
docker compose restart openclaw-proxy
6. Docker 소켓 권한 오류
증상: Error: permission denied while trying to connect to Docker daemon socket
해결:
# 현재 사용자를 docker 그룹에 추가
sudo usermod -aG docker $USER
# 로그아웃 후 다시 로그인하거나
newgrp docker
# 또는 docker 소켓 권한 변경 (비권장)
sudo chmod 666 /var/run/docker.sock
보안 강화 팁
1. 강력한 비밀번호 사용
# 랜덤 비밀번호 생성
openssl rand -base64 20
# 출력: Kj9xMn2Vp5Qw8Rt7Yz4Ua6Gb3Nc2. 파일 권한 설정
# .env 파일 (토큰 포함)
chmod 600 .env
# .htpasswd 파일
chmod 644 .htpasswd3. HTTPS 적용 (선택사항)
프로덕션 환경에서는 HTTPS를 권장합니다:
# compose.yml에 HTTPS 엔트리포인트 추가
services:
openclaw-proxy:
command:
# ... 기존 설정 ...
- "--entrypoints.websecure.address=:443"
- "[email protected]"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
ports:
- "127.0.0.1:443:443"
volumes:
# ... 기존 볼륨 ...
- ./letsencrypt:/letsencrypt
HTTPS 사용을 원하는 경우에는 별도의 SSL 인증서가 필요하며 letsencrypt 와 같은 무료 인증서 발급 기관을 통해 인증서를 발급받아 사용하면 됩니다.
4. IP 화이트리스트
특정 IP만 허용하려면:
# compose.yml
services:
openclaw-gateway:
labels:
# IP 화이트리스트 미들웨어 추가
traefik.http.middlewares.ipwhitelist.ipwhitelist.sourcerange: "192.168.1.0/24,127.0.0.1/32"
# 미들웨어 체인에 추가
traefik.http.routers.gateway.middlewares: "auth,ipwhitelist"
5. Rate Limiting
DDoS 공격 방어:
# compose.yml
services:
openclaw-gateway:
labels:
# Rate Limit 미들웨어
traefik.http.middlewares.ratelimit.ratelimit.average: "100"
traefik.http.middlewares.ratelimit.ratelimit.burst: "50"
# 미들웨어 체인에 추가
traefik.http.routers.gateway.middlewares: "auth,ratelimit"
6. 로그 모니터링
# 실패한 인증 시도 모니터링
docker compose logs openclaw-proxy | grep "401"
# 특정 IP에서의 과도한 요청 감지
docker compose logs openclaw-proxy | awk '{print $1}' | sort | uniq -c | sort -nr
유용한 명령어 모음
서비스 관리
# 시작
docker compose up -d
# 중지
docker compose stop
# 재시작
docker compose restart
# 완전 종료 및 정리
docker compose down
# 볼륨까지 삭제
docker compose down -v
사용자 관리
# 사용자 추가
htpasswd .htpasswd newuser
# 사용자 삭제
htpasswd -D .htpasswd olduser
# 비밀번호 변경
htpasswd .htpasswd existinguser
# 사용자 목록 확인
cut -d: -f1 .htpasswd
로그 및 모니터링
# 실시간 로그
docker compose logs -f
# 특정 서비스 로그
docker compose logs -f openclaw-proxy
# 최근 100줄
docker compose logs --tail=100 openclaw-gateway
# 특정 시간 이후 로그
docker compose logs --since 2024-01-01T00:00:00
디버깅
# 컨테이너 내부 접속
docker compose exec openclaw-proxy sh
# htpasswd 파일 내용 확인
docker compose exec openclaw-proxy cat /auth/.htpasswd
# 네트워크 정보
docker network inspect openclaw_openclaw
# 리소스 사용량
docker stats
성능 최적화
1. 로그 로테이션
# compose.yml
services:
openclaw-gateway:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
openclaw-proxy:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
2. 리소스 제한
# compose.yml
services:
openclaw-gateway:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
memory: 1G
3. Health Check
# compose.yml
services:
openclaw-gateway:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:18789/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
마무리
이제 OpenClaw Gateway가 Traefik과 Basic Auth로 보호되고 있습니다! 🎉