VPS에 1Panel을 설치하고, Discourse를 컨테이너로 배포한 뒤, OpenResty(컨테이너 배포)로 리버스 프록시를 설정했습니다. 도메인은 Cloudflare에 호스팅되어 있으며, CDN(오렌지 클라우드)이 활성화되어 있습니다. 아래는 사용자 IP가 Cloudflare에서 온 것으로 표시되는 문제가 아니라, 실제 사용자 브라우저 IP로 표시되도록 해결하는 방법입니다.
1. 1Panel에서 정기 작업을 생성하여 매주 최신 Cloudflare IP 목록을 다운로드하고 OpenResty 설정 디렉터리에 저장합니다.
-
1Panel 왼쪽 메뉴바에서 **“정기 작업”**을 클릭합니다.
-
오른쪽 상단의 **“정기 작업 생성”**을 클릭합니다.
-
아래 매개변수에 따라 입력합니다(복사해서 붙여넣기 가능):
-
작업 유형: Shell 스크립트 선택.
-
작업 이름: 예:
Cloudflare IP 세그먼트 자동 업데이트. -
실행 주기: 매주를 권장합니다(예: 매주 토요일 오전 03:00).
-
스크립트 내용: 아래 전체 코드를 그대로 복사하여 붙여넣으십시오(주의: 코드의 맨 위쪽 컨테이너 이름과 설정 디렉터리 경로를 먼저 수정해야 합니다):
#!/bin/bash
# 설정 영역
CONTAINER_NAME="1Panel에서 openresty 컨테이너 이름"
# 지정된 웹사이트 proxy 디렉터리로 수정
CONF_DIR="/opt/1panel/www/sites/www.당신의도메인.club/proxy"
echo "[$(date)] Cloudflare 공식 사이트에서 최신 IP 세그먼트 가져오기 시작..."
TEMP_DIR=$(mktemp -d)
# IP 목록을 가져와 Nginx가 인식하는 형식으로 변환
curl -fsS https://www.cloudflare.com/ips-v4 | sed 's/.*/set_real_ip_from &;/' > $TEMP_DIR/cf-ips-v4.conf
curl -fsS https://www.cloudflare.com/ips-v6 | sed 's/.*/set_real_ip_from &;/' > $TEMP_DIR/cf-ips-v6.conf
# 파일 확인 및 이동
if [[ -s $TEMP_DIR/cf-ips-v4.conf ]] && [[ -s $TEMP_DIR/cf-ips-v6.conf ]]; then
mv $TEMP_DIR/cf-ips-v4.conf $CONF_DIR/
mv $TEMP_DIR/cf-ips-v6.conf $CONF_DIR/
echo "[$(date)] 설정 파일이 $CONF_DIR에 성공적으로 업데이트되었습니다."
else
echo "[$(date)] 오류: Cloudflare IP 가져오기 실패!"
rm -rf $TEMP_DIR
exit 1
fi
rm -rf $TEMP_DIR
# Nginx 테스트 및 재로드
echo "[$(date)] Nginx 설정 테스트 중..."
if docker exec $CONTAINER_NAME nginx -t; then
docker exec $CONTAINER_NAME nginx -s reload
echo "[$(date)] 성공! OpenResty 설정 재로드 완료."
else
echo "[$(date)] 실패! Nginx 설정 테스트를 통과하지 못했습니다."
exit 1
fi
작업이 생성된 후에는 토요일을 기다릴 필요가 없습니다. 바로 테스트할 수 있습니다: “정기 작업” 목록에서 방금 생성한 작업을 찾습니다.
오른쪽의 “보고서” 버튼을 클릭합니다. 팝업된 로그 창을 확인합니다. 마지막 몇 줄에 성공! OpenResty 설정 재로드 완료라고 표시되면 1Panel 내부에서 전체 프로세스가 완벽하게 작동하고 있음을 의미합니다!
2. OpenResty에 realip 설정 추가
호스트 머신의 /opt/1panel/www/sites/www.당신의도메인/proxy/ 디렉터리에 새 파일을 생성합니다(파일명은 임의이며, .conf로 끝나면 됩니다. 메인 설정의 include *.conf에 의해 자동으로 로드됩니다): realip.conf
# 컨테이너 내 경로 사용
include /www/sites/www.당신의도메인/proxy/cf-ips-v4.conf;
include /www/sites/www.당신의도메인/proxy/cf-ips-v6.conf;
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
3. OpenResty 재로드
docker exec 1Panel에서 openresty 컨테이너 이름 nginx -t
docker exec 1Panel에서 openresty 컨테이너 이름 nginx -s reload
4. OpenResty가 실제 IP를 가져오는지 확인
OpenResty의 access 로그를 확인합니다:
tail -f /opt/1panel/www/sites/www.당신의도메인/log/access.log
설정이 올바르게 되어 있다면, 로그의 첫 번째 IP가 Cloudflare의 173.245.x.x 등의 세그먼트가 아니라 실제 공개 IP로 변경되어야 합니다.
5. Discourse 측 설정
app.yml을 편집하고, run: 코드 블록 내에 다음 내용을 추가합니다:
#docker로 discourse를 배포한 후, 다음 세 단계를 추가하여 포럼 사용자의 실제 IP가 전달되도록 보장해야 합니다
- file:
path: /etc/nginx/conf.d/outlets/server/set-real-ip-from-docker.conf
chmod: 644
contents: |
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 127.0.0.1;
- file:
path: /etc/nginx/conf.d/outlets/server/real-ip-header.conf
chmod: 644
contents: |
real_ip_header x-forwarded-for;
- file:
path: /etc/nginx/conf.d/outlets/server/real-ip-recursive.conf
chmod: 644
contents: |
real_ip_recursive on;
이렇게 하면 Discourse 내장 Nginx는 다음을 수행합니다:
- Docker 네트워크 세그먼트(
172.16.0.0/12)를 신뢰합니다. x-forwarded-for에서 실제 IP를 읽습니다.- 다중 프록시를 재귀적으로 분석합니다.
6. 참고 사항
Discourse의 app.yml에 - "templates/cloudflare.template.yml"를 추가하는 것은 Discourse가 Cloudflare에 직접 노출될 때만 유효합니다. 중간에 OpenResty 리버스 프록시를 추가했기 때문에, Discourse 컨테이너가 보는 출처 IP는 실제로 Docker 게이트웨이(예: 172.17.0.1 또는 172.18.0.1)입니다. 따라서 해당 템플릿의 set_real_ip_from <CloudflareIP>는 매칭되지 않습니다.
따라서 Discourse의 app.yml에 - "templates/cloudflare.template.yml"를 추가할 필요가 없습니다.
2026-07-03 업데이트