# Tailscale / vnet 런타임 메모 — 2026-06-27 ## 결론 - Tailnet 전용 접속점은 `https://alpaca-home.taile93291.ts.net`이다. - 현재 머신에서 `tailscale serve` 루트 HTTPS가 `http://127.0.0.1:5173`으로 연결된다. - Tailnet 런타임은 API를 `8010`에 띄우고, Vite proxy가 `VITE_API_PROXY_TARGET=http://127.0.0.1:8010`을 보도록 분리했다. 기존 8000 reloader 잔류와 충돌하지 않게 하기 위해서다. - Tailnet dev-login은 `AUTH_DEV_LOGIN_EXTRA_ORIGINS=["https://alpaca-home.taile93291.ts.net"]`가 있을 때만 dev 환경에서 열린다. prod에서는 계속 차단된다. - Tailnet dev-origin에서는 Google OAuth 버튼을 비활성화하고, 직접 `/api/auth/login?provider=google`을 열어도 `local_oauth_unavailable` 안내로 되돌린다. 현재 redirect URI가 `https://api-vignette.chanpaca.net/auth/callback`로 고정되어 있어 Tailnet API가 만든 OAuth state를 public API callback이 검증할 수 없기 때문이다. 원격 수동검증은 `로컬 테스트 계정으로 계속`을 사용한다. - Vite proxy는 원래 프론트 `Host`/proto를 `X-Forwarded-Host`/`X-Forwarded-Proto`로 API에 넘긴다. 이 헤더가 없으면 dev OAuth 차단 redirect가 public 로그인으로 새는 회귀가 생긴다. - `scripts/dev-up.ps1`는 API 포트와 `VITE_API_PROXY_TARGET`을 같은 값으로 강제한다. Vite가 8010을 보는데 API가 8000/8002로 떠서 `/api/auth/config`가 500을 내던 회귀를 막기 위한 조치다. ## 검증 - `tailscale serve status`: - `https://alpaca-home.taile93291.ts.net` → `http://127.0.0.1:5173` - `GET https://alpaca-home.taile93291.ts.net/login` → `200` - `GET https://alpaca-home.taile93291.ts.net/api/auth/config` → `dev_login_enabled: true` - `POST https://alpaca-home.taile93291.ts.net/api/auth/dev-login` + cookie 재사용 `GET /api/auth/me` → `200` - `GET https://alpaca-home.taile93291.ts.net/api/auth/login?provider=google&next=%2Flearn` → `302 https://alpaca-home.taile93291.ts.net/login?oauth=local_oauth_unavailable` - Playwright DOM 확인: `https://alpaca-home.taile93291.ts.net/login`에 `로컬 테스트`, `학습자`, `교수자`, `관리자`, `로컬 테스트 계정으로 계속`이 표시된다. - Tailnet auth readiness E2E: `PLAYWRIGHT_BASE_URL=https://alpaca-home.taile93291.ts.net PLAYWRIGHT_SKIP_WEB_SERVER=1 npx playwright test e2e/auth.spec.ts --project=chromium-desktop --grep "shows Google OAuth readiness"` → `1 passed` - Tailnet dev-login E2E: `PLAYWRIGHT_BASE_URL=https://alpaca-home.taile93291.ts.net PLAYWRIGHT_SKIP_WEB_SERVER=1 npx playwright test e2e/auth.spec.ts --project=chromium-desktop --grep "shows Google OAuth readiness|logs in locally"` → `2 passed` - 로컬 리스너: - gateway `127.0.0.1:9099` - Tailnet API `127.0.0.1:8010` - web `127.0.0.1:5173` - 2026-06-27 17:00 KST 재확인: Tailnet `GET /login`이 `403 Blocked request. This host ... is not allowed`를 반환하던 원인은 Vite가 stale env로 떠서 `VITE_ALLOWED_HOSTS=alpaca-home.taile93291.ts.net`를 반영하지 못한 상태였다. `scripts/start-tailscale-runtime.ps1 -ApiPort 8010 -WebPort 5173 -SkipServeUpdate` 재기동 후 `GET /login` 200, `GET /api/health` dev/db/engine true, direct Google start 302 `local_oauth_unavailable`로 복구 확인. - 2026-06-27 18:25 KST 재확인: 같은 stale Vite `allowedHosts` 증상이 재발해 `scripts/start-tailscale-runtime.ps1 -ApiPort 8010 -WebPort 5173`로 스택을 재기동했다. 현재 `https://alpaca-home.taile93291.ts.net/login` 200, `/api/health` 200(`dev`, `db:true`, `engine:true`), `/api/auth/config` 200이다. 함께 확인한 공개 경로도 `https://vignette.chanpaca.net/login` 200, `https://api-vignette.chanpaca.net/health` 200(`prod`, `db:true`, `engine:true`)이다. ## 공개 vnet.18ka.net 상태 코드와 스크립트는 `vnet.18ka.net` / `api-vnet.18ka.net`을 인식하도록 준비했다. - backend `FRONTEND_ORIGIN_MAP` 기본값: - `api-vignette.chanpaca.net` → `https://vignette.chanpaca.net` - `api-vnet.18ka.net` → `https://vnet.18ka.net` - frontend public API fallback: - `vnet.18ka.net` → `https://api-vnet.18ka.net` - `scripts/start-public-runtime.ps1`는 `vnet.18ka.net` web preview(`5174`)와 `api-vnet.18ka.net` API(`8001`) ingress를 생성하도록 갱신했다. 아직 live 완료가 아닌 이유: - 현재 `vnet.18ka.net`과 `api-vnet.18ka.net`은 DNS가 없다. - 현재 cloudflared 인증 컨텍스트는 `18ka.net` zone을 관리하지 못한다. `cloudflared tunnel route dns vignette vnet.18ka.net` 실행 시 원하는 `18ka.net`이 아니라 `vnet.18ka.net.chanpaca.net` 레코드를 만들었다. - prod API는 현재 `127.0.0.1:8001`에서 `db:true`, `engine:true`로 건강하다. 다만 `api-vnet.18ka.net` DNS가 없어 외부 vnet 도메인으로는 아직 도달할 수 없다. - Google OAuth Console에도 `https://api-vnet.18ka.net/auth/callback`을 Authorized redirect URI로 추가해야 실제 Google 로그인이 완료된다. ## 재기동 명령 ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File scripts\start-tailscale-runtime.ps1 ``` 공개 vnet은 DB와 DNS가 준비된 뒤: ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File scripts\start-public-runtime.ps1 ```