> ## Content Index
> Fetch the complete content index at: https://www.popit.kr/llms.txt
> Use this file to discover other available public pages before exploring further.

# proxy 뒤에서 docker의 wordpress, https 적용
- URL: https://www.popit.kr/docker-wordpress-https-behind-proxy/
- Published: 2020-03-31T01:04:44.000Z
- Updated: 2020-03-31T05:32:14.000Z
- Author: 김형준
- Tags: #소프트웨어, WordPress, 도커, https

이번 글은 Nginx proxy 뒤에 다시 Docker 실행된 wordpress에 https 를 적용하면서 겪었던 문제 및 해결 방법을 공유한 글입니다.

이런 구성을 말로만 설명하려니 조금 복잡한데 아래 글에 있는 구성에서 이 서버에 홈페이지를 추가 하기 위해 wordpress docker container를 실행했습니다.

- [커머스 코드 자산화 개발일지 - 4 출시](https://www.popit.kr/commerce-code-asset-4-launch/)

실제 구성은 다음과 같이 됩니다.

![wordpress_docker_https](https://www.popit.kr/content/images/wp/2020/03/wordpress_docker_https-600x492.png)

구성을 보시면 하나의 서버에 다양한 API 서버가 실행되고 있고 각각은 다른 서브 도메인을 사용하고 있습니다. 이들 도메인 간의 proxy 설정을 위해 가장 앞 단에 nginx를 위치하고 있습니다.

## 기본 설정

이런 구성에서 위 구성의 하단에 있는 wordpress를 이용하여 홈페이지를 새롭게 설치하려고 합니다. wordpress도 설치를 쉽게 하기 위해 공식적으로 제공하는 Wordpress docker 를 사용하였습니다. Wordpress docker의 경우 Apache 서버, PHP, Wordpress가 하나의 이미지로 구성된 이미지 파일입니다. Apache의 기본 port는 80으로 실행되어 있습니다. 대략 세부 구성은 다음과 같습니다.

- 앞 단의 Nginx가 80 포트 사용
- Docker내의 Apache는 8080으로 구성

Wordpress의 사이트 URL을 https로 변경  

```
define( 'WP_HOME', 'https://www.eryuan.co/' );
define( 'WP_SITEURL', 'https://www.eryuan.co/' );
```

**\[보완 2020-03-31\] 글 작성 후 댓글로 위 설정 중 X-Forworded-Proto 설정을 변경하면 된다고 제안하신 분이 있어 다음과 같이 설정하였습니다. 이렇게 수정한 다음에는 wp-config.php를 수정하지 않아도 정상 동작하였습니다. 참고하세요.**

```
proxy_set_header        X-Forwarded-Proto https;
proxy_set_header        X-Forwarded-Port  443;
```

Nginx에서 다음과 같은 설정을 통해 https 구성 및 Redirect 설정  

```
server {
    listen      80;
    server_name www.eryuan.co;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name www.eryuan.co;

    ssl_certificate /workspace/https_key/www/www.eryuan.co.pem;
    ssl_certificate_key /workspace/https_key/www/www.eryuan.co.key;
    location / {
        proxy_set_header        X-Real-IP         $remote_addr;
        proxy_set_header        X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header        Host              $host;
        proxy_set_header        X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_set_header        X-Forwarded-Port  $http_x_forwarded_port;

        proxy_pass              http://127.0.0.1:8080/;
    }
}
```

위 구성에서 다음과 같은 앞 단의 nginx가 80 포트를 사용하고 있기 때문에 Apache의 port는 8080을 설정하였습니다.

## https 요청에 대한 처리

이런 구성에서 http://www.eryuan.co로 오는 요청의 경우 위 nginx 설정에 있는 listen 80 설정에서 return 301 항목을 보면 https로 바꾸어서 redirect를 보내고 있습니다. 이렇게 하면 브라우저가 이 응답을 받은 후 다시 https://www.eryuan.co로 요청을 보냅니다.

https://www.eryuan.co 요청을 받으면 listen 443 ssl 설정 부분을 통해 인증서를 찾고, proxy\_pass 설정에 의해 로컬의 docker에 설치된 8080 포트로 리다이렉트 합니다. 이때 wordpress docker에 있는 Apache에는 https와 관련된 설정은 아무것도 하지 않고 http 로만 설정된 상태입니다.

## 발생한 문제

이런 구성에서 wordpress 관리를 위해 https://www.eryuan.co/wp-admin 으로 접속하면 문제가 발생합니다.

![wordpress_admin_error](https://www.popit.kr/content/images/wp/2020/03/wordpress_admin_error-600x309.png)

자세히 보면 ERR\_TOO\_MANY\_REDIRECTS 에러가 발생하고 있습니다. 브라우저의 개발자 도구에서 네트워크 상황을 보면 다음과 같습니다.

![https_error_details](https://www.popit.kr/content/images/wp/2020/03/https_error_details-600x425.jpg)

Response를 302(Redirect) https://www.eryuan.co/wp-admin/ 로 받았기 때문에 다시 서버로 요청하게 되는데 이 요청의 결과도 다시 302 Redirect가 오게 되어 무한 반복되는 문제가 발생합니다.

## 문제 해결

여러 워드프레스 관련 질의 응답 페이지를 확인해 보았지만 대부분은 docker 자체가 직접 https 를 받는 경우에 대한 설명이라 이들 설명을 바탕으로 조금 응용을 해야만 했습니다. wp-config.php 코드 중 https 요청에 대한 인식 부분을 수정하여 문제를 해결했습니다.

원래 코드는 다음과 같습니다.  

```
// If we're behind a proxy server and using HTTPS, we need to alert Wordpress of that fact
// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] = 'on';
}
```

대략 주석과 코드를 보면 HTTP\_X\_FORWARDED\_PROTO가 https 로 설정되어 있으면 HTTPS 설정을 on 시키겠다는 의미인 것 같습니다. 이 값은 워드프레스의 웹서버로 설정된 Apache 로 부터 받아야 하는데 Apache의 설정이 http로 되어 있기 때문에 이 설정이 on이 되지 않다고 생각을 하고 아래와 같이 강제로 $\_SERVER\['HTTPS'\] = 'on'; 이 코드가 실행되도록 하였습니다.  

```
//if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] = 'on';
//}
```

if 로직 부분을 주석 처리만 하였습니다.

이렇게 수정한 후에는 정상적으로 잘 동작하는 것을 확인할 수 있었습니다.

**\[보완 2020-03-31\] nginx 설정에서 X-Forwarded-Proto 값을 강제적으로 https 로 설정하면 wp-congif.php 소스 코드를 수정하지 않아도 정상동작합니다.** 

## 결론

워드프레스의 코드에 있는 HTTP\_X\_FORWARDED\_PROTO 이 부분을 앞단의 웹 서버에서 어떻게 전달해야 하는지 정확하게 알면 소스 코드 수정없이 설정만으로 작업을 할 수 있을 것 같은데 거기까지 확인은 해보지 않았습니다. 따라서 필자의 해결 방법은 임시적인 해결 방법이라고 할 수 있습니다. 좀 더 웹서버, 워드 프레스의 동작 원리를 찾아봐야 정확하게 설정하는 방법을 알겠지만 시간적인 여유나 귀챠니즘으로 인해 여기까지만 확인하고 중단하였습니다. 이런 경험을 글로 공유하여 비슷한 문제를 겪으시는 분들에게 조금이나마 도움이 되었으면 하는 바램과 이 부분에 대해 잘 아시는 분의 답변을 기다리기로 했습니다.

\[보완\] 이 글을 쓴 취지에 맞게 글 공유된 후 바로 댓글로 해결책을 알려주셨습니다. 적용 후 정상 동작하는 것을 확인하였습니다. 본문에 내용 반영하였습니다. 다만 아직도 애매한 부분은 nginx에서 443 listen시 "$http\_x\_forwarded\_proto" 변수 값이 https가 아니고 무엇이지 하는 생각은 듭니다. 구글 검색을 해도 잘 나오지 않네요.

\[보완 2차\]

다음 글은 박종훈 님이 페북 댓글로 달아주신 내용입니다.

\=================

'$http\_x\_forwarded\_proto' 변수와 같이 $http\_xxx로 시작하는 변수는 ngx\_http\_core\_module 모듈에서 추가해주는 변수입니다.  
(참고: [https://nginx.org/en/docs/http/ngx\_http\_core\_module.html](https://nginx.org/en/docs/http/ngx%5Fhttp%5Fcore%5Fmodule.html?ref=popit.kr))

위 URL을 보시면, 다음과 같이 설명을 하고 있습니다.

> 'The ngx\_http\_core\_module module supports embedded variables with names matching the Apache Server variables. First of all, these are variables representing client request header fields, such as $http\_user\_agent, $http\_cookie, and so on.'

HTTP 요청헤더의 필드들을 자동으로 변수에 세팅해줍니다. 가령, Cookie 헤더는 $http\_cookie로, User-Agent 헤더는 $http\_user\_agent 변수로 세팅을 해줍니다.

마찬가지로, 요청헤더에 X-Forwarded-Proto 라는 헤더가 있다면 $http\_x\_forwarded\_proto 라는 변수로 세팅되었을 것입니다. (그래서 구글링해도 잘 안나왔을 겁니다ㅠㅠ 모듈에서 자동으로 추가해주는 값이라..)

추측 하건데, 이전에 nginx 앞단에 LB나 다른 프록시 역할을 하는 layer가 있어서 해당 설정을 추가하셨던것이 아닌가 생각됩니다\~ 그런데 구성이 바뀌면서 해당 설정이 오히려 문제를 일으켰던것 같습니다^^;

\=================