# 1. 서버 인프라 개요

[목차로 돌아가기](./README.md)

---

## 운영서버 (sam-prod)

### 서버 사양

| 항목 | 값 |
|------|-----|
| IP | 211.117.60.189 |
| 호스트명 | sam-prod |
| OS | Ubuntu 24.04.4 LTS |
| 커널 | 6.8.0-100-generic |
| CPU | 2 vCPU |
| RAM | 8GB |
| Swap | 4GB |
| 디스크 | 98GB (여유 79GB) |
| 사용자 | hskwon(개발팀장), pro(개발실장/잠금), kkk(개발자/잠금) |

### 도메인 목록

| 도메인 | 서비스 | 백엔드 | 포트 |
|--------|--------|--------|------|
| sam.it.kr | Next.js 15 프론트엔드 | PM2 cluster x2 | 3000 |
| api.sam.it.kr | Laravel 12 API | PHP-FPM api pool | unix socket |
| mng.codebridge-x.com | Laravel 12 Admin | PHP-FPM admin pool | unix socket |
| sales.codebridge-x.com | Plain PHP 레거시 | PHP-FPM sales pool | unix socket |
| codebridge-x.com (+ www) | 정적 랜딩페이지 | Nginx direct | 80/443 |
| stage.sam.it.kr | Next.js Stage | PM2 fork x1 | 3100 |
| stage-api.sam.it.kr | Laravel API Stage | PHP-FPM api-stage pool | unix socket |

모든 도메인은 Let's Encrypt SSL 적용 (알림: develop@codebridge-x.com).

### 서비스 현황

| 서비스 | 버전 | 포트 | 상태 |
|--------|------|------|------|
| Nginx | 1.24.0 | 80/443 | active |
| PHP-FPM | 8.4.18 | unix socket (4개 pool) | active |
| MySQL | 8.4.8 | 3306 | active |
| Redis | 7.0.15 | 6379 (localhost) | active |
| PM2 | 6.0.14 | 3000 (cluster x2), 3100 (fork x1) | active |
| Supervisor | - | - | active (queue worker x2) |
| Laravel Scheduler | - | - | cron (API + MNG, www-data) |
| node_exporter | 1.8.2 | 9100 | active |
| Certbot | 2.9.0 | - | timer active |
| fail2ban | - | - | active |

### 주요 디렉토리

```
/home/webservice/
  api/              Laravel API (운영) - releases/shared 구조
    current -> releases/...
    releases/
    shared/ (.env, storage/)
  api-stage/        Laravel API (Stage) - 동일 구조
  mng/              Laravel Admin - 동일 구조
  sales/            Plain PHP 레거시 (.env, uploads/)
  react/            Next.js 운영 - releases/shared 구조
  react-stage/      Next.js Stage - 동일 구조
  landing/          정적 랜딩페이지
  ecosystem.config.js   PM2 설정
```

### 주요 설정 파일

| 구분 | 경로 |
|------|------|
| Nginx 메인 설정 | /etc/nginx/nginx.conf |
| Nginx 사이트 설정 | /etc/nginx/sites-available/*.conf |
| Nginx 보안 스니펫 | /etc/nginx/snippets/security.conf |
| PHP-FPM Pool (API) | /etc/php/8.4/fpm/pool.d/api.conf |
| PHP-FPM Pool (Admin) | /etc/php/8.4/fpm/pool.d/admin.conf |
| PHP-FPM Pool (Sales) | /etc/php/8.4/fpm/pool.d/sales.conf |
| PHP-FPM Pool (API Stage) | /etc/php/8.4/fpm/pool.d/api-stage.conf |
| MySQL 튜닝 | /etc/mysql/mysql.conf.d/sam-tuning.cnf |
| Redis | /etc/redis/redis.conf |
| Supervisor | /etc/supervisor/conf.d/sam-queue.conf |
| PM2 | /home/webservice/ecosystem.config.js |
| API .env | /home/webservice/api/shared/.env |
| MNG .env | /home/webservice/mng/shared/.env |
| Sales .env | /home/webservice/sales/.env |

### 메모리 배분

| 서비스 | 할당 | 설정 |
|--------|------|------|
| MySQL 8.4 | ~2GB | innodb_buffer_pool_size=2G |
| Redis | ~0.5GB | maxmemory 512mb |
| PHP-FPM (API) | ~0.8GB | max_children=10 |
| PHP-FPM (Admin) | ~0.3GB | max_children=5 |
| PHP-FPM (Sales) | ~0.2GB | max_children=3 |
| PHP-FPM (API-Stage) | ~0.2GB | max_children=3 |
| Next.js 운영 (PM2 cluster×2) | ~0.6GB | max-old-space-size=256 |
| Next.js Stage (PM2 fork×1) | ~0.15GB | max-old-space-size=128 |
| Supervisor (Queue Worker) | ~0.1GB | numprocs=2 |
| Nginx | ~0.1GB | worker_connections 1024 |
| node_exporter | ~10MB | - |
| OS + 여유 | ~2.9GB | 스왑 4GB |

### 방화벽 (UFW) 규칙

| 포트 | 프로토콜 | 허용 범위 | 용도 |
|------|----------|-----------|------|
| 22 | TCP | Anywhere | SSH |
| 80 | TCP | Anywhere | HTTP |
| 443 | TCP | Anywhere | HTTPS |
| 9100 | TCP | 110.10.147.46 only | node_exporter (Prometheus) |
| 3306 | TCP | 110.10.147.46 only | MySQL 백업 (CI/CD 서버) |

### 데이터베이스 사용자

| 사용자 | 인증 방식 | 권한 | 용도 |
|--------|-----------|------|------|
| codebridge@localhost | 비밀번호 | sam, sam_stage, sam_stat, codebridge | 애플리케이션 |
| hskwon@localhost | auth_socket | ALL (WITH GRANT OPTION) | 관리자 |
| pro@localhost | 비밀번호 (잠금) | codebridge, sam, sam_stage, sam_stat | 개발실장 |
| kkk@localhost | 비밀번호 (잠금) | codebridge, sam, sam_stage, sam_stat | 개발자 (2026-03-13) |
| root@localhost | auth_socket | ALL | 시스템 (sudo mysql) |
| sam_backup@110.10.147.46 | 비밀번호 | SELECT, LOCK TABLES (sam, sam_stat) | CI/CD 백업 |

---

## CI/CD 서버 (sam-cicd)

### 서버 사양

| 항목 | 값 |
|------|-----|
| IP | 110.10.147.46 |
| SSH 별칭 | sam-cicd |
| OS | Ubuntu 24.04.4 LTS |
| Kernel | 6.8.0-106-generic |
| CPU | 8 vCPU |
| RAM | 16GB (Swap 4GB) |
| Disk | 98GB (사용 32GB / 여유 61GB) |
| 사용자 | hskwon(개발팀장), pro(개발실장/잠금), kkk(개발자/잠금) |

### 도메인 매핑

| 도메인 | 서비스 | 백엔드 포트 | SSL |
|--------|--------|------------|-----|
| git.sam.it.kr | Gitea | :3000 | Let's Encrypt |
| ci.sam.it.kr | Jenkins | :8080 | Let's Encrypt |
| monitor.sam.it.kr | Grafana | :3100 | Let's Encrypt |

### 서비스 현황

| 서비스 | 버전 | 포트 | 도메인 |
|--------|------|------|--------|
| Nginx | 1.24.0 | 80/443 | 리버스 프록시 |
| Jenkins | LTS (2.541.2) | 8080 | ci.sam.it.kr |
| Gitea | 1.22.6 | 3000 | git.sam.it.kr |
| MySQL | 8.4.8 | 3306 | - |
| Prometheus | 2.51.0 | 9090 | - (localhost only) |
| Grafana | - | 3100 | monitor.sam.it.kr |
| node_exporter | 1.8.2 | 9100 | - |
| Java | OpenJDK 21.0.10 | - | Jenkins 런타임 |
| Certbot | - | - | SSL 자동 갱신 |
| fail2ban | - | - | SSH 보호 |

### 메모리 배분

| 서비스 | 할당 | 설정 |
|--------|------|------|
| Jenkins | ~1.2GB | -Xmx2048m |
| Jenkins Agent | ~0.3GB | local-agent (WebSocket) |
| MySQL | ~0.7GB | innodb_buffer_pool_size=1536M |
| Gitea | ~0.2GB | Go 기반 |
| Prometheus | ~0.1GB | retention 30d |
| Grafana | ~0.3GB | - |
| Nginx | ~0.1GB | - |
| node_exporter | ~10MB | - |
| OS + 여유 | ~13GB | Swap 4GB |

### 주요 설정 파일

| 설정 | 경로 |
|------|------|
| Nginx 사이트 | /etc/nginx/sites-available/{ci,git,monitor}.sam.it.kr |
| Jenkins 홈 | /var/lib/jenkins/ |
| Jenkins JVM 설정 | /etc/systemd/system/jenkins.service.d/override.conf |
| Jenkins Agent | /var/lib/jenkins-agent/ (workspace, agent.jar) |
| Jenkins Agent 서비스 | /etc/systemd/system/jenkins-agent.service |
| Jenkins 환경파일 | /var/lib/jenkins/env-files/react/.env.{develop,stage,main} |
| Gitea 설정 | /etc/gitea/app.ini |
| Gitea 저장소 | /var/lib/gitea/data/repositories/ |
| Gitea 로그 | /var/lib/gitea/log/ |
| Prometheus 설정 | /etc/prometheus/prometheus.yml |
| Prometheus 데이터 | /var/lib/prometheus/ |
| Grafana 설정 | /etc/grafana/grafana.ini |
| MySQL 튜닝 | /etc/mysql/mysql.conf.d/sam-tuning.cnf |
| fail2ban 설정 | /etc/fail2ban/ |
| SSL 인증서 | /etc/letsencrypt/live/ |
| 백업 스크립트 | /data/scripts/backup-db.sh |
| 백업 인증 | /data/scripts/.sam_backup.cnf |
| 백업 저장소 | /data/backups/mysql/ |

### 방화벽 (UFW) 규칙

| 포트 | 프로토콜 | 용도 |
|------|---------|------|
| 22/tcp | ALLOW | SSH |
| 80/tcp | ALLOW | HTTP |
| 443/tcp | ALLOW | HTTPS |

---

## 개발서버 (sam-dev)

### 서버 사양

| 항목 | 값 |
|------|-----|
| IP | 114.203.209.83 |
| 호스트명 | sam-dev |
| OS | Ubuntu 24.04.2 LTS |
| 사용자 | hskwon(개발팀장), pro(개발실장), kkk(개발자) |

### 서비스 현황

| 서비스 | 포트 | 상태 | 비고 |
|--------|------|------|------|
| Nginx | 80/443 | active | |
| PHP 8.4 FPM | unix socket | active | SAM 앱 (api, mng, sales) |
| PHP 7.3 FPM | unix socket | active | 5130.codebridge-x.com 레거시 전용 |
| MySQL 8.4 | 3306 (localhost) | active | binlog 7일 보관 |
| Gitea | 3000 | active | |
| Next.js (PM2) | 3001 | active | |
| fail2ban | - | active | |
| Swap | - | active | 4G (/swapfile, fstab 등록) |
| ~~Apache~~ | ~~8080~~ | **disabled** | 2026-03-09 비활성화 (front.5130.co.kr 미사용) |
| ~~PHP 5.6 FPM~~ | - | **disabled** | 2026-03-09 비활성화 (미사용) |

### 자동 정리 (cron, hskwon)

| 작업 | 주기 | 설명 |
|------|------|------|
| Gitea repo-archive 캐시 정리 | 매주 일요일 04:00 | 7일 이상 된 캐시 파일 삭제 + 빈 디렉토리 정리 |

### 방화벽 (UFW) 규칙

| 포트 | 프로토콜 | 용도 |
|------|---------|------|
| 22/tcp | ALLOW | SSH |
| 80/tcp | ALLOW | HTTP |
| 443/tcp | ALLOW | HTTPS |
| 3000/tcp | ALLOW | Gitea |

> MySQL(3306), Apache(8080), Next.js(3001), CUPS(631) 등은 외부 차단

### 주요 디렉토리

```
/home/webservice/
  react/           Next.js 프론트엔드
  api/             Laravel API
  mng/             Laravel Admin
  sales/           Plain PHP 레거시

/data/GIT/samproject/   Gitea bare repositories
```

---

## 아키텍처 다이어그램

### 운영서버

```
┌──────────────────────────────────────────────────────────┐
│               운영서버 (2 vCPU / 8GB)                     │
│               Ubuntu 24.04 / IP: 211.117.60.189          │
│                                                           │
│  ┌──────────┐  ┌───────────┐  ┌───────────────────────┐  │
│  │ Nginx    │  │ Certbot   │  │ UFW (22,80,443,9100)  │  │
│  └────┬─────┘  └───────────┘  └───────────────────────┘  │
│       │                                                   │
│  ┌────┴───────────────────────────────────────────────┐   │
│  │  sam.it.kr ──────────→ Next.js (PM2 cluster, :3000)│   │
│  │  api.sam.it.kr ──────→ PHP-FPM (api pool)          │   │
│  │  mng.codebridge-x.com ──→ PHP-FPM (admin pool)     │   │
│  │  sales.codebridge-x.com → PHP-FPM (sales pool)     │   │
│  │  stage.sam.it.kr ────→ Next.js (PM2 fork, :3100)   │   │
│  │  stage-api.sam.it.kr → PHP-FPM (api-stage pool)    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                           │
│  ┌────────────┐  ┌────────────┐  ┌─────────────────┐     │
│  │ MySQL 8.4  │  │ Redis      │  │ Supervisor      │     │
│  │ (Master)   │  │ (캐시/큐)  │  │ (Queue Worker)  │     │
│  └────────────┘  └────────────┘  └─────────────────┘     │
│                                                           │
│  ┌─────────────────────────────────────────────────┐      │
│  │ node_exporter (:9100) → CI/CD Prometheus        │      │
│  └─────────────────────────────────────────────────┘      │
└───────────────────────────────────────────────────────────┘
```

### CI/CD 서버

```
┌──────────────────────────────────────────────────────────┐
│               CI/CD서버 (8 vCPU / 16GB)                   │
│               Ubuntu 24.04 / IP: 110.10.147.46           │
│                                                           │
│  ┌──────────┐  ┌───────────┐  ┌───────────────────────┐  │
│  │ Nginx    │  │ Certbot   │  │ UFW (22,80,443)       │  │
│  └────┬─────┘  └───────────┘  └───────────────────────┘  │
│       │                                                   │
│  ┌────┴───────────────────────────────────────────────┐   │
│  │  git.sam.it.kr ──────────→ Gitea (:3000)           │   │
│  │  ci.sam.it.kr ───────────→ Jenkins (:8080)         │   │
│  │  monitor.sam.it.kr ──────→ Grafana (:3100)         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                           │
│  ┌────────────┐  ┌────────────┐  ┌────────────────────┐  │
│  │ Gitea      │  │ Jenkins    │  │ MySQL 8.4          │  │
│  │ (운영 Git) │  │ (CI/CD)   │  │ (Gitea DB + 백업)  │  │
│  └────────────┘  └────────────┘  └────────────────────┘  │
│                                                           │
│  ┌──────────────┐  ┌──────────────┐                      │
│  │ Prometheus   │  │ Grafana      │                      │
│  │ (:9090)      │  │ (:3100)      │                      │
│  └──────────────┘  └──────────────┘                      │
└──────────────────────────────────────────────────────────┘
```

### 도메인 환경 분리

| 서비스 | 운영 | Stage | 개발 |
|--------|------|-------|------|
| Front | sam.it.kr | stage.sam.it.kr | dev.codebridge-x.com |
| API | api.sam.it.kr | stage-api.sam.it.kr | api.codebridge-x.com |
| Admin | mng.codebridge-x.com | - | admin.codebridge-x.com |
| Sales | sales.codebridge-x.com | - | salesdev.codebridge-x.com |
| Landing | codebridge-x.com | - | - |

### 타이틀 접두사 (환경 구분)

브라우저 탭에서 환경을 즉시 구분할 수 있도록 타이틀에 접두사를 표시한다.

| 환경 | 접두사 | 예시 |
|------|--------|------|
| 로컬 | `[L]` | `[L]SAM_MNG` |
| 개발 | `[D]` | `[D]SAM_SYSTEM` |
| 운영 | 없음 | `SAM_SYSTEM` |

**설정 위치:**

| 프로젝트 | 방식 | 설정 파일 |
|---------|------|----------|
| mng | `.env`의 `APP_NAME`에 접두사 포함 | 로컬: `mng/.env`, 개발: `/home/webservice/mng/.env` |
| api | `.env`의 `APP_NAME`에 접두사 포함 | 로컬: `api/.env`, 개발: `/home/webservice/api/.env` |
| react | 코드에서 `NEXT_PUBLIC_APP_ENV` 값으로 자동 판별 | CI/CD: `/var/lib/jenkins/env-files/react/.env.develop` |