# RO-BEING 관리자 대시보드 구축 및 트러블슈팅 **날짜**: 2025-07-14 **작업자**: Claude (RO-BEING 시스템 관리) ## 개요 기존 8000번 포트 backend에 `/admin/*` 경로로 종합 관리 대시보드를 구축하는 과정에서 발생한 문제들과 해결 방법을 기록합니다. ## 프로젝트 목표 ### 구현 기능 - 시스템 리소스 모니터링 (CPU, 메모리, 디스크) - Docker 컨테이너 상태 및 관리 - 서비스 Health Check (Nginx, Gitea, Frontend, Backend, Test-API) - Nginx 상태 확인 및 재로드 - Gitea Actions Runner 모니터링 - Git 활동 추적 - 실시간 로그 조회 - JWT 기반 인증 시스템 ### 접속 정보 - **URL**: http://ro-being.com/admin - **로그인 비밀번호**: 19800508 ## 발생한 문제들과 해결 과정 ### 1. 포트 충돌 문제 **문제**: 8000번 포트가 이미 고객용 서비스로 사용 중 **초기 계획**: 별도 포트(9000)나 독립 컨테이너 사용 **최종 해결**: 경로 분리 방식 채택 (`/admin/*` 경로) **장점**: - 기존 고객 서비스에 영향 없음 - 통합 관리 가능 - 추가 포트 오픈 불필요 ### 2. 외부 접속 불가 문제 **증상**: `ERR_CONNECTION_TIMED_OUT` 오류 발생 **원인**: nginx 설정에 `/admin` 경로 프록시 설정 누락 **해결책**: nginx 설정 추가 ```nginx # Admin dashboard location /admin { proxy_pass http://localhost:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } ``` **배포 방법**: Gitea Actions 자동 배포 활용 ### 3. 서비스 Health Check 실패 **문제**: 모든 서비스가 `unreachable` 또는 `timeout` 상태 **원인**: 1. 잘못된 health check 엔드포인트 2. 서비스별 상태 코드 차이 미고려 **해결책**: 서비스별 맞춤 설정 ```python SERVICES = { "nginx": {"port": 80, "url": "http://localhost", "health_path": "/health", "timeout": 3}, "gitea": {"port": 3000, "url": "http://localhost:3000", "health_path": "/api/healthz", "timeout": 3}, "frontend": {"port": 5173, "url": "http://localhost:5173", "health_path": "/", "timeout": 3}, "backend": {"port": 8000, "url": "http://localhost:8000", "health_path": "/health", "timeout": 3}, "test-api": {"port": 10508, "url": "http://localhost:10508", "health_path": "/health", "timeout": 3} } ``` **개선사항**: - nginx: 404도 정상으로 인식 - gitea: `/api/healthz` 엔드포인트 사용 - frontend: 200/304 상태 코드 모두 허용 - 타임아웃 3초로 단축 ### 4. Docker API 접근 실패 (HTTP 500) **증상**: 컨테이너 상태, Nginx 상태, Gitea Runners 모든 API에서 500 에러 **원인**: 컨테이너에서 Docker 소켓 접근 불가 **진단**: ```bash docker exec frontend-backend-1 ls -la /var/run/docker.sock # ls: cannot access '/var/run/docker.sock': No such file or directory ``` **해결책**: docker-compose.yml 수정 ```yaml backend: build: context: ./backend dockerfile: Dockerfile ports: - "8000:8000" volumes: - ./backend:/app - /var/run/docker.sock:/var/run/docker.sock:ro # Docker 소켓 마운트 - /var/log/nginx:/var/log/nginx:ro # Nginx 로그 접근 - /home/admin:/host_home:ro # 호스트 홈 디렉터리 접근 environment: - PYTHONPATH=/app privileged: true # Docker 권한 부여 ``` ### 5. 파일 경로 접근 문제 **문제**: 컨테이너 내부에서 호스트 파일 시스템 접근 불가 **영향받는 기능**: - Gitea Runner 로그 파일 읽기 - Git 저장소 활동 조회 - 시스템 로그 접근 **해결책**: 경로 매핑 및 코드 수정 ```python # 수정 전 log_file = "/home/admin/org_runner.log" repo_path = "/home/admin/github-migration/nginx-infra" # 수정 후 log_file = "/host_home/org_runner.log" repo_path = "/host_home/github-migration/nginx-infra" ``` ### 6. 권한 및 보안 설정 **요구사항**: - Docker 소켓 읽기 권한 - 시스템 명령어 실행 권한 (ps, systemctl) - 로그 파일 읽기 권한 **구현**: - `privileged: true` 설정 - 읽기 전용(`:ro`) 볼륨 마운트로 보안 강화 - JWT 토큰 기반 인증 (2시간 세션) ## 최종 아키텍처 ### 백엔드 구조 ``` /home/admin/frontend/backend/ ├── main.py # 기존 고객용 API + 관리자 라우터 등록 ├── admin_routes.py # 관리자 전용 API 엔드포인트 ├── admin_static/ │ └── index.html # 관리자 대시보드 프론트엔드 └── requirements.txt # 추가 dependencies (docker, psutil, PyJWT, requests) ``` ### API 엔드포인트 - `POST /admin/login` - 관리자 로그인 - `GET /admin/verify` - 토큰 검증 - `GET /admin/system/overview` - 시스템 리소스 - `GET /admin/containers` - Docker 컨테이너 상태 - `GET /admin/services/status` - 서비스 Health Check - `GET /admin/nginx/status` - Nginx 상태 - `GET /admin/gitea/runners` - Gitea Runners 상태 - `GET /admin/git/recent-activity` - Git 활동 - `GET /admin/logs/{service}` - 서비스 로그 - `POST /admin/containers/{id}/restart` - 컨테이너 재시작 - `POST /admin/nginx/reload` - Nginx 재로드 ### 추가 Dependencies ``` docker==6.1.3 psutil==5.9.6 PyJWT==2.8.0 requests==2.31.0 ``` ## 성능 최적화 ### 자동 새로고침 - 30초마다 주요 지표 자동 업데이트 - 로그인 세션 2시간 유지 - 비동기 API 호출로 빠른 응답 ### 사용자 경험 - 반응형 모바일 친화적 UI - 실시간 상태 표시 (색상 인디케이터) - 원클릭 관리 기능 (재시작, 재로드) ## 트러블슈팅 가이드 ### 일반적인 문제들 **문제**: 관리자 페이지 접속 안됨 **해결**: nginx 설정에 `/admin` 경로 추가 확인 **문제**: 모든 API에서 500 에러 **해결**: Docker 소켓 마운트 및 privileged 권한 확인 **문제**: 서비스 상태가 모두 unreachable **해결**: 서비스별 health check 엔드포인트 및 타임아웃 설정 확인 **문제**: 로그 파일 not found **해결**: 호스트 디렉터리 마운트 및 경로 매핑 확인 **문제**: Git 활동 조회 실패 **해결**: `/host_home` 경로로 Git 저장소 접근 확인 ### 모니터링 명령어 ```bash # 컨테이너 상태 확인 docker ps | grep frontend # 관리자 백엔드 로그 확인 docker logs frontend-backend-1 --tail=20 # Docker 소켓 마운트 확인 docker exec frontend-backend-1 ls -la /var/run/docker.sock # 권한 확인 docker exec frontend-backend-1 whoami docker exec frontend-backend-1 ps aux # API 테스트 curl -X POST http://localhost:8000/admin/login \ -H "Content-Type: application/json" \ -d '{"password":"19800508"}' ``` ## 보안 고려사항 ### 구현된 보안 기능 - JWT 토큰 기반 인증 - 비밀번호 하드코딩 (임시) - 읽기 전용 볼륨 마운트 - HTTPS 접속 (nginx SSL) ### 향후 개선사항 - 환경변수 기반 비밀번호 관리 - 다중 사용자 지원 - 세션 로깅 및 감사 - API 요청 제한 (Rate Limiting) ## 참고 자료 - **관리자 대시보드**: http://ro-being.com/admin - **백엔드 API 문서**: FastAPI 자동 생성 문서 (/docs) - **Docker Compose 설정**: `/home/admin/frontend/docker-compose.yml` - **Nginx 설정**: `/etc/nginx/sites-available/default` - **Gitea Actions**: nginx-infra 저장소 워크플로우 --- *이 문서는 Claude에 의해 자동 생성되었습니다.*