사설 HTTPS 워드프레스 사이트 를 만들면서 겪었던 시행착오 또는 유사한 요구사항을 가진 분들이 있을 것 같아서 정리하였습니다.

HTTPS 워드프레스 사이트 구축 요구사항

  • 간단한 변경사항 또는 SEO 작업 등을 추가 개발 없이 수행할 수 있어야 한다.
  • 언제든 쉽게 기존 데이터를 가지고 서버를 변경하여 이식 가능해야 한다.
  • HTTPS를 지원해야 한다.

워드프레스는 간편하게 설치할 수 있고, 운영에 필요한 모든 것이 갖춰져 있어 추가 개발이 거의 필요하지 않아 기본 플랫폼으로 선택하였습니다. 사설 HTTPS 워드프레스 사이트를 구축하고 언제든 확장 서버로 이전하거나 클라우드 플랫폼으로 이식할 수 있도록 portable하게 구성하였습니다.

언제든 쉽게 기존 데이터를 가지고 서버를 변경할 수 있도록 Docker 서비스를 이용하였습니다.

HTTPS를 지원하기 위한 Certificate는 Let’s encrypt의 Certbot을 이용해 발급받아 적용하였습니다.

HTTPS 워드프레스 사이트 구축 System Design

HTTPS 워드프레스 사이트 웹서버는 호스트에서 직접 Nginx를 이용해 구동합니다. 그리고 웹 어플리케이션 구성요소로 필요한 WordPress와 MySQL은 공개되어 있는 Docker 이미지를 이용해 컨테이너로 구동합니다. 호스트에서 구동한 Nginx 웹서버는 HTTPS를 처리하는 동시에 Reverse Proxy 역할만 합니다. 그리고 HTTP 요청에 대해서는 HTTPS로 Redirection해 줍니다. 그 이외에 모든 애플리케이션 요청은 Docker 컨테이너에서 처리합니다. 아래는 요구사항을 구현하는 시스템 구성도입니다.

HTTPS 워드프레스 사이트 시스템 구성도
시스템 구성도

Server Preparation

예제에서는 Google Cloud Platform(GCP)을 사용해서 서버 인스턴스를 생성하였습니다. 이 부분은 익숙한 Cloud/Local/IDC/사설호스팅 서버 등을 사용하시면 되겠습니다. 이미 서버가 준비되었다면 이 단락은 생략해도 됩니다.

GCP Console에서 VM 인스턴스 생성
GCP Console에서 VM 인스턴스 생성

예제에서는 인스턴스를 생성할 때 DB 데이터와 워드프레스 데이터를 별도의 디스크에 저장하도록 설정하였습니다. 기본 디스크가 사이트를 운영하는데 충분할 정도로 크다면 별도의 디스크를 생성할 필요가 없습니다.

예제에서는 20GB의 기본 디스크에 Ubuntu 18.04 운영체제 이미지를 이용해 인스턴스를 생성하였습니다. 여기에 200GB의 데이터용 보조 디스크를 추가하였습니다. 디스크를 추가하는 방법은 이 문서에서 잘 설명하고 있습니다. 대부분의 리눅스 기반 운영체제에서 유사한 방식으로 디스크를 추가하게 됩니다. 기술적인 내용을 잘 모르더라도 문서를 따라서 하다보면 쉽게 디스크를 추가할 수 있습니다.

그 외에 고정 IP 설정과 DNS 레코드 추가 등 네트워크를 위해 필요한 작업도 마무리하고 서버 콘솔에 SSH로 접속해 봅니다.

그리고 DNS 서비스를 통해 새로 생성한 인스턴스를 voidint.com 이라는 도메인 이름으로 등록하였습니다.

Docker Installation

아래의 명령어로 Docker 설치를 위해 필요한 패키지를 먼저 설치합니다.

$ sudo apt update && sudo apt install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

다음은 도커의 GPG 키를 다운로드하고 저장소에 추가합니다.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

그리고 Docker 패키지들을 저장소 소스 목록에 업데이트합니다.

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

패키지 저장소를 갱신하고 Docker 패키지가 검색되는지 확인합니다.

$ sudo apt update && sudo apt-cache search docker-ce

위의 과정이 정상적으로 진행되었다면 다음과 유사한 출력을 확인할 수 있습니다.

docker-ce-cli - Docker CLI: the open-source application container engine
docker-ce - Docker: the open-source application container engine

Docker를 설치합니다.

$ sudo apt install docker-ce

설치가 완료되었다면 현재 사용자를 docker 그룹에 추가해 줍니다. 그룹에 추가하지 않은 사용자는 docker CLI를 사용할 수 없게 되므로 추가하는 것을 권합니다.

$ sudo usermod -aG docker $USER

MySQL & WordPress Container

시스템 구성도와 같이 MySQL과 WordPress는 Docker 컨테이너로 구동할 것입니다. 그리고 각각의 데이터용 volume은 데이터 디스크에 지정하도록 하겠습니다. Docker 설치가 잘 되었다면 컨테이너를 구동하는 것은 간단합니다.

컨테이너를 구동하는 방법은 inline 방식으로 구동할 수도 있고, docker-compose를 이용할 수도 있습니다. 예제에서는 docker-compose를 이용해 구동하도록 하겠습니다. 어렵지 않습니다. 우선 docker-compose를 설치합니다.

$ sudo apt install docker-compose

적당한 디렉토리에 docker-compose.yml 파일을 다음과 같이 생성합니다. “MY_”로 시작하는 부분은 각자의 필요에 맞게 설정해 주면 됩니다.

version: "3.1"
services:
  wordpress:
    image: wordpress:latest
    container_name: mywp
    depends_on:
      - db
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: MY_USERNAME
      WORDPRESS_DB_PASSWORD: MY_PASSWORD
      WORDPRESS_DB_NAME: MY_DBNAME
      WORDPRESS_TABLE_PREFIX: wp_
    volumes:
      - /mnt/disks/data-disk-200g/wordpress-data:/var/www/html

  db:
    image: mysql:latest
    container_name: mydb
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: MY_DBNAME
      MYSQL_USER: MY_USERNAME
      MYSQL_PASSWORD: MY_PASSWORD
      MYSQL_ROOT_PASSWORD: MY_ROOT_PASSWORD
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    volumes:
      - /mnt/disks/data-disk-200g/mysql-data:/var/lib/mysql

다음의 명령어로 Docker 컨테이너를 구동합니다.

$ docker-compose up -d

컨테이너가 잘 동작하고 있는지 확인해 보겠습니다.

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
d97xxxxxx4c9        wordpress:latest    "docker-entrypoint.s…"   2 minutes ago        Up 2 minutes         0.0.0.0:8080->80/tcp                mywp
261xxxxxxb7d        mysql:latest        "docker-entrypoint.s…"   2 minutes ago        Up 2 minutes         0.0.0.0:3306->3306/tcp, 33060/tcp   mydb

워드프레스가 구동되고 있는 mywp 컨테이너와 MySQL이 구동되고 있는 mydb 컨테이너가 잘 동작하고 있는 것을 확인할 수 있을 것입니다.

HTTPS 워드프레스 사이트 Certificate Issuance

Let’s Encrypt의 Certbot을 이용하여 HTTPS 인증서를 발급받을 수 있습니다. 무료이고 과정 대부분 자동화되어 있어 어렵지 않습니다. Docker 설치시와 유사하게 아래의 명령을 차례로 실행하여 Certbot을 패키지 저장소 목록에 업데이트합니다.

이 명령어 블럭은 더 이상 동작하지 않는 것으로 확인되었습니다. 사용하지 마세요.
$ sudo apt update
$ sudo apt install software-properties-common
$ sudo add-apt-repository universe
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt update

아래의 명령을 실행하여 Certbot을 설치합니다.

이 명령어 블럭은 더 이상 동작하지 않는 것으로 확인되었습니다. 사용하지 마세요.
$ sudo apt install certbot python-certbot-nginx

Certbot에서 apt 서비스를 삭제해서 더 이상 동작하지 않는 것으로 확인됩니다. (2021.04.14 기준) 아래의 커맨드를 이용해 certbot을 설치할 수 있습니다.

$ sudo snap install certbot --classic

Certbot CLI를 이용하여 인증서를 발급받습니다.

$ sudo certbot --standalone -d voidint.com certonly

이후 입력을 필요로 하는 항목에 긍정적으로 답변을 하다 보면 인증서 발급이 완료됩니다.

Host Web Server Nginx

서버 머신의 호스트에서 직접 동작하는 웹서버를 구동하여 Reverse Proxy 역할 및 HTTPS 처리를 담당하도록 구성해 보겠습니다. 먼저 nginx를 설치합니다.

$ sudo apt install nginx

Nginx 설치가 완료되면 새로운 서버 블록 파일을 생성합니다. 익숙한 편집기를 이용하여 아래의 파일을 생성합니다.

$ sudo vi /etc/nginx/sites-available/reverse-proxy.conf

편집시 reverse-proxy.conf 파일은 아래와 같이 설정합니다. “voidint.com” 부분만 자신이 소유한 도메인 이름으로 변경하면 됩니다.

server {
    server_name voidint.com;

    location / {
        proxy_redirect off;
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://localhost:8080/;
        proxy_redirect off;
        proxy_http_version 1.1;
    }

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/voidint.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/voidint.com/privkey.pem; # managed by Certbot
}
server {
    if ($host = voidint.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    if ($host = www.voidint.com) {
        return 301 https://voidint.com$request_uri;
    }

    listen 80;

    server_name voidint.com;
    return 404; # managed by Certbot

}

내용을 약간 살펴보면 HTTPS 프로토콜 요청 입수시 http://localhost:8080 프록시 하도록 설정했습니다. localhost의 8080 포트는 앞서 구동한 워드프레스 도커 컨테이너로 요청하게 됩니다. 혹시 규모가 커져서 서버를 분리하는 경우 해당 서버의 목적지를 써주면 다를 바 없이 설정에 기술한 대상을 Reverse Proxy하게 됩니다. HTTP 요청 입수시에는 301로 https://$host$request_uri 로 redirection 하도록 설정된 것을 확인할 수 있습니다.

활성화된 사이트에 기본 설정된 사이트를 삭제하고, 방금 생성한 reverse proxy conf 파일의 링크를 연결해 줍니다.

$ cd /etc/nginx/sites-enabled
$ sudo rm default
$ sudo ln -s /etc/nginx/sites-available/reverse-proxy.conf reverse-proxy

이제 모든 설정이 완료되었습니다. Nginx를 재구동합니다.

$ sudo service nginx restart

브라우저를 열어 자신의 워드프레스 사이트에 접속하고 마음껏 컨텐츠를 만들어 보시기 바랍니다. 미흡한 내용이나 보충하고 싶은 이야기가 있으시다면 댓글을 이용해 제안해 주시기 바랍니다.


Jay

Jay

S/W Engineer!!

8개의 댓글

자유인 · 2020-07-09 01:03

따라 하니 금방 구축했습니다. 추천합니다!!!

성문경 · 2020-07-30 13:58

혹시 비용 정산하고 구축이나 운영은 별도로 안해 주시나요? 간단한 내용 홍보할 수 있는 일반적인 회사 홈페이지 정도입니다. 연락 주세요.

Django DB 로 MySQL 도커 컨테이너 사용하기 - voidint.com · 2020-11-09 17:13

[…] 설치는 이전 글에 기술했던 Docker Installation 부분과 […]

Snap으로 docker 설치 하기 Ubuntu 20.04 - voidint.com · 2021-06-28 19:15

[…] 여러 글에서 Docker를 이용하는 내용이 많았는데, 요즘에는 Snap으로 docker 설치 가 무척 간편해졌습니다. 이에 […]

서버 리부팅시 도커 컨테이너 재시작 - voidint.com · 2022-02-04 11:03

[…] 과거에 작성한 글에서 언급한 바와 같이 블로그 사이트는 docker-compose 를 이용해서 구동하였습니다. 구동을 위한 YAML 파일은 아래와 같은 형태로 작성이 되었는데요. […]

워드프레스 사이트 해킹 복구 과정 - voidint.com · 2022-08-11 11:44

[…] 계시는 사이트도 워드프레스 기반입니다. 설치를 염두에 두고 있는 분은 이 글을 참고하시고 보안성 강화 차원에서 본 글도 일독을 […]

답글 남기기

Avatar placeholder