diff --git a/PROJECT_DOCUMENTATION.md b/PROJECT_DOCUMENTATION.md index 1a5fc83..56e8cd9 100644 --- a/PROJECT_DOCUMENTATION.md +++ b/PROJECT_DOCUMENTATION.md @@ -1,266 +1,340 @@ -# Nginx Proxy Manager + Cloudflare R2 로그 시스템 구축 문서 +# Nginx Proxy Manager 자동화 구축 문서 ## 📅 프로젝트 개요 -**작업일**: 2025년 9월 10일 -**서버**: debian-jp-tyo-3 (100.115.167.93) -**목적**: Nginx Proxy Manager 로그를 Cloudflare R2에 실시간으로 업로드하여 CrowdSec 보안 분석 시스템과 연동 +**작업일**: 2025년 9월 11일 +**서버**: AWS EC2 Instance (3.35.209.51) +**OS**: Debian 13 (Trixie), Kernel 6.12.41 +**목적**: Podman + Quadlet을 활용한 nginx-proxy-manager 자동 실행 시스템 구축 -## 🏗️ 구축 완료 항목 +## 🏗️ 시스템 아키텍처 -### 1. 시스템 환경 설정 +### 1. 컨테이너 런타임 +- **Podman 5.4.2**: Rootless 컨테이너 엔진 +- **Quadlet**: systemd 기반 컨테이너 오케스트레이션 +- **systemd**: 서비스 자동 시작 및 관리 -#### 1.1 서버 기본 설정 -- **호스트명 변경**: npm-jp-tko3 → debian-jp-tyo-3 -- **타임존 설정**: UTC → Asia/Tokyo (JST) -- **시스템**: Debian 13 (trixie), Kernel 6.12.43 +### 2. 네트워크 구성 +- **포트 바인딩**: 80 (HTTP), 81 (관리 UI), 443 (HTTPS) +- **네트워크 백엔드**: netavark (Podman 기본) +- **DNS**: pasta를 통한 네트워크 격리 -#### 1.2 시스템 튜닝 -**커널 파라미터 최적화** (`/etc/sysctl.d/99-container-tuning.conf`) +## 🔧 시스템 설정 + +### 1. 커널 튜닝 설정 + +**파일**: `/etc/sysctl.d/99-container-tuning.conf` ```bash # 메모리 관리 -vm.swappiness=10 # 스왑 사용률 최소화 -vm.dirty_ratio=15 # 더티 페이지 비율 -vm.vfs_cache_pressure=50 # 캐시 압력 감소 +vm.swappiness=10 +vm.dirty_ratio=15 +vm.vfs_cache_pressure=50 # 네트워크 최적화 (프록시 워크로드) -net.core.somaxconn=65535 # 연결 큐 크기 -net.core.netdev_max_backlog=5000 # 네트워크 백로그 -net.ipv4.tcp_fin_timeout=30 # TCP 연결 종료 시간 -net.ipv4.tcp_max_syn_backlog=8192 # SYN 백로그 크기 -net.ipv4.ip_unprivileged_port_start=80 # 특권 포트 허용 +net.core.somaxconn=65535 +net.core.netdev_max_backlog=5000 +net.ipv4.tcp_fin_timeout=30 +net.ipv4.tcp_max_syn_backlog=8192 +net.ipv4.ip_unprivileged_port_start=80 # 컨테이너 최적화 -kernel.pid_max=4194304 # 최대 PID 수 -vm.max_map_count=262144 # 메모리 매핑 수 -fs.file-max=2097152 # 최대 파일 수 +kernel.pid_max=4194304 +vm.max_map_count=262144 +fs.file-max=2097152 ``` -**시스템 리소스 제한** (`/etc/systemd/system.conf.d/limits.conf`) +**핵심 설정**: +- `net.ipv4.ip_unprivileged_port_start=80`: rootless 컨테이너에서 포트 80 사용 허용 +- `vm.swappiness=10`: 스왑 사용률 최소화로 컨테이너 성능 향상 +- `net.core.somaxconn=65535`: 대용량 연결 처리를 위한 소켓 큐 확장 + +### 2. systemd 리소스 제한 + +**파일**: `/etc/systemd/system.conf.d/limits.conf` ```bash +[Manager] DefaultLimitNOFILE=65536 DefaultLimitNPROC=65536 DefaultLimitCORE=infinity DefaultLimitMEMLOCK=infinity ``` -### 2. Nginx Proxy Manager 설치 (Podman + Quadlet) - -#### 2.1 컨테이너 서비스 -- **npm-app.service**: Nginx Proxy Manager 메인 애플리케이션 -- **npm-db.service**: MariaDB 10.11 데이터베이스 -- **네트워크**: Podman 사용자 네트워크 (npm) -- **포트**: 80, 81 (관리자), 443 - -#### 2.2 데이터 디렉토리 -``` -/home/kaffa/nginx-proxy-manager/ -├── data/ # NPM 데이터 -├── letsencrypt/ # SSL 인증서 -├── db/ # MariaDB 데이터 -└── data/logs/ # 로그 파일 -``` - -### 3. Cloudflare R2 연동 - -#### 3.1 rclone 설치 및 설정 -**설치된 버전**: rclone v1.60.1-DEV - -**설정 파일** (`~/.config/rclone/rclone.conf`): -```ini -[cloudflare-r2] -type = s3 -provider = Cloudflare -access_key_id = 90b141de4479101392691a20c60d2696 -secret_access_key = [REDACTED] -endpoint = https://d8e5997eb4040f8b489f09095c0f623c.r2.cloudflarestorage.com -region = auto -``` - -#### 3.2 R2 버킷 구조 -``` -npm-logs/ -└── debian-jp-tyo-3/ - └── 2025-09-10/ - ├── npm_access.log - ├── npm_error.log - ├── fallback_access.log - ├── fallback_error.log - ├── npm-app-recent.log - └── npm-db-recent.log -``` - -### 4. 로그 스트리밍 시스템 - -#### 4.1 로그 수집 스크립트 -**백업 스크립트** (`/home/kaffa/scripts/npm-log-backup.sh`) -- 일일 백업용 (압축 아카이브) -- systemd 타이머로 자동 실행 -- 로컬 백업 7일 보관 - -**실시간 스트리밍 스크립트** (`/home/kaffa/scripts/npm-log-streamer.sh`) -- CrowdSec용 실시간 업로드 (압축 없음) -- 1분 간격 동기화 -- 에러 복구 로직 포함 - -#### 4.2 주요 기능 +### 3. 사용자 서비스 활성화 ```bash -# 로그 수집 소스 -- Podman 컨테이너 내부 로그 -- systemd journal (npm-app, npm-db) -- 호스트 마운트 로그 파일 - -# 업로드 특징 -- 개별 파일 업로드 (압축 없음) -- 재시도 로직 (3회) -- 타임아웃 보호 (300초) -- 실패 시 계속 작동 +# 사용자 서비스 영구 활성화 (로그인 없이 자동 시작) +sudo loginctl enable-linger admin ``` -#### 4.3 systemd 서비스 -**npm-log-backup.timer**: 일일 백업 (00:00) -**npm-log-streamer.service**: 실시간 스트리밍 (상시 가동) +## 📦 Quadlet 설정 -### 5. 문제 해결 내역 - -#### 5.1 R2 연결 문제 -**문제**: TLS handshake 실패 -**원인**: 잘못된 API 자격증명 -**해결**: -- API Token 대신 S3 호환 Access Key/Secret Key 사용 -- 32자리 Access Key ID 형식 준수 -- 올바른 Account ID로 엔드포인트 수정 - -#### 5.2 rootless 컨테이너 포트 바인딩 -**문제**: 포트 80 바인딩 권한 오류 -**해결**: `net.ipv4.ip_unprivileged_port_start=80` 설정 - -#### 5.3 스크립트 에러 판정 로직 -**문제**: rclone 출력 텍스트 파싱으로 잘못된 실패 판정 -**해결**: Exit code 기반 판정으로 변경 (0=성공) - -## 📊 성능 및 비용 분석 - -### 현재 운영 현황 -- **업로드 빈도**: 1분당 6-8개 파일 -- **일일 업로드**: 약 8,640개 파일 -- **월간 데이터**: 약 2.81GB -- **성공률**: 99.93% - -### 월간 비용 예상 +### 1. 디렉토리 구조 ``` -스토리지: $0.042 (2.81GB × $0.015) -PUT 작업: $0.78 (172,800회 × $4.50/백만) -총 비용: $0.822/월 (약 1,200원) +~/.config/containers/systemd/ +└── nginx-proxy-manager.container ``` -### 비용 최적화 방안 -1. **현재 (4개 파일)**: $0.82/월 -2. **500개 파일 시**: $102/월 → 주기 조정 필요 -3. **권장**: 중요도별 차등 업로드 +### 2. Quadlet 설정 파일 -## 🔧 유지보수 명령어 +**파일**: `~/.config/containers/systemd/nginx-proxy-manager.container` +```ini +[Unit] +Description=Nginx Proxy Manager +Wants=network-online.target +After=network-online.target +RequiresMountsFor=%t/containers -### 서비스 관리 +[Container] +Image=docker.io/jc21/nginx-proxy-manager:latest +ContainerName=nginx-proxy-manager +AutoUpdate=registry +PublishPort=80:80 +PublishPort=81:81 +PublishPort=443:443 +Volume=nginx-proxy-manager-data:/data +Volume=nginx-proxy-manager-letsencrypt:/etc/letsencrypt +Environment=DISABLE_IPV6=true + +[Service] +Restart=always +TimeoutStartSec=900 + +[Install] +WantedBy=default.target +``` + +### 3. Quadlet 작동 원리 +1. Quadlet이 `.container` 파일을 읽어 systemd 서비스 파일 자동 생성 +2. systemd가 생성된 서비스를 `default.target`에 등록 +3. 부팅 시 자동으로 컨테이너 시작 + +## 🚀 설치 및 배포 절차 + +### 1. 기본 시스템 설정 +```bash +# 시스템 업데이트 +sudo apt update + +# Podman 설치 +sudo apt install -y podman + +# 사용자 lingering 활성화 +sudo loginctl enable-linger admin +``` + +### 2. 커널 튜닝 적용 +```bash +# 커널 파라미터 설정 +sudo tee /etc/sysctl.d/99-container-tuning.conf << EOF +# [위의 커널 튜닝 설정 내용] +EOF + +# systemd 리소스 제한 설정 +sudo mkdir -p /etc/systemd/system.conf.d +sudo tee /etc/systemd/system.conf.d/limits.conf << EOF +# [위의 systemd 설정 내용] +EOF + +# 커널 파라미터 즉시 적용 +sudo sysctl -p /etc/sysctl.d/99-container-tuning.conf +``` + +### 3. Quadlet 설정 배포 +```bash +# Quadlet 디렉토리 생성 +mkdir -p ~/.config/containers/systemd + +# nginx-proxy-manager 설정 파일 생성 +cat > ~/.config/containers/systemd/nginx-proxy-manager.container << EOF +# [위의 Quadlet 설정 내용] +EOF + +# systemd 데몬 재로드 +systemctl --user daemon-reload + +# 서비스 시작 +systemctl --user start nginx-proxy-manager.service +``` + +## 📊 리부팅 테스트 결과 + +### 부팅 타임라인 (2025-09-11 테스트) +``` +01:13:13 - 시스템 셧다운 시작 +01:13:17 - nginx-proxy-manager 정상 종료 +-- 리부팅 -- +01:13:53 - nginx-proxy-manager 자동 시작 (부팅 후 40초) +01:13:58 - 서비스 완전 준비 완료 +``` + +### 검증된 기능 +- ✅ **자동 시작**: 부팅 후 40초 만에 서비스 시작 +- ✅ **포트 바인딩**: 80, 81, 443 포트 정상 바인딩 +- ✅ **커널 파라미터 유지**: 리부팅 후에도 모든 설정 유지 +- ✅ **서비스 안정성**: systemd를 통한 자동 재시작 +- ✅ **컨테이너 생성**: 새로운 컨테이너 ID로 정상 생성 + +## 🔧 운영 관리 + +### 서비스 관리 명령어 ```bash # 서비스 상태 확인 -systemctl --user status npm-app npm-db npm-log-streamer +systemctl --user status nginx-proxy-manager.service -# 로그 스트리밍 재시작 -systemctl --user restart npm-log-streamer.service +# 서비스 중지/시작/재시작 +systemctl --user stop nginx-proxy-manager.service +systemctl --user start nginx-proxy-manager.service +systemctl --user restart nginx-proxy-manager.service -# 로그 확인 -journalctl --user -u npm-log-streamer.service -f - -# 수동 로그 동기화 -/home/kaffa/scripts/npm-log-streamer.sh sync - -# R2 연결 테스트 -/home/kaffa/scripts/npm-log-streamer.sh test -``` - -### R2 작업 -```bash -# 업로드된 파일 확인 -rclone ls cloudflare-r2:npm-logs/ - -# 버킷 리스트 -rclone lsd cloudflare-r2: - -# 수동 업로드 -rclone copy file.log cloudflare-r2:npm-logs/path/ -``` - -### 모니터링 -```bash -# 업로드 통계 -grep -c 'SUCCESS:' /home/kaffa/logs/npm-streamer.log - -# 최근 로그 -tail -f /home/kaffa/logs/npm-streamer.log - -# 디스크 사용량 -du -sh /home/kaffa/nginx-proxy-manager/data/logs/ -``` - -## 🚀 향후 개선 사항 - -### 단기 개선 -1. CrowdSec 연동 구성 및 테스트 -2. 로그 필터링 규칙 적용 (중요 로그 우선) -3. 알림 시스템 구축 (업로드 실패 시) - -### 장기 개선 -1. 로그 분석 대시보드 구축 -2. 자동 스케일링 (로그 양에 따른 주기 조정) -3. 다중 지역 백업 (재해 복구) -4. 로그 압축 아카이빙 (30일 이상) - -## 📝 트러블슈팅 가이드 - -### R2 연결 실패 -```bash -# 자격증명 확인 -cat ~/.config/rclone/rclone.conf - -# 직접 연결 테스트 -rclone lsd cloudflare-r2: --verbose - -# 네트워크 확인 -curl -v https://[account-id].r2.cloudflarestorage.com -``` - -### 서비스 재시작 루프 -```bash # 서비스 로그 확인 -journalctl --user -u npm-log-streamer.service -n 50 +journalctl --user -u nginx-proxy-manager.service -f -# 스크립트 권한 확인 -ls -la /home/kaffa/scripts/ - -# 수동 실행 테스트 -bash -x /home/kaffa/scripts/npm-log-streamer.sh sync -``` - -### 로그 누락 -```bash # 컨테이너 상태 확인 podman ps -# 로그 파일 존재 확인 -podman exec npm-app ls -la /data/logs/ - -# 마운트 확인 -ls -la /home/kaffa/nginx-proxy-manager/data/logs/ +# 포트 바인딩 확인 +ss -tlnp | grep ':80\|:81\|:443' ``` +### 컨테이너 관리 +```bash +# 컨테이너 내부 접근 +podman exec -it nginx-proxy-manager /bin/bash + +# 볼륨 확인 +podman volume ls + +# 컨테이너 로그 확인 +podman logs nginx-proxy-manager + +# 이미지 업데이트 (AutoUpdate=registry로 자동) +podman auto-update +``` + +### 시스템 파라미터 확인 +```bash +# 커널 파라미터 확인 +cat /proc/sys/net/ipv4/ip_unprivileged_port_start +cat /proc/sys/vm/swappiness +cat /proc/sys/net/core/somaxconn + +# Lingering 상태 확인 +loginctl show-user admin | grep Linger + +# 서비스 의존성 확인 +systemctl --user list-dependencies nginx-proxy-manager.service +``` + +## 🛡️ 보안 고려사항 + +### 1. Rootless 컨테이너 +- 루트 권한 없이 컨테이너 실행 +- 호스트 시스템과 격리된 사용자 네임스페이스 +- 보안 취약점 영향 범위 최소화 + +### 2. 네트워크 격리 +- pasta를 통한 네트워크 네임스페이스 격리 +- 컨테이너별 독립적인 네트워크 스택 +- 불필요한 포트 노출 차단 + +### 3. 자동 업데이트 +- `AutoUpdate=registry`: 레지스트리에서 최신 이미지 자동 갱신 +- 보안 패치 자동 적용 +- `podman auto-update` 명령으로 수동 업데이트 가능 + +## 📈 성능 최적화 + +### 1. 메모리 관리 +- `vm.swappiness=10`: 메모리 우선 사용으로 I/O 대기 시간 감소 +- `vm.dirty_ratio=15`: 쓰기 성능 최적화 +- `vm.vfs_cache_pressure=50`: 파일시스템 캐시 효율성 향상 + +### 2. 네트워크 성능 +- `net.core.somaxconn=65535`: 대용량 동시 연결 처리 +- `net.core.netdev_max_backlog=5000`: 네트워크 패킷 처리 최적화 +- `net.ipv4.tcp_fin_timeout=30`: TCP 연결 종료 시간 단축 + +### 3. 컨테이너 최적화 +- `kernel.pid_max=4194304`: 대용량 프로세스 지원 +- `fs.file-max=2097152`: 파일 디스크립터 한계 확장 +- `vm.max_map_count=262144`: 메모리 매핑 영역 확장 + +## 🔍 트러블슈팅 + +### 서비스 시작 실패 +```bash +# 서비스 상태 및 로그 확인 +systemctl --user status nginx-proxy-manager.service --no-pager +journalctl --user -u nginx-proxy-manager.service -n 20 + +# Quadlet 설정 검증 +/usr/libexec/podman/quadlet --user --dryrun + +# 포트 충돌 확인 +ss -tlnp | grep ':80\|:81\|:443' +``` + +### 포트 바인딩 실패 +```bash +# 커널 파라미터 확인 +cat /proc/sys/net/ipv4/ip_unprivileged_port_start + +# 수동으로 커널 파라미터 적용 +sudo sysctl net.ipv4.ip_unprivileged_port_start=80 + +# 영구 설정 확인 +cat /etc/sysctl.d/99-container-tuning.conf +``` + +### 자동 시작 실패 +```bash +# Lingering 상태 확인 +loginctl show-user admin | grep Linger + +# Lingering 활성화 +sudo loginctl enable-linger admin + +# 서비스 활성화 확인 +systemctl --user is-enabled nginx-proxy-manager.service +``` + +## 🎯 확장 및 개선 방향 + +### 1. 모니터링 시스템 +- Prometheus + Grafana를 통한 컨테이너 메트릭 수집 +- 로그 중앙화 (ELK Stack 또는 Loki) +- 알림 시스템 (서비스 다운 시 Slack/이메일 알림) + +### 2. 백업 및 복구 +- 컨테이너 볼륨 정기 백업 +- 설정 파일 버전 관리 (Git) +- 재해 복구 절차 수립 + +### 3. 고가용성 +- 다중 노드 클러스터 구성 +- 로드 밸런서를 통한 트래픽 분산 +- 헬스체크 및 자동 복구 + +### 4. 보안 강화 +- Podman의 SELinux 연동 +- 컨테이너 이미지 취약점 스캔 +- 네트워크 정책 세분화 + ## ✅ 프로젝트 성과 -1. **보안 강화**: 실시간 로그 분석 기반 구축 -2. **비용 효율**: 월 $0.82 (1,200원)로 엔터프라이즈급 로그 관리 -3. **자동화**: 무인 운영 가능한 시스템 구축 -4. **확장성**: 500개 파일까지 확장 가능한 아키텍처 -5. **신뢰성**: 99.93% 업로드 성공률 +1. **완전 자동화**: 부팅 시 무인 자동 시작 달성 +2. **안정성**: systemd 기반 서비스 관리로 높은 안정성 확보 +3. **성능 최적화**: 커널 튜닝을 통한 프록시 워크로드 최적화 +4. **보안**: Rootless 컨테이너로 보안 위험 최소화 +5. **유지보수성**: Quadlet을 통한 선언적 설정 관리 + +## 📝 기술 스택 + +- **컨테이너**: Podman 5.4.2 (Rootless) +- **오케스트레이션**: Quadlet + systemd +- **네트워킹**: netavark + pasta +- **OS**: Debian 13 (Trixie) +- **관리도구**: systemctl, journalctl, podman CLI --- -*Documentation created: 2025-09-11* -*System operational since: 2025-09-10 17:13 JST* \ No newline at end of file +*Documentation created: 2025-09-11* +*System tested and operational: 리부팅 테스트 완료* +*Auto-start verification: ✅ 40초 만에 자동 시작 확인* \ No newline at end of file