# 중앙 인증 서버(auth.ro-being.com) 구축 **날짜**: 2025-07-16 **관련 서비스**: auth-server, nginx-infra **작성자**: Claude AI Assistant ## 작업 개요 로빙 프로젝트의 모든 외부 서비스(Gmail, Slack, Notion 등) OAuth 인증을 중앙에서 관리하기 위한 auth.ro-being.com 서버를 구축했습니다. ## 주요 작업 내용 ### 1. 인증 서버 아키텍처 설계 **문제 상황**: - Gmail OAuth 리디렉션 URI 설정 필요 - 각 로빙 컨테이너가 개별적으로 인증을 관리하면 복잡도 증가 - 토큰 관리의 중앙화 필요 **해결 방안**: - auth.ro-being.com을 중앙 인증 허브로 구축 - 모든 OAuth 토큰을 중앙 DB에 저장 - 로빙 컨테이너는 API를 통해 토큰 조회 ### 2. auth-server 저장소 생성 ```bash # 저장소 생성 git.ro-being.com/ivada_Ro-being/auth-server # 기본 구조 auth-server/ ├── app/ │ ├── main.py # FastAPI 메인 │ ├── providers/ # OAuth 제공자별 모듈 │ │ └── gmail.py # Gmail OAuth (구현 예정) │ └── api/ # API 엔드포인트 │ └── tokens.py # 토큰 관리 API ├── docker-compose.yml # 포트 9000 설정 ├── Dockerfile └── requirements.txt ``` ### 3. Nginx 리버스 프록시 설정 **nginx-infra/default.conf 수정**: ```nginx # Auth server configuration server { listen 80; server_name auth.ro-being.com; location / { proxy_pass http://192.168.0.100:9000/; # 끝에 / 중요! 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; # OAuth 콜백 타임아웃 늘리기 proxy_read_timeout 300s; proxy_connect_timeout 75s; } } ``` **주의사항**: - `proxy_pass` 끝에 `/` 필수 - 없으면 하위 경로 전달 안됨 - 기존 서버 블록에 `server_name` 패턴 추가하여 auth 제외 ### 4. Docker 구성 **docker-compose.yml**: ```yaml services: auth-server: build: . container_name: auth-server ports: - "9000:9000" environment: - PORT=9000 - DATABASE_URL=${DATABASE_URL} - JWT_SECRET_KEY=${JWT_SECRET_KEY} - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} networks: - appnet ``` ## 전체 인증 플로우 ``` 1. 사용자 요청: "Gmail 읽어줘" ↓ 2. 로빙 컨테이너: 토큰 확인 ↓ 3. 토큰 없음 → auth.ro-being.com/auth/gmail/login 링크 전송 ↓ 4. 사용자: 링크 클릭 → Google 로그인 ↓ 5. Google → auth.ro-being.com/auth/gmail/callback ↓ 6. auth-server: 토큰 저장 (PostgreSQL) ↓ 7. 로빙: API로 토큰 조회하여 Gmail 접근 ``` ## 다음 단계 1. **서버 작업**: - auth-server 클론 및 빌드 - `.env` 파일 설정 - `docker-compose up -d` 실행 - nginx reload 2. **개발 작업**: - Gmail OAuth provider 구현 - PostgreSQL 토큰 저장 모델 - JWT 기반 API 인증 - rb10508_test에 Gmail 스킬 통합 ## 관련 파일 - `/home/happybell/projects/ivada/auth-server/` - 인증 서버 - `/home/happybell/projects/ivada/nginx-infra/default.conf` - Nginx 설정 - `/home/happybell/projects/ivada/skill_email/` - Gmail 스킬 (통합 예정) ## SSL/HTTPS 설정 추가 ### 문제 상황 - HTTP는 정상 작동하지만 HTTPS 접속 불가 - SSL 인증서는 이미 발급되어 있음 (auth.ro-being.com) - nginx 설정에 HTTPS 서버 블록 누락 ### 해결 과정 1. **nginx-infra 저장소 구조 파악**: - `default.conf`: Docker nginx 설정 (legacy) - `server-nginx-default`: 실제 서버 nginx 설정 파일 - Gitea Actions가 `server-nginx-default`를 서버의 `/etc/nginx/sites-available/default`로 복사 2. **HTTPS 서버 블록 추가**: ```nginx # Auth server configuration server { listen 80; server_name auth.ro-being.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name auth.ro-being.com; ssl_certificate /etc/letsencrypt/live/auth.ro-being.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/auth.ro-being.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; location / { proxy_pass http://localhost:9000/; # 끝에 / 필수! 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; # OAuth 콜백 타임아웃 늘리기 proxy_read_timeout 300s; proxy_connect_timeout 75s; } } ``` ### 최종 결과 - ✅ HTTPS 접속: 정상 작동 - ✅ HTTP → HTTPS 리다이렉션: 설정됨 - ✅ SSL 인증서: 유효 (2025-10-14까지) - ✅ Health check: 정상 응답 - ✅ OAuth 타임아웃: 300초로 설정 ## 교훈 1. **Nginx proxy_pass 설정**: 끝에 `/` 유무가 경로 전달에 중요한 영향 2. **중앙 인증의 장점**: 토큰 관리 일원화, 보안 강화, 확장성 3. **마이크로서비스 구조**: 각 서비스(인증, API, 로빙)를 독립적으로 관리 4. **SSL 설정 패턴**: HTTP는 HTTPS로 리다이렉션, HTTPS 블록에 실제 프록시 설정 5. **nginx-infra 워크플로우**: 로컬 수정 → Git push → Gitea Actions → 서버 배포 ## nginx/TLS 현재 상태 (2025-09-15 확인) ### 443 포트 사용 현황 ```bash sudo ss -tlnp | grep 443 # nginx (PID: 1732569)가 443 포트 사용 중 ``` ### nginx 설정 파일 위치 - **메인 설정**: `/etc/nginx/sites-available/default` - **활성 설정**: `/etc/nginx/sites-enabled/default` (심볼릭 링크) - **실행 중 설정 확인**: `sudo nginx -T` ### SSL 인증서 위치 및 상태 - **Let's Encrypt 인증서 디렉토리**: `/etc/letsencrypt/live/` - `ro-being.com/`: fullchain.pem, privkey.pem, cert.pem, chain.pem (2025-09-12 갱신) - `auth.ro-being.com/`: 동일 구조 - **인증서 유효기간**: 2025-09-11 ~ 2025-12-10 (Let's Encrypt R13 발급) - **Certbot 자동 갱신**: 90일마다 ### HTTPS 활성화된 도메인 (sites-available/default) 1. **ro-being.com** (161번 라인 server 블록) - listen 443 ssl; (Certbot 관리) - 문서 루트: `/home/admin/frontend-customer/dist` 2. **git.ro-being.com** (314번 라인) - listen 443 ssl http2; (315번 라인) - 프록시: localhost:3000 (Gitea) - 인증서: `/etc/letsencrypt/live/ro-being.com/` 3. **auth.ro-being.com** (348번 라인) - listen 443 ssl http2; (349번 라인) - 프록시: localhost:9000 (auth-server) - 인증서: `/etc/letsencrypt/live/auth.ro-being.com/` ### 프록시 설정 패턴 ```nginx location /api/ { 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; } ``` ### 포트별 서비스 - **80**: nginx (HTTP → HTTPS 리다이렉트) - **443**: nginx (HTTPS) - **3000**: Gitea - **8000**: 다른 서비스 (health check 응답) - **9000**: auth-server - **9200**: OpenSearch (HTTP only) - **5601**: OpenSearch Dashboards ### OpenSearch 상태 - **컨테이너**: opensearch (hostexecutor-opensearch-node) - **TLS**: 데모 인증서만 설정 (esnode.pem) - **접속**: http://localhost:9200 (내부 HTTP) - **결정**: nginx 리버스 프록시 방식 사용 (TLS 종료) ### 유용한 확인 명령어 ```bash # nginx 설정에서 443 포트 찾기 grep -n "listen 443" /etc/nginx/sites-available/default # 인증서 확인 sudo ls -la /etc/letsencrypt/live/ # SSL 핸드셰이크 테스트 openssl s_client -connect localhost:443 -servername ro-being.com # HTTPS 응답 확인 curl -I https://ro-being.com ```