# TK Factory Services - NAS 배포 가이드

> 최종 업데이트: 2026-03-12

## 아키텍처 개요

```
                    Cloudflare Tunnel
                         |
          +--------------+--------------+
          |              |              |
  tkfb.techni..    tkreport.techni..   tkqc.techni..
          |              |              |
    tk-gateway:80   tk-system2-web:80  tk-system3-web:80
     (포털+S1)         (S2 신고)       (S3 부적합)
          |              |              |
    system1-api:3005  system2-api:3005  system3-api:8000
          |              |              |
          +--- MariaDB --+       PostgreSQL
               (공유)
```

### 서브도메인 라우팅

| 서브도메인 | Cloudflare Tunnel 대상 | 역할 |
|-----------|----------------------|------|
| `tkfb.technicalkorea.net` | `http://tk-gateway:80` | 통합 포털 + System 1 (공장관리) |
| `tkreport.technicalkorea.net` | `http://tk-system2-web:80` | System 2 (신고) |
| `tkqc.technicalkorea.net` | `http://tk-system3-web:80` | System 3 (부적합관리) |

### SSO 인증 방식

- 로그인: `tkfb.technicalkorea.net/login`에서 통합 로그인
- 토큰 저장: 쿠키 (`domain=.technicalkorea.net`, 7일 만료) + localStorage 이중 저장
- 시스템 간 이동: 쿠키가 서브도메인 간 자동 공유되므로 재로그인 불필요

### Docker 서비스 (13개)

| 서비스 | 컨테이너명 | 포트 |
|--------|-----------|------|
| MariaDB | tk-mariadb | 30306:3306 |
| PostgreSQL | tk-postgres | 30432:5432 |
| Redis | tk-redis | - |
| SSO Auth | tk-sso-auth | 30050:3000 |
| System 1 API | tk-system1-api | 30005:3005 |
| System 1 Web | tk-system1-web | 30080:80 |
| System 1 FastAPI | tk-system1-fastapi | 30008:8000 |
| System 2 API | tk-system2-api | 30105:3005 |
| System 2 Web | tk-system2-web | 30180:80 |
| System 3 API | tk-system3-api | 30200:8000 |
| System 3 Web | tk-system3-web | 30280:80 |
| phpMyAdmin | tk-phpmyadmin | 30880:80 |
| Cloudflared | tk-cloudflared | - |
| Gateway | tk-gateway | 30000:80 |

---

## 배포 전 준비 (로컬)

### 1. .env 파일 생성

```bash
cp .env.example .env
vi .env
```

필수 설정값:

```
# NAS 기존 TK-FB의 DB 패스워드와 동일하게 설정
MYSQL_ROOT_PASSWORD=<기존 tkfb_db root 패스워드>
MYSQL_PASSWORD=<기존 tkfb_db hyungi_user 패스워드>

# 새로 생성할 SSO 시크릿 (32자 이상 랜덤 문자열)
SSO_JWT_SECRET=<openssl rand -hex 32 로 생성>
SSO_JWT_REFRESH_SECRET=<openssl rand -hex 32 로 생성>

# NAS 기존 TKQC의 DB 패스워드와 동일하게 설정
POSTGRES_PASSWORD=<기존 tkqc-db mproject 패스워드>

# System 3 관리자 (기존 TKQC 관리자)
SYSTEM3_ADMIN_USERNAME=hyungi
SYSTEM3_ADMIN_PASSWORD=<기존 TKQC 관리자 비밀번호>

# Cloudflare Tunnel 토큰
CLOUDFLARE_TUNNEL_TOKEN=<Cloudflare Zero Trust 대시보드에서 확인>
```

기존 패스워드 확인 방법 (NAS SSH):
```bash
# TK-FB MariaDB 패스워드
cat "/volume1/Technicalkorea Document/tkfb-package/.env" | grep MYSQL

# TKQC PostgreSQL 패스워드
cat /volume1/docker/tkqc/tkqc-package/.env | grep POSTGRES

# Cloudflare Tunnel 토큰
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker inspect tkfb_cloudflared | grep TUNNEL_TOKEN
```

---

## NAS 배포 절차

### Step 1: 기존 서비스 백업

```bash
# NAS SSH 접속
ssh hyungi@192.168.0.3

# 백업 디렉토리 생성
mkdir -p /volume1/docker/backups/$(date +%Y%m%d)

# MariaDB 백업
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker exec tkfb_db \
  mysqldump -u root -p<ROOT_PASSWORD> --all-databases > \
  /volume1/docker/backups/$(date +%Y%m%d)/mariadb-all.sql

# PostgreSQL 백업
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker exec tkqc-db \
  pg_dumpall -U mproject > \
  /volume1/docker/backups/$(date +%Y%m%d)/postgres-all.sql

# uploads 백업
cp -r "/volume1/Technicalkorea Document/tkfb-package/uploads" \
  /volume1/docker/backups/$(date +%Y%m%d)/tkfb-uploads
cp -r /volume1/docker/tkqc/tkqc-package/uploads \
  /volume1/docker/backups/$(date +%Y%m%d)/tkqc-uploads
```

### Step 2: 프로젝트 NAS 전송 (git 기반)

NAS에 git이 설치되어 있으므로, Gitea에서 직접 clone/pull 합니다.

**최초 설정 (1회):**
```bash
# NAS SSH 접속
ssh hyungi@192.168.0.3

# git credential 저장 설정
git config --global credential.helper store

# 기존 배포 디렉토리 백업 후 clone
cd /volume1/docker_1/
mv tk-factory-services tk-factory-services.bak
git clone https://git.hyungi.net/hyungi/tk-factory-services.git

# 기존 .env 복원
cp tk-factory-services.bak/.env tk-factory-services/.env

# 확인 후 백업 삭제
cd tk-factory-services && git log -1
rm -rf ../tk-factory-services.bak
```

**이후 배포 (맥북에서 원커맨드):**
```bash
# 맥북에서 실행 - 자동으로 push 확인, NAS 비교, 빌드, health check 수행
./scripts/deploy-remote.sh
```

> **참고**: 설정 파일 `~/.tk-deploy-config` 필요 (아래 "원격 배포 스크립트" 섹션 참고)

### Step 3: 기존 서비스 중지

```bash
# NAS SSH
# TK-FB 중지
cd "/volume1/Technicalkorea Document/tkfb-package"
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose down

# TKQC 중지
cd /volume1/docker/tkqc/tkqc-package
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose down
```

### Step 4: 통합 서비스 기동

```bash
cd /volume1/docker/tk-factory-services

# Docker 이미지 빌드 + 서비스 기동
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose up --build -d

# 로그 확인
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose logs -f --tail=50
```

### Step 5: DB 마이그레이션

```bash
# SSO 유저 테이블은 docker-compose.yml에 의해 자동 실행됨
# (scripts/migrate-users.sql → MariaDB init)

# PostgreSQL 마이그레이션도 자동 실행됨
# (system3-nonconformance/api/migrations/ → PostgreSQL init)

# 헬스체크 확인
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose ps
```

### Step 6: Cloudflare Tunnel 설정

Cloudflare Zero Trust 대시보드 (`https://one.dash.cloudflare.com/`)에서:

1. **Networks → Tunnels** → 기존 터널 선택
2. **Public Hostname** 탭에서 3개 서브도메인 설정:

| Subdomain | Domain | Service |
|-----------|--------|---------|
| tkfb | technicalkorea.net | `http://tk-gateway:80` |
| tkreport | technicalkorea.net | `http://tk-system2-web:80` |
| tkqc | technicalkorea.net | `http://tk-system3-web:80` |

> 기존 `tkfb.technicalkorea.net`과 `tkqc.technicalkorea.net`은 대상 서비스만 변경

### Step 7: 테스트

```bash
# 1. 헬스체크
curl -s http://localhost:30005/api/health  # System 1 API
curl -s http://localhost:30105/api/health  # System 2 API
curl -s http://localhost:30200/api/health  # System 3 API
curl -s http://localhost:30050/api/health  # SSO Auth

# 2. 웹 접속 테스트 (브라우저)
# - https://tkfb.technicalkorea.net/ → 포털 표시
# - https://tkfb.technicalkorea.net/login → 로그인 페이지
# - 로그인 후 → 대시보드 이동
# - https://tkreport.technicalkorea.net/ → System 2 (재로그인 없이)
# - https://tkqc.technicalkorea.net/ → System 3 (재로그인 없이)

# 3. SSO 쿠키 확인 (브라우저 개발자 도구)
# - Application → Cookies에서 sso_token, sso_user 확인
# - domain이 .technicalkorea.net인지 확인
```

---

## 원격 배포 스크립트

맥북에서 원커맨드로 배포/확인/롤백할 수 있는 스크립트입니다.

### 설정 파일

`~/.tk-deploy-config` 생성 (git 추적 안 함):
```bash
NAS_HOST=100.71.132.52
NAS_USER=hyungi
NAS_DEPLOY_PATH=/volume1/docker_1/tk-factory-services
NAS_SUDO_PASS=<sudo 비밀번호>
```

### 사용법

```bash
# 배포 (pre-flight 체크 → NAS 비교 → 빌드 → health check → 로그 기록)
./scripts/deploy-remote.sh

# 배포 상태 확인 (NAS 버전, origin 대비 차이, 컨테이너 상태)
./scripts/check-version.sh

# 특정 커밋으로 롤백
./scripts/rollback-remote.sh <commit-hash>
```

### 배포 흐름

1. 로컬에서 코드 수정 → `git commit` → `git push`
2. `./scripts/deploy-remote.sh` 실행
3. 스크립트가 자동으로: 로컬 clean 확인 → origin push 확인 → NAS 버전 비교 → 배포될 커밋 표시 → 사용자 확인 → git pull → docker build → nginx 재시작 → health check

---

## 롤백 방법

### git 기반 롤백 (권장)

```bash
# 맥북에서 실행 - 특정 커밋으로 롤백
./scripts/rollback-remote.sh <commit-hash>

# 최근 커밋 목록 확인
git log --oneline -10
```

### 레거시 서비스 복원 (통합 이전으로)

문제 발생 시 기존 개별 서비스로 복원:

```bash
# 통합 서비스 중지
cd /volume1/docker_1/tk-factory-services
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose down

# TK-FB 복원
cd "/volume1/Technicalkorea Document/tkfb-package"
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose up -d

# TKQC 복원
cd /volume1/docker/tkqc/tkqc-package
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose up -d
```

---

## 트러블슈팅

| 증상 | 원인 | 해결 |
|------|------|------|
| 403 Forbidden (nginx) | Docker 내부 IP 차단 | nginx.conf에 `allow 172.16.0.0/12` 추가 |
| SSO 로그인 후 다른 시스템에서 미인증 | 쿠키 domain 설정 오류 | 브라우저 쿠키에서 domain이 `.technicalkorea.net`인지 확인 |
| DB 연결 실패 | 패스워드 불일치 | `.env`의 DB 패스워드가 기존과 동일한지 확인 |
| Cloudflare 502 | 컨테이너 미기동 | `docker compose ps`로 상태 확인, `docker compose logs <서비스>` |
| SCP 실패 | Synology subsystem | `scp -O` 옵션 사용 |
| sudo 파이프 실패 | Synology 제한 | `echo 'password' \| sudo -S` 패턴 사용 |
