gunicorn 명령어 기반 uvicorn 실행시 사용되는 설정파일 추가, logrotate 설정 추가.
parent
628b22dd03
commit
94b5633065
|
|
@ -0,0 +1,11 @@
|
|||
PROJECT_DIR=django_sample
|
||||
WORKERS=4
|
||||
GUNICORN_PORT=8000
|
||||
REQUIREMENTS=./requirements.txt
|
||||
PROJECT_NAME=django_sample
|
||||
LOG_DRIVER=json-file
|
||||
LOG_OPT_MAXF=5
|
||||
LOG_OPT_MAXS=100m
|
||||
CELERY_BROKER_URL=redis://redis:6379/3
|
||||
FLOWER_ID=admin
|
||||
FLOWER_PWD=admin
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
services:
|
||||
webserver:
|
||||
build: ../../../docker/nginx/
|
||||
logging:
|
||||
driver: "${LOG_DRIVER}"
|
||||
options:
|
||||
max-file: "${LOG_OPT_MAXF}"
|
||||
max-size: "${LOG_OPT_MAXS}"
|
||||
working_dir: /application
|
||||
container_name: nginx-uvicorn-webserver
|
||||
volumes:
|
||||
- ../../../www:/www
|
||||
- ../../../script/:/script/
|
||||
- ../../../config/web-server/nginx/gunicorn/conf.d/:/etc/nginx/conf.d/
|
||||
- ../../../config/web-server/nginx/gunicorn/nginx_conf/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ../../../config/web-server/nginx/gunicorn/proxy_params/proxy_params:/etc/nginx/proxy_params
|
||||
- ./ssl/certs/:/etc/ssl/certs/
|
||||
- ./ssl/letsencrypt/:/etc/letsencrypt/
|
||||
- ../../../log/:/log/
|
||||
- ../../../script/logrotate/nginx/nginx:/etc/logrotate.d/nginx
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
environment:
|
||||
TZ: "Asia/Seoul"
|
||||
restart: always
|
||||
|
||||
uvicorn-app:
|
||||
build: ../../../docker/gunicorn/
|
||||
logging:
|
||||
driver: "${LOG_DRIVER}"
|
||||
options:
|
||||
max-file: "${LOG_OPT_MAXF}"
|
||||
max-size: "${LOG_OPT_MAXS}"
|
||||
working_dir: /www/${PROJECT_DIR}
|
||||
container_name: uvicorn-app
|
||||
volumes:
|
||||
- ../../../www:/www
|
||||
- ../../../log:/log
|
||||
- ../../../config/app-server/uvicorn/:/uvicorn
|
||||
- ../../../script/logrotate/uvicorn/uvicorn:/etc/logrotate.d/uvicorn
|
||||
command: bash -c "poetry config virtualenvs.create false && poetry install --no-root --without test && gunicorn -c /uvicorn/gunicorn_uvicorn.conf.py"
|
||||
environment:
|
||||
TZ: "Asia/Seoul"
|
||||
restart: always
|
||||
|
||||
celery:
|
||||
build: ../../../docker/gunicorn/
|
||||
logging:
|
||||
driver: "${LOG_DRIVER}"
|
||||
options:
|
||||
max-file: "${LOG_OPT_MAXF}"
|
||||
max-size: "${LOG_OPT_MAXS}"
|
||||
working_dir: /www/${PROJECT_DIR}
|
||||
container_name: celery-app
|
||||
volumes:
|
||||
- ../../../www:/www
|
||||
- ../../../log:/log
|
||||
- ../../../script/logrotate/uvicorn/celery/uvicorn-celery:/etc/logrotate.d/uvicorn-celery
|
||||
command: bash -c "poetry config virtualenvs.create false && \
|
||||
poetry install --no-root && \
|
||||
celery -A config worker \
|
||||
--loglevel=INFO \
|
||||
--logfile=/log/uvicorn/celery/worker-%n%I.log "
|
||||
environment:
|
||||
TZ: "Asia/Seoul"
|
||||
restart: always
|
||||
depends_on:
|
||||
- redis
|
||||
- gunicorn-uvicorn-app
|
||||
profiles:
|
||||
- celery
|
||||
|
||||
celery-beat:
|
||||
build: ../../../docker/gunicorn/
|
||||
logging:
|
||||
driver: "${LOG_DRIVER}"
|
||||
options:
|
||||
max-file: "${LOG_OPT_MAXF}"
|
||||
max-size: "${LOG_OPT_MAXS}"
|
||||
working_dir: /www/${PROJECT_DIR}
|
||||
container_name: celerybeat-app
|
||||
volumes:
|
||||
- ../../../www:/www
|
||||
- ../../../log:/log
|
||||
- ../../../script/logrotate/uvicorn/celerybeat/uvicorn-celerybeat:/etc/logrotate.d/uvicorn-celerybeat
|
||||
command: bash -c "poetry config virtualenvs.create false && \
|
||||
poetry install --no-root && \
|
||||
celery -A config beat \
|
||||
--loglevel=INFO \
|
||||
--scheduler django_celery_beat.schedulers:DatabaseScheduler \
|
||||
--logfile=/log/uvicorn/celerybeat/celerybeat.log "
|
||||
environment:
|
||||
TZ: "Asia/Seoul"
|
||||
restart: always
|
||||
depends_on:
|
||||
- celery
|
||||
profiles:
|
||||
- celery
|
||||
|
||||
flower:
|
||||
image: mher/flower:master
|
||||
logging:
|
||||
driver: "${LOG_DRIVER}"
|
||||
options:
|
||||
max-file: "${LOG_OPT_MAXF}"
|
||||
max-size: "${LOG_OPT_MAXS}"
|
||||
container_name: flower
|
||||
ports:
|
||||
- "5555:5555"
|
||||
environment:
|
||||
- CELERY_BROKER_URL=${CELERY_BROKER_URL}
|
||||
- FLOWER_BASIC_AUTH=${FLOWER_ID}:${FLOWER_PWD}
|
||||
restart: always
|
||||
depends_on:
|
||||
- celery-beat
|
||||
profiles:
|
||||
- celery
|
||||
|
||||
redis:
|
||||
image: redis:latest
|
||||
logging:
|
||||
driver: "${LOG_DRIVER}"
|
||||
options:
|
||||
max-file: "${LOG_OPT_MAXF}"
|
||||
max-size: "${LOG_OPT_MAXS}"
|
||||
container_name: redis_db
|
||||
# ports:
|
||||
# - 6379:6379
|
||||
volumes:
|
||||
- ./redis/data:/data
|
||||
- ./redis/conf/:/usr/local/etc/redis/
|
||||
labels:
|
||||
- "name=redis"
|
||||
- "mode=standalone"
|
||||
environment:
|
||||
TZ: "Asia/Seoul"
|
||||
restart: always
|
||||
command: redis-server /usr/local/etc/redis/redis.conf
|
||||
|
||||
redis-stats:
|
||||
image: insready/redis-stat:latest
|
||||
logging:
|
||||
driver: "${LOG_DRIVER}"
|
||||
options:
|
||||
max-file: "${LOG_OPT_MAXF}"
|
||||
max-size: "${LOG_OPT_MAXS}"
|
||||
container_name: redis-stats
|
||||
ports:
|
||||
- 63790:63790
|
||||
command: ["--verbose", "--server", "redis:6379"]
|
||||
environment:
|
||||
TZ: "Asia/Seoul"
|
||||
depends_on:
|
||||
- redis
|
||||
restart: always
|
||||
profiles:
|
||||
- redis
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
"""
|
||||
Gunicorn Configuration for Production FastAPI Service
|
||||
=====================================================
|
||||
환경: Production Level
|
||||
서버 사양: 쿼드코어 CPU, 4GB RAM, ~50 req/s
|
||||
백엔드: FastAPI REST API with Uvicorn Workers
|
||||
프록시: Nginx (SSL/TLS, DDoS, Rate Limiting 처리)
|
||||
=====================================================
|
||||
"""
|
||||
|
||||
# ============================================================================
|
||||
# 네트워크 바인딩 설정
|
||||
# ============================================================================
|
||||
# 바인딩 주소 및 포트
|
||||
# 역할: Gunicorn이 수신할 네트워크 주소
|
||||
# 0.0.0.0:8000 - 모든 네트워크 인터페이스에서 수신 (Docker/컨테이너 환경)
|
||||
# 127.0.0.1:8000 - 로컬 전용 (Nginx와 동일 호스트, 보안 강화)
|
||||
# Nginx 연동: Nginx가 외부 트래픽 처리, Gunicorn은 내부 전용
|
||||
bind = "0.0.0.0:8000"
|
||||
|
||||
# ============================================================================
|
||||
# Worker 프로세스 설정
|
||||
# ============================================================================
|
||||
# Worker 수
|
||||
# 역할: 동시 요청 처리를 위한 프로세스 수
|
||||
# 공식: I/O 집약적 작업 = (CPU 코어 * 2) + 1
|
||||
# 계산: 쿼드코어(4) → 9개 권장, 하지만 4GB RAM 제약으로 4개 설정
|
||||
# 각 워커 메모리: 200-500MB
|
||||
# 4 워커 × 500MB = 2GB (시스템 예비 2GB 확보)
|
||||
# 성능: ~50 req/s는 4개 워커로 충분 (워커당 ~12.5 req/s)
|
||||
# 환경 변수: GUNICORN_WORKERS=6 으로 오버라이드 가능
|
||||
# workers = multiprocessing.cpu_count() * 2 + 1
|
||||
workers = 4
|
||||
|
||||
# Worker 클래스
|
||||
# 역할: ASGI 애플리케이션(FastAPI) 처리를 위한 Worker 타입
|
||||
# uvicorn.workers.UvicornWorker: 비동기 I/O, uvloop 이벤트 루프
|
||||
# 기대 효과: sync 워커 대비 2-5배 높은 동시성, 메모리 효율적
|
||||
worker_class = "uvicorn.workers.UvicornWorker"
|
||||
|
||||
# Worker 동시 연결 수 (주석 처리 - UvicornWorker는 이 설정 미사용)
|
||||
# Nginx가 앞단에서 연결 관리하므로 불필요
|
||||
# worker_connections = 1000
|
||||
|
||||
# ============================================================================
|
||||
# 프로세스 관리 설정
|
||||
# ============================================================================
|
||||
# 데몬 모드
|
||||
# 역할: 백그라운드 실행 여부
|
||||
# False: systemd/Docker가 프로세스 관리 (현대적 방식)
|
||||
# True: 수동 관리 시 사용 (pidfile 필수)
|
||||
daemon = False
|
||||
|
||||
# PID 파일 (주석 처리 - systemd/Docker 사용 시 불필요)
|
||||
# 역할: Master 프로세스 ID 저장
|
||||
# 수동 관리 시 활성화: pidfile = '/var/run/gunicorn/gunicorn.pid'
|
||||
# pidfile = '/tmp/gunicorn.pid'
|
||||
|
||||
# ============================================================================
|
||||
# ASGI 애플리케이션 경로
|
||||
# ============================================================================
|
||||
# ASGI 애플리케이션 경로
|
||||
# 역할: Gunicorn이 실행할 FastAPI 앱 지정
|
||||
# 형식: "모듈경로:변수명"
|
||||
# 예: config.asgi:application (Django 스타일)
|
||||
# main:app (FastAPI 기본)
|
||||
wsgi_app = "config.asgi:application"
|
||||
|
||||
# ============================================================================
|
||||
# 타임아웃 설정
|
||||
# ============================================================================
|
||||
# Worker 타임아웃
|
||||
# 역할: Worker가 요청 처리 최대 허용 시간 (초)
|
||||
# 동작: 타임아웃 초과 시 Worker 강제 종료 후 재시작
|
||||
# 계산: FastAPI REST API 평균 응답 1-5초
|
||||
# 파일 업로드 고려 (100MB / 10Mbps = 80초)
|
||||
# Nginx 연동: proxy_read_timeout(60s)보다 짧거나 같게 설정
|
||||
# 30초: 일반 API 응답 충분, 긴 작업은 백그라운드 처리 권장
|
||||
timeout = 30
|
||||
|
||||
# Keep-Alive 타임아웃
|
||||
# 역할: HTTP Keep-Alive 연결 유지 시간 (초)
|
||||
# 동작: 연결 재사용으로 핸드셰이크 오버헤드 감소
|
||||
# Nginx 연동: Nginx keepalive_timeout(30s)보다 짧게 설정
|
||||
# Nginx가 먼저 종료하도록 하여 리소스 효율화
|
||||
# 2초: Nginx 앞단에서 연결 관리하므로 짧게 설정
|
||||
keepalive = 2
|
||||
|
||||
# Graceful 종료 타임아웃
|
||||
# 역할: Worker 재시작/종료 시 진행 중인 요청 완료 대기 시간 (초)
|
||||
# 동작: SIGTERM 수신 후 새 요청 거부, 기존 요청 처리
|
||||
# 타임아웃 초과 시 SIGKILL로 강제 종료
|
||||
# 기대 효과: Graceful reload로 무중단 배포
|
||||
# kill -HUP <pid> 또는 systemctl reload gunicorn
|
||||
# timeout과 동일하게 설정
|
||||
graceful_timeout = 30
|
||||
|
||||
# ============================================================================
|
||||
# 프로세스 리소스 관리 (메모리 누수 방지)
|
||||
# ============================================================================
|
||||
# Worker 최대 요청 수
|
||||
# 역할: Worker가 처리할 최대 요청 후 자동 재시작
|
||||
# 목적: 메모리 누수 방어, 장기 운영 안정성
|
||||
# 동작: max_requests 도달 시 Worker graceful 종료 후 재시작
|
||||
# 계산: ~50 req/s 기준
|
||||
# 1000으로 설정 시 워커당 20초마다 재시작 (1000/50)
|
||||
# 메모리 누수 우려 시 유지, 안정적이면 5000-10000 증가 가능
|
||||
# 모니터링: htop으로 워커 메모리 사용량 추이 확인
|
||||
max_requests = 1000
|
||||
|
||||
# 최대 요청 수 Jitter
|
||||
# 역할: max_requests에 랜덤성 추가
|
||||
# 목적: 모든 Worker가 동시에 재시작하는 것 방지
|
||||
# 동작: 실제 재시작 = max_requests ± random(0, jitter)
|
||||
# 기대 효과: 재시작 부하 분산, 서비스 연속성 보장
|
||||
# 권장: max_requests의 5-10%
|
||||
max_requests_jitter = 50
|
||||
|
||||
# ============================================================================
|
||||
# 애플리케이션 로딩 설정
|
||||
# ============================================================================
|
||||
# 애플리케이션 사전 로딩
|
||||
# 역할: Worker fork 전 앱 로딩 방식 결정
|
||||
# False: 각 Worker가 독립적으로 앱 로딩
|
||||
# - 장점: Graceful reload 가능 (무중단 배포)
|
||||
# - 단점: 메모리 중복 사용 (Worker 수만큼)
|
||||
# True: Master 프로세스에서 앱 로딩 후 Worker fork
|
||||
# - 장점: 메모리 20-40% 절감 (Copy-on-Write)
|
||||
# - 단점: reload 시 전체 재시작 필요 (다운타임)
|
||||
# 프로덕션 권장: False (무중단 배포 우선)
|
||||
preload_app = False
|
||||
|
||||
# 코드 변경 감지 자동 재시작
|
||||
# 역할: 파일 변경 시 Worker 자동 재시작
|
||||
# 성능 영향: CPU 5-10% 오버헤드, 메모리 50-100MB 추가
|
||||
# 보안: 예기치 않은 재시작으로 서비스 불안정
|
||||
# **프로덕션에서는 반드시 False**
|
||||
# 개발 환경에서만 True 사용
|
||||
# 배포: CI/CD 파이프라인에서 명시적 재시작
|
||||
reload = False
|
||||
|
||||
# ============================================================================
|
||||
# 로깅 설정
|
||||
# ============================================================================
|
||||
# 애플리케이션 출력 캡처
|
||||
# 역할: FastAPI의 print(), logging을 Gunicorn 로그로 리다이렉트
|
||||
# False: 앱 로거가 독립적으로 관리 (권장)
|
||||
# True: stdout/stderr를 errorlog로 통합
|
||||
# FastAPI 권장: False (자체 로거 사용)
|
||||
capture_output = False
|
||||
|
||||
# 로그 레벨
|
||||
# 역할: 출력할 로그의 최소 수준
|
||||
# 레벨: critical > error > warning > info > debug
|
||||
# info: 일반 정보 + 에러 (프로덕션 권장)
|
||||
# warning: 경고 이상만 (로그 양 감소)
|
||||
# debug: 모든 세부 정보 (성능 저하, 개발용)
|
||||
loglevel = "info"
|
||||
|
||||
# 액세스 로그 파일
|
||||
# 역할: HTTP 요청 로그 저장
|
||||
# 형식: 시간별 로그 파일 생성 (access_2025-01-05_14.log)
|
||||
# 로테이션: 시간별 자동 분리, logrotate 추가 권장
|
||||
# 성능: 버퍼링으로 I/O 최적화
|
||||
# Docker/K8s: "-" 사용으로 stdout 출력 권장
|
||||
accesslog = "/log/uvicorn/uvicorn_access.log"
|
||||
|
||||
# 에러 로그 파일
|
||||
# 역할: Gunicorn 에러, Worker 크래시 로그
|
||||
# 포함: Worker 타임아웃, 메모리 에러, 예외 등
|
||||
# 모니터링: 장애 탐지를 위한 핵심 로그
|
||||
errorlog = "/log/uvicorn/uvicorn_error.log"
|
||||
|
||||
# 액세스 로그 포맷 (선택사항, 필요 시 주석 해제)
|
||||
# 역할: 요청 로그 형식 커스터마이징
|
||||
# 기본 포맷으로도 충분, 상세 정보 필요 시 활성화
|
||||
access_log_format = (
|
||||
'%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s %(p)s'
|
||||
)
|
||||
|
||||
# 워커 프로세스 이름 설정 (모니터링 시 유용)
|
||||
proc_name = "fastapi_gunicorn"
|
||||
|
||||
# ==========================================
|
||||
# 성능 최적화
|
||||
# ==========================================
|
||||
# - 최대 2048개의 연결이 Accept Queue에서 대기 가능
|
||||
# - 동시에 많은 연결 요청이 들어와도 2048개까지는 거부되지 않음
|
||||
# - 실제 적용값 = min(2048, 시스템 somaxconn)
|
||||
# 낮은 트래픽 (기본값 충분)
|
||||
# backlog = 2048 # 기본값 사용
|
||||
# workers = 4
|
||||
#
|
||||
# 높은 트래픽 (증가 필요)
|
||||
# backlog = 4096
|
||||
# workers = 8
|
||||
# OS 설정도 함께 조정 필요
|
||||
# /etc/sysctl.conf
|
||||
# net.core.somaxconn = 4096
|
||||
#
|
||||
# 증가해야 할 때:
|
||||
# ss -lnt 명령으로 Send-Q가 계속 가득 찬 경우
|
||||
# ss -lnt | grep :8000
|
||||
# 순간적인 트래픽 급증이 예상되는 경우
|
||||
# connection refused 에러가 자주 발생하는 경우
|
||||
|
||||
backlog = 2048
|
||||
|
||||
# 임시 파일 디렉토리 (업로드 처리 시 사용)
|
||||
# 재부팅 시 자동 삭제
|
||||
# Gunicorn 기본값
|
||||
# worker_tmp_dir = None # /tmp 디렉토리 사용 (디스크 기반)
|
||||
# 사용하는 경우 (권장):
|
||||
# 파일 업로드가 많은 서비스
|
||||
# 큰 요청/응답 처리
|
||||
# 충분한 RAM이 있는 경우
|
||||
# RAM이 부족한 경우
|
||||
# worker_tmp_dir = "/tmp" # 디스크 사용
|
||||
# 파일 업로드/다운로드가 거의 없는 경우
|
||||
# worker_tmp_dir = None # 기본값 사용
|
||||
# Docker 사용시 고려 필요
|
||||
# shm_size: '2gb' # /dev/shm 크기 증가
|
||||
# volumes:
|
||||
# - /dev/shm:/dev/shm # 호스트 공유 (선택)
|
||||
|
||||
# worker_tmp_dir = "/dev/shm" # RAM 기반 tmpfs 사용으로 I/O 성능 향상
|
||||
worker_tmp_dir = None
|
||||
|
||||
"""
|
||||
배포 전 체크리스트:
|
||||
|
||||
[권장]
|
||||
1. 로그 로테이션 설정 (logrotate)
|
||||
2. 헬스체크 엔드포인트 구현 (/health)
|
||||
3. 성능 테스트 (wrk, locust)
|
||||
|
||||
성능 모니터링:
|
||||
# 프로세스 확인
|
||||
ps aux | grep gunicorn
|
||||
|
||||
# 리소스 사용량
|
||||
htop -p $(pgrep -d',' gunicorn)
|
||||
|
||||
# 로그 실시간 확인
|
||||
tail -f /log/uvicorn/access_*.log
|
||||
tail -f /log/uvicorn/error_*.log
|
||||
|
||||
설정 최적화 가이드:
|
||||
- workers: CPU 사용률 80% 이하 유지
|
||||
- timeout: 응답 시간 + 여유분 (평균 * 2)
|
||||
- max_requests: 메모리 누수 없으면 5000-10000으로 증가
|
||||
- keepalive: Nginx keepalive_timeout보다 짧게
|
||||
"""
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2020 devspoons
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,562 @@
|
|||
map $http_user_agent $bad_bot {
|
||||
default 0;
|
||||
~*360Spider 1;
|
||||
~*360Spider 1;
|
||||
~*80legs 1;
|
||||
~*Abonti 1;
|
||||
~*Aboundex 1;
|
||||
~*AcoonBot 1;
|
||||
~*Acunetix 1;
|
||||
~*adbeat_bot 1;
|
||||
~*AddThis.com 1;
|
||||
~*adidxbot 1;
|
||||
~*ADmantX 1;
|
||||
~*AhrefsBot 1;
|
||||
~*AIBOT 1;
|
||||
~*aiHitBot 1;
|
||||
~*Alexibot 1;
|
||||
~*Alligator 1;
|
||||
~*AllSubmitter 1;
|
||||
~*AngloINFO 1;
|
||||
~*Antelope 1;
|
||||
~*Apexoo 1;
|
||||
~*asterias 1;
|
||||
~*attach 1;
|
||||
~*BackDoorBot 1;
|
||||
~*BackStreet 1;
|
||||
~*BackWeb 1;
|
||||
~*Badass 1;
|
||||
~*Baid 1;
|
||||
~*Bandit 1;
|
||||
~*BatchFTP 1;
|
||||
~*BBBike 1;
|
||||
~*BeetleBot 1;
|
||||
~*Bigfoot 1;
|
||||
~*billigerbot 1;
|
||||
~*binlar 1;
|
||||
~*bitlybot 1;
|
||||
~*Black.Hole 1;
|
||||
~*BlackWidow 1;
|
||||
~*BLEXBot 1;
|
||||
~*Blow 1;
|
||||
~*BlowFish 1;
|
||||
~*BLP_bbot 1;
|
||||
~*BoardReader 1;
|
||||
~*Bolt\ 0 1;
|
||||
~*BOT\ for\ JCE 1;
|
||||
~*Bot\ mailto\:craftbot@yahoo\.com 1;
|
||||
~*BotALot 1;
|
||||
~*Buddy 1;
|
||||
~*BuiltBotTough 1;
|
||||
~*Bullseye 1;
|
||||
~*BunnySlippers 1;
|
||||
~*casper 1;
|
||||
~*CazoodleBot 1;
|
||||
~*CCBot 1;
|
||||
~*Cegbfeieh 1;
|
||||
~*checkprivacy 1;
|
||||
~*CheeseBot 1;
|
||||
~*CherryPicker 1;
|
||||
~*ChinaClaw 1;
|
||||
~*chromeframe 1;
|
||||
~*Clerkbot 1;
|
||||
~*Cliqzbot 1;
|
||||
~*clshttp 1;
|
||||
~*Cogentbot 1;
|
||||
~*cognitiveseo 1;
|
||||
~*Collector 1;
|
||||
~*CommonCrawler 1;
|
||||
~*comodo 1;
|
||||
~*Copier 1;
|
||||
~*CopyRightCheck 1;
|
||||
~*cosmos 1;
|
||||
~*CPython 1;
|
||||
~*crawler4j 1;
|
||||
~*Crawlera 1;
|
||||
~*CRAZYWEBCRAWLER 1;
|
||||
~*Crescent 1;
|
||||
~*CSHttp 1;
|
||||
~*Curious 1;
|
||||
~*Curl 1;
|
||||
~*Custo 1;
|
||||
~*CWS_proxy 1;
|
||||
~*Default\ Browser\ 0 1;
|
||||
~*Demon 1;
|
||||
~*DeuSu 1;
|
||||
~*Devil 1;
|
||||
~*diavol 1;
|
||||
~*DigExt 1;
|
||||
~*Digincore 1;
|
||||
~*DIIbot 1;
|
||||
~*DISCo 1;
|
||||
~*discobot 1;
|
||||
~*DittoSpyder 1;
|
||||
~*DoCoMo 1;
|
||||
~*DotBot 1;
|
||||
~*Download.Demon 1;
|
||||
~*Download.Devil 1;
|
||||
~*Download.Wonder 1;
|
||||
~*Download\ Demo 1;
|
||||
~*dragonfly 1;
|
||||
~*Drip 1;
|
||||
~*DTS.Agent 1;
|
||||
~*EasouSpider 1;
|
||||
~*EasyDL 1;
|
||||
~*ebingbong 1;
|
||||
~*eCatch 1;
|
||||
~*ecxi 1;
|
||||
~*EirGrabber 1;
|
||||
~*Elmer 1;
|
||||
~*EmailCollector 1;
|
||||
~*EmailSiphon 1;
|
||||
~*EmailWolf 1;
|
||||
~*EroCrawler 1;
|
||||
~*Exabot 1;
|
||||
~*ExaleadCloudView 1;
|
||||
~*ExpertSearch 1;
|
||||
~*ExpertSearchSpider 1;
|
||||
~*Express 1;
|
||||
~*Express\ WebPictures 1;
|
||||
~*extract 1;
|
||||
~*Extractor 1;
|
||||
~*ExtractorPro 1;
|
||||
~*EyeNetIE 1;
|
||||
~*Ezooms 1;
|
||||
~*F2S 1;
|
||||
~*FastSeek 1;
|
||||
~*feedfinder 1;
|
||||
~*FeedlyBot 1;
|
||||
~*FHscan 1;
|
||||
~*finbot 1;
|
||||
~*Flamingo_SearchEngine 1;
|
||||
~*FlappyBot 1;
|
||||
~*FlashGet 1;
|
||||
~*flicky 1;
|
||||
~*Flipboard 1;
|
||||
~*FlipboardProxy 1;
|
||||
~*flunky 1;
|
||||
~*Foobot 1;
|
||||
~*FrontPage 1;
|
||||
~*g00g1e 1;
|
||||
~*GalaxyBot 1;
|
||||
~*genieo 1;
|
||||
~*Genieo 1;
|
||||
~*GetRight 1;
|
||||
~*GetWeb\! 1;
|
||||
~*GigablastOpenSource 1;
|
||||
~*Go\-Ahead\-Got\-It 1;
|
||||
~*Go\!Zilla 1;
|
||||
~*gotit 1;
|
||||
~*GozaikBot 1;
|
||||
~*grab 1;
|
||||
~*Grabber 1;
|
||||
~*GrabNet 1;
|
||||
~*Grafula 1;
|
||||
~*GrapeshotCrawler 1;
|
||||
~*GT\:\:WWW 1;
|
||||
~*GTB5 1;
|
||||
~*Guzzle 1;
|
||||
~*harvest 1;
|
||||
~*Harvest 1;
|
||||
~*HEADMasterSEO 1;
|
||||
~*heritrix 1;
|
||||
~*hloader 1;
|
||||
~*HMView 1;
|
||||
~*HomePageBot 1;
|
||||
~*htmlparser 1;
|
||||
~*HTTP\:\:Lite 1;
|
||||
~*httrack 1;
|
||||
~*HTTrack 1;
|
||||
~*HubSpot 1;
|
||||
~*humanlinks 1;
|
||||
~*ia_archiver 1;
|
||||
~*icarus6 1;
|
||||
~*id\-search 1;
|
||||
~*IDBot 1;
|
||||
~*IlseBot 1;
|
||||
~*Image.Stripper 1;
|
||||
~*Image.Sucker 1;
|
||||
~*Image\ Stripper 1;
|
||||
~*Image\ Sucker 1;
|
||||
~*imagefetch 1;
|
||||
~*Indigonet 1;
|
||||
~*Indy\ Library 1;
|
||||
~*InfoNaviRobot 1;
|
||||
~*InfoTekies 1;
|
||||
~*integromedb 1;
|
||||
~*Intelliseek 1;
|
||||
~*InterGET 1;
|
||||
~*Internet\ Ninja 1;
|
||||
~*InternetSeer\.com 1;
|
||||
~*Iria 1;
|
||||
~*IRLbot 1;
|
||||
~*ISC\ Systems\ iRc\ Search\ 2\.1 1;
|
||||
~*jakarta 1;
|
||||
~*Jakarta 1;
|
||||
~*Java 1;
|
||||
~*JennyBot 1;
|
||||
~*JetCar 1;
|
||||
~*JikeSpider 1;
|
||||
~*JobdiggerSpider 1;
|
||||
~*JOC 1;
|
||||
~*JOC\ Web\ Spider 1;
|
||||
~*Jooblebot 1;
|
||||
~*JustView 1;
|
||||
~*Jyxobot 1;
|
||||
~*kanagawa 1;
|
||||
~*Kenjin.Spider 1;
|
||||
~*Keyword.Density 1;
|
||||
~*KINGSpider 1;
|
||||
~*kmccrew 1;
|
||||
~*larbin 1;
|
||||
~*LeechFTP 1;
|
||||
~*LeechGet 1;
|
||||
~*LexiBot 1;
|
||||
~*lftp 1;
|
||||
~*libWeb 1;
|
||||
~*libwww 1;
|
||||
~*libwww-perl 1;
|
||||
~*likse 1;
|
||||
~*Lingewoud 1;
|
||||
~*LinkChecker 1;
|
||||
~*linkdexbot 1;
|
||||
~*LinkextractorPro 1;
|
||||
~*LinkScan 1;
|
||||
~*LinksCrawler 1;
|
||||
~*LinksManager\.com_bot 1;
|
||||
~*linkwalker 1;
|
||||
~*LinkWalker 1;
|
||||
~*LinqiaRSSBot 1;
|
||||
~*LivelapBot 1;
|
||||
~*LNSpiderguy 1;
|
||||
~*ltx71 1;
|
||||
~*LubbersBot 1;
|
||||
~*lwp\-trivial 1;
|
||||
~*Mag-Net 1;
|
||||
~*Magnet 1;
|
||||
~*Mail.RU_Bot 1;
|
||||
~*majestic12 1;
|
||||
~*MarkWatch 1;
|
||||
~*Mass.Downloader 1;
|
||||
~*Mass\ Downloader 1;
|
||||
~*masscan 1;
|
||||
~*Mata.Hari 1;
|
||||
~*maverick 1;
|
||||
~*Maxthon$ 1;
|
||||
~*Mediatoolkitbot 1;
|
||||
~*megaindex 1;
|
||||
~*MegaIndex 1;
|
||||
~*Memo 1;
|
||||
~*MetaURI 1;
|
||||
~*MFC_Tear_Sample 1;
|
||||
~*Microsoft\ URL\ Control 1;
|
||||
~*microsoft\.url 1;
|
||||
~*MIDown\ tool 1;
|
||||
~*MIIxpc 1;
|
||||
~*miner 1;
|
||||
~*Missigua\ Locator 1;
|
||||
~*Mister\ PiX 1;
|
||||
~*MJ12bot 1;
|
||||
~*Mozilla.*Indy 1;
|
||||
~*Mozilla.*NEWT 1;
|
||||
~*MSFrontPage 1;
|
||||
~*MSIECrawler 1;
|
||||
~*msnbot 1;
|
||||
~*NAMEPROTECT 1;
|
||||
~*Navroad 1;
|
||||
~*NearSite 1;
|
||||
~*Net\ Vampire 1;
|
||||
~*NetAnts 1;
|
||||
~*Netcraft 1;
|
||||
~*netEstate 1;
|
||||
~*NetMechanic 1;
|
||||
~*NetSpider 1;
|
||||
~*NetZIP 1;
|
||||
~*NextGenSearchBot 1;
|
||||
~*NICErsPRO 1;
|
||||
~*niki\-bot 1;
|
||||
~*NimbleCrawler 1;
|
||||
~*Nimbostratus\-Bot 1;
|
||||
~*Ninja 1;
|
||||
~*nmap 1;
|
||||
~*Nmap 1;
|
||||
~*NPbot 1;
|
||||
~*nutch 1;
|
||||
~*Octopus 1;
|
||||
~*Offline\.Explorer 1;
|
||||
~*Offline\.Navigator 1;
|
||||
~*Offline\ Explorer 1;
|
||||
~*Offline\ Navigator 1;
|
||||
~*Openfind 1;
|
||||
~*OpenindexSpider 1;
|
||||
~*OpenLinkProfiler 1;
|
||||
~*OpenWebSpider 1;
|
||||
~*OrangeBot 1;
|
||||
~*OutfoxBot 1;
|
||||
~*Owlin 1;
|
||||
~*PageGrabber 1;
|
||||
~*PagesInventory 1;
|
||||
~*panopta 1;
|
||||
~*panscient\.com 1;
|
||||
~*Papa\ Foto 1;
|
||||
~*pavuk 1;
|
||||
~*pcBrowser 1;
|
||||
~*PECL\:\:HTTP 1;
|
||||
~*PeoplePal 1;
|
||||
~*Photon 1;
|
||||
~*PHPCrawl 1;
|
||||
~*Pixray 1;
|
||||
~*planetwork 1;
|
||||
~*PleaseCrawl 1;
|
||||
~*PNAMAIN\.EXE 1;
|
||||
~*Pockey 1;
|
||||
~*PodcastPartyBot 1;
|
||||
~*prijsbest 1;
|
||||
~*probethenet 1;
|
||||
~*ProPowerBot 1;
|
||||
~*ProWebWalker 1;
|
||||
~*proximic 1;
|
||||
~*psbot 1;
|
||||
~*Pump 1;
|
||||
~*purebot 1;
|
||||
~*pycurl 1;
|
||||
~*python\-requests 1;
|
||||
~*QueryN\.Metasearch 1;
|
||||
~*QuerySeekerSpider 1;
|
||||
~*R6_CommentReader 1;
|
||||
~*R6_FeedFetcher 1;
|
||||
~*RealDownload 1;
|
||||
~*Reaper 1;
|
||||
~*Recorder 1;
|
||||
~*ReGet 1;
|
||||
~*RepoMonkey 1;
|
||||
~*Riddler 1;
|
||||
~*Ripper 1;
|
||||
~*Rippers\ 0 1;
|
||||
~*RMA 1;
|
||||
~*rogerbot 1;
|
||||
~*RSSingBot 1;
|
||||
~*rv\:1\.9\.1 1;
|
||||
~*RyzeCrawler 1;
|
||||
~*SafeSearch 1;
|
||||
~*SBIder 1;
|
||||
~*scanbot 1;
|
||||
~*Scrapy 1;
|
||||
~*Screaming 1;
|
||||
~*SeaMonkey$ 1;
|
||||
~*search_robot 1;
|
||||
~*SearchmetricsBot 1;
|
||||
~*Semrush 1;
|
||||
~*SemrushBot 1;
|
||||
~*semrush\.com 1;
|
||||
~*SemrushBot-BA 1;
|
||||
~*SentiBot 1;
|
||||
~*SEOkicks 1;
|
||||
~*SEOkicks\-Robot 1;
|
||||
~*seoscanners 1;
|
||||
~*SeznamBot 1;
|
||||
~*ShowyouBot 1;
|
||||
~*SightupBot 1;
|
||||
~*Siphon 1;
|
||||
~*SISTRIX 1;
|
||||
~*sitecheck\.internetseer\.com 1;
|
||||
~*siteexplorer\.info 1;
|
||||
~*Siteimprove 1;
|
||||
~*SiteSnagger 1;
|
||||
~*SiteSucker 1;
|
||||
~*skygrid 1;
|
||||
~*Slackbot 1;
|
||||
~*Slurp 1;
|
||||
~*SlySearch 1;
|
||||
~*SmartDownload 1;
|
||||
~*Snake 1;
|
||||
~*Snapbot 1;
|
||||
~*Snoopy 1;
|
||||
~*sogou 1;
|
||||
~*Sogou 1;
|
||||
~*Sosospider 1;
|
||||
~*SpaceBison 1;
|
||||
~*SpankBot 1;
|
||||
~*spanner 1;
|
||||
~*spaumbot 1;
|
||||
~*spbot 1;
|
||||
~*Spinn4r 1;
|
||||
~*Sqworm 1;
|
||||
~*Steeler 1;
|
||||
~*Stripper 1;
|
||||
~*sucker 1;
|
||||
~*Sucker 1;
|
||||
~*SuperBot 1;
|
||||
~*Superfeedr 1;
|
||||
~*SuperHTTP 1;
|
||||
~*SurdotlyBot 1;
|
||||
~*Surfbot 1;
|
||||
~*suzuran 1;
|
||||
~*Szukacz 1;
|
||||
~*tAkeOut 1;
|
||||
~*Teleport 1;
|
||||
~*Teleport\ Pro 1;
|
||||
~*Telesoft 1;
|
||||
~*The\.Intraformant 1;
|
||||
~*TheNomad 1;
|
||||
~*TightTwatBot 1;
|
||||
~*TinEye 1;
|
||||
~*TinEye\-bot 1;
|
||||
~*Titan 1;
|
||||
~*Toata\ dragostea\ mea\ pentru\ diavola 1;
|
||||
~*Toplistbot 1;
|
||||
~*trendictionbot 1;
|
||||
~*trovitBot 1;
|
||||
~*True_Robot 1;
|
||||
~*turingos 1;
|
||||
~*turnit 1;
|
||||
~*TurnitinBot 1;
|
||||
~*Twitterbot 1;
|
||||
~*URI\:\:Fetch 1;
|
||||
~*urllib 1;
|
||||
~*URLy\.Warning 1;
|
||||
~*Vacuum 1;
|
||||
~*Vagabondo 1;
|
||||
~*VCI 1;
|
||||
~*VidibleScraper 1;
|
||||
~*vikspider 1;
|
||||
~*VoidEYE 1;
|
||||
~*VoilaBot 1;
|
||||
~*WallpapersHD 1;
|
||||
~*WBSearchBot 1;
|
||||
~*Web.Image.Collector 1;
|
||||
~*Web\ Image\ Collector 1;
|
||||
~*Web\ Sucker 1;
|
||||
~*webalta 1;
|
||||
~*WebAuto 1;
|
||||
~*WebBandit 1;
|
||||
~*WebCollage 1;
|
||||
~*WebCopier 1;
|
||||
~*WebEnhancer 1;
|
||||
~*WebFetch 1;
|
||||
~*WebFuck 1;
|
||||
~*WebGo\ IS 1;
|
||||
~*WebLeacher 1;
|
||||
~*WebmasterWorldForumBot 1;
|
||||
~*WebPix 1;
|
||||
~*WebReaper 1;
|
||||
~*WebSauger 1;
|
||||
~*WebShag 1;
|
||||
~*Website\.eXtractor 1;
|
||||
~*Website\ eXtractor 1;
|
||||
~*Website\ Quester 1;
|
||||
~*Webster 1;
|
||||
~*WebStripper 1;
|
||||
~*WebSucker 1;
|
||||
~*WebWhacker 1;
|
||||
~*WebZIP 1;
|
||||
~*Wells\ Search\ II 1;
|
||||
~*WEP\ Search 1;
|
||||
~*WeSEE 1;
|
||||
~*Wget 1;
|
||||
~*Whack 1;
|
||||
~*Whacker 1;
|
||||
~*Widow 1;
|
||||
~*WinHTTrack 1;
|
||||
~*WinInet 1;
|
||||
~*WISENutbot 1;
|
||||
~*woobot 1;
|
||||
~*woopingbot 1;
|
||||
~*worldwebheritage.org 1;
|
||||
~*Wotbox 1;
|
||||
~*WPScan 1;
|
||||
~*WWW\-Collector\-E 1;
|
||||
~*WWW\-Mechanize 1;
|
||||
~*WWWOFFLE 1;
|
||||
~*Xaldon 1;
|
||||
~*Xaldon\ WebSpider 1;
|
||||
~*Xenu 1;
|
||||
~*XoviBot 1;
|
||||
~*yacybot 1;
|
||||
~*YisouSpider 1;
|
||||
~*Zade 1;
|
||||
~*zermelo 1;
|
||||
~*Zeus 1;
|
||||
~*zh\-CN 1;
|
||||
~*ZmEu 1;
|
||||
~*ZumBot 1;
|
||||
~*Zyborg 1;
|
||||
~*ZyBorg 1;
|
||||
~*Yandex 1;
|
||||
~*YandexBot 1;
|
||||
~*Baiduspider 1;
|
||||
~*BaiduSpider 1;
|
||||
~*Slackbot 1;
|
||||
}
|
||||
|
||||
map $http_user_agent $bad_bot1 {
|
||||
default 0;
|
||||
~*^Lynx 0; # Let Lynx go through
|
||||
libwww-perl 1;
|
||||
~*(?i)(80legs|360Spider|Aboundex|AhrefsBot|Daumoa|DataForSeoBot|DaumBot|applebot|BLEXBot|serpstatbot|MediaMathbot|Abonti|Acunetix|^AIBOT|^Alexibot|Alligator|AllSubmitter|Apexoo|^asterias|^attach|^BackDoorBot|^BackStreet|^BackWeb|Badass|Bandit|petalbot|Baid|Baiduspider|^BatchFTP|^Bigfoot|^Black.Hole|^BlackWidow|BlackWidow|^BlowFish|Blow|^BotALot|Buddy|^BuiltBotTough|^Bullseye|^BunnySlippers|BBBike|^Cegbfeieh|^CheeseBot|^CherryPicker|^ChinaClaw|^Cogentbot|CPython|Collector|cognitiveseo|Copier|^CopyRightCheck|^cosmos|^Crescent|CSHttp|^Custo|^Demon|^Devil|^DISCo|^DIIbot|discobot|^DittoSpyder|Download.Demon|Download.Devil|Download.Wonder|^dragonfly|^Drip|^eCatch|^EasyDL|^ebingbong|^EirGrabber|^EmailCollector|^EmailSiphon|^EmailWolf|^EroCrawler|^Exabot|^Express|Extractor|^EyeNetIE|FHscan|^FHscan|^flunky|^Foobot|^FrontPage|GalaxyBot|^gotit|Grabber|^GrabNet|^Grafula|^Harvest|^HEADMasterSEO|^hloader|^HMView|^HTTrack|httrack|HTTrack|htmlparser|^humanlinks|^IlseBot|Image.Stripper|Image.Sucker|imagefetch|^InfoNaviRobot|^InfoTekies|^Intelliseek|^InterGET|^Iria|^Jakarta|^JennyBot|^JetCar|JikeSpider|^JOC|^JustView|^Jyxobot|^Kenjin.Spider|^Keyword.Density|libwww|^larbin|LeechFTP|LeechGet|^LexiBot|^lftp|^libWeb|^likse|^LinkextractorPro|^LinkScan|^LNSpiderguy|^LinkWalker|msnbot|MSIECrawler|MJ12bot|MegaIndex|^Magnet|^Mag-Net|^MarkWatch|Mass.Downloader|masscan|^Mata.Hari|^Memo|^MIIxpc|^NAMEPROTECT|^Navroad|^NearSite|^NetAnts|^Netcraft|^NetMechanic|^NetSpider|^NetZIP|^NextGenSearchBot|^NICErsPRO|^niki-bot|^NimbleCrawler|^Nimbostratus-Bot|^Ninja|^Nmap|nmap|^NPbot|Offline.Explorer|Offline.Navigator|OpenLinkProfiler|^Octopus|^Openfind|^OutfoxBot|Pixray|probethenet|proximic|^PageGrabber|^pavuk|^pcBrowser|^Pockey|^ProPowerBot|^ProWebWalker|^psbot|^Pump|python-requests|^QueryN.Metasearch|^RealDownload|Reaper|^Reaper|^Ripper|Ripper|Recorder|^ReGet|^RepoMonkey|^RMA|scanbot|SEOkicks-Robot|seoscanners|^Stripper|^Sucker|Siphon|Siteimprove|^SiteSnagger|SiteSucker|^SlySearch|^SmartDownload|^Snake|^Snapbot|^Snoopy|Sosospider|^sogou|spbot|^SpaceBison|^spanner|^SpankBot|Spinn4r|^Sqworm|Sqworm|Stripper|Sucker|^SuperBot|SuperHTTP|^SuperHTTP|^Surfbot|^suzuran|^Szukacz|^tAkeOut|^Teleport|^Telesoft|^TurnitinBot|^The.Intraformant|^TheNomad|^TightTwatBot|^Titan|^True_Robot|^turingos|^TurnitinBot|^URLy.Warning|^Vacuum|^VCI|VidibleScraper|^VoidEYE|^WebAuto|^WebBandit|^WebCopier|^WebEnhancer|^WebFetch|^Web.Image.Collector|^WebLeacher|^WebmasterWorldForumBot|WebPix|^WebReaper|^WebSauger|Website.eXtractor|^Webster|WebShag|^WebStripper|WebSucker|^WebWhacker|^WebZIP|Whack|Whacker|^Widow|Widow|WinHTTrack|^WISENutbot|WWWOFFLE|^WWWOFFLE|^WWW-Collector-E|^Xaldon|^Xenu|^Zade|^Zeus|ZmEu|^Zyborg|SemrushBot|^WebFuck|^MJ12bot|^majestic12|^WallpapersHD) 1;
|
||||
}
|
||||
|
||||
## Add here all referrers that are to blocked.
|
||||
map $http_referer $bad_referer {
|
||||
default 0;
|
||||
~(?i)(adcash|advair|allegra|ambien|amoxicillin|adult|anal|asshole|babes|baccarat|betting|bithack|blackjack|cash|casino|celeb|cheap|cialis|craps|credit|click|cunt|deal|debt|drug|diamond|effexor|equity|faxo|finance|fisting|forsale|gambling|gaysex|girl|hardcore|hold-em|holdem|iconsurf|ilovevitaly|insurance|interest|internetsupervision|jewelry|keno|levitra|lipitor|loan|loans|love|makemoneyonline|make-money-online|meds|money|mortgage|myftpupload|nudit|omaha|organic|paxil|pharmacy|pharmacies|phentermine|pheromone|pills|piss|poker|porn|poweroversoftware|refinance|replica|rimming|roulette|screentoolkit|seoexperimenty|sex|snuff|scout|seventwentyfour|slot|slots|syntryx|teen|texas|t0phackteam|tournament|tramadol|tramidol|valtrex|vvakhrin-ws1|viagra|vicodin|webcam|xanax|xnxx|xxxrus|zanax|zippo|zoloft) 1;
|
||||
}
|
||||
|
||||
## Add here all bad referer domains to be blocked - broken up into sections
|
||||
## Alphabetical A - E (incl numbers)
|
||||
map $http_referer $bad_urls1 {
|
||||
default 0;
|
||||
~(?i)(^http://(www\.)?38ha(-|.).*$|^http://(www\.)?4free(-|.).*$|^http://(www\.)?4hs8(-|.).*$|^http://(www\.)?4t(-|.).*$|^http://(www\.)?4u(-|.).*$|^http://(www\.)?6q(-|.).*$|^http://(www\.)?7makemoneyonline(-|.).*$|^http://(www\.)?8gold(-|.).*$|^http://(www\.)?911(-|.).*$|^http://(www\.)?adcash(-|.).*$|^http://(www\.)?.*(-|.)?adult(-|.).*$|^http://(www\.)?.*(-|.)?acunetix-referrer(-|.).*$|^http://(www\.)?abalone(-|.).*$|^http://(www\.)?adminshop(-|.).*$|^http://(www\.)?adultactioncam(-|.).*$|^http://(www\.)?aizzo(-|.).*$|^http://(www\.)?alphacarolinas(-|.).*$|^http://(www\.)?amateur(-|.).*$|^http://(www\.)?amateurxpass(-|.).*$|^http://(www\.)?.*(-|.)?anal(-|.).*$|^http://(www\.)?ansar-u-deen(-|.).*$|^http://(www\.)?atelebanon(-|.).*$|^http://(www\.)?beastiality(-|.).*$|^http://(www\.)?bestiality(-|.).*$|^http://(www\.)?belize(-|.).*$|^http://(www\.)?best-deals(-|.).*$|^http://(www\.)?bithack(-|.).*$|^http://(www\.)?blogincome(-|.).*$|^http://(www\.)?bontril(-|.).*$|^http://(www\.)?bruce-holdeman(-|.).*$|^http://(www\.)?.*(-|.)?blow.?job(-|.).*$|^http://(www\.)?buttons-for-website(-|.).*$|^http://(www\.)?ca-america(-|.).*$|^http://(www\.)?chatt-net(-|.).*$|^http://(www\.)?cenokos(-|.).*$|^http://(www\.)?cenoval(-|.).*$|^http://(www\.)?cityadspix(-|.).*$|^http://(www\.)?commerce(-|.).*$|^http://(www\.)?condo(-|.).*$|^http://(www\.)?conjuratia(-|.).*$|^http://(www\.)?consolidate(-|.).*$|^http://(www\.)?coswap(-|.).*$|^http://(www\.)?crescentarian(-|.).*$|^http://(www\.)?crepesuzette(-|.).*$|^http://(www\.)?darodar(-|.).*$|^http://(www\.)?dating(-|.).*$|^http://(www\.)?devaddict(-|.).*$|^http://(www\.)?discount(-|.).*$|^http://(www\.)?doobu(-|.).*$|^http://(www\.)?domainsatcost(-|.).*$|^http://(www\.)?econom.co(-|.).*$|^http://(www\.)?edakgfvwql(-|.).*$|^http://(www\.)?.*(-|.)?sex(-|.).*$|^http://(www\.)?e-site(-|.).*$|^http://(www\.)?egygift(-|.).*$|^http://(www\.)?empathica(-|.).*$|^http://(www\.)?empirepoker(-|.).*$|^http://(www\.)?e-poker-2005(-|.).*$|^http://(www\.)?escal8(-|.).*$|^http://(www\.)?eurip(-|.).*$|^http://(www\.)?exitq(-|.).*$|^http://(www\.)?eyemagination(-|.).*$) 1;
|
||||
}
|
||||
## F - I
|
||||
map $http_referer $bad_urls2 {
|
||||
default 0;
|
||||
~(?i)(^http://(www\.)?fastcrawl(-|.).*$|^http://(www\.)?fearcrow(-|.).*$|^http://(www\.)?ferretsoft(-|.).*$|^http://(www\.)?fick(-|.).*$|^http://(www\.)?finance(-|.).*$|^http://(www\.)?flafeber(-|.).*$|^http://(www\.)?fidelityfunding(-|.).*$|^http://(www\.)?freakycheats(-|.).*$|^http://(www\.)?freeality(-|.).*$|^http://(www\.)?fuck(-|.).*$|^http://(www\.)?future-2000(-|.).*$|^http://(www\.)?.*(-|.)?gay(-|.).*$|^http://(www\.)?gobongo.info(-|.).*$|^http://(www\.)?gabriola(-|.).*$|^http://(www\.)?gallerylisting(-|.).*$|^http://(www\.)?gb.com(-|.).*$|^http://(www\.)?ghostvisitor(-|.).*$|^http://(www\.)?globusy(-|.).*$|^http://(www\.)?golf-e-course(-|.).*$|^http://(www\.)?gospelcom(-|.).*$|^http://(www\.)?gradfinder(-|.).*$|^http://(www\.)?hasfun(-|.).*$|^http://(www\.)?herbal(-|.).*$|^http://(www\.)?hermosa(-|.).*$|^http://(www\.)?highprofitclub(-|.).*$|^http://(www\.)?hilton(-|.).*$|^http://(www\.)?teaminspection(-|.).*$|^http://(www\.)?hotel(-|.).*$|^http://(www\.)?houseofseven(-|.).*$|^http://(www\.)?hurricane(-|.).*$|^http://(www\.)?.*(-|.)?incest(-|.).*$|^http://(www\.)?iaea(-|.).*$|^http://(www\.)?ilovevitality(-|.).*$|^http://(www\.)?ime(-|.).*$|^http://(www\.)?info(-|.).*$|^http://(www\.)?ingyensms(-|.).*$|^http://(www\.)?inkjet-toner(-|.).*$|^http://(www\.)?isacommie(-|.).*$|^http://(www\.)?istarthere(-|.).*$|^http://(www\.)?it.tt(-|.).*$|^http://(www\.)?italiancharms(-|.).*$|^http://(www\.)?iwantu(-|.).*$|^http://(www\.)?ilovevitality(-|.).*$|^http://(www\.)?iskalko.ru(-|.).*$) 1;
|
||||
}
|
||||
## J - P
|
||||
map $http_referer $bad_urls3 {
|
||||
default 0;
|
||||
~(?i)(^http://(www\.)?jfcadvocacy(-|.).*$|^http://(www\.)?jmhic(-|.).*$|^http://(www\.)?juris(-|.).*$|^http://(www\.)?kylos(-|.).*$|^http://(www\.)?laser-eye(-|.).*$|^http://(www\.)?leathertree(-|.).*$|^http://(www\.)?lillystar(-|.).*$|^http://(www\.)?linkerdome(-|.).*$|^http://(www\.)?livenet(-|.).*$|^http://(www\.)?low-limit(-|.).*$|^http://(www\.)?lowest-price(-|.).*$|^http://(www\.)?luxup.ru(-|.).*$|^http://(www\.)?macsurfer(-|.).*$|^http://(www\.)?mall.uk(-|.).*$|^http://(www\.)?maloylawn(-|.).*$|^http://(www\.)?marketing(-|.).*$|^http://(www\.)?.*(-|.)?mature(-|.).*$|^http://(www\.)?mcdortaklar(-|.).*$|^http://(www\.)?mediavisor(-|.).*$|^http://(www\.)?medications(-|.).*$|^http://(www\.)?mirror.sytes(-|.).*$|^http://(www\.)?mp3(-|.).*$|^http://(www\.)?(-|.)musicbox1(-|.).*$|^http://(www\.)?myftpupload(-|.).*$|^http://(www\.)?naked(-|.).*$|^http://(www\.)?netdisaster(-|.).*$|^http://(www\.)?netfirms(-|.).*$|^http://(www\.)?newtruths(-|.).*$|^http://(www\.)?no-limit(-|.).*$|^http://(www\.)?nude(-|.).*$|^http://(www\.)?nudeceleb(-|.).*$|^http://(www\.)?nutzu(-|.).*$|^http://(www\.)?odge(-|.).*$|^http://(www\.)?oiline(-|.).*$|^http://(www\.)?onlinegamingassoc(-|.).*$|^http://(www\.)?outpersonals(-|.).*$|^http://(www\.)?o-o-6-o-o.ru(-|.).*$|^http://(www\.)?o-o-8-o-o.ru(-|.).*$|^http://(www\.)?pagetwo(-|.).*$|^http://(www\.)?paris(-|.).*$|^http://(www\.)?passions(-|.).*$|^http://(www\.)?peblog(-|.).*$|^http://(www\.)?peng(-|.).*$|^http://(www\.)?perfume-cologne(-|.).*$|^http://(www\.)?personal(-|.).*$|^http://(www\.)?php-soft(-|.).*$|^http://(www\.)?pisoc(-|.).*$|^http://(www\.)?pisx(-|.).*$|^http://(www\.)?popwow(-|.).*$|^http://(www\.)?porn(-|.).*$|^http://(www\.)?prescriptions(-|.).*$|^http://(www\.)?priceg(-|.).*$|^http://(www\.)?.*(-|.)?pus*y(-|.).*$|^http://(www\.)?printdirectforless(-|.).*$|^http://(www\.)?ps2cool(-|.).*$|^http://(www\.)?psnarones(-|.).*$|^http://(www\.)?psxtreme(-|.).*$) 1;
|
||||
}
|
||||
## Q - Z
|
||||
map $http_referer $bad_urls4 {
|
||||
default 0;
|
||||
~(?i)(^http://(www\.)?quality-traffic(-|.).*$|^http://(www\.)?registrarprice(-|.).*$|^http://(www\.)?reliableresults(-|.).*$|^http://(www\.)?rimpim(-|.).*$|^http://(www\.)?ro7kalbe(-|.).*$|^http://(www\.)?rohkalby(-|.).*$|^http://(www\.)?ronnieazza(-|.).*$|^http://(www\.)?rulo.biz(-|.).*$|^http://(www\.)?responsinator(-|.).*$|^http://(www\.)?s5(-|.).*$|^http://(www\.)?samiuls(-|.).*$|^http://(www\.)?savefrom(-|.).*$|^http://(www\.)?savetubevideo.com(-|.).*$|^http://(www\.)?screentoolkit.com(-|.).*$|^http://(www\.)?searchedu(-|.).*$|^http://(www\.)?semalt.com(-|.).*$|^http://(www\.)?seoexperimenty(-|.).*$|^http://(www\.)?seventwentyfour(-|.).*$|^http://(www\.)?seventwentyfour.*$|^http://(www\.)?sex(-|.).*$|^http://(www\.)?sexsearch(-|.).*$|^http://(www\.)?sexsq(-|.).*$|^http://(www\.)?shoesdiscount(-|.).*$|^http://(www\.)?site-4u(-|.).*$|^http://(www\.)?site5(-|.).*$|^http://(www\.)?slatersdvds(-|.).*$|^http://(www\.)?slftsdybbg.ru(-|.).*$|^http://(www\.)?sml338(-|.).*$|^http://(www\.)?sms(-|.).*$|^http://(www\.)?smsportali(-|.).*$|^http://(www\.)?socialseet.ru(-|.).*$|^http://(www\.)?software(-|.).*$|^http://(www\.)?sortthemesitesby(-|.).*$|^http://(www\.)?spears(-|.).*$|^http://(www\.)?spoodles(-|.).*$|^http://(www\.)?sportsparent(-|.).*$|^http://(www\.)?srecorder(-|.).*$|^http://(www\.)?stmaryonline(-|.).*$|^http://(www\.)?superiends.org(-|.).*$|^http://(www\.)?strip(-|.).*$|^http://(www\.)?suttonjames(-|.).*$|^http://(www\.)?talk.uk-yankee(-|.).*$|^http://(www\.)?tecrep-inc(-|.).*$|^http://(www\.)?teen(-|.).*$|^http://(www\.)?terashells(-|.).*$|^http://(www\.)?thatwhichis(-|.).*$|^http://(www\.)?thorcarlson(-|.).*$|^http://(www\.)?.*(-|.)?tits(-|.).*$|^http://(www\.)?.*(-|.)?titten(-|.).*$|^http://(www\.)?tmsathai(-|.).*$|^http://(www\.)?traffixer(-|.).*$|^http://(www\.)?tranny(-|.).*$|^http://(www\.)?valeof(-|.).*$|^http://(www\.)?video(-|.).*$|^http://(www\.)?vinhas(-|.).*$|^http://(www\.)?vixen1(-|.).*$|^http://(www\.)?vpshs(-|.).*$|^http://(www\.)?vrajitor(-|.).*$|^http://(www\.)?vodkoved.ru(-|.).*$|^http://(www\.)?w3md(-|.).*$|^http://(www\.)?websocial.me(-|.).*$|^http://(www\.)?webdevsquare(-|.).*$|^http://(www\.)?whois(-|.).*$|^http://(www\.)?withdrawal(-|.).*$|^http://(www\.)?worldemail(-|.).*$|^http://(www\.)?wslp24(-|.).*$|^http://(www\.)?ws-op(-|.).*$|^http://(www\.)?xnxx(-|.).*$|^http://(www\.)?xopy(-|.).*$|^http://(www\.)?xxx(-|.).*$|^http://(www\.)?yelucie(-|.).*$|^http://(www\.)?youradulthosting(-|.).*$|^http://(www\.)?ykecwqlixx.ru(-|.).*$|^http://(www\.)?yougetsignal.com(-|.).*$|^http://(www\.)?(-|.)zindagi(-|.).*$) 1;
|
||||
}
|
||||
## Domains Linked to Yontoo Browser Malware and a Few Other New Ones
|
||||
## Have split this into it's own section to keep lines shorter NOTE: changes to instructions
|
||||
## adding if ($bad_urls5) and if ($bad_urls6) to your site(s) config.
|
||||
map $http_referer $bad_urls5 {
|
||||
default 0;
|
||||
~(?i)(^http://(www\.)?101raccoon.ru(-|.).*$|^http://(www\.)?28n2gl3wfyb0.ru(-|.).*$|^http://(www\.)?627ad6438b58439cad1fc8cf6d67a92e.com(-|.).*$|^http://(www\.)?6ab9743d0152486387559b4abaa02ada.com(-|.).*$|^http://(www\.)?a342ae9750004b14b55f7310eff0ab65.com(-|.).*$|^http://(www\.)?aa08daf7e13b6345e09e92f771507fa5f4.com(-|.).*$|^http://(www\.)?aa14ab57a3339c4064bd9ae6fad7495b5f.com(-|.).*$|^http://(www\.)?aa625d84f1587749c1ab011d6f269f7d64.com(-|.).*$|^http://(www\.)?aa81bf391151884adfa3dd677e41f94be1.com(-|.).*$|^http://(www\.)?aa8780bb28a1de4eb5bff33c28a218a930.com(-|.).*$|^http://(www\.)?aa8b68101d388c446389283820863176e7.com(-|.).*$|^http://(www\.)?aa9bd78f328a6a41279d0fad0a88df1901.com(-|.).*$|^http://(www\.)?aa9d046aab36af4ff182f097f840430d51.com(-|.).*$|^http://(www\.)?aaa38852e886ac4af1a3cff9b47cab6272.com(-|.).*$|^http://(www\.)?aab94f698f36684c5a852a2ef272e031bb.com(-|.).*$|^http://(www\.)?aac500b7a15b2646968f6bd8c6305869d7.com(-|.).*$|^http://(www\.)?aac52006ec82a24e08b665f4db2b5013f7.com(-|.).*$|^http://(www\.)?aad1f4acb0a373420d9b0c4202d38d94fa.com(-|.).*$|^http://(www\.)?asrv-a.akamoihd.net(-|.).*$|^http://(www\.)?asrvrep-a.akamaihd.net(-|.).*$|^http://(www\.)?bestpriceninja.com(-|.).*$|^http://(www\.)?bronzeaid-a.akamaihd.net(-|.).*$|^http://(www\.)?browsepulse-a.akamaihd.net(-|.).*$|^http://(www\.)?cashkitten-a.akamaihd.net(-|.).*$|^http://(www\.)?coolbar.pro(-|.).*$) 1;
|
||||
}
|
||||
map $http_referer $bad_urls6 {
|
||||
default 0;
|
||||
~(?i)(^http://(www\.)?davebestdeals.com(-|.).*$|^http://(www\.)?discovertreasure-a.akamaihd.net(-|.).*$|^http://(www\.)?discovertreasurenow.com(-|.).*$|^http://(www\.)?foxydeal.com(-|.).*$|^http://(www\.)?gameonasia.com(-|.).*$|^http://(www\.)?gameplexcity.com(-|.).*$|^http://(www\.)?gamerextra.com(-|.).*$|^http://(www\.)?gamerscorps.com(-|.).*$|^http://(www\.)?gamewrath.com(-|.).*$|^http://(www\.)?generousdeal-a.akamaihd.net(-|.).*$|^http://(www\.)?girlgamerdaily.com(-|.).*$|^http://(www\.)?hdapp1008-a.akamaihd.net(-|.).*$|^http://(www\.)?highstairs-a.akamaihd.net(-|.).*$|^http://(www\.)?hotshoppymac.com(-|.).*$|^http://(www\.)?matchpal-a.akamaihd.net(-|.).*$|^http://(www\.)?mecash.ru(-|.).*$|^http://(www\.)?monarchfind-a.akamaihd.net(-|.).*$|^http://(www\.)?myshopmatemac.com(-|.).*$|^http://(www\.)?nottyu.xyz(-|.).*$|^http://(www\.)?onlinemegax.com(-|.).*$|^http://(www\.)?outrageousdeal-a.akamaihd.net(-|.).*$|^http://(www\.)?pijoto.net(-|.).*$|^http://(www\.)?recordpage-a.akamaihd.net(-|.).*$|^http://(www\.)?resultshub-a.akamaihd.net(-|.).*$|^http://(www\.)?rvzr-a.akamaihd.net(-|.).*$|^http://(www\.)?savingsslider-a.akamaihd.net(-|.).*$|^http://(www\.)?searchinterneat-a.akamaihd.net(-|.).*$|^http://(www\.)?searchwebknow-a.akamaihd.net(-|.).*$|^http://(www\.)?seeresultshub-a.akamaihd.net(-|.).*$|^http://(www\.)?shoppytoolmac.com(-|.).*$|^http://(www\.)?skytraf.xyz(-|.).*$|^http://(www\.)?splendorsearch-a.akamaihd.net(-|.).*$|^http://(www\.)?strongsignal-a.akamaihd.net(-|.).*$|^http://(www\.)?surfbuyermac.com(-|.).*$|^http://(www\.)?treasuretrack-a.akamaihd.net(-|.).*$|^http://(www\.)?webshoppermac.com(-|.).*$|^http://(www\.)?pospr.waw.pl(-|.).*$|^http://(www\.)?abclauncher.com(-|.).*$|^http://(www\.)?alert-fjg.xyz(-|.).*$|^http://(www\.)?analytics-ads.xyz(-|.).*$|^http://(www\.)?bamo.xsl.pt(-|.).*$|^http://(www\.)?compliance-olga.top(-|.).*$|^http://(www\.)?digital-video-processing.com(-|.).*$|^http://(www\.)?eu-cookie-law.info(-|.).*$|^http://(www\.)?findpik.com(-|.).*$|^http://(www\.)?forum20.smailik.org(-|.).*$|^http://(www\.)?free-share-buttons.top(-|.).*$|^http://(www\.)?free-social-buttons2.xyz(-|.).*$|^http://(www\.)?free-social-buttons3.xyz(-|.).*$|^http://(www\.)?free-social-buttons4.xyz(-|.).*$|^http://(www\.)?free-social-buttons5.xyz(-|.).*$|^http://(www\.)?front.to(-|.).*$|^http://(www\.)?infokonkurs.ru(-|.).*$|^http://(www\.)?mapquestz.us(-|.).*$|^http://(www\.)?quick-offer.com(-|.).*$|^http://(www\.)?rank-checker.online(-|.).*$|^http://(www\.)?rankchecker.online(-|.).*$|^http://(www\.)?rapidokbrain.com(-|.).*$|^http://(www\.)?real-time-analytics.com(-|.).*$|^http://(www\.)?sharebutton.net(-|.).*$|^http://(www\.)?sharebutton.org(-|.).*$|^http://(www\.)?shemale-sex.net(-|.).*$|^http://(www\.)?site-speed-check.site(-|.).*$|^http://(www\.)?site-speed-checker.site(-|.).*$|^http://(www\.)?trafficmania.com(-|.).*$|^http://(www\.)?website-speed-up.site(-|.).*$|^http://(www\.)?website-speed-up.top(-|.).*$|^http://(www\.)?xn--80aagddcgkbcqbad7amllnejg6dya.xn--p1ai(-|.).*$|^http://(www\.)?xn--80aikhbrhr.net(-|.).*$|^http://(www\.)?pila.pl(-|.).*$|^http://(www\.)?dytohqka.su(-|.).*$|^http://(www\.)?fqvjhqciw.net.ru(-|.).*$|^http://(www\.)?wycjrqzy.ua(-|.).*$|^http://(www\.)?0ca29773681c7e82.com(-|.).*$|^http://(www\.)?intervsem.ru(-|.).*$|^http://(www\.)?candy-glam-hp.com(-|.).*$|^http://(www\.)?thecoolimages.net(-|.).*$|^http://(www\.)?rebuildermedical.com(-|.).*$|^http://(www\.)?gaygalls.net(-|.).*$|^http://(www\.)?keywordteam.net(-|.).*$|^http://(www\.)?netfacet.net(-|.).*$|^http://(www\.)?pattersonsweb.com(-|.).*$|^http://(www\.)?trapit.com.gg(-|.).*$) 1;
|
||||
}
|
||||
## Add here all hosts that should be spared any referrer checking.
|
||||
## Whitelist all your own IPs in this section, each IP followed by a 0;
|
||||
geo $bad_referer {
|
||||
127.0.0.1 0;
|
||||
111.111.111.111 0;
|
||||
}
|
||||
|
||||
# Geo directive to deny certain ip addresses
|
||||
geo $validate_client {
|
||||
default 0;
|
||||
|
||||
# Cyveillance
|
||||
38.100.19.8/29 1;
|
||||
38.100.21.0/24 1;
|
||||
38.100.41.64/26 1;
|
||||
38.105.71.0/25 1;
|
||||
38.105.83.0/27 1;
|
||||
38.112.21.140/30 1;
|
||||
38.118.42.32/29 1;
|
||||
65.213.208.128/27 1;
|
||||
65.222.176.96/27 1;
|
||||
65.222.185.72/29 1;
|
||||
85.25.176.0/20 1;
|
||||
85.25.192.0/20 1;
|
||||
85.25.208.0/22 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# ip access drop
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
return 444;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
server {
|
||||
listen 80;
|
||||
server_name localhost www.localhost;
|
||||
|
||||
access_log /log/nginx/django_sample.com.access.log main;
|
||||
error_log /log/nginx/django_sample.com.error.log warn;
|
||||
|
||||
# Django media
|
||||
location /media {
|
||||
gzip_static on;
|
||||
expires max;
|
||||
#alias /www/django_sample/django_sample/media;
|
||||
alias /www/django_sample/media; # your Django project's media files - amend as required
|
||||
#include /etc/nginx/mime.types;
|
||||
}
|
||||
|
||||
location /static {
|
||||
gzip_static on;
|
||||
expires max;
|
||||
#alias /www/django_sample/django_sample/static;
|
||||
# normally static folder is named as /static
|
||||
alias /www/django_sample/static; # your Django project's static files - amend as required
|
||||
#include /etc/nginx/mime.types;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://gunicorn-app:8000;
|
||||
# proxy_redirect http:// https://;
|
||||
|
||||
}
|
||||
|
||||
# Allow Lets Encrypt Domain Validation Program
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/django_sample;
|
||||
}
|
||||
|
||||
# Block dot file (.htaccess .htpasswd .svn .git .env and so on.)
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Block (log file, binary, certificate, shell script, sql dump file) access.
|
||||
location ~* \.(log|binary|pem|enc|crt|conf|cnf|sql|sh|key|yml|lock)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Block access
|
||||
location ~* (composer\.json|composer\.lock|composer\.phar|contributing\.md|license\.txt|readme\.rst|readme\.md|readme\.txt|copyright|artisan|gulpfile\.js|package\.json|phpunit\.xml|access_log|error_log|gruntfile\.js)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /robots.txt {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
#!/bin/bash
|
||||
|
||||
while :
|
||||
do
|
||||
echo "* if your webroot has sub-level, you should be insert as \\\/A\\\/B\\\/C"
|
||||
echo "ex) shop\\\/django_sample"
|
||||
echo -n "Enter the service web root without the path of '/www/' >"
|
||||
read webroot
|
||||
echo "Entered service web root: $webroot"
|
||||
if [[ "$webroot" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the service portnumber >"
|
||||
read portnumber
|
||||
echo "Entered service portnumber: $portnumber"
|
||||
if [[ "$portnumber" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the service domain >"
|
||||
read domain
|
||||
echo "Entered service domain: $domain"
|
||||
if [[ "$domain" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the app name >"
|
||||
read appname
|
||||
echo "Entered app name: $appname"
|
||||
if [[ "$appname" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Enter the serviceport"
|
||||
echo -n "if you push enter with none, there are no port number >"
|
||||
read serviceport
|
||||
echo "Entered proxy port: $serviceport"
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the file name >"
|
||||
read filename
|
||||
echo "Entered file name: $filename"
|
||||
if [[ "$filename" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
sed 's/webroot/'$webroot'/g' sample_nginx.conf > $filename'1'.temp
|
||||
sed 's/portnumber/'$portnumber'/g' $filename'1'.temp > $filename'2'.temp
|
||||
sed 's/domain/'$domain'/g' $filename'2'.temp > $filename'3'.temp
|
||||
sed 's/appname/'$appname'/g' $filename'3'.temp > $filename'4'.temp
|
||||
if [[ "$serviceport" == "" ]]; then
|
||||
sed 's/:serviceport/''/g' $filename'4'.temp > $filename'5'.temp
|
||||
else
|
||||
sed 's/serviceport/'$serviceport'/g' $filename'4'.temp > $filename'5'.temp
|
||||
fi
|
||||
sed 's/filename/'$filename'/g' $filename'5'.temp > ./conf.d/$filename'_gunicorn_ng'.conf
|
||||
|
||||
rm *.temp
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
user www-data;
|
||||
worker_processes auto;
|
||||
|
||||
# worker_rlimit_nofile directive
|
||||
# CPU: 쿼드코어, RAM: 4GB, 요청수: ~50/s 기반 설정시
|
||||
worker_rlimit_nofile 8192;
|
||||
# worker_rlimit_nofile 8192;
|
||||
# worker_priority 0;
|
||||
# worker_cpu_affinity 0001 0010 0100 1000;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
# Load ModSecurity dynamic module
|
||||
# load_module /etc/nginx/modules/ngx_http_modsecurity_module.so
|
||||
|
||||
events {
|
||||
use epoll; # 리눅스에서 권장
|
||||
accept_mutex on; # 기본값이지만 명시해두면 좋음
|
||||
|
||||
# 단일 워커당 동시 연결 수
|
||||
# worker_processes * worker_connections = 최대 동시 연결 수
|
||||
# 여기에 워커가 상시 쓰는 FD(에러/액세스 로그, 리스닝 소켓, epoll 등) 오버헤드를 조금 빼고 잡아야 안전하다 (약 50~150 정도 버퍼).
|
||||
|
||||
# CPU: 쿼드코어, RAM: 4GB, 요청수: ~50/s 기반 설정시
|
||||
# off 설정에 대한 효과
|
||||
# 부하 분산: 워커 간 균등한 연결 분배
|
||||
# 안정성: 한 워커가 과부하되는 것 방지
|
||||
# 예측 가능한 성능: 일관된 응답 시간
|
||||
multi_accept off;
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/main_access.log main;
|
||||
error_log /var/log/nginx/main_error.log;
|
||||
|
||||
server_tokens off;
|
||||
|
||||
charset utf-8;
|
||||
|
||||
resolver 8.8.8.8 8.8.4.4 valid=300s; # resolver $DNS-IP-1 $DNS-IP-2 valid=300s;
|
||||
resolver_timeout 5s;
|
||||
|
||||
# 기본 헤더 버퍼 (대부분의 요청 처리)
|
||||
client_header_buffer_size 4k;
|
||||
|
||||
# 큰 헤더 버퍼 (JWT, 큰 쿠키 등)
|
||||
large_client_header_buffers 4 16k;
|
||||
|
||||
# POST나 PUT 요청으로 전송하는 본문(body) 데이터를 받을 때, Nginx가 메모리(RAM)에 임시 저장할 버퍼의 크기
|
||||
client_body_buffer_size 128k; # 일반적으로 64KB~256KB 권장
|
||||
client_body_timeout 15s; # 클라이언트 본문 수신 타임아웃
|
||||
client_header_timeout 15s; # 클라이언트 헤더 수신 타임아웃
|
||||
|
||||
# 효율적인 파일 전송 설정
|
||||
sendfile on; # 커널 공간에서 직접 파일 전송 (제로카피)
|
||||
tcp_nopush on; # sendfile 사용 시 패킷 효율 향상
|
||||
tcp_nodelay on; # Keep-alive 연결에서 지연 없이 전송 (실시간 통신에 유리)
|
||||
|
||||
# Keep-alive 연결 설정
|
||||
keepalive_timeout 30s; # 연결 유지 시간
|
||||
keepalive_requests 1000; # 연결당 최대 요청 수
|
||||
send_timeout 15s; # 클라이언트로 응답 전송 타임아웃
|
||||
|
||||
# ===== 해시 테이블 =====
|
||||
# MIME 타입 해시 테이블 설정
|
||||
# mime.types 파일에 정의된 파일 확장자와 MIME 타입 매핑을 저장
|
||||
# 예: .html -> text/html, .jpg -> image/jpeg 등의 매핑을 빠르게 찾기 위해 사용됨
|
||||
|
||||
types_hash_max_size 2048; # 기본 mime.types의 수백 개 타입을 충분히 수용하는 크기
|
||||
types_hash_bucket_size 64; # 각 해시 버킷 크기, CPU 캐시 라인과 정렬하여 성능 최적화
|
||||
|
||||
# 서버 이름 해시 테이블 설정 (server_name 지시자에 정의된 도메인명만 해당)
|
||||
# server 블록의 server_name 지시자에 설정된 도메인명들을 빠르게 매칭하기 위한 해시 테이블
|
||||
server_names_hash_max_size 1024; # 여러 도메인/서브도메인 운영 시 충분한 공간 확보
|
||||
server_names_hash_bucket_size 64; # 도메인명 길이를 고려한 버킷 크기 (일반적으로 32~64면 충분)
|
||||
|
||||
# Nginx 변수 해시 테이블 설정
|
||||
# $host, $remote_addr 같은 내장 변수와 map/set으로 정의한 커스텀 변수들을 저장하는 해시 테이블
|
||||
# HTTP 헤더를 변수로 변환한 $http_* 변수들도 여기에 포함됨 (예: $http_user_agent, $http_referer)
|
||||
variables_hash_max_size 2048; # 내장 변수 + 커스텀 변수를 위한 충분한 공간
|
||||
variables_hash_bucket_size 64; # 변수명 길이와 충돌 방지를 위한 적절한 버킷 크기
|
||||
|
||||
# ===== 압축 설정 =====
|
||||
# 실시간 압축 비활성화 (CPU 부하 감소)
|
||||
gzip off;
|
||||
|
||||
# 미리 압축된 .gz 파일 제공
|
||||
# 예: style.css 요청 시 → style.css.gz 파일을 찾아서 전송
|
||||
gzip_static on;
|
||||
|
||||
# Vary: Accept-Encoding 헤더 추가 (프록시 캐시 호환성)
|
||||
gzip_vary on;
|
||||
|
||||
include /etc/nginx/proxy_params/*;
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
include /etc/nginx/sites-enabled/*.conf;
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
#!/bin/bash
|
||||
|
||||
while :
|
||||
do
|
||||
echo "* if your webroot has sub-level, you should be insert as \\\/A\\\/B\\\/C"
|
||||
echo "ex) shop\\\/django_sample"
|
||||
echo -n "Enter the service web root without the path of '/www/' >"
|
||||
read webroot
|
||||
echo "Entered service web root: $webroot"
|
||||
if [[ "$webroot" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the service portnumber >"
|
||||
read portnumber
|
||||
echo "Entered service portnumber: $portnumber"
|
||||
if [[ "$portnumber" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the service domain >"
|
||||
read domain
|
||||
echo "Entered service domain: $domain"
|
||||
if [[ "$domain" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the app name >"
|
||||
read appname
|
||||
echo "Entered app name: $appname"
|
||||
if [[ "$appname" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Enter the serviceport"
|
||||
echo -n "if you push enter with none, there are no port number >"
|
||||
read serviceport
|
||||
echo "Entered proxy port: $serviceport"
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the file name >"
|
||||
read filename
|
||||
echo "Entered file name: $filename"
|
||||
if [[ "$filename" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
sed 's/webroot/'$webroot'/g' sample_nginx_https.conf > $filename'1'.temp
|
||||
sed 's/portnumber/'$portnumber'/g' $filename'1'.temp > $filename'2'.temp
|
||||
sed 's/domain/'$domain'/g' $filename'2'.temp > $filename'3'.temp
|
||||
sed 's/appname/'$appname'/g' $filename'3'.temp > $filename'4'.temp
|
||||
if [[ "$serviceport" == "" ]]; then
|
||||
sed 's/:serviceport/''/g' $filename'4'.temp > $filename'5'.temp
|
||||
else
|
||||
sed 's/serviceport/'$serviceport'/g' $filename'4'.temp > $filename'5'.temp
|
||||
fi
|
||||
sed 's/filename/'$filename'/g' $filename'5'.temp > ./conf.d/$filename'_gunicorn_https_ng'.conf
|
||||
|
||||
rm *.temp
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header Connection keep-alive;
|
||||
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
proxy_buffering off;
|
||||
proxy_redirect off;
|
||||
proxy_connect_timeout 90;
|
||||
proxy_send_timeout 90;
|
||||
proxy_read_timeout 90;
|
||||
proxy_buffers 32 4k;
|
||||
proxy_headers_hash_max_size 512;
|
||||
proxy_headers_hash_bucket_size 64;
|
||||
|
|
@ -0,0 +1,774 @@
|
|||
# Nginx HTTPS 설정 검토 보고서
|
||||
|
||||
## 요약
|
||||
|
||||
본 보고서는 `sample_nginx_https.conf` (템플릿)와 `https.conf` (code.devspoon.com의 운영 설정)을 비교하고, 현재 설정의 운영 준비 상태를 평가합니다.
|
||||
|
||||
**종합 평가**: `https.conf`는 샘플 템플릿보다 훨씬 더 운영 환경에 적합하며, 최신 보안 헤더와 우수한 설정을 갖추고 있습니다. 그러나 일부 개선 사항이 권장됩니다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 설정 비교 분석
|
||||
|
||||
### 1.1 HTTP 서버 블록 (포트 80)
|
||||
|
||||
#### 샘플 설정의 문제점:
|
||||
```nginx
|
||||
server {
|
||||
listen portnumber;
|
||||
server_name domain www.domain;
|
||||
|
||||
rewrite ^ https://$host$request_uri permanent;
|
||||
|
||||
# if ($host !~* ^(domain\.com|www\.domain\.com)$) {
|
||||
# return 444;
|
||||
# }
|
||||
}
|
||||
```
|
||||
|
||||
**문제점:**
|
||||
- 일반적인 플레이스홀더 사용 (`portnumber`, `domain`)
|
||||
- `return 301` 대신 더 이상 권장되지 않는 `rewrite` 지시어 사용
|
||||
- 호스트 검증이 주석 처리됨
|
||||
- Let's Encrypt ACME 챌린지 location 누락
|
||||
|
||||
#### 운영 설정 (https.conf) - 올바름:
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name code.devspoon.com www.code.devspoon.com;
|
||||
|
||||
# 리다이렉트 전 호스트 검증
|
||||
if ($host !~* ^(code\.devspoon\.com|www\.code\.devspoon\.com)$) {
|
||||
return 444;
|
||||
}
|
||||
|
||||
# 리다이렉트 전 ACME 챌린지
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/certbot;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# HTTPS로 리다이렉트
|
||||
location / {
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**장점:**
|
||||
✅ `return 301` 사용 (rewrite보다 효율적)
|
||||
✅ 호스트 검증 활성화
|
||||
✅ 리다이렉트 전 ACME 챌린지 적절히 처리
|
||||
✅ location 블록으로 더 나은 구조
|
||||
✅ `$host` 대신 `$server_name` 사용 (더 안전함)
|
||||
|
||||
---
|
||||
|
||||
### 1.2 HTTPS 서버 블록 (포트 443)
|
||||
|
||||
#### SSL/TLS 설정
|
||||
|
||||
**샘플 설정 - 구식:**
|
||||
```nginx
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
|
||||
```
|
||||
|
||||
**운영 설정 - 최신 & 올바름:**
|
||||
```nginx
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers off; # TLSv1.3에서는 OFF
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
```
|
||||
|
||||
**분석:**
|
||||
- ✅ 운영 설정에서 `ssl_prefer_server_ciphers off` 사용 - TLSv1.3에 **올바름** (클라이언트 선호가 더 나음)
|
||||
- ✅ 일반적인 약칭 대신 명시적이고 최신 암호화 스위트 사용
|
||||
- ✅ 모바일 장치 최적화를 위한 CHACHA20-POLY1305 포함
|
||||
|
||||
---
|
||||
|
||||
### 1.3 보안 헤더
|
||||
|
||||
**샘플 설정 - 누락:**
|
||||
- 보안 헤더가 전혀 없음
|
||||
|
||||
**운영 설정 - 우수:**
|
||||
```nginx
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
add_header X-Frame-Options DENY always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss: ws:;" always;
|
||||
```
|
||||
|
||||
**평가:**
|
||||
✅ **HSTS** (preload 포함) - 다운그레이드 공격 방지
|
||||
✅ **X-Frame-Options** - 클릭재킹 방지
|
||||
✅ **X-Content-Type-Options** - MIME 스니핑 방지
|
||||
✅ **X-XSS-Protection** - 레거시 XSS 보호
|
||||
✅ **Referrer-Policy** - 리퍼러 정보 제어
|
||||
✅ **CSP** - XSS 방지를 위한 콘텐츠 보안 정책
|
||||
✅ 모든 헤더에 `always` 플래그 사용 - 오류 응답에도 헤더 보장
|
||||
|
||||
---
|
||||
|
||||
### 1.4 OCSP 스테이플링
|
||||
|
||||
**샘플 설정 - 누락**
|
||||
|
||||
**운영 설정 - 구현됨:**
|
||||
```nginx
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_trusted_certificate /etc/letsencrypt/live/code.devspoon.com/chain.pem;
|
||||
resolver 1.1.1.1 8.8.8.8 valid=300s;
|
||||
resolver_timeout 5s;
|
||||
```
|
||||
|
||||
**평가:**
|
||||
✅ OCSP 스테이플링으로 SSL 핸드셰이크 성능 향상
|
||||
✅ Cloudflare (1.1.1.1)와 Google (8.8.8.8) DNS 리졸버 사용
|
||||
✅ OCSP 경고에 대한 유용한 주석 포함
|
||||
|
||||
---
|
||||
|
||||
### 1.5 프록시 설정
|
||||
|
||||
**샘플 설정 - 기본:**
|
||||
```nginx
|
||||
location / {
|
||||
autoindex off;
|
||||
proxy_pass http://appname:serviceport;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
```
|
||||
|
||||
**운영 설정 - 포괄적:**
|
||||
```nginx
|
||||
location / {
|
||||
proxy_pass http://code-server:8443;
|
||||
|
||||
# WebSocket 지원
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# 완전한 프록시 헤더
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# 최적화된 타임아웃
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
|
||||
# 버퍼 설정
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
```
|
||||
|
||||
**평가:**
|
||||
✅ WebSocket 지원 (code-server에 필수)
|
||||
✅ 포괄적인 forwarded 헤더
|
||||
✅ 적절한 타임아웃 설정
|
||||
✅ 대화형 애플리케이션에 최적화된 버퍼 설정
|
||||
⚠️ 샘플에는 WebSocket 지원이 완전히 없음
|
||||
|
||||
---
|
||||
|
||||
### 1.6 정적 파일 처리
|
||||
|
||||
**샘플 설정 - 존재:**
|
||||
```nginx
|
||||
location /media {
|
||||
autoindex off;
|
||||
gzip_static on;
|
||||
expires max;
|
||||
alias /www/webroot/media;
|
||||
}
|
||||
|
||||
location /static {
|
||||
autoindex off;
|
||||
gzip_static on;
|
||||
expires max;
|
||||
alias /www/webroot/static;
|
||||
}
|
||||
```
|
||||
|
||||
**운영 설정 - 누락:**
|
||||
- /media 또는 /static location 없음
|
||||
|
||||
**평가:**
|
||||
⚠️ **누락** - 애플리케이션이 정적 파일을 제공하는 경우 `https.conf`에 추가해야 함
|
||||
ℹ️ code-server의 경우, 내부적으로 정적 파일을 처리하므로 의도적일 수 있음
|
||||
⚠️ **권장사항**: Django/Flask 백엔드를 추가하는 경우 정적 파일 location 포함
|
||||
|
||||
---
|
||||
|
||||
### 1.7 Let's Encrypt ACME 챌린지
|
||||
|
||||
**샘플 설정:**
|
||||
```nginx
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/webroot;
|
||||
}
|
||||
```
|
||||
|
||||
**운영 설정:**
|
||||
```nginx
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/certbot;
|
||||
try_files $uri =404; # 보안 추가
|
||||
}
|
||||
```
|
||||
|
||||
**평가:**
|
||||
✅ 운영 설정에 `try_files $uri =404` 추가 - 디렉토리 순회 방지
|
||||
✅ 전용 `/www/certbot` 디렉토리 사용
|
||||
|
||||
---
|
||||
|
||||
### 1.8 보안 블록 Location
|
||||
|
||||
**샘플 설정:**
|
||||
```nginx
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~* \.(log|binary|pem|enc|crt|conf|cnf|sql|sh|key|yml|lock)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~* (composer\.json|...) {
|
||||
deny all;
|
||||
}
|
||||
```
|
||||
|
||||
**운영 설정 - 향상됨:**
|
||||
```nginx
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off; # 차단된 시도는 로그에 남기지 않음
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~* \.(log|binary|pem|enc|crt|conf|cnf|sql|sh|key|yml|lock)$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~* (composer\.json|...) {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
```
|
||||
|
||||
**평가:**
|
||||
✅ 운영 설정에서 차단된 요청에 대한 로깅 비활성화 - 로그 노이즈 감소
|
||||
✅ 스캐너 시도를 로그에 남기지 않아 성능 향상
|
||||
|
||||
---
|
||||
|
||||
## 2. https.conf에 누락된 운영 준비 기능
|
||||
|
||||
### 2.1 속도 제한 - **누락**
|
||||
|
||||
**권장사항: 추가**
|
||||
```nginx
|
||||
# http 블록 또는 server 블록에 추가
|
||||
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
|
||||
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
|
||||
limit_conn_zone $binary_remote_addr zone=addr:10m;
|
||||
|
||||
# location 블록에
|
||||
location / {
|
||||
limit_req zone=general burst=20 nodelay;
|
||||
limit_conn addr 10;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
**영향:** DDoS 및 무차별 대입 공격으로부터 보호
|
||||
|
||||
---
|
||||
|
||||
### 2.2 클라이언트 본문 크기 제한 - **누락**
|
||||
|
||||
**권장사항: 추가**
|
||||
```nginx
|
||||
client_max_body_size 10M; # 애플리케이션 요구사항에 따라 조정
|
||||
client_body_buffer_size 128k;
|
||||
client_body_timeout 60s;
|
||||
```
|
||||
|
||||
**영향:** 메모리 고갈 공격 방지
|
||||
|
||||
---
|
||||
|
||||
### 2.3 연결 제한 - **누락**
|
||||
|
||||
**권장사항: 추가**
|
||||
```nginx
|
||||
keepalive_timeout 65;
|
||||
keepalive_requests 100;
|
||||
send_timeout 60s;
|
||||
```
|
||||
|
||||
**영향:** 더 나은 리소스 관리
|
||||
|
||||
---
|
||||
|
||||
### 2.4 Gzip 압축 - **누락**
|
||||
|
||||
**권장사항: 추가**
|
||||
```nginx
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
|
||||
gzip_disable "msie6";
|
||||
```
|
||||
|
||||
**영향:** 대역폭 사용량을 크게 감소
|
||||
|
||||
---
|
||||
|
||||
### 2.5 오류 페이지 - **누락**
|
||||
|
||||
**권장사항: 추가**
|
||||
```nginx
|
||||
error_page 404 /404.html;
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
location = /404.html {
|
||||
internal;
|
||||
root /www/error_pages;
|
||||
}
|
||||
|
||||
location = /50x.html {
|
||||
internal;
|
||||
root /www/error_pages;
|
||||
}
|
||||
```
|
||||
|
||||
**영향:** 더 나은 사용자 경험 및 정보 노출 방지
|
||||
|
||||
---
|
||||
|
||||
### 2.6 요청 메서드 제한 - **누락**
|
||||
|
||||
**권장사항: 추가**
|
||||
```nginx
|
||||
location / {
|
||||
limit_except GET POST HEAD OPTIONS {
|
||||
deny all;
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
**영향:** HTTP 동사 변조 공격 방지
|
||||
|
||||
---
|
||||
|
||||
### 2.7 버전 정보 숨김 - **누락**
|
||||
|
||||
**권장사항: 추가** (http 블록에)
|
||||
```nginx
|
||||
server_tokens off;
|
||||
more_clear_headers 'Server';
|
||||
more_clear_headers 'X-Powered-By';
|
||||
```
|
||||
|
||||
**영향:** 정보 노출 감소
|
||||
|
||||
---
|
||||
|
||||
## 3. SSL/TLS 모범 사례 검증
|
||||
|
||||
### 현재 설정 평가:
|
||||
|
||||
| 설정 | 현재 값 | 상태 | 권장사항 |
|
||||
|------|---------|------|----------|
|
||||
| ssl_protocols | TLSv1.2 TLSv1.3 | ✅ 올바름 | 현재 유지 |
|
||||
| ssl_prefer_server_ciphers | off | ✅ 올바름 | 유지 (TLSv1.3 모범 사례) |
|
||||
| ssl_session_cache | shared:SSL:20m | ✅ 좋음 | 트래픽이 많으면 50m 고려 |
|
||||
| ssl_session_timeout | 10m | ✅ 좋음 | 현재 유지 |
|
||||
| ssl_session_tickets | off | ✅ 올바름 | 유지 (더 나은 보안) |
|
||||
| ssl_stapling | on | ✅ 올바름 | 현재 유지 |
|
||||
| ssl_dhparam | 4096-bit | ✅ 우수 | 현재 유지 |
|
||||
| HSTS max-age | 31536000 | ✅ 올바름 | 유지 (1년) |
|
||||
|
||||
---
|
||||
|
||||
## 4. 성능 최적화 격차
|
||||
|
||||
### 4.1 캐싱 헤더 누락
|
||||
|
||||
**권장사항: 추가**
|
||||
```nginx
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 열린 파일 캐시 누락
|
||||
|
||||
**권장사항: 추가**
|
||||
```nginx
|
||||
open_file_cache max=1000 inactive=20s;
|
||||
open_file_cache_valid 30s;
|
||||
open_file_cache_min_uses 2;
|
||||
open_file_cache_errors on;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 로깅 개선
|
||||
|
||||
### 현재 설정:
|
||||
```nginx
|
||||
access_log /log/nginx/code.devspoon.com.nginx.log main;
|
||||
error_log /log/nginx/code.devspoon.com.nginx_error.log warn;
|
||||
```
|
||||
|
||||
**권장사항:**
|
||||
```nginx
|
||||
# I/O 감소를 위한 버퍼 추가
|
||||
access_log /log/nginx/code.devspoon.com.nginx.log main buffer=32k flush=5s;
|
||||
error_log /log/nginx/code.devspoon.com.nginx_error.log warn;
|
||||
|
||||
# 더 많은 세부 정보를 포함한 로그 형식 추가
|
||||
log_format detailed '$remote_addr - $remote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent" '
|
||||
'$request_time $upstream_response_time '
|
||||
'$upstream_addr $upstream_status';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 권장 최종 설정 구조
|
||||
|
||||
```nginx
|
||||
# HTTP 블록 (포트 80)
|
||||
server {
|
||||
listen 80;
|
||||
server_name code.devspoon.com www.code.devspoon.com;
|
||||
|
||||
# 호스트 검증
|
||||
if ($host !~* ^(code\.devspoon\.com|www\.code\.devspoon\.com)$) {
|
||||
return 444;
|
||||
}
|
||||
|
||||
# ACME 챌린지
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/certbot;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# HTTPS로 리다이렉트
|
||||
location / {
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# HTTPS 블록 (포트 443)
|
||||
server {
|
||||
listen 443 ssl;
|
||||
http2 on;
|
||||
server_name code.devspoon.com www.code.devspoon.com;
|
||||
|
||||
# SSL 인증서
|
||||
ssl_certificate /etc/letsencrypt/live/code.devspoon.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/code.devspoon.com/privkey.pem;
|
||||
ssl_dhparam /etc/ssl/certs/code.devspoon.com/dhparam.pem;
|
||||
|
||||
# 최신 SSL 설정
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_timeout 10m;
|
||||
ssl_session_tickets off;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
ssl_ecdh_curve secp384r1;
|
||||
|
||||
# OCSP 스테이플링
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_trusted_certificate /etc/letsencrypt/live/code.devspoon.com/chain.pem;
|
||||
resolver 1.1.1.1 8.8.8.8 valid=300s;
|
||||
resolver_timeout 5s;
|
||||
|
||||
# 보안 헤더
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
add_header X-Frame-Options DENY always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss: ws:;" always;
|
||||
|
||||
# 신규: 보안 설정
|
||||
server_tokens off;
|
||||
client_max_body_size 10M;
|
||||
client_body_buffer_size 128k;
|
||||
client_body_timeout 60s;
|
||||
|
||||
# 신규: 성능 설정
|
||||
keepalive_timeout 65;
|
||||
keepalive_requests 100;
|
||||
send_timeout 60s;
|
||||
|
||||
# 신규: Gzip 압축
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;
|
||||
|
||||
# 신규: 파일 캐시
|
||||
open_file_cache max=1000 inactive=20s;
|
||||
open_file_cache_valid 30s;
|
||||
open_file_cache_min_uses 2;
|
||||
open_file_cache_errors on;
|
||||
|
||||
# 버퍼링을 사용한 로깅
|
||||
access_log /log/nginx/code.devspoon.com.nginx.log main buffer=32k flush=5s;
|
||||
error_log /log/nginx/code.devspoon.com.nginx_error.log warn;
|
||||
|
||||
# 호스트 검증
|
||||
if ($host !~* ^(code\.devspoon\.com|www\.code\.devspoon\.com)$) {
|
||||
return 444;
|
||||
}
|
||||
|
||||
# 나쁜 봇 차단
|
||||
if ($bad_bot) {
|
||||
return 403;
|
||||
}
|
||||
|
||||
# 메인 애플리케이션
|
||||
location / {
|
||||
# 신규: 속도 제한
|
||||
limit_req zone=general burst=20 nodelay;
|
||||
limit_conn addr 10;
|
||||
|
||||
# 신규: 메서드 제한
|
||||
limit_except GET POST HEAD OPTIONS {
|
||||
deny all;
|
||||
}
|
||||
|
||||
proxy_pass http://code-server:8443;
|
||||
|
||||
# WebSocket 지원
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# 프록시 헤더
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# 타임아웃
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
|
||||
# 버퍼 설정
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
|
||||
# ACME 챌린지
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/certbot;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# 신규: 정적 파일 캐싱 (필요시)
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# 닷 파일 차단
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# 민감한 파일 차단
|
||||
location ~* \.(log|binary|pem|enc|crt|conf|cnf|sql|sh|key|yml|lock)$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# 민감한 설정 파일 차단
|
||||
location ~* (composer\.json|composer\.lock|composer\.phar|contributing\.md|license\.txt|readme\.rst|readme\.md|readme\.txt|copyright|artisan|gulpfile\.js|package\.json|phpunit\.xml|access_log|error_log|gruntfile\.js)$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# 파비콘 및 robots
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /robots.txt {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
allow all;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 우선순위 실행 항목
|
||||
|
||||
### 긴급 (즉시 구현)
|
||||
1. ✅ **이미 존재**: 보안 헤더 (HSTS, CSP 등)
|
||||
2. ✅ **이미 존재**: OCSP 스테이플링
|
||||
3. ⚠️ **추가**: 속도 제한 설정
|
||||
4. ⚠️ **추가**: `server_tokens off`
|
||||
5. ⚠️ **추가**: `client_max_body_size` 제한
|
||||
|
||||
### 높은 우선순위 (권장)
|
||||
6. ⚠️ **추가**: Gzip 압축
|
||||
7. ⚠️ **추가**: 열린 파일 캐시
|
||||
8. ⚠️ **추가**: 오류 페이지 처리
|
||||
9. ⚠️ **추가**: HTTP 메서드 제한
|
||||
10. ⚠️ **추가**: 로깅 버퍼 설정
|
||||
|
||||
### 중간 우선순위 (선택 사항)
|
||||
11. ⚠️ **추가**: 정적 파일 캐싱 헤더
|
||||
12. ⚠️ **고려**: SSL 세션 캐시 크기 증가
|
||||
13. ⚠️ **고려**: 향상된 로깅 형식
|
||||
14. ⚠️ **검토**: 특정 애플리케이션 요구사항에 맞는 CSP 정책
|
||||
|
||||
---
|
||||
|
||||
## 8. 설정 의존성
|
||||
|
||||
### nginx.conf (http 블록)에 필요:
|
||||
```nginx
|
||||
# 서버 블록 전에 정의되어야 함
|
||||
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
|
||||
limit_conn_zone $binary_remote_addr zone=addr:10m;
|
||||
|
||||
# 나쁜 봇 탐지 맵
|
||||
map $http_user_agent $bad_bot {
|
||||
default 0;
|
||||
~*malicious 1;
|
||||
~*scrapy 1;
|
||||
~*bot 1;
|
||||
~*crawler 1;
|
||||
}
|
||||
|
||||
# WebSocket 업그레이드 맵
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
# 로그 형식
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. SSL/TLS 테스트 권장사항
|
||||
|
||||
변경 사항 구현 후 다음으로 테스트:
|
||||
|
||||
1. **SSL Labs**: https://www.ssllabs.com/ssltest/
|
||||
- 목표 등급: A+
|
||||
|
||||
2. **Mozilla Observatory**: https://observatory.mozilla.org/
|
||||
- 목표 점수: A+ 또는 100+
|
||||
|
||||
3. **Security Headers**: https://securityheaders.com/
|
||||
- 목표 등급: A+
|
||||
|
||||
4. **OpenSSL CLI**:
|
||||
```bash
|
||||
openssl s_client -connect code.devspoon.com:443 -tls1_2
|
||||
openssl s_client -connect code.devspoon.com:443 -tls1_3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 요약
|
||||
|
||||
### https.conf에서 이미 우수한 점:
|
||||
✅ 최신 SSL/TLS 설정
|
||||
✅ 포괄적인 보안 헤더
|
||||
✅ OCSP 스테이플링
|
||||
✅ WebSocket 지원
|
||||
✅ 적절한 ACME 챌린지 처리
|
||||
✅ 향상된 프록시 설정
|
||||
✅ 로깅 최적화가 적용된 보안 블록 location
|
||||
|
||||
### 추가해야 할 사항:
|
||||
⚠️ 속도 제한
|
||||
⚠️ 클라이언트 본문 크기 제한
|
||||
⚠️ Gzip 압축
|
||||
⚠️ 열린 파일 캐시
|
||||
⚠️ 서버 토큰 숨김
|
||||
⚠️ 오류 페이지 처리
|
||||
⚠️ HTTP 메서드 제한
|
||||
|
||||
### 결론:
|
||||
**https.conf는 sample_nginx_https.conf보다 훨씬 우수하며** 최신 모범 사례를 따릅니다. 샘플 파일은 구식이고 중요한 보안 기능이 누락되어 있습니다. 위의 권장 추가 사항을 적용하면 `https.conf`는 운영 등급의 엔터프라이즈 준비 nginx 설정이 될 것입니다.
|
||||
|
||||
---
|
||||
|
||||
## 11. 다음 단계
|
||||
|
||||
1. 긴급 우선순위 항목 검토 및 구현
|
||||
2. 설정 테스트: `nginx -t`
|
||||
3. 변경 사항 적용 전 현재 설정 백업
|
||||
4. 변경 사항을 점진적으로 적용
|
||||
5. 문제가 있는지 로그 모니터링
|
||||
6. A+ 등급 확인을 위한 SSL/TLS 테스트 실행
|
||||
7. 속도 제한 및 성능 메트릭 모니터링 설정
|
||||
|
||||
---
|
||||
|
||||
**보고서 생성**: sample_nginx_https.conf vs https.conf 비교 기반
|
||||
**기준선**: https.conf (code.devspoon.com의 운영 설정)
|
||||
**평가**: 권장 개선 사항을 포함한 운영 준비 완료
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
server {
|
||||
listen portnumber;
|
||||
server_name domain www.domain;
|
||||
|
||||
if ($bad_bot) {
|
||||
return 403;
|
||||
}
|
||||
|
||||
access_log /log/nginx/filename.com.gunicorn_access.log main;
|
||||
error_log /log/nginx/filename.com.gunicorn_error.log warn;
|
||||
|
||||
# if ($host !~* ^(domain\.com|www\.domain\.com)$) {
|
||||
# return 444;
|
||||
# }
|
||||
|
||||
# Django media
|
||||
location /media {
|
||||
autoindex off;
|
||||
gzip_static on;
|
||||
expires max;
|
||||
#alias /www/django_sample/media;
|
||||
alias /www/webroot/media; # your Django project's media files - amend as required
|
||||
#include /etc/nginx/mime.types;
|
||||
}
|
||||
|
||||
location /static {
|
||||
autoindex off;
|
||||
gzip_static on;
|
||||
expires max;
|
||||
#alias /www/django_sample/static;
|
||||
# normally static folder is named as /static
|
||||
alias /www/webroot/static; # your Django project's static files - amend as required
|
||||
#include /etc/nginx/mime.types;
|
||||
}
|
||||
|
||||
location / {
|
||||
autoindex off;
|
||||
proxy_pass http://appname:serviceport;
|
||||
# proxy_redirect http:// https://;
|
||||
|
||||
}
|
||||
|
||||
# Allow Lets Encrypt Domain Validation Program
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/webroot;
|
||||
}
|
||||
|
||||
# Block dot file (.htaccess .htpasswd .svn .git .env and so on.)
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Block (log file, binary, certificate, shell script, sql dump file) access.
|
||||
location ~* \.(log|binary|pem|enc|crt|conf|cnf|sql|sh|key|yml|lock)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# Block access
|
||||
location ~* (composer\.json|composer\.lock|composer\.phar|contributing\.md|license\.txt|readme\.rst|readme\.md|readme\.txt|copyright|artisan|gulpfile\.js|package\.json|phpunit\.xml|access_log|error_log|gruntfile\.js)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /robots.txt {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
# ===============================================
|
||||
# Production Level Nginx Configuration (Sample Template)
|
||||
# 서버 사양: 쿼드코어 CPU, 4GB RAM, ~50 req/s
|
||||
# 백엔드: FastAPI REST API Server
|
||||
# ===============================================
|
||||
|
||||
# HTTP 서버 블록 (포트 80) - HTTPS로 리다이렉트
|
||||
server {
|
||||
listen 80;
|
||||
server_name domain www.domain;
|
||||
|
||||
# 보안을 위한 호스트 검증 - 허용되지 않은 도메인 차단
|
||||
# 도메인 확장자가 다르다면 추가해줘야함
|
||||
if ($host !~* ^(www\.)?domain\.(com|kr|net|org)$) {
|
||||
return 444;
|
||||
}
|
||||
|
||||
# Let's Encrypt 도메인 검증 프로그램 허용 (리다이렉트 전에 처리)
|
||||
# SSL 인증서 갱신을 위해 필수
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/certbot;
|
||||
try_files $uri =404; # 디렉토리 순회 공격 방지
|
||||
}
|
||||
|
||||
# HTTP를 HTTPS로 리다이렉트 (acme-challenge 제외)
|
||||
# return 301은 rewrite보다 효율적이며 $server_name이 $host보다 안전함
|
||||
location / {
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
# HTTPS 서버 블록 (포트 443) - 메인 애플리케이션
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name domain.com www.domain.com;
|
||||
|
||||
# 악성 봇 차단 (nginx.conf의 http 블록에서 $bad_bot 맵 정의 필요)
|
||||
if ($bad_bot) {
|
||||
return 403;
|
||||
}
|
||||
|
||||
# SSL/TLS 인증서 설정
|
||||
ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem;
|
||||
ssl_dhparam /etc/ssl/certs/domain/dhparam.pem; # openssl dhparam -out /etc/ssl/certs/domain/dhparam.pem 2048
|
||||
|
||||
# 최신 SSL/TLS 설정 - SSL Labs A+ 등급 달성 가능
|
||||
ssl_session_cache shared:SSL:50m; # SSL 세션 캐시 크기 증가 (트래픽 많을 시 유용)
|
||||
ssl_session_timeout 10m; # SSL 세션 타임아웃
|
||||
ssl_session_tickets off; # 보안 향상을 위해 세션 티켓 비활성화 (nginx >= 1.5.9)
|
||||
ssl_protocols TLSv1.2 TLSv1.3; # 최신 TLS 프로토콜만 사용
|
||||
ssl_prefer_server_ciphers off; # TLSv1.3에서는 클라이언트 선호 암호화 사용 (모범 사례)
|
||||
# 최신 암호화 스위트 - CHACHA20-POLY1305 포함 (모바일 최적화)
|
||||
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
|
||||
ssl_ecdh_curve secp384r1; # ECDH 곡선 설정 (nginx >= 1.1.0)
|
||||
|
||||
# OCSP 스테이플링 - SSL 핸드셰이크 성능 향상
|
||||
# 인증서에 OCSP URL이 없으면 자동으로 비활성화됨 (경고는 정상)
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
ssl_trusted_certificate /etc/letsencrypt/live/domain/chain.pem;
|
||||
resolver 1.1.1.1 8.8.8.8 valid=300s; # Cloudflare와 Google DNS 사용
|
||||
resolver_timeout 5s;
|
||||
|
||||
# 보안 헤더 - 다양한 공격으로부터 보호
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; # HSTS - 다운그레이드 공격 방지
|
||||
add_header X-Frame-Options "DENY" always; # 클릭재킹 방지
|
||||
add_header X-Content-Type-Options "nosniff" always; # MIME 스니핑 방지
|
||||
add_header X-XSS-Protection "1; mode=block" always; # 레거시 XSS 보호
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always; # 리퍼러 정보 제어
|
||||
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' ''; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' wss: ws:;" always;
|
||||
# XSS 방지를 위한 CSP
|
||||
# 'unsafe-inline'은 범용 설정이 아니며, 보안상 위험한 설정입니다. CSP의 핵심 보호 기능을 무력화시키므로, 개발 환경이나 레거시 코드 마이그레이션 과정에서만 임시로 사용하고, 프로덕션 환경에서는 nonce, hash, 또는 외부 파일 분리 방식으로 대체해야 합니다.
|
||||
|
||||
# 클라이언트가 업로드할 수 있는 전체 요청 본문(body) 의 최대 허용 크기
|
||||
# 요청 바디(파일, 폼 데이터 등)가 이 값을 초과하면 Nginx는 즉시 413 Request Entity Too Large 에러를 반환
|
||||
# 업로드 제한선.
|
||||
client_max_body_size 100M; # 최대 업로드 크기 제한 (애플리케이션에 맞게 조정)
|
||||
|
||||
# 파일 캐시 - I/O 성능 향상
|
||||
open_file_cache max=1000 inactive=20s; # 최대 1000개 파일 캐시, 20초 비활성 시 제거
|
||||
open_file_cache_valid 30s; # 캐시 유효성 검사 주기
|
||||
open_file_cache_min_uses 2; # 최소 2회 사용 시 캐시
|
||||
open_file_cache_errors on; # 파일 오류도 캐시
|
||||
|
||||
# 로깅 설정 - 버퍼링으로 I/O 감소
|
||||
access_log /log/nginx/domain.com.gunicorn_access.log main buffer=32k flush=5s;
|
||||
error_log /log/nginx/domain.com.gunicorn_error.log warn;
|
||||
|
||||
# frontend에 오류 페이지 정의가 되어 있는 경우 사용 가능
|
||||
# # 커스텀 오류 페이지 - 더 나은 사용자 경험 및 정보 노출 방지
|
||||
# error_page 404 /404.html;
|
||||
# error_page 500 502 503 504 /50x.html;
|
||||
|
||||
# location = /404.html {
|
||||
# internal; # 내부 리다이렉트만 허용
|
||||
# root /www/error_pages;
|
||||
# }
|
||||
|
||||
# location = /50x.html {
|
||||
# internal; # 내부 리다이렉트만 허용
|
||||
# root /www/error_pages;
|
||||
# }
|
||||
|
||||
# Fastapi 미디어 파일 - 사용자 업로드 파일
|
||||
location /media {
|
||||
autoindex off; # 디렉토리 목록 비활성화
|
||||
# gzip_static on; # 사전 압축된 .gz 파일 사용
|
||||
expires 30d; # 브라우저 캐시 30일 후 브라우저가 다시 요청할 때 재검증
|
||||
alias /www/webroot/media; # Fastapi 프로젝트의 미디어 파일 경로
|
||||
|
||||
# 정적 파일 캐싱 - 브라우저 캐시 최적화
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off; # 액세스 로그 비활성화로 성능 향상
|
||||
}
|
||||
|
||||
# Fastapi 정적 파일 - CSS, JS, 이미지 등
|
||||
location /static {
|
||||
autoindex off; # 디렉토리 목록 비활성화
|
||||
# gzip_static on; # 사전 압축된 .gz 파일 사용 압축된 파일이 없다면 설정 무의미
|
||||
expires 30d; # 브라우저 캐시 30일 후 브라우저가 다시 요청할 때 재검증
|
||||
alias /www/webroot/static; # Fastapi 프로젝트의 정적 파일 경로
|
||||
|
||||
# 정적 파일 캐싱 - 브라우저 캐시 최적화
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off; # 액세스 로그 비활성화로 성능 향상
|
||||
}
|
||||
|
||||
# 메인 애플리케이션 - 백엔드로 프록시
|
||||
location / {
|
||||
autoindex off; # 디렉토리 목록 비활성화
|
||||
|
||||
# 속도 제한 - DDoS 및 무차별 대입 공격 방지
|
||||
# (nginx.conf의 http 블록에서 limit_req_zone과 limit_conn_zone 정의 필요)
|
||||
limit_req zone=general burst=20 nodelay; # 초당 요청 제한
|
||||
limit_conn addr 10; # IP당 동시 연결 제한
|
||||
|
||||
# HTTP 메서드 제한 - HTTP 동사 변조 공격 방지
|
||||
limit_except GET POST HEAD OPTIONS {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# 백엔드 애플리케이션으로 프록시
|
||||
proxy_pass http://appname:serviceport;
|
||||
|
||||
# WebSocket 지원 - 실시간 통신 애플리케이션에 필수
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade; # nginx.conf에서 $connection_upgrade 맵 정의 필요
|
||||
|
||||
# 프록시 헤더 - 클라이언트 정보 전달
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# 타임아웃 설정 - 애플리케이션에 맞게 조정
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
|
||||
# 버퍼 설정 - 대화형 애플리케이션에 최적화 - Websocket 사용시 설정
|
||||
# proxy_buffering off; # 즉시 응답 전달
|
||||
# proxy_request_buffering off; # 즉시 요청 전달
|
||||
|
||||
# 버퍼링 활성화 (기본값) - 기본 fastapi 사용시 설정
|
||||
proxy_buffering on;
|
||||
proxy_request_buffering on;
|
||||
|
||||
# 버퍼 크기 설정 - 기본 fastapi 사용시 설정
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 8 4k;
|
||||
proxy_busy_buffers_size 8k;
|
||||
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
}
|
||||
|
||||
# Let's Encrypt 도메인 검증 프로그램 허용 (HTTPS에서도 필요시)
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/certbot;
|
||||
try_files $uri =404; # 디렉토리 순회 공격 방지
|
||||
}
|
||||
|
||||
# 정적 리소스 캐싱 - 이미지, 폰트, CSS, JS 등
|
||||
# 브라우저 캐시로 로드 시간 단축 및 서버 부하 감소
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ {
|
||||
expires 1y; # 1년 캐시
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off; # 액세스 로그 비활성화로 성능 향상
|
||||
}
|
||||
|
||||
# 닷 파일 차단 - .htaccess, .htpasswd, .svn, .git, .env 등
|
||||
# 민감한 설정 파일 노출 방지
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off; # 차단된 시도 로그 비활성화
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# 민감한 파일 확장자 차단 - 로그, 인증서, 스크립트, SQL 등
|
||||
# 보안을 위해 직접 접근 차단
|
||||
location ~* \.(log|binary|pem|enc|crt|conf|cnf|sql|sh|key|yml|lock)$ {
|
||||
deny all;
|
||||
access_log off; # 차단된 시도 로그 비활성화
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# 민감한 설정 파일 차단 - composer, package.json, phpunit 등
|
||||
# 프로젝트 메타데이터 및 설정 파일 노출 방지
|
||||
location ~* (composer\.json|composer\.lock|composer\.phar|contributing\.md|license\.txt|readme\.rst|readme\.md|readme\.txt|copyright|artisan|gulpfile\.js|package\.json|phpunit\.xml|access_log|error_log|gruntfile\.js)$ {
|
||||
deny all;
|
||||
access_log off; # 차단된 시도 로그 비활성화
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# 파비콘 - 로그 노이즈 제거
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# robots.txt - 검색 엔진 크롤러 제어
|
||||
location = /robots.txt {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
allow all;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
FROM ubuntu:latest
|
||||
|
||||
RUN apt-get update
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends apt-utils
|
||||
|
||||
ENV TZ=Asia/Seoul
|
||||
|
||||
RUN apt-get install -yq tzdata
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
# curl/wget/git/gnupg2/lsb-release/lz4/zstd
|
||||
RUN apt-get install -y curl wget git tar gnupg2 lsb-release lz4 zstd
|
||||
# vim
|
||||
RUN apt-get install -y vim
|
||||
|
||||
# Python
|
||||
RUN apt-get install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev
|
||||
RUN cd /usr/src ; wget https://www.python.org/ftp/python/3.14.0/Python-3.14.0.tar.xz ; tar -xf Python-3.14.0.tar.xz ; cd Python-3.14.0 ; ./configure ; make altinstall
|
||||
RUN rm -rf /usr/src/Python-3.14.0 /usr/src/Python-3.14.0.tar.xz
|
||||
|
||||
# replace python version to have 3.14 as default
|
||||
RUN rm -f /usr/bin/python
|
||||
RUN rm -f /usr/bin/python3
|
||||
RUN ln -s /usr/local/bin/python3.14 /usr/bin/python
|
||||
RUN ln -s /usr/local/bin/python3.14 /usr/bin/python3
|
||||
RUN ln -s /usr/local/bin/python3.14 /usr/local/bin/python
|
||||
RUN ln -s /usr/local/bin/python3.14 /usr/local/bin/python3
|
||||
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
# create links to pip3.14
|
||||
RUN ln -s /usr/local/bin/pip3.14 /usr/bin/pip
|
||||
RUN ln -s /usr/local/bin/pip3.14 /usr/bin/pip3
|
||||
RUN ln -s /usr/local/bin/pip3.14 /usr/local/bin/pip
|
||||
RUN ln -s /usr/local/bin/pip3.14 /usr/local/bin/pip3
|
||||
|
||||
# update apt-get
|
||||
RUN apt-get update && apt-get -y upgrade
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip3 install --upgrade pip
|
||||
|
||||
RUN apt-get install -y python3-dev libmysqlclient-dev pkg-config
|
||||
|
||||
RUN pip3 install wheel
|
||||
|
||||
# SQLAlchemy
|
||||
RUN pip3 install sqlalchemy alembic pydantic
|
||||
|
||||
# postgresql 동기 / 비동기
|
||||
RUN pip3 install psycopg2-binary asyncpg
|
||||
|
||||
# mysql 동기 / 비동기
|
||||
RUN pip3 install mysqlclient asyncmy
|
||||
|
||||
# mysql 백업
|
||||
RUN curl -O https://repo.percona.com/apt/percona-release_latest.generic_all.deb
|
||||
RUN apt-get install -y ./percona-release_latest.generic_all.deb
|
||||
RUN rm -f percona-release_latest.generic_all.deb
|
||||
RUN apt-get update
|
||||
RUN percona-release enable pxb-84-lts
|
||||
RUN apt-get install -y percona-xtrabackup-84
|
||||
|
||||
# postgresql 백업
|
||||
RUN apt-get -y install pgbackrest
|
||||
|
||||
# gunicorn & uvicorn
|
||||
RUN pip3 install gunicorn uvicorn[standard]
|
||||
|
||||
# pip3 package
|
||||
RUN pip3 install fastapi uv
|
||||
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
RUN update-ca-certificates
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
FROM nginx:latest
|
||||
|
||||
# ========================================
|
||||
# 1. APT 업데이트
|
||||
# ========================================
|
||||
RUN apt-get update
|
||||
|
||||
# ========================================
|
||||
# 2. APT 기본 도구 설치 (경고 제거용)
|
||||
# ========================================
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends apt-utils
|
||||
|
||||
# ========================================
|
||||
# 3. 타임존 설정 (Asia/Seoul)
|
||||
# ========================================
|
||||
ENV TZ=Asia/Seoul
|
||||
RUN apt-get install -yq tzdata
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
# ========================================
|
||||
# 4. 필요한 패키지 설치
|
||||
# ========================================
|
||||
RUN apt-get install -y sendmail wget gnupg
|
||||
|
||||
# ========================================
|
||||
# 7. Cron 및 Certbot 설치 (SSL 인증서 자동 갱신)
|
||||
# ========================================
|
||||
RUN apt-get install -y cron certbot python3-certbot-nginx
|
||||
|
||||
# ========================================
|
||||
# 8. CA 인증서 설치 및 업데이트
|
||||
# ========================================
|
||||
RUN apt-get update && apt-get install -y ca-certificates
|
||||
RUN update-ca-certificates
|
||||
RUN chmod 644 /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# ========================================
|
||||
# 9. APT 캐시 정리
|
||||
# ========================================
|
||||
RUN apt-get autoremove -y && apt-get clean
|
||||
RUN rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# ========================================
|
||||
# 10. Certbot 자동 갱신 Cron 작업 등록
|
||||
# ========================================
|
||||
RUN crontab -l | { cat; echo "0 5 * * 1 certbot renew --quiet --deploy-hook \"nginx -t && service nginx reload\" >> /log/nginx/crontab_$(date +\%Y\%m\%d).log 2>&1"; } | crontab -
|
||||
|
||||
# ========================================
|
||||
# 11. Nginx 시작 스크립트에 Cron 추가
|
||||
# ========================================
|
||||
RUN sed -i'' -r -e "/set/i\cron" docker-entrypoint.sh
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "0 6 * * 1 root docker restart nginx-gunicorn-webserver" >> /etc/crontab
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
#!/bin/bash
|
||||
|
||||
my_array=()
|
||||
delimiter="-d"
|
||||
domain_string=""
|
||||
|
||||
apt-get update && apt-get install -y sendmail wget vim cron certbot python3-certbot-nginx ca-certificates
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the service webroot_folder >"
|
||||
read webroot_folder
|
||||
echo "Entered service webroot_folder: $webroot_folder"
|
||||
if [[ "$webroot_folder" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "To add a subdomain, type something like 'aaa.com www.aaa.com sub.aaa.com', but all domains refer to the same web root"
|
||||
echo -n "A domain in aaa.com format must be entered first."
|
||||
echo -n "Enter the service domain >"
|
||||
read domain
|
||||
echo "Entered service domain: $domain"
|
||||
if [[ "$domain" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
IFS=' ' read -ra my_array <<< "$domain"
|
||||
|
||||
while :
|
||||
do
|
||||
echo -n "Enter the user e-mail >"
|
||||
read mail
|
||||
echo "Entered user e-mail: $mail"
|
||||
if [[ "$mail" != "" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
for element in "${my_array[@]}"; do
|
||||
domain_string+=" $delimiter $element"
|
||||
done
|
||||
|
||||
# Remove leading space
|
||||
# domain_string="${domain_string# }"
|
||||
|
||||
# for element in "${my_array[@]}"; do
|
||||
if ! test -f /ssl/${my_array[0]}/dhparam.pem ; then
|
||||
if ! test -f /etc/ssl/certs/${my_array[0]}/dhparam.pem ; then
|
||||
echo "try to create ssl key using openssl "
|
||||
if ! test -d /etc/ssl/certs/${my_array[0]}/ ; then
|
||||
echo "create "${my_array[0]}" folder: /etc/ssl/certs/"${my_array[0]}"/"
|
||||
mkdir -p /etc/ssl/certs/${my_array[0]}/
|
||||
fi
|
||||
openssl dhparam -out /etc/ssl/certs/${my_array[0]}/dhparam.pem 4096
|
||||
if ! test -d /ssl/${my_array[0]}/ ; then
|
||||
echo "create "${my_array[0]}" folder: /ssl/"${my_array[0]}"/"
|
||||
mkdir -p /ssl/${my_array[0]}/
|
||||
fi
|
||||
cp /etc/ssl/certs/${my_array[0]}/dhparam.pem /ssl/${my_array[0]}/ -r
|
||||
# else
|
||||
# echo "copy ssl folder by already maden"
|
||||
# cp /ssl/certs/$domain/dhparam.pem /etc/ssl/certs/dhparam.pem -r
|
||||
fi
|
||||
else
|
||||
if ! test -d /etc/ssl/certs/${my_array[0]}/ ; then
|
||||
echo "create "${my_array[0]}" folder: /etc/ssl/certs/"${my_array[0]}"/"
|
||||
mkdir -p /etc/ssl/certs/${my_array[0]}/
|
||||
fi
|
||||
cp /ssl/${my_array[0]}/dhparam.pem /etc/ssl/certs/${my_array[0]}/ -r
|
||||
fi
|
||||
# done
|
||||
|
||||
#if ! test -d /etc/letsencrypt/live/test.com ;
|
||||
if ! test -d /etc/letsencrypt/${my_array[0]}/letsencrypt ; then
|
||||
echo "try to create authentication key using certbot "
|
||||
certbot certonly --non-interactive --agree-tos --email $mail --webroot -w /www/$webroot_folder$domain_string
|
||||
echo "certbot certonly --non-interactive --agree-tos --email "$mail" --webroot -w /www/"$webroot_folder$domain_string
|
||||
# if ! test -d /ssl/letsencrypt/$domain/ ; then
|
||||
# echo "create domain folder: /ssl/letsencrypt/"$domain"/"
|
||||
# mkdir -p /ssl/letsencrypt/$domain/
|
||||
# fi
|
||||
#cp /etc/letsencrypt/ /ssl/letsencrypt/$domain/ -r
|
||||
# else
|
||||
# echo "copy letsencrypt folder by already maden"
|
||||
# cp /ssl/letsencrypt/$domain/ /etc/letsencrypt/ -r
|
||||
fi
|
||||
|
||||
cat <(crontab -l) <(echo '0 5 * * 1 certbot renew --quiet --deploy-hook "service nginx restart" > /log/nginx/crontab_renew.log 2>&1') | crontab -
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Uvicorn Celery Worker 로그 로테이션 설정
|
||||
# - Docker 컨테이너 환경에서 무중단 운영을 위해 copytruncate 방식 사용
|
||||
# - copytruncate: 로그 파일을 복사 후 원본을 비우는 방식 (서비스 재시작 불필요)
|
||||
# - 로테이션 순간 극소량의 로그가 누락될 수 있으나 서비스는 중단되지 않음
|
||||
/log/uvicorn/celery/*.log {
|
||||
daily
|
||||
size 100M
|
||||
rotate 30
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
delaycompress
|
||||
copytruncate
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Uvicorn Celery Beat 로그 로테이션 설정
|
||||
# - Docker 컨테이너 환경에서 무중단 운영을 위해 copytruncate 방식 사용
|
||||
# - copytruncate: 로그 파일을 복사 후 원본을 비우는 방식 (서비스 재시작 불필요)
|
||||
# - 로테이션 순간 극소량의 로그가 누락될 수 있으나 서비스는 중단되지 않음
|
||||
/log/uvicorn/celerybeat/*.log {
|
||||
daily
|
||||
rotate 30
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
delaycompress
|
||||
copytruncate
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Uvicorn 로그 로테이션 설정
|
||||
# - Docker 컨테이너 환경에서 무중단 운영을 위해 copytruncate 방식 사용
|
||||
# - copytruncate: 로그 파일을 복사 후 원본을 비우는 방식 (서비스 재시작 불필요)
|
||||
# - 로테이션 순간 극소량의 로그가 누락될 수 있으나 서비스는 중단되지 않음
|
||||
/log/uvicorn/*.log {
|
||||
daily
|
||||
size 100M
|
||||
rotate 30
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
delaycompress
|
||||
copytruncate
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# Nginx 로그 로테이션 설정
|
||||
# - Docker 컨테이너 환경에서 무중단 운영을 위해 copytruncate 방식 사용
|
||||
# - copytruncate: 로그 파일을 복사 후 원본을 비우는 방식 (서비스 재시작 불필요)
|
||||
# - 로테이션 순간 극소량의 로그가 누락될 수 있으나 서비스는 중단되지 않음
|
||||
/log/nginx/*.log {
|
||||
daily
|
||||
size 100M
|
||||
rotate 30
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
delaycompress
|
||||
create 0640 nginx nginx
|
||||
sharedscripts
|
||||
postrotate
|
||||
# Nginx에 USR1 signal 전송
|
||||
if [ -f /var/run/nginx.pid ]; then
|
||||
kill -USR1 `cat /var/run/nginx.pid`
|
||||
fi
|
||||
endscript
|
||||
}
|
||||
Loading…
Reference in New Issue