WordPress 설치 자동화를 위한 NGINX Unit 자습서
WordPress 설치에 대한 엄청난 양의 정보가 있습니다. 구글에서 “WordPress 설치”를 검색하면 이 글을 작성한 시점에서 488,000개의 결과를 얻을 수 있습니다. 그러나 이러한 결과 중에는 장기적으로 유지 관리할 수 있는 방식으로 WordPress와 기본 운영 체제를 모두 설치하는 방법을 포괄적으로 설명하는 자습서가 거의 없습니다. 아마도 그것은 올바른 구성이 특정 요구 사항에 따라 너무 많이 다르기 때문이거나 포괄적인 가이드가 읽기 쉽게 만들지 않기 때문일 수 있습니다.
이 포스트에서 우리는 Ubuntu에서 WordPress 설치를 자동화하는 bash 스크립트를 제공하고 각 섹션이 수행하는 작업과 우리가 만든 디자인 장단점을 설명하기 위해 이를 살펴봄으로써 두 세계의 장점을 결합하려고 합니다. (고급 사용자인 경우 이 포스트를 건너뛰고 스크립트로 직접 이동하여 다운로드하고 환경에 맞게 수정할 수 있습니다.) 결과적으로 WordPress 설치는 스크립트 가능하고 Let’s Encrypt를 지원하며 NGINX Unit을 사용하고 Production 준비 설정이 있습니다.
- WordPress CLI
- Let’s Encrypt 및 TLS/SSL 인증서
- 자동 Let’s Encrypt 갱신
- NGINX Caching
- NGINX Compression
- NGINX HTTPS 및 HTTP/2
- 프로세스 자동화
이 포스트는 정적 자산 웹 서버, PHP processing 서버 및 데이터베이스가 같은 위치한 단일 노드에서 WordPress를 설정하는 방법에 대해 설명합니다. 다중 호스트, 다중 서비스 WordPress 구성 설치가 향후 잠재적인 주제입니다.
목차
1. WordPress 설치를 위한 전제조건
2. WordPress 설치를 위한 NGINX Unit 아키텍처(Architecture) 개요
3. 일반 원칙
4. 환경 변수 설정
5. 파생 환경 변수 설정
6. 컴퓨팅 인스턴스에 WordPress 사이트 호스트 이름 할당
7. /etc/hosts에 WordPress 사이트 호스트 이름 추가
8. 이후 단계에 필요한 도구 설치
9. NGINX Unit 및 NGINX Open Source Repository 추가
10. NGINX, NGINX Unit, PHP MariaDB, Certbot(Let’s Encrypt) 및 종속성 설치
11. NGINX Unit 및 WordPress와 함께 사용할 PHP 구성
12. WordPress MariaDB 데이터베이스 초기화
13. WordPress CLI 유틸리티 설치
14. WordPress 설치 및 구성
15. NGINX Unit 구성
16. NGINX Unit 구성
16-1. Core NGINX 매개변수 구성
16-2. NGINX 압축 설정 구성
16-3. WordPress에 대한 NGINX 매개변수 구성
17. Let’s Encrypt 인증서 및 자동 갱신을 위한 Certbot 구성
18. WordPress 사이트 사용자 정의
1. WordPress 설치를 위한 전제조건
- Ubuntu 18.04 이상을 실행하는 최소 512MB의 사용 가능한 메모리가 있는 컴퓨팅 인스턴스 – 컨테이너(LXC 또는 LXD), 가상 머신 또는 Bare Metal 머신
- 컴퓨팅 인스턴스의 포트 80 및 443은 인터넷이 열려 있어야 합니다.
- 컴퓨팅 인스턴스의 Public IP 주소와 이미 연결된 도메인 이름
- root 권한 또는 sudo를 통한 동등한 액세스
2. WordPress 설치를 위한 NGINX Unit 아키텍처(Architecture) 개요
여기에는 PHP 프로세서에 의해 실행되어야 하는 PHP 스크립트와 웹 서버에 의해 전달되어야 하는 정적 파일이 포함됩니다.

3. 일반 원칙
- 스크립트의 구성 명령 대부분은 Idempotency을 위해 조건문(if 문)으로 둘러싸여 있습니다. 스크립트는 이미 올바른 설정을 변경할 위험 없이 여러 번 실행할 수 있습니다.
- 스크립트는 가능 Repository에서 소프트웨어를 설치합니다. 이를 통해 단일 명령(Ubuntu의 경우 apt upgrade)으로 시스템에 보안 패치를 적용할 수 있습니다.
- 명령은 컨테이너에서 실행 중인지 감지하고 그에 따라 구성을 변경하기 위해 최선을 다합니다.
- 구성에서 실행할 프로세스 또는 스레드 수를 지정할 때 스크립트는 컨테이너, 가상 머신 또는 Bare Metal 머신(NGINX Unit의 경우 278행, NGINX의 경우 306행)에서 작동하는 자동 구성 매개변수에 대한 최상의 추측을 제공합니다.
- 자동화 우선 접근 방식을 사용하여 구성을 작성했으며, 이를 통해 재사용 가능한 인프라를 코드로 만들 수 있는 모델이 될 수 있습니다.
- 모든 명령은 코어 시스템 구성을 변경하기 때문에 root로 실행되지만, 런타임 상태에서 WordPress는 일반 사용자 ID로 실행됩니다.
4. 환경 변수 설정
스크립트를 실행하기 전에 다음 환경 변수를 설정하십시오.
- WORDPRESS_DB_PASSWORD – WordPress 데이터베이스의 비밀번호입니다.
- WORDPRESS_ADMIN_USER – WordPress 관리자의 사용자 이름입니다.
- WORDPRESS_ADMIN_PASSWORD – WordPress 관리자의 비밀번호입니다.
- WORDPRESS_ADMIN_EMAIL – WordPress 관리자의 이메일 주소입니다.
- WORDPRESS_URL – https://로 시작하는 WordPress 사이트의 전체 URL입니다.
- LETS_ENCRYPT_STAGING – 기본적으로 공백이지만 구성의 새 배포를 자주 테스트할 때 필요한 스테이징(Staging) Let’s Encrypt 서버를 사용하는 경우 1로 설정됩니다. 그렇지 않으면 Let’s Encrypt가 과도한 요청을 위해 일시적으로 IP 주소를 차단할 수 있습니다.
이 스크립트는 WordPress 관련 변수가 설정되었는지 확인하고 설정되지 않은 경우 종료합니다(8–42행, 여기에 표시되지 않음). 572~576행은 LETS_ENCRYPT_STAGING 값을 확인합니다.
5. 파생 환경 변수 설정
스크립트(55-61행, 여기에 표시되지 않음)는 다음 환경 변수를 하드코딩(Hard-coding)된 값 또는 이전 섹션에서 설정한 변수에서 파생된 값으로 설정합니다.
- DEBIAN_FRONTEND=”noninteractive” – 자동화된 스크립트가 명령을 실행 중이며 사용자 상호 작용이 불가능함을 나타냅니다.
- WORDPRESS_CLI_VERSION=”2.4.0″ – 다운로드할 WordPress CLI의 버전입니다.
- WORDPRESS_CLI_MD5= “dedd5a662b80cda66e9e25d44c23b25c” – WordPress CLI 2.4.0 binary (WORDPRESS_CLI_VERSION 변수로 지정된 버전)의 암호화 체크섬. 162행은 이 값을 사용하여 올바른 WordPress CLI 버전인지 확인합니다.
- UPLOAD_MAX_FILESIZE=”16M” – WordPress에 업로드할 수 있는 파일의 최대 크기입니다. 이 설정은 구성의 여러 위치에서 사용되며 중앙에서 정의하는 것이 유용합니다.
- TLS_HOSTNAME= “$(echo ${WORDPRESS_URL} | cut -d’/’ -f3)” – WORDPRESS_URL 변수에서 추출한 시스템의 주소 지정 가능한 호스트 이름입니다. Let’s Encrypt에서 적절한 TLS/SSL 인증서를 가져오고 WordPress가 자체적으로 ping해야 할 때 사용됩니다.
- NGINX_CONF_DIR=”/etc/nginx” – NGINX 구성 및 기본 구성 파일인 nginx.conf가 포함된 디렉토리의 경로입니다.
- CERT_DIR=”/etc/letsencrypt/live/${TLS_HOSTNAME}” – TLS_HOSTNAME 변수에서 파생된 WordPress 사이트의 호스트 이름에 대한 Let’s Encrypt 인증서의 경로입니다.
6. 컴퓨팅 인스턴스에 WordPress 사이트 호스트 이름 할당
다음 스크립트는 컴퓨팅 인스턴스의 호스트 이름을 WordPress 사이트의 도메인 이름과 일치하도록 설정합니다. 이 옵션은 선택 사항이며 모든 구성에 필요한 것은 아니지만 스크립트에서 구성된 것과 같은 단일 호스트 설정에서 SMTP를 통해 이메일을 보낼 때 유용합니다.
# Change the hostname to be the same as the WordPress hostname
if [ ! "$(hostname)" == "${TLS_HOSTNAME}" ]; then
echo "▶ Changing hostname to ${TLS_HOSTNAME}"
hostnamectl set-hostname "${TLS_HOSTNAME}"
fi
7. /etc/hosts에 WordPress 사이트 호스트 이름 추가
WP‑Cron 플러그인은 WordPress에서 예약된 작업을 실행하는 데 사용되며, WordPress가 HTTP를 통해 자체적으로 ping할 수 있어야 합니다. WP‑Cron이 모든 환경에서 제대로 작동하도록 하기 위해 스크립트는 /etc/hosts에 항목을 추가하여 WordPress가 로컬 Loopback 인터페이스를 통해 자체로 라우팅할 수 있도록 합니다.
# Add the hostname to /etc/hosts
if [ "$(grep -m1 "${TLS_HOSTNAME}" /etc/hosts)" = "" ]; then
echo "▶ Adding hostname ${TLS_HOSTNAME} to /etc/hosts so that WordPress can ping itself"
printf "::1 %s\n127.0.0.1 %s\n" "${TLS_HOSTNAME}" "${TLS_HOSTNAME}" >> /etc/hosts
fi
8. 이후 단계에 필요한 도구 설치
스크립트의 후반부는 특정 유틸리티를 사용하고 저장소 인덱스가 업데이트된 것으로 가정합니다. Repo 인덱스(77행)를 업데이트하고 이 지점(78–84행)에 필요한 도구를 설치합니다.
# Make sure tools needed for install are present
echo "▶ Installing prerequisite tools"
apt-get -qq update
apt-get -qq install -y \
bc \
ca-certificates \
coreutils \
curl \
gnupg2 \
lsb-release
9. NGINX Unit 및 NGINX Open Source Repository 추가
이 스크립트는 NGINX Repository에서 NGINX Unit 및 NGINX Open Source를 설치하여 항상 최신 보안 업데이트 및 버그 수정을 받을 수 있도록 합니다.
여기서 스크립트는 시스템에 서명 키를 추가하고 인터넷에서 Repository의 위치를 정의하는 apt 구성에 파일을 추가하여 NGINX Unit Repository(87–91행) 및 NGINX Open Source Repository(94–98행)를 설치합니다.
NGINX Unit 및 NGINX Open Source의 실제 설치는 다음 섹션에서 진행됩니다. Metadata를 여러 번 업데이트하지 않도록 미리 Repository를 추가하여 전체 설치 속도를 높입니다.
# Install the NGINX Unit repository
if [ ! -f /etc/apt/sources.list.d/unit.list ]; then
echo "▶ Installing NGINX Unit repository"
curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add -
echo "deb https://packages.nginx.org/unit/ubuntu/ $(lsb_release -cs) unit" > /etc/apt/sources.list.d/unit.list
fi
# Install the NGINX repository
if [ ! -f /etc/apt/sources.list.d/nginx.list ]; then
echo "▶ Installing NGINX repository"
curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add -
echo "deb https://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" > /etc/apt/sources.list.d/nginx.list
fi
10. NGINX, NGINX Unit, PHP MariaDB, Certbot(Let’s Encrypt) 및 종속성 설치
모든 Repository가 준비되면 Repository Metadata를 업데이트하고 애플리케이션을 설치합니다. 스크립트에 의해 설치된 패키지에는 WordPress를 실행할 때 권장되는 PHP 확장이 포함되어 있습니다.
echo "▶ Updating repository metadata"
apt-get -qq update
# Install PHP with dependencies and NGINX Unit
echo "▶ Installing PHP, NGINX Unit, NGINX, Certbot, and MariaDB"
apt-get -qq install -y --no-install-recommends \
certbot \
python3-certbot-nginx \
php-cli \
php-common \
php-bcmath \
php-curl \
php-gd \
php-imagick \
php-mbstring \
php-mysql \
php-opcache \
php-xml \
php-zip \
ghostscript \
nginx \
unit \
unit-php \
mariadb-server
11. NGINX Unit 및 WordPress와 함께 사용할 PHP 구성
이 스크립트는 PHP conf.d 디렉토리에 구성 파일을 생성합니다(136–147행). PHP용 업로드 파일의 최대 크기를 설정하고(142행), PHP 오류를 STDERR로 전달하여(145행) NGINX Unit 로그에 기록되도록 하고, NGINX Unit을 다시 시작합니다(151행).
# Find the major and minor PHP version so that we can write to its conf.d directory
PHP_MAJOR_MINOR_VERSION="$(php -v | head -n1 | cut -d' ' -f2 | cut -d'.' -f1,2)"
if [ ! -f "/etc/php/${PHP_MAJOR_MINOR_VERSION}/embed/conf.d/30-wordpress-overrides.ini" ]; then
echo "▶ Configuring PHP for use with NGINX Unit and WordPress"
# Add PHP configuration overrides
cat > "/etc/php/${PHP_MAJOR_MINOR_VERSION}/embed/conf.d/30-wordpress-overrides.ini" << EOM
; Set a larger maximum upload size so that WordPress can handle
; bigger media files.
upload_max_filesize=${UPLOAD_MAX_FILESIZE}
post_max_size=${UPLOAD_MAX_FILESIZE}
; Write error log to STDERR so that error messages show up in the NGINX Unit log
error_log=/dev/stderr
EOM
fi
# Restart NGINX Unit because we have reconfigured PHP
echo "▶ Restarting NGINX Unit"
service unit restart
12. WordPress MariaDB 데이터베이스 초기화
WordPress 데이터베이스로 MySQL 대신 MariaDB를 사용하기로 했습니다. MariaDB는 보다 활발한 오픈 소스 커뮤니티를 보유하고 있으며 더 좋은 성능을 제공합니다.
이 스크립트는 새 데이터베이스를 초기화하고 WordPress가 로컬 Loopback 주소를 통해 액세스할 수 있도록 자격 증명을 생성합니다.
# Set up the WordPress database
echo "▶ Configuring MariaDB for WordPress"
mysqladmin create wordpress || echo "Ignoring above error because database may already exist"
mysql -e "GRANT ALL PRIVILEGES ON wordpress.* TO \"wordpress\"@\"localhost\" IDENTIFIED BY \"$WORDPRESS_DB_PASSWORD\"; FLUSH PRIVILEGES;"
13. WordPress CLI 유틸리티 설치
이제 스크립트가 WP‑CLI 유틸리티를 설치합니다. 이를 사용하여 WordPress를 설치 및 관리하면 파일을 수동으로 수정하거나 데이터베이스를 업데이트하거나 WordPress 관리자 패널로 이동하지 않고도 WordPress 구성을 완전히 제어할 수 있습니다. 테마 또는 플러그인을 설치하고 WordPress를 업그레이드하는 데 사용할 수도 있습니다.
if [ ! -f /usr/local/bin/wp ]; then
# Install the WordPress CLI
echo "▶ Installing the WordPress CLI tool"
curl --retry 6 -Ls "https://github.com/wp-cli/wp-cli/releases/download/v${WORDPRESS_CLI_VERSION}/wp-cli-${WORDPRESS_CLI_VERSION}.phar" > /usr/local/bin/wp
echo "$WORDPRESS_CLI_MD5 /usr/local/bin/wp" | md5sum -c -
chmod +x /usr/local/bin/wp
fi
14. WordPress 설치 및 구성
이 스크립트는 최신 버전의 WordPress를 /var/www/wordpress 디렉토리에 설치하고 다음 설정을 구성합니다.
- 데이터베이스는 TCP 트래픽 양을 줄이기 위해 TCP Loopback 인터페이스 대신 Unix 도메인 소켓 Loopback 인터페이스를 통해 연결합니다(175행).
- WordPress는 클라이언트가 HTTPS를 통해 NGINX에 연결할 때 URL에 https:// 접두사를 추가하고 원격 호스트 이름(NGINX에서 제공)을 PHP에 전달합니다. 이 구성을 위해 PHP 코드 Snippet을 사용합니다(180–189행).
- WordPress는 로그인을 위해 HTTPS를 요구합니다(194행).
- WordPress의 기본 URL 구조는 리소스 기반입니다(201행).
- 올바른 파일 시스템 권한이 WordPress 디렉토리에 적용됩니다(207–210행).
if [ ! -d /var/www/wordpress ]; then
# Create WordPress directories
mkdir -p /var/www/wordpress
chown -R www-data:www-data /var/www
# Download WordPress using the WordPress CLI
echo "▶ Installing WordPress"
su -s /bin/sh -c 'wp --path=/var/www/wordpress core download' www-data
WP_CONFIG_CREATE_CMD="wp --path=/var/www/wordpress config create --extra-php --dbname=wordpress --dbuser=wordpress --dbhost=\"localhost:/var/run/mysqld/mysqld.sock\" --dbpass=\"${WORDPRESS_DB_PASSWORD}\""
# This snippet is injected into the wp-config.php file when it is created;
# it informs WordPress that we are behind a reverse proxy and as such
# allows it to generate links using HTTPS
cat > /tmp/wp_forwarded_for.php << 'EOM'
/* Turn HTTPS 'on' if HTTP_X_FORWARDED_PROTO matches 'https' */
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
$_SERVER['HTTPS'] = 'on';
}
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
EOM
# Create WordPress configuration
su -s /bin/sh -p -c "cat /tmp/wp_forwarded_for.php | ${WP_CONFIG_CREATE_CMD}" www-data
rm /tmp/wp_forwarded_for.php
su -s /bin/sh -p -c "wp --path=/var/www/wordpress config set 'FORCE_SSL_ADMIN' 'true'" www-data
# Install WordPress
WP_SITE_INSTALL_CMD="wp --path=/var/www/wordpress core install --url=\"${WORDPRESS_URL}\" --title=\"${WORDPRESS_SITE_TITLE}\" --admin_user=\"${WORDPRESS_ADMIN_USER}\" --admin_password=\"${WORDPRESS_ADMIN_PASSWORD}\" --admin_email=\"${WORDPRESS_ADMIN_EMAIL}\" --skip-email"
su -s /bin/sh -p -c "${WP_SITE_INSTALL_CMD}" www-data
# Set permalink structure to a sensible default that isn't in the UI
su -s /bin/sh -p -c "wp --path=/var/www/wordpress option update permalink_structure '/%year%/%monthnum%/%postname%/'" www-data
# Remove sample file because it is cruft and could be a security problem
rm /var/www/wordpress/wp-config-sample.php
# Ensure that WordPress permissions are correct
find /var/www/wordpress -type d -exec chmod g+s {} \;
chmod g+w /var/www/wordpress/wp-content
chmod -R g+w /var/www/wordpress/wp-content/themes
chmod -R g+w /var/www/wordpress/wp-content/plugins
fi
15. NGINX Unit 구성
이 스크립트는 PHP를 실행하고 WordPress 경로를 처리하도록 NGINX Unit을 구성하고, PHP 프로세스 Namespace를 격리하고, 성능 설정을 조정합니다. 세 가지 주목할만한 기능은 다음과 같습니다.
1. Namespace 지원은 스크립트가 컨테이너에서 실행되고 있는지 여부에 따라 조건부로 정의됩니다(213–224행). 이는 대부분의 컨테이너 구성이 내부에서 추가 컨테이너 실행을 지원하지 않기 때문에 이 작업이 필요합니다.
2. Namespace 지원이 활성화되면 네트워크 Namespace가 비활성화됩니다(218행). 이는 WordPress가 자체 Endpoint에 도달하고 인터넷을 호출할 수 있도록 하는 데 필요합니다.
3. 프로세스의 최대 수는 다음 알고리즘을 사용하여 계산됩니다(226–228행): (MariaDB 및 NGINX Unit 실행 시 사용 가능한 메모리) / (PHP 메모리 제한 + 5). 그런 다음 값은(277-280행)의 NGINX 장치 구성에서 설정됩니다.
이 값은 적어도 두 개 이상의 PHP 프로세스가 실행되도록 합니다. 이는 WordPress가 자체적으로 많은 비동기 Callout을 만들고 추가 프로세스가 없으면 WP‑Cron과 같은 작업이 실패하기 때문에 중요합니다. 여기에서 생성된 설정은 보수적이기 때문에 특정 WordPress 구성에 따라 이 설정을 늘리거나 줄여야 할 수 있습니다. 많은 Production 시스템에서 10에서 100 사이의 설정이 일반적입니다.
if [ ! -d /var/www/wordpress ]; then
# Create WordPress directories
mkdir -p /var/www/wordpress
chown -R www-data:www-data /var/www
# Download WordPress using the WordPress CLI
echo "▶ Installing WordPress"
su -s /bin/sh -c 'wp --path=/var/www/wordpress core download' www-data
WP_CONFIG_CREATE_CMD="wp --path=/var/www/wordpress config create --extra-php --dbname=wordpress --dbuser=wordpress --dbhost=\"localhost:/var/run/mysqld/mysqld.sock\" --dbpass=\"${WORDPRESS_DB_PASSWORD}\""
# This snippet is injected into the wp-config.php file when it is created;
# it informs WordPress that we are behind a reverse proxy and as such
# allows it to generate links using HTTPS
cat > /tmp/wp_forwarded_for.php << 'EOM'
/* Turn HTTPS 'on' if HTTP_X_FORWARDED_PROTO matches 'https' */
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
$_SERVER['HTTPS'] = 'on';
}
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
EOM
# Create WordPress configuration
su -s /bin/sh -p -c "cat /tmp/wp_forwarded_for.php | ${WP_CONFIG_CREATE_CMD}" www-data
rm /tmp/wp_forwarded_for.php
su -s /bin/sh -p -c "wp --path=/var/www/wordpress config set 'FORCE_SSL_ADMIN' 'true'" www-data
# Install WordPress
WP_SITE_INSTALL_CMD="wp --path=/var/www/wordpress core install --url=\"${WORDPRESS_URL}\" --title=\"${WORDPRESS_SITE_TITLE}\" --admin_user=\"${WORDPRESS_ADMIN_USER}\" --admin_password=\"${WORDPRESS_ADMIN_PASSWORD}\" --admin_email=\"${WORDPRESS_ADMIN_EMAIL}\" --skip-email"
su -s /bin/sh -p -c "${WP_SITE_INSTALL_CMD}" www-data
# Set permalink structure to a sensible default that isn't in the UI
su -s /bin/sh -p -c "wp --path=/var/www/wordpress option update permalink_structure '/%year%/%monthnum%/%postname%/'" www-data
# Remove sample file because it is cruft and could be a security problem
rm /var/www/wordpress/wp-config-sample.php
# Ensure that WordPress permissions are correct
find /var/www/wordpress -type d -exec chmod g+s {} \;
chmod g+w /var/www/wordpress/wp-content
chmod -R g+w /var/www/wordpress/wp-content/themes
chmod -R g+w /var/www/wordpress/wp-content/plugins
fi
16. NGINX Unit 구성
16-1. Core NGINX 매개변수 구성
이 스크립트는 NGINX Cache를 위한 디렉토리를 생성한 다음(301행) 기본 NGINX nginx.conf 구성 파일을 생성합니다(304–341행). 구성 설정 중에는 NGINX Worker Process 수(306행)와 최대 업로드 크기(325행)가 있습니다. 329행은 다음 섹션에서 정의된 압축 구성을 가져오고 332-337행은 Caching 매개변수를 설정합니다.
# Make directory for NGINX cache
mkdir -p /var/cache/nginx/proxy
echo "▶ Configuring NGINX"
cat > ${NGINX_CONF_DIR}/nginx.conf << EOM
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include ${NGINX_CONF_DIR}/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/access.log main;
sendfile on;
client_max_body_size ${UPLOAD_MAX_FILESIZE};
keepalive_timeout 65;
# gzip settings
include ${NGINX_CONF_DIR}/gzip_compression.conf;
# Cache settings
proxy_cache_path /var/cache/nginx/proxy
levels=1:2
keys_zone=wp_cache:10m
max_size=10g
inactive=60m
use_temp_path=off;
include ${NGINX_CONF_DIR}/conf.d/*.conf;
}
EOM
16-2. NGINX Compression(압축) 설정 구성
콘텐츠를 클라이언트에 보내기 전에 즉시 압축하는 것이 웹 사이트 성능을 개선하는 좋은 방법이지만 압축이 올바르게 구성된 경우에만 가능합니다. 이 스크립트는 GitHub의 h5bp Repository에서 구성(346–414행)을 사용합니다.
cat > ${NGINX_CONF_DIR}/gzip_compression.conf << 'EOM'
# Credit: https://github.com/h5bp/server-configs-nginx/
# ----------------------------------------------------------------------
# | Compression |
# ----------------------------------------------------------------------
# https://nginx.org/en/docs/http/ngx_http_gzip_module.html
# Enable gzip compression.
# Default: off
gzip on;
# Compression level (1-9).
# 5 is a perfect compromise between size and CPU usage, offering about 75%
# reduction for most ASCII files (almost identical to level 9).
# Default: 1
gzip_comp_level 6;
# Don't compress anything that's already small and unlikely to shrink much if at
# all (the default is 20 bytes, which is bad as that usually leads to larger
# files after gzipping).
# Default: 20
gzip_min_length 256;
# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
# Default: off
gzip_proxied any;
# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
# Avoids the issue where a non-gzip capable client (which is extremely rare
# today) would display gibberish if their proxy gave them the gzipped version.
# Default: off
gzip_vary on;
# Compress all output labeled with one of the following MIME-types.
# `text/html` is always compressed by gzip module.
# Default: text/html
gzip_types
application/atom+xml
application/geo+json
application/javascript
application/x-javascript
application/json
application/ld+json
application/manifest+json
application/rdf+xml
application/rss+xml
application/vnd.ms-fontobject
application/wasm
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/eot
font/otf
font/ttf
image/bmp
image/svg+xml
text/cache-manifest
text/calendar
text/css
text/javascript
text/markdown
text/plain
text/xml
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy;
EOM
16-3. WordPress에 대한 NGINX 매개변수 구성
다음 스크립트는 WordPress에 대한 설정으로 conf.d 디렉토리에 default.conf라는 NGINX 구성 파일을 생성합니다(417–541행).
- Certbot을 통해 Let’s Encrypt에서 얻은 TLS 인증서를 활성화합니다(445–447행, Certbot 구성은 다음 섹션 참조).
- Let’s Encrypt에서 모범 사례로 정의한 TLS 보안 설정을 구현합니다(449–454행).
- 기본적으로 1시간 동안 Proxy 요청의 캐싱을 활성화합니다(458행).
- 일반적으로 요청되는 두 파일인 favicon.ico 및 robots.txt(465–474행)에 대해 액세스 로깅을 비활성화하고 자산을 찾을 수 없을 때 오류 로깅을 비활성화합니다.
- 불법 액세스 또는 부주의한 실행을 방지하기 위해 숨겨진 파일 및 특정 .php 파일에 대한 액세스를 거부합니다(476–500행).
- 정적 파일 콘텐츠 및 글꼴 파일의 액세스 로깅을 비활성화합니다(503–510행).
- 글꼴 파일에 대한 Access-Control-Allow-Origin 헤더를 설정합니다(508행).
- index.php 파일 및 기타 정적 파일에 대한 라우팅 설정을 적용합니다(512–539행).
cat > ${NGINX_CONF_DIR}/conf.d/default.conf << EOM
upstream unit_php_upstream {
server 127.0.0.1:8080;
keepalive 32;
}
server {
listen 80;
listen [::]:80;
# ACME-challenge used by Certbot for Let's Encrypt
location ^~ /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://${TLS_HOSTNAME}\$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${TLS_HOSTNAME};
root /var/www/wordpress/;
# Let's Encrypt configuration
ssl_certificate ${CERT_DIR}/fullchain.pem;
ssl_certificate_key ${CERT_DIR}/privkey.pem;
ssl_trusted_certificate ${CERT_DIR}/chain.pem;
include ${NGINX_CONF_DIR}/options-ssl-nginx.conf;
ssl_dhparam ${NGINX_CONF_DIR}/ssl-dhparams.pem;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# Proxy caching
proxy_cache wp_cache;
proxy_cache_valid 200 302 1h;
proxy_cache_valid 404 1m;
proxy_cache_revalidate on;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Deny all attempts to access hidden files such as .htaccess, .htpasswd,
# .DS_Store (Mac)
# Keep logging the requests to parse later (or to pass to firewall utilities
# such as fail2ban)
location ~ /\. {
deny all;
}
# Deny access to any files with a .php extension in the uploads directory;
# works in subdirectory installs and also in multi-site network.
# Keep logging the requests to parse later (or to pass to firewall utilities
# such as fail2ban).
location ~* /(?:uploads|files)/.*\.php\$ {
deny all;
}
# WordPress: deny access to wp-content, wp-includes PHP files
location ~* ^/(?:wp-content|wp-includes)/.*\.php\$ {
deny all;
}
# Deny public access to wp-config.php
location ~* wp-config.php {
deny all;
}
# Do not log access for static assets, media
location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
access_log off;
}
location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
add_header Access-Control-Allow-Origin "*";
access_log off;
}
location / {
try_files \$uri @index_php;
}
location @index_php {
proxy_socket_keepalive on;
proxy_http_version 1.1;
proxy_set_header Connection "";
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 Host \$host;
proxy_pass http://unit_php_upstream;
}
location ~* \.php\$ {
proxy_socket_keepalive on;
proxy_http_version 1.1;
proxy_set_header Connection "";
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 Host \$host;
try_files \$uri =404;
proxy_pass http://unit_php_upstream;
}
}
EOM
17. Let’s Encrypt 인증서 및 자동 갱신을 위한 Certbot 구성
Certbot은 Let’s Encrypt에서 TLS 인증서를 획득하고 자동 갱신하는 EFF(Electronic Frontier Foundation)의 무료 도구입니다. 이 스크립트는 NGINX용 Let’s Encrypt 인증서를 처리하도록 Certbot을 구성하는 다음 작업을 수행합니다.
- NGINX를 중지합니다(544 행).
- 현재 권장 설정으로 TLS 매개변수를 다운로드합니다(550–564행).
- Certbot을 실행하여 사이트에 대한 TLS 인증서를 검색합니다(578–585행).
- TLS 인증서를 사용하기 위해 NGINX를 다시 시작하고 NGINX Unit 서비스를 활성화합니다(588-589행).
- 인증서 자동 갱신 구성(592–609행)
echo "▶ Stopping NGINX in order to set up Let's Encrypt"
service nginx stop
mkdir -p /var/www/certbot
chown www-data:www-data /var/www/certbot
chmod g+s /var/www/certbot
if [ ! -f ${NGINX_CONF_DIR}/options-ssl-nginx.conf ]; then
echo "▶ Downloading recommended TLS parameters"
curl --retry 6 -Ls -z "Tue, 14 Apr 2020 16:36:07 GMT" \
-o "${NGINX_CONF_DIR}/options-ssl-nginx.conf" \
"https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf" \
|| echo "Couldn't download latest options-ssl-nginx.conf"
fi
if [ ! -f ${NGINX_CONF_DIR}/ssl-dhparams.pem ]; then
echo "▶ Downloading recommended TLS DH parameters"
curl --retry 6 -Ls -z "Tue, 14 Apr 2020 16:49:18 GMT" \
-o "${NGINX_CONF_DIR}/ssl-dhparams.pem" \
"https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem" \
|| echo "Couldn't download latest ssl-dhparams.pem"
fi
# If tls_certs_init.sh hasn't been run before, remove the self-signed certs
if [ ! -d "/etc/letsencrypt/accounts" ]; then
echo "▶ Removing self-signed certificates"
rm -rf "${CERT_DIR}"
fi
if [ "" = "${LETS_ENCRYPT_STAGING:-}" ] || [ "0" = "${LETS_ENCRYPT_STAGING}" ]; then
CERTBOT_STAGING_FLAG=""
else
CERTBOT_STAGING_FLAG="--staging"
fi
if [ ! -f "${CERT_DIR}/fullchain.pem" ]; then
echo "▶ Generating certificates with Let's Encrypt"
certbot certonly --standalone \
-m "${WORDPRESS_ADMIN_EMAIL}" \
${CERTBOT_STAGING_FLAG} \
--agree-tos --force-renewal --non-interactive \
-d "${TLS_HOSTNAME}"
fi
echo "▶ Starting NGINX to use new configuration and enabling NGINX Unit service"
service nginx start
systemctl enable unit.service
# Periodic Let's Encrypt cert renewal
if [ ! -f "/etc/systemd/system/certbot-renewal.timer" ]; then
echo "▶ Adding systemd Certbot renewal service timer"
cat > /etc/systemd/system/certbot-renewal.timer << EOM
[Unit]
Description=Timer for Certbot Renewal
[Timer]
OnBootSec=300
OnUnitActiveSec=1w
[Install]
WantedBy=multi-user.target
EOM
fi
echo "▶ Enabling Let's Encrypt auto-renewal"
systemctl start certbot-renewal.timer
systemctl enable certbot-renewal.timer
18. WordPress 사이트 사용자 정의
지금까지 bash 스크립트가 TLS/SSL이 활성화된 Production 준비 웹 사이트를 제공하도록 NGINX Open Source 및 NGINX Unit를 구성하는 방법을 설명했습니다. 필요에 따라 사이트를 추가로 사용자 지정할 수 있습니다.
- HTTPS를 통한 즉각적인 압축 성능 향상을 위해 Brotli 활성화
- WordPress 규칙과 함께 ModSecurity를 설치하여 사이트에 대한 자동화된 공격을 방지합니다.
- 사용자의 필요에 맞는 WordPress 백업 절차 설정
- AppArmor로 WordPress 설치 보호(Ubuntu에서)
- WordPress가 Outbound 이메일을 보낼 수 있도록 Postfix 또는 msmtp 설치
- 사이트를 벤치마킹하여 얼마나 많은 트래픽을 지원할 수 있는지 파악하십시오.
웹 사이트 성능을 향상시키기 위해 NGINX Open Source를 기반 상업적으로 지원되는 엔터프라이즈급 제품인 NGINX Plus로 업그레이드하는 것이 좋습니다. NGINX Plus 구독자는 동적으로 로드되는 Brotli 모듈과 (추가 비용으로) NGINX ModSecurity WAF를 받습니다. 또한 업계 최고의 보안 기술을 기반으로 하는 NGINX Plus용 WAF 모듈인 NGINX App Protect를 제공합니다.
솔루션 개요를 확인하고 NGINX Plus 성능을 직접 테스트 및 사용해 보려면 지금 30일 무료 평가판을 신청하거나 사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.
댓글을 달려면 로그인해야 합니다.