# 3. 운영서버 서비스 관리 [목차로 돌아가기](./README.md) | 서버: sam-prod (211.117.60.189) --- ## Nginx **명령어:** ```bash sudo systemctl status nginx sudo nginx -t # 설정 테스트 (반드시 reload/restart 전에 실행) sudo systemctl reload nginx # 설정 리로드 (무중단) sudo systemctl restart nginx # 재시작 (연결 끊김 발생) sudo systemctl stop nginx sudo systemctl start nginx ``` **설정 파일:** | 파일 | 용도 | |------|------| | /etc/nginx/nginx.conf | 메인 설정 (worker_connections 1024, client_max_body_size 50M) | | /etc/nginx/sites-available/ | 사이트별 설정 | | /etc/nginx/sites-enabled/ | 활성화된 사이트 (심링크) | | /etc/nginx/snippets/security.conf | 보안 규칙 (.env, .git 차단) | **로그 파일:** | 파일 | 내용 | |------|------| | /var/log/nginx/api.sam.it.kr.access.log | API 접근 로그 | | /var/log/nginx/api.sam.it.kr.error.log | API 에러 로그 | | /var/log/nginx/sam.it.kr.access.log | 프론트엔드 접근 로그 | | /var/log/nginx/sam.it.kr.error.log | 프론트엔드 에러 로그 | | /var/log/nginx/mng.codebridge-x.com.access.log | Admin 접근 로그 | | /var/log/nginx/mng.codebridge-x.com.error.log | Admin 에러 로그 | | /var/log/nginx/sales.codebridge-x.com.access.log | Sales 접근 로그 | | /var/log/nginx/sales.codebridge-x.com.error.log | Sales 에러 로그 | **주요 설정 값:** - worker_processes: auto - worker_connections: 1024 - client_max_body_size: 50M - keepalive_timeout: 65 - gzip: on (text/plain, application/json, application/javascript, text/css) --- ## PHP-FPM **명령어:** ```bash sudo systemctl status php8.4-fpm sudo systemctl reload php8.4-fpm # 무중단, 설정 변경 시 sudo systemctl restart php8.4-fpm sudo systemctl stop php8.4-fpm sudo systemctl start php8.4-fpm ``` **Pool 설정:** | Pool | 설정 파일 | 소켓 | max_children | memory_limit | |------|----------|------|-------------|-------------| | api | /etc/php/8.4/fpm/pool.d/api.conf | /run/php/php8.4-fpm-api.sock | 10 | 128M | | admin | /etc/php/8.4/fpm/pool.d/admin.conf | /run/php/php8.4-fpm-admin.sock | 5 | 128M | | sales | /etc/php/8.4/fpm/pool.d/sales.conf | /run/php/php8.4-fpm-sales.sock | 3 | 128M | | api-stage | /etc/php/8.4/fpm/pool.d/api-stage.conf | /run/php/php8.4-fpm-api-stage.sock | 3 | 128M | 모든 Pool 공통 설정: upload_max_filesize=50M, post_max_size=50M, display_errors=Off **로그:** /var/log/php8.4-fpm.log --- ## MySQL **명령어:** ```bash sudo systemctl status mysql sudo systemctl restart mysql # 주의: 연결 끊김 sudo systemctl stop mysql sudo systemctl start mysql # 접속 sudo mysql # root (auth_socket) mysql -u hskwon # hskwon (auth_socket, sudo 불필요) mysql -u codebridge -p sam # 앱 사용자 ``` **설정 파일:** | 파일 | 용도 | |------|------| | /etc/mysql/mysql.conf.d/sam-tuning.cnf | 성능 튜닝 | | /etc/mysql/mysql.conf.d/mysqld.cnf | 기본 설정 | **주요 튜닝 값:** - innodb_buffer_pool_size: 2048M - innodb_log_file_size: 512M - innodb_flush_log_at_trx_commit: 2 - max_connections: 100 - slow_query_log: ON (long_query_time: 2s) **로그:** | 파일 | 내용 | |------|------| | /var/log/mysql/slow.log | 느린 쿼리 (2초 이상) | | /var/log/mysql/error.log | 에러 로그 | **데이터베이스:** | DB 이름 | 용도 | |---------|------| | sam | 메인 운영 DB | | sam_stage | Stage 환경 DB | | sam_stat | 통계 DB | | codebridge | Sales 레거시 DB | --- ## Redis **명령어:** ```bash sudo systemctl status redis-server sudo systemctl restart redis-server sudo systemctl stop redis-server sudo systemctl start redis-server redis-cli # CLI 접속 redis-cli ping # 연결 테스트 → PONG ``` **설정 파일:** /etc/redis/redis.conf **주요 설정:** - bind: 127.0.0.1 ::1 (로컬 전용) - maxmemory: 512mb - maxmemory-policy: allkeys-lru - supervised: systemd **Redis CLI 유용한 명령어:** ```bash redis-cli info memory # 메모리 사용량 redis-cli dbsize # 키 개수 redis-cli keys '*' | head -20 # 키 확인 (운영 주의) redis-cli ttl "키이름" # TTL 확인 redis-cli flushall # 전체 삭제 (주의: 세션도 삭제됨) ``` **용도:** | 기능 | 드라이버 | .env 설정 | |------|---------|----------| | 캐시 | Redis | CACHE_STORE=redis | | 세션 | Database | SESSION_DRIVER=database | | 큐 | Redis | Supervisor에서 `queue:work redis` 명시 | --- ## PM2 (Next.js) **명령어:** ```bash pm2 status # 전체 상태 pm2 reload sam-front # 운영 무중단 재시작 (cluster 모드) pm2 restart sam-front-stage # Stage 재시작 pm2 logs sam-front --lines 100 # 로그 확인 pm2 logs sam-front-stage --lines 100 pm2 monit # 실시간 CPU/메모리 pm2 describe sam-front # 상세 정보 pm2 stop all # 전체 정지 pm2 start all # 전체 시작 cd /home/webservice && pm2 start ecosystem.config.js # 설정 파일로 시작 pm2 save # 현재 상태 저장 (부팅 시 자동 복구용) ``` **설정 파일:** /home/webservice/ecosystem.config.js **프로세스 목록:** | 프로세스명 | 모드 | 인스턴스 | 포트 | 메모리 제한 | 용도 | |-----------|------|---------|------|-----------|------| | sam-front | cluster | 2 | 3000 | 300M (max-old-space-size=256) | 운영 프론트엔드 | | sam-front-stage | fork | 1 | 3100 | 200M (max-old-space-size=128) | Stage 프론트엔드 | **로그 파일:** ~/.pm2/logs/ (sam-front-out.log, sam-front-error.log 등) --- ## Supervisor (Queue Worker) **명령어:** ```bash sudo supervisorctl status # 전체 상태 sudo supervisorctl restart sam-queue-worker:* # 재시작 sudo supervisorctl stop sam-queue-worker:* # 정지 sudo supervisorctl start sam-queue-worker:* # 시작 sudo supervisorctl reread # 설정 리로드 sudo supervisorctl update ``` **설정 파일:** /etc/supervisor/conf.d/sam-queue.conf **프로세스 구성:** - 프로그램명: sam-queue-worker - 프로세스 수: 2 (numprocs=2) - 실행 명령: `php /home/webservice/api/current/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600` - 실행 사용자: www-data - 자동 재시작: true **로그:** /home/webservice/api/shared/storage/logs/queue-worker.log --- ## node_exporter ```bash sudo systemctl status node_exporter sudo systemctl restart node_exporter curl -s localhost:9100/metrics | head -20 # 메트릭 확인 ``` **포트:** 9100 (UFW에서 CI/CD 서버 IP만 허용) **역할:** CPU, RAM, 디스크, 네트워크 메트릭을 CI/CD 서버의 Prometheus에 제공. --- ## Certbot (SSL) ```bash sudo certbot certificates # 인증서 목록 및 만료일 sudo systemctl status certbot.timer # 자동 갱신 타이머 sudo certbot renew --dry-run # 갱신 시뮬레이션 sudo certbot renew # 수동 갱신 sudo certbot --nginx -d 도메인명 --email develop@codebridge-x.com # 새 도메인 발급 ``` 자동 갱신은 systemd 타이머(certbot.timer)가 처리한다. 별도 crontab 불필요. --- ## fail2ban ```bash sudo systemctl status fail2ban sudo fail2ban-client status # jail 목록 sudo fail2ban-client status sshd # SSH jail 상태 (차단 IP 목록) sudo fail2ban-client set sshd unbanip 차단된_IP주소 # IP 차단 해제 sudo systemctl restart fail2ban ``` **설정 파일:** /etc/fail2ban/jail.local (또는 jail.d/) --- ## UFW (방화벽) ```bash sudo ufw status verbose # 상태 확인 (규칙 목록) sudo ufw status numbered # 번호로 규칙 목록 sudo ufw allow from IP주소 to any port 포트번호 # 규칙 추가 sudo ufw delete 번호 # 규칙 삭제 (번호 기반) sudo ufw disable # 비활성화 (비상시만) sudo ufw enable # 활성화 ``` --- ## LibreOffice (문서 변환) API 서버에서 문서 변환(Excel→PDF 등)에 사용. 헤드리스 모드로 동작. **버전:** 24.2.7.2 (개발/운영 동일) **명령어:** ```bash libreoffice --version # 버전 확인 libreoffice --headless --convert-to pdf input.xlsx # CLI 변환 테스트 ``` **설치 패키지:** ```bash sudo apt-get install -y libreoffice-core libreoffice-writer libreoffice-calc libreoffice-impress ``` --- ## 폰트 LibreOffice 문서 변환 시 폰트가 없으면 글자가 깨지므로 개발/운영 서버 동일하게 설치 필수. **설치된 한글 폰트:** | 폰트 | 설치 방식 | 경로 | |------|----------|------| | **Pretendard** (9 웨이트) | 수동 설치 (OTF) | `/usr/local/share/fonts/Pretendard-*.otf` | | **Nanum** (고딕/명조/스퀘어/손글씨 등) | apt (`fonts-nanum`, `fonts-nanum-extra`) | `/usr/share/fonts/truetype/nanum/` | | **Noto CJK** (Sans/Serif) | apt (`fonts-noto-cjk`) | `/usr/share/fonts/opentype/noto/` | **폰트 관리 명령어:** ```bash fc-list :lang=ko family | sort -u # 설치된 한글 폰트 목록 fc-list | grep -i pretendard # Pretendard 설치 확인 sudo fc-cache -fv # 폰트 캐시 갱신 (새 폰트 추가 후 필수) ``` **새 폰트 추가 시:** ```bash # 1. OTF/TTF 파일을 /usr/local/share/fonts/ 에 복사 sudo cp *.otf /usr/local/share/fonts/ # 2. 폰트 캐시 갱신 sudo fc-cache -fv # 3. 확인 fc-list | grep -i "폰트이름" ``` > **주의:** 개발서버에 폰트를 추가하면 운영서버에도 동일하게 설치해야 변환 결과가 일치한다. ```