# 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에 의해 자동 생성되었습니다.*