# MongolCar 서버 인프라 구성 계획

## 1. 서버 현황

| 서버 | IP | CPU | RAM | SSD | 상태 |
|------|-----|-----|-----|-----|------|
| Server1 | 192.168.0.201 | Ryzen 7700 | 64GB | 2TB | 신규 설치 |
| Server2 | 192.168.0.202 | Ryzen 7700 | 64GB | 확인 필요 | 정리 필요 |
| Server3 | 192.168.0.203 | Ryzen 7700 | 64GB | 확인 필요 | 정리 필요 |

## 2. 운영 사이트

| 도메인 | 용도 |
|--------|------|
| www.autonetsellcar.com | 몽골 중고차 수출 플랫폼 (MongolCar) |
| www.grantech.kr | Grantech 기업 사이트 |
| www.cylinx.kr | Cylinx 기업 사이트 |

---

## 3. 권장 아키텍처: Master-Worker 구성

### 3.1 서버 역할 분배

```
┌─────────────────────────────────────────────────────────────────────┐
│                        Server1 (192.168.0.201)                       │
│                           [ MASTER NODE ]                            │
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                  │
│  │   Nginx     │  │  PostgreSQL │  │    Redis    │                  │
│  │   Proxy     │  │   (Primary) │  │   (Primary) │                  │
│  │   Manager   │  │             │  │             │                  │
│  └─────────────┘  └─────────────┘  └─────────────┘                  │
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐                  │
│  │  Portainer  │  │   Grafana   │  │ Prometheus  │                  │
│  │  (Docker)   │  │ (Monitoring)│  │  (Metrics)  │                  │
│  └─────────────┘  └─────────────┘  └─────────────┘                  │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                        Server2 (192.168.0.202)                       │
│                          [ WORKER NODE 1 ]                           │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │              www.autonetsellcar.com (MongolCar)           │       │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐       │       │
│  │  │   Next.js   │  │   FastAPI   │  │   Carmodoo  │       │       │
│  │  │  Frontend   │  │   Backend   │  │    Agent    │       │       │
│  │  │   :3000     │  │   :8000     │  │  (Cron Job) │       │       │
│  │  └─────────────┘  └─────────────┘  └─────────────┘       │       │
│  └──────────────────────────────────────────────────────────┘       │
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐                                   │
│  │ PostgreSQL  │  │    Redis    │                                   │
│  │  (Replica)  │  │  (Replica)  │                                   │
│  └─────────────┘  └─────────────┘                                   │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                        Server3 (192.168.0.203)                       │
│                          [ WORKER NODE 2 ]                           │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │                   www.grantech.kr                         │       │
│  │  ┌─────────────┐  ┌─────────────┐                        │       │
│  │  │   Next.js   │  │   FastAPI   │                        │       │
│  │  │  Frontend   │  │   Backend   │                        │       │
│  │  │   :3001     │  │   :8001     │                        │       │
│  │  └─────────────┘  └─────────────┘                        │       │
│  └──────────────────────────────────────────────────────────┘       │
│                                                                      │
│  ┌──────────────────────────────────────────────────────────┐       │
│  │                    www.cylinx.kr                          │       │
│  │  ┌─────────────┐  ┌─────────────┐                        │       │
│  │  │   Next.js   │  │   FastAPI   │                        │       │
│  │  │  Frontend   │  │   Backend   │                        │       │
│  │  │   :3002     │  │   :8002     │                        │       │
│  │  └─────────────┘  └─────────────┘                        │       │
│  └──────────────────────────────────────────────────────────┘       │
│                                                                      │
│  ┌─────────────┐  ┌─────────────┐                                   │
│  │ PostgreSQL  │  │    Redis    │                                   │
│  │  (Replica)  │  │  (Replica)  │                                   │
│  └─────────────┘  └─────────────┘                                   │
└─────────────────────────────────────────────────────────────────────┘
```

---

## 4. 네트워크 구성

### 4.1 외부 접근 (인터넷 → 서버)

```
인터넷
   │
   ▼
┌─────────────────┐
│   공유기/방화벽   │
│   (Port Forward) │
└─────────────────┘
   │
   ├── 80/443 ──→ Server1:80/443 (Nginx Proxy Manager)
   │
   └── 22 ──→ Server1:22 (SSH - VPN 권장)
```

### 4.2 내부 네트워크

| 용도 | 포트 | 서버 |
|------|------|------|
| SSH | 22 | 모든 서버 |
| PostgreSQL | 5432 | Server1 (Primary) |
| Redis | 6379 | Server1 (Primary) |
| Nginx Proxy Manager | 80, 443, 81 | Server1 |
| Portainer | 9000 | Server1 |
| Grafana | 3100 | Server1 |
| Prometheus | 9090 | Server1 |
| MongolCar Frontend | 3000 | Server2 |
| MongolCar Backend | 8000 | Server2 |
| Grantech Frontend | 3001 | Server3 |
| Grantech Backend | 8001 | Server3 |
| Cylinx Frontend | 3002 | Server3 |
| Cylinx Backend | 8002 | Server3 |

---

## 5. Docker 컨테이너 구성

### 5.1 Server1 (Master) - docker-compose.yml

```yaml
version: '3.8'

services:
  # Reverse Proxy
  nginx-proxy-manager:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginx-proxy-manager
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'
      - '81:81'  # Admin UI
    volumes:
      - ./data/nginx/data:/data
      - ./data/nginx/letsencrypt:/etc/letsencrypt

  # Database
  postgres:
    image: postgres:16-alpine
    container_name: postgres-primary
    restart: unless-stopped
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: mongolcar
    ports:
      - '5432:5432'
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
      - ./init-db:/docker-entrypoint-initdb.d

  # Cache
  redis:
    image: redis:7-alpine
    container_name: redis-primary
    restart: unless-stopped
    ports:
      - '6379:6379'
    volumes:
      - ./data/redis:/data
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}

  # Docker Management
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - '9000:9000'
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data/portainer:/data

  # Monitoring
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    ports:
      - '9090:9090'
    volumes:
      - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./data/prometheus:/prometheus

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    ports:
      - '3100:3000'
    environment:
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
    volumes:
      - ./data/grafana:/var/lib/grafana

networks:
  default:
    name: master-network
```

### 5.2 Server2 (MongolCar) - docker-compose.yml

```yaml
version: '3.8'

services:
  # MongolCar Frontend
  mongolcar-frontend:
    build: ./mongolcar/frontend
    container_name: mongolcar-frontend
    restart: unless-stopped
    ports:
      - '3000:3000'
    environment:
      - NEXT_PUBLIC_API_URL=http://192.168.0.202:8000
    depends_on:
      - mongolcar-backend

  # MongolCar Backend
  mongolcar-backend:
    build: ./mongolcar/backend
    container_name: mongolcar-backend
    restart: unless-stopped
    ports:
      - '8000:8000'
    environment:
      - DATABASE_URL=postgresql://admin:${DB_PASSWORD}@192.168.0.201:5432/mongolcar
      - REDIS_URL=redis://:${REDIS_PASSWORD}@192.168.0.201:6379/0
      - SECRET_KEY=${SECRET_KEY}
    volumes:
      - ./data/uploads:/app/uploads

  # Carmodoo Agent (차량 데이터 수집)
  carmodoo-agent:
    build: ./carmodoo-agent
    container_name: carmodoo-agent
    restart: unless-stopped
    environment:
      - CARMODOO_USER_ID=${CARMODOO_USER_ID}
      - CARMODOO_PASSWORD=${CARMODOO_PASSWORD}
      - API_SERVER_URL=http://mongolcar-backend:8000/api
      - AGENT_API_KEY=${AGENT_API_KEY}
    volumes:
      - ./data/agent:/app/data
      - ./logs/agent:/app/logs
    depends_on:
      - mongolcar-backend

networks:
  default:
    name: mongolcar-network
```

### 5.3 Server3 (Grantech & Cylinx) - docker-compose.yml

```yaml
version: '3.8'

services:
  # Grantech Frontend
  grantech-frontend:
    build: ./grantech/frontend
    container_name: grantech-frontend
    restart: unless-stopped
    ports:
      - '3001:3000'
    environment:
      - NEXT_PUBLIC_API_URL=http://192.168.0.203:8001

  # Grantech Backend
  grantech-backend:
    build: ./grantech/backend
    container_name: grantech-backend
    restart: unless-stopped
    ports:
      - '8001:8000'
    environment:
      - DATABASE_URL=postgresql://admin:${DB_PASSWORD}@192.168.0.201:5432/grantech
      - REDIS_URL=redis://:${REDIS_PASSWORD}@192.168.0.201:6379/1

  # Cylinx Frontend
  cylinx-frontend:
    build: ./cylinx/frontend
    container_name: cylinx-frontend
    restart: unless-stopped
    ports:
      - '3002:3000'
    environment:
      - NEXT_PUBLIC_API_URL=http://192.168.0.203:8002

  # Cylinx Backend
  cylinx-backend:
    build: ./cylinx/backend
    container_name: cylinx-backend
    restart: unless-stopped
    ports:
      - '8002:8000'
    environment:
      - DATABASE_URL=postgresql://admin:${DB_PASSWORD}@192.168.0.201:5432/cylinx
      - REDIS_URL=redis://:${REDIS_PASSWORD}@192.168.0.201:6379/2

networks:
  default:
    name: sites-network
```

---

## 6. 데이터베이스 설계

### 6.1 PostgreSQL 데이터베이스 분리

| 데이터베이스 | 용도 | Redis DB |
|-------------|------|----------|
| mongolcar | MongolCar 서비스 | 0 |
| grantech | Grantech 서비스 | 1 |
| cylinx | Cylinx 서비스 | 2 |

### 6.2 MongolCar 주요 테이블

```sql
-- 제조사
CREATE TABLE car_makers (
    id SERIAL PRIMARY KEY,
    code VARCHAR(10) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    name_en VARCHAR(100),
    created_at TIMESTAMP DEFAULT NOW()
);

-- 모델
CREATE TABLE car_models (
    id SERIAL PRIMARY KEY,
    code VARCHAR(10) NOT NULL,
    maker_id INTEGER REFERENCES car_makers(id),
    name VARCHAR(100) NOT NULL,
    name_en VARCHAR(100),
    UNIQUE(code, maker_id)
);

-- 차량
CREATE TABLE cars (
    id SERIAL PRIMARY KEY,
    source VARCHAR(50) NOT NULL DEFAULT 'carmodoo',
    source_id VARCHAR(50) NOT NULL,
    source_key TEXT,  -- encrypted key
    maker_id INTEGER REFERENCES car_makers(id),
    model_id INTEGER REFERENCES car_models(id),
    car_name VARCHAR(200),
    year INTEGER,
    month INTEGER,
    mileage INTEGER,
    price_krw BIGINT,
    price_usd DECIMAL(12,2),
    fuel VARCHAR(20),
    transmission VARCHAR(20),
    color VARCHAR(50),
    displacement INTEGER,
    car_number VARCHAR(20),
    seize_count INTEGER DEFAULT 0,
    collateral_count INTEGER DEFAULT 0,
    check_num VARCHAR(50),
    dealer_name VARCHAR(100),
    dealer_phone VARCHAR(50),
    shop_name VARCHAR(100),
    status VARCHAR(20) DEFAULT 'active',
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    synced_at TIMESTAMP,
    UNIQUE(source, source_id)
);

-- 차량 이미지
CREATE TABLE car_images (
    id SERIAL PRIMARY KEY,
    car_id INTEGER REFERENCES cars(id) ON DELETE CASCADE,
    url VARCHAR(500),
    local_path VARCHAR(500),
    is_main BOOLEAN DEFAULT FALSE,
    sort_order INTEGER DEFAULT 0
);

-- 차량 옵션
CREATE TABLE car_options (
    id SERIAL PRIMARY KEY,
    car_id INTEGER REFERENCES cars(id) ON DELETE CASCADE,
    option_name VARCHAR(100)
);

-- 사용자 (바이어)
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    name VARCHAR(100),
    phone VARCHAR(50),
    country VARCHAR(50) DEFAULT 'Mongolia',
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP DEFAULT NOW()
);

-- 문의
CREATE TABLE inquiries (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    car_id INTEGER REFERENCES cars(id),
    message TEXT,
    status VARCHAR(20) DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT NOW()
);

-- 인덱스
CREATE INDEX idx_cars_maker ON cars(maker_id);
CREATE INDEX idx_cars_model ON cars(model_id);
CREATE INDEX idx_cars_price ON cars(price_krw);
CREATE INDEX idx_cars_year ON cars(year);
CREATE INDEX idx_cars_status ON cars(status);
```

---

## 7. Nginx Proxy Manager 설정

### 7.1 Proxy Hosts 설정

| Domain | Scheme | Forward Host | Forward Port | SSL |
|--------|--------|--------------|--------------|-----|
| autonetsellcar.com | http | 192.168.0.202 | 3000 | Let's Encrypt |
| api.autonetsellcar.com | http | 192.168.0.202 | 8000 | Let's Encrypt |
| grantech.kr | http | 192.168.0.203 | 3001 | Let's Encrypt |
| api.grantech.kr | http | 192.168.0.203 | 8001 | Let's Encrypt |
| cylinx.kr | http | 192.168.0.203 | 3002 | Let's Encrypt |
| api.cylinx.kr | http | 192.168.0.203 | 8002 | Let's Encrypt |
| portainer.local | http | 192.168.0.201 | 9000 | - |
| grafana.local | http | 192.168.0.201 | 3100 | - |

---

## 8. 설치 순서

### Phase 1: Server1 (Master) 설정

```bash
# 1. Docker 설치
sudo apt update && sudo apt upgrade -y
sudo apt install -y docker.io docker-compose
sudo systemctl enable docker
sudo usermod -aG docker $USER

# 2. 디렉토리 구조 생성
mkdir -p ~/master/{data,config,init-db}
mkdir -p ~/master/data/{nginx,postgres,redis,portainer,prometheus,grafana}

# 3. docker-compose.yml 작성 및 실행
cd ~/master
# docker-compose.yml 파일 생성
docker-compose up -d

# 4. PostgreSQL 초기 DB 생성
docker exec -it postgres-primary psql -U admin -c "CREATE DATABASE grantech;"
docker exec -it postgres-primary psql -U admin -c "CREATE DATABASE cylinx;"
```

### Phase 2: Server2 (MongolCar) 설정

```bash
# 1. Docker 설치 (동일)
# 2. 프로젝트 디렉토리 구조
mkdir -p ~/mongolcar/{frontend,backend,carmodoo-agent,data,logs}

# 3. 코드 배포 및 실행
cd ~/mongolcar
# docker-compose.yml 파일 생성
docker-compose up -d
```

### Phase 3: Server3 (Grantech & Cylinx) 설정

```bash
# 1. Docker 설치 (동일)
# 2. 프로젝트 디렉토리 구조
mkdir -p ~/sites/{grantech,cylinx}
mkdir -p ~/sites/grantech/{frontend,backend}
mkdir -p ~/sites/cylinx/{frontend,backend}

# 3. 코드 배포 및 실행
cd ~/sites
# docker-compose.yml 파일 생성
docker-compose up -d
```

### Phase 4: DNS 및 SSL 설정

```bash
# 1. 도메인 DNS A 레코드 설정 (공인 IP로)
# autonetsellcar.com → 공인IP
# grantech.kr → 공인IP
# cylinx.kr → 공인IP

# 2. 공유기 포트포워딩
# 80 → 192.168.0.201:80
# 443 → 192.168.0.201:443

# 3. Nginx Proxy Manager에서 SSL 인증서 발급
# http://192.168.0.201:81 접속
# Proxy Hosts 추가 및 Let's Encrypt SSL 설정
```

---

## 9. 백업 전략

### 9.1 자동 백업 스크립트 (Server1)

```bash
#!/bin/bash
# /home/user/backup.sh

BACKUP_DIR="/backup/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# PostgreSQL 백업
docker exec postgres-primary pg_dumpall -U admin > $BACKUP_DIR/postgres_all.sql

# Redis 백업
docker exec redis-primary redis-cli -a $REDIS_PASSWORD BGSAVE
cp ~/master/data/redis/dump.rdb $BACKUP_DIR/

# 7일 이상 된 백업 삭제
find /backup -type d -mtime +7 -exec rm -rf {} \;
```

### 9.2 Cron 설정

```bash
# 매일 새벽 3시 백업
0 3 * * * /home/user/backup.sh
```

---

## 10. 모니터링 항목

### 10.1 Prometheus 수집 대상

- Node Exporter (각 서버 시스템 메트릭)
- PostgreSQL Exporter
- Redis Exporter
- Docker Container 메트릭
- Nginx 메트릭

### 10.2 Grafana 대시보드

- 서버 리소스 (CPU, Memory, Disk, Network)
- 컨테이너 상태
- 데이터베이스 연결/쿼리 성능
- API 응답시간
- 에러율

---

## 11. 보안 체크리스트

- [ ] SSH 키 기반 인증 설정
- [ ] 방화벽 (UFW) 설정
- [ ] Fail2ban 설치
- [ ] 불필요한 포트 차단
- [ ] PostgreSQL 외부 접근 제한
- [ ] Redis 비밀번호 설정
- [ ] HTTPS 강제 리다이렉트
- [ ] 환경변수로 비밀정보 관리
- [ ] 정기 보안 업데이트

---

## 12. 예상 리소스 사용량

| 서버 | CPU 예상 | RAM 예상 | Disk 예상 |
|------|----------|----------|-----------|
| Server1 (Master) | 10-20% | 8-12GB | 100GB+ |
| Server2 (MongolCar) | 20-40% | 8-16GB | 500GB+ (이미지) |
| Server3 (Sites) | 10-30% | 4-8GB | 50GB |

---

## 13. 다음 단계

1. **Server2, Server3 SSD 용량 확인**
2. **Server1 Docker 환경 구축**
3. **MongolCar Backend API 개발 (FastAPI)**
4. **MongolCar Frontend 개발 (Next.js)**
5. **Carmodoo Agent Docker화**
6. **DNS 설정 및 SSL 인증서 발급**

---

*Generated by Claude Code - 2025-11-28*
