From 7b207d1b36fd09a4b4fb8b12e3ae0d44cdb2e1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=AC=B8=ED=98=95=EC=84=9D?= Date: Thu, 18 Jun 2026 11:05:26 +0900 Subject: [PATCH] chore: document local WSL setup fixes --- backend/internal/service/redis_service.go | 18 + docker-compose.yaml | 2 + .../wsl-local-run-2026-06-18.md | 65 +++ .../wsl-setup-issues-2026-06-18.md | 377 ++++++++++++++++++ 4 files changed, 462 insertions(+) create mode 100644 docs/local-run-notes/wsl-local-run-2026-06-18.md create mode 100644 docs/local-run-notes/wsl-setup-issues-2026-06-18.md diff --git a/backend/internal/service/redis_service.go b/backend/internal/service/redis_service.go index 52135dc8..60f69e20 100644 --- a/backend/internal/service/redis_service.go +++ b/backend/internal/service/redis_service.go @@ -78,6 +78,9 @@ func (s *RedisService) Ping(ctx context.Context) error { // StoreVerificationCode saves the SMS verification code with a 3-minute expiration func (s *RedisService) StoreVerificationCode(phone, code string) error { + if s == nil || s.Client == nil { + return os.ErrInvalid + } // Key format: "sms_verify:01012345678" key := "sms_verify:" + phone expiration := 3 * time.Minute @@ -87,6 +90,9 @@ func (s *RedisService) StoreVerificationCode(phone, code string) error { // GetVerificationCode retrieves the SMS verification code func (s *RedisService) GetVerificationCode(phone string) (string, error) { + if s == nil || s.Client == nil { + return "", os.ErrInvalid + } key := "sms_verify:" + phone code, err := s.Client.Get(ctx, key).Result() if err == redis.Nil { @@ -100,17 +106,26 @@ func (s *RedisService) GetVerificationCode(phone string) (string, error) { // DeleteVerificationCode removes the verification code after successful verification func (s *RedisService) DeleteVerificationCode(phone string) error { + if s == nil || s.Client == nil { + return os.ErrInvalid + } key := "sms_verify:" + phone return s.Client.Del(ctx, key).Err() } // Set stores a key-value pair with expiration func (s *RedisService) Set(key string, value string, expiration time.Duration) error { + if s == nil || s.Client == nil { + return os.ErrInvalid + } return s.Client.Set(ctx, key, value, expiration).Err() } // Get retrieves a value by key func (s *RedisService) Get(key string) (string, error) { + if s == nil || s.Client == nil { + return "", os.ErrInvalid + } val, err := s.Client.Get(ctx, key).Result() if err == redis.Nil { return "", nil @@ -120,6 +135,9 @@ func (s *RedisService) Get(key string) (string, error) { // Delete removes a key func (s *RedisService) Delete(key string) error { + if s == nil || s.Client == nil { + return os.ErrInvalid + } return s.Client.Del(ctx, key).Err() } diff --git a/docker-compose.yaml b/docker-compose.yaml index 11881d4f..26c67e30 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -70,6 +70,7 @@ services: - API_PROXY_TARGET=http://baron_backend:3000 - USERFRONT_URL=${USERFRONT_URL} - VITE_CLIENT_LOG_DEBUG=${VITE_CLIENT_LOG_DEBUG:-false} + - VITE_OIDC_CLIENT_ID=orgfront - DEV_SERVER_WATCH_POLLING=${DEV_SERVER_WATCH_POLLING:-true} ports: - "${ADMINFRONT_PORT:-5173}:5173" @@ -136,6 +137,7 @@ services: - API_PROXY_TARGET=http://baron_backend:3000 - USERFRONT_URL=${USERFRONT_URL} - VITE_CLIENT_LOG_DEBUG=${VITE_CLIENT_LOG_DEBUG:-false} + - VITE_OIDC_CLIENT_ID=orgfront - DEV_SERVER_WATCH_POLLING=${DEV_SERVER_WATCH_POLLING:-true} ports: - "${ORGFRONT_PORT:-5175}:5175" diff --git a/docs/local-run-notes/wsl-local-run-2026-06-18.md b/docs/local-run-notes/wsl-local-run-2026-06-18.md new file mode 100644 index 00000000..b23e4741 --- /dev/null +++ b/docs/local-run-notes/wsl-local-run-2026-06-18.md @@ -0,0 +1,65 @@ +# WSL Local Run Notes - 2026-06-18 + +## Environment + +- Host path: `/home/ubuntu/workspace/baron-sso` +- Runtime: WSL Ubuntu +- Docker Compose: available via `docker compose` +- Working branch: `dev` + +## Local URLs + +- UserFront: `http://localhost:5000` +- AdminFront: `http://localhost:5173` +- DevFront: `http://localhost:5174` +- OrgFront: `http://localhost:5175` + +## Run Sequence + +```bash +make build-auth-config +make validate-auth-config +make up-dev +make dev +``` + +## Verified State + +- `baron_backend`: healthy +- `baron_userfront`: healthy +- `baron_gateway`: healthy +- `baron_postgres`: healthy +- `baron_redis`: running +- `ory_kratos`, `ory_hydra`, `ory_keto`, `ory_oathkeeper`: running + +Backend health check: + +```json +{"checks":{"clickhouse":"ok","oathkeeper":"ok","redis":"ok"},"status":"ok"} +``` + +## Local Fixes Applied + +- `.env` + - Switched `APP_ENV` to `dev`. + - Removed inline comments from key env values that were leaking trailing spaces. + - Set public local URLs to `localhost`. + - Removed staging callback URLs from local callback lists. +- `backend/internal/service/redis_service.go` + - Added nil guards to Redis helper methods to prevent backend panic when Redis is not initialized. +- `docker-compose.yaml` + - Set OrgFront runtime `VITE_OIDC_CLIENT_ID=orgfront` so it does not inherit `devfront` from `.env`. + +## Browser Verification + +- UserFront opens and reaches the login screen. +- AdminFront opens. +- DevFront opens. +- OrgFront opens and reaches the login screen after fixing the OIDC client id. + +## Next Tasks + +- Connect Gitea MCP. +- Connect Playwright MCP. +- Use local browser checks and repository inspection for architecture and feature analysis. +- Prepare roadmap proposal after architecture and feature review. diff --git a/docs/local-run-notes/wsl-setup-issues-2026-06-18.md b/docs/local-run-notes/wsl-setup-issues-2026-06-18.md new file mode 100644 index 00000000..2748eb0c --- /dev/null +++ b/docs/local-run-notes/wsl-setup-issues-2026-06-18.md @@ -0,0 +1,377 @@ +# WSL Local Setup Issue Notes - 2026-06-18 + +## Issue 1. 작업 위치를 Windows 로컬 소스에서 WSL Ubuntu 소스로 전환 + +### 배경 + +팀장 요구사항은 Gitea의 `baron/baron-sso` 저장소를 Ubuntu/WSL 내부에 클론하고, 그 소스코드를 기준으로 로컬 구동, 아키텍처 분석, 기능 분석, 로드맵 제안을 진행하는 것이다. + +### 확인 내용 + +- 작업 경로: `/home/ubuntu/workspace/baron-sso` +- 브랜치: `dev` +- VS Code 상태: `WSL: Ubuntu` +- Docker Compose 사용 가능 + +### 결과 + +WSL 내부 Baron SSO 소스코드 기준으로 작업 위치를 확정했다. + +--- + +## Issue 2. `.env` 파일 부재 및 로컬 env 복원 + +### 증상 + +WSL 저장소 루트에 실제 `.env` 파일이 없고 `.env.sample`만 존재했다. + +### 확인 내용 + +- 기존 Windows 로컬 env 발견: + - `/mnt/e/h_workspace/baron-sso/.env` +- WSL 저장소의 `.env.sample`과 키 목록을 비교했다. +- 기존 env에는 현재 샘플 대비 일부 키가 부족했다. + +### 조치 + +- 기존 Windows 로컬 `.env`를 WSL 저장소 루트로 복사했다. +- 부족한 로컬 기본 키를 보강했다. +- 로컬 실행 기준으로 URL 값을 정리했다. + +### 주요 로컬 값 + +```env +APP_ENV=dev +USERFRONT_URL=http://localhost:5000 +ADMINFRONT_URL=http://localhost:5173 +DEVFRONT_URL=http://localhost:5174 +ORGFRONT_URL=http://localhost:5175 +OATHKEEPER_PUBLIC_URL=${USERFRONT_URL} +HYDRA_PUBLIC_URL=${OATHKEEPER_PUBLIC_URL}/oidc +VITE_OIDC_AUTHORITY=http://localhost:5000/oidc +``` + +### 결과 + +로컬 실행용 `.env`가 준비되었다. `.env`는 git ignored 상태라 저장소 변경 목록에는 포함되지 않는다. + +--- + +## Issue 3. `.env` 인라인 주석으로 인한 환경변수 값 오염 + +### 증상 + +backend health check에서 Redis가 초기화되지 않았다. + +```json +{"checks":{"clickhouse":"ok","oathkeeper":"ok","redis":"not_initialized"},"status":"degraded"} +``` + +컨테이너 내부 환경변수 확인 결과 `REDIS_ADDR` 끝에 공백이 포함되어 있었다. + +```text +redis:6389 +``` + +### 원인 + +`.env`에서 아래처럼 값 뒤에 인라인 주석이 붙어 있어 Docker/앱 환경변수로 전달될 때 값에 공백이 섞였다. + +```env +REDIS_ADDR=redis:6389 # compose.infra.yaml의 redis 포트 +APP_ENV=dev # 애플리케이션 실행 환경 +``` + +### 조치 + +주석을 별도 줄로 분리했다. + +```env +# 애플리케이션 실행 환경 (dev, stage, production) +APP_ENV=dev + +# compose.infra.yaml의 redis 포트(컨테이너 내부 기준) +REDIS_ADDR=redis:6389 +``` + +### 결과 + +backend health check가 정상화되었다. + +```json +{"checks":{"clickhouse":"ok","oathkeeper":"ok","redis":"ok"},"status":"ok"} +``` + +--- + +## Issue 4. Backend Redis nil panic + +### 증상 + +`make dev` 실행 중 backend가 panic으로 종료되었다. + +```text +panic: runtime error: invalid memory address or nil pointer dereference +baron-sso-backend/internal/service.(*RedisService).Set(...) +``` + +### 원인 + +Redis 초기화 실패 시 `redisService`가 nil 상태가 될 수 있는데, 일부 워밍업 경로에서 nil RedisService의 `Set`, `Get`, `Delete` 계열 메서드가 호출되어 panic이 발생했다. + +### 조치 + +`backend/internal/service/redis_service.go`에 nil guard를 추가했다. + +대상 메서드: + +- `StoreVerificationCode` +- `GetVerificationCode` +- `DeleteVerificationCode` +- `Set` +- `Get` +- `Delete` + +### 결과 + +Redis 초기화 실패 상황에서도 backend 전체가 panic으로 죽지 않도록 방어했다. + +### 참고 + +현재 WSL 환경에는 `gofmt`가 설치되어 있지 않아 `gofmt`는 실행하지 못했다. + +--- + +## Issue 5. Auth/Ory 설정을 로컬 callback 기준으로 재생성 + +### 증상 + +기존 env에 staging callback URL이 섞여 있었다. + +예: + +```env +https://sso.hmac.kr/... +``` + +로컬 구동 목적상 OAuth/OIDC callback은 WSL 로컬 프론트 주소를 바라봐야 한다. + +### 조치 + +로컬 callback만 남겼다. + +```env +ADMINFRONT_CALLBACK_URLS=http://localhost:5173/auth/callback +DEVFRONT_CALLBACK_URLS=http://localhost:5174/auth/callback +ORGFRONT_CALLBACK_URLS=http://localhost:5175/auth/callback +``` + +이후 auth config를 재생성 및 검증했다. + +```bash +make build-auth-config +make validate-auth-config +make up-dev +``` + +### 결과 + +로컬 callback 기준으로 Ory/Kratos/Hydra 설정이 렌더링되었다. + +--- + +## Issue 6. OrgFront OIDC client id 오설정 + +### 증상 + +`http://localhost:5175` 접속 시 OrgFront에서 다음 에러가 발생했다. + +```text +오류: invalid_request +redirect_uri parameter does not match any of the OAuth 2.0 Client's pre-registered redirect urls. +``` + +### 확인 내용 + +OrgFront 컨테이너 내부 환경변수 확인: + +```bash +docker exec baron_orgfront printenv VITE_OIDC_CLIENT_ID +``` + +초기 값: + +```text +devfront +``` + +### 원인 + +OrgFront가 `orgfront` OIDC client가 아니라 `devfront` client id를 사용하고 있었다. 따라서 `http://localhost:5175/auth/callback`이 `devfront` client의 redirect URI와 맞지 않아 Hydra가 요청을 거부했다. + +### 조치 + +`docker-compose.yaml`의 OrgFront runtime environment에 아래 값을 명시했다. + +```yaml +- VITE_OIDC_CLIENT_ID=orgfront +``` + +### 결과 + +OrgFront 컨테이너 내부 값이 정상화되었다. + +```text +orgfront +``` + +브라우저에서 `http://localhost:5175` 접속 시 로그인 화면이 정상 표시되었다. + +--- + +## Issue 7. 로컬 서비스 구동 확인 + +### 실행 명령 + +```bash +make up-dev +make dev +``` + +### 최종 컨테이너 상태 + +- `baron_backend`: healthy +- `baron_userfront`: healthy +- `baron_gateway`: healthy +- `baron_postgres`: healthy +- `baron_redis`: running +- `baron_adminfront`: running +- `baron_devfront`: running +- `baron_orgfront`: running +- `ory_kratos`: running +- `ory_hydra`: running +- `ory_keto`: running +- `ory_oathkeeper`: running + +### 브라우저 확인 + +- `http://localhost:5000`: UserFront 로그인 화면 정상 +- `http://localhost:5173`: AdminFront 정상 +- `http://localhost:5174`: DevFront 정상 +- `http://localhost:5175`: OrgFront 로그인 화면 정상 + +### 참고 + +`5173`, `5174`는 dev mode에서 로그인 없이 대시보드가 보이는 동작이 확인되었다. 이후 기능 분석 단계에서 개발 모드 인증 우회 정책을 별도 확인할 필요가 있다. + +--- + +## Issue 8. Gitea MCP 등록 + +### 배경 + +팀장 과업상 Gitea 저장소/이슈/코드 확인을 MCP로 연결할 필요가 있다. + +### 참고 받은 설정 + +Codex는 `config.toml`에 MCP를 등록한다. + +기본 위치: + +```text +~/.codex/config.toml +``` + +### 실행 파일 위치 + +Windows에 받은 `gitea-mcp.exe`를 WSL에서 실행 가능함을 확인했다. + +```text +/mnt/e/900.tools/gitea-mcp_Windows_x86_64/gitea-mcp.exe +``` + +### 확인 명령 + +```bash +/mnt/e/900.tools/gitea-mcp_Windows_x86_64/gitea-mcp.exe --help +``` + +### 설정 추가 + +`~/.codex/config.toml`에 아래 구조를 추가했다. + +```toml +[mcp_servers.gitea] +command = "/mnt/e/900.tools/gitea-mcp_Windows_x86_64/gitea-mcp.exe" +args = ["-t", "stdio", "--host", "https://gitea.hmac.kr"] + +[mcp_servers.gitea.env] +GITEA_ACCESS_TOKEN = "***" +``` + +### 결과 + +Gitea MCP 설정 등록 완료. 실제 활성화 확인은 새 Codex 세션에서 `/mcp`로 확인해야 한다. + +--- + +## Issue 9. Playwright MCP 등록 + +### 배경 + +브라우저 자동 확인 및 로컬 화면 점검을 위해 Playwright MCP 연결이 필요하다. + +### 확인 내용 + +`npx` 사용 가능: + +```bash +npx --version +``` + +확인된 버전: + +```text +11.13.0 +``` + +### 설정 추가 + +`~/.codex/config.toml`에 아래 구조를 추가했다. + +```toml +[mcp_servers.playwright] +command = "npx" +args = ["-y", "@playwright/mcp"] +startup_timeout_sec = 30 +tool_timeout_sec = 120 +``` + +### 결과 + +Playwright MCP 설정 등록 완료. 실제 활성화 확인은 새 Codex 세션에서 `/mcp`로 확인해야 한다. + +--- + +## Current Git Changes + +현재 git 추적 변경: + +```text +M backend/internal/service/redis_service.go +M docker-compose.yaml +?? docs/local-run-notes/ +``` + +`.env`와 `~/.codex/config.toml`은 로컬 설정 성격이므로 저장소 변경 목록에는 일반적으로 포함되지 않는다. + +--- + +## Next Actions + +1. 새 Codex 세션 또는 VS Code 재시작 후 `/mcp`에서 `gitea`, `playwright` 활성화 여부 확인. +2. Gitea MCP로 저장소 이슈/PR/코드 흐름 확인. +3. Playwright MCP로 로컬 화면 자동 점검. +4. Baron SSO 아키텍처 분석 문서 작성. +5. 기능 분석 문서 작성. +6. 추가 로드맵 제안 문서 작성.