Thủ thuật Website

Lưu trữ WordPress qua HTTPS với Docker

CẬP NHẬT 13/10/2020: Xin chào! Rừng từ tương lai đây! Tôi không còn sử dụng thiết lập này nữa. Và, tôi không có ý định cập nhật nó. Vì tôi không còn duy trì điều này cho chính mình nữa và vì nó là một giải pháp rất tùy chỉnh, nên tôi không có thời gian để tạo một kho lưu trữ cho nó.

Giải pháp này ít nhất là 3 năm tuổi. Nếu bạn buộc phải sử dụng phiên bản cũ của WordPress và giải pháp này phù hợp với bạn, tôi rất vui vì đã giúp được bạn. Mặt khác, nếu bạn đang sử dụng phiên bản mới hơn của WordPress, Nginx, Docker hoặc Certbot, có thể có một số thông tin hữu ích ở đây, nhưng ngoài ra, tôi còn chúc bạn may mắn!

Chúc mừng! 😄

Mới ngày hôm trước , tôi đã chuyển danh mục đầu tư của mình sang một máy chủ riêng và bắt đầu phân phối nó qua HTTPS. Tôi đã rất hấp dẫn khi tất cả đã hoàn thành! Tôi muốn nói một chút về những bước tôi đã thực hiện, vì tôi đã tìm thấy một số lỗi khó chịu trên đường đi. Đây không phải là hướng dẫn từng bước, thay vào đó tôi đang chia sẻ các cấu hình mà cuối cùng nó đã hoạt động cho tôi.

Tôi sử dụng example.comnhư một trình giữ chỗ ở đây. Nếu bạn đang đọc điều này và cố gắng thiết lập của riêng bạn hoạt động, bạn sẽ thay thế example.combằng tên miền của riêng mình. Ngoài ra, mặc dù tôi nghi ngờ nó cần phải được nói, không sử dụng rootlàm mật khẩu MySQL của bạn.

Ngăn xếp máy chủ

 

Tôi sử dụng Docker để cô lập các máy chủ của mình, để tất cả chúng đều có thể có môi trường riêng. Điều đó, và nếu tôi làm hỏng thứ gì đó trên vùng chứa Docker, tôi có thể xây dựng lại nó. Ngoài ra, tôi sử dụng Docker Compose để xử lý việc nhóm các vùng chứa của mình lại với nhau.

Tôi đã chọn Nginx làm proxy và máy chủ web WordPress của mình. Lưu ý rằng proxy không cần thiết ở đây, nhưng tôi cần nó cho một số việc khác. Tôi muốn giữ mọi thứ nhất quán, vì vậy đó là lý do tại sao tôi chọn sử dụng Nginx trên diện rộng.

Nếu bạn đang cố gắng đạt được thiết lập tương tự, nhưng sans-proxy, bạn cũng có thể cung cấp chứng chỉ SSL cho máy chủ Nginx của vùng chứa WordPress của mình và thêm vào các khối máy chủ thích hợp để hỗ trợ SSL. Tôi đề cập đến những thứ bên dưới trong phần Nginx Proxy Container .

Đối với chứng chỉ SSL của tôi, tôi đang sử dụng Let’s Encrypt qua Certbot . Đó là một công cụ nhỏ đáng yêu tự động hóa toàn bộ quy trình đăng ký chứng chỉ.

Tổng quan về cấu hình soạn thảo Docker

ToC

Các phần sau liệt kê tất cả các cấu hình cần thiết cho các vùng chứa sau:

- proxy:
  - nginx
- wordpress:
  - nginx
  - wordpress
  - mariadb

Vùng chứa Proxy Nginx

docker-compos.yml

version: '3.3'

services:
  nginx-proxy:
    container_name: nginx-proxy
    build: .
    image: nginx-proxy:0.0.2
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "./etc/letsencrypt/:/etc/letsencrypt/"
      - "./etc/ssl/:/etc/ssl/"
    command: bash -c "startup.sh"
    restart: always

Vùng chứa sử dụng Dockerfile liền kề để tạo hình ảnh nginx-proxy tùy chỉnh. Bộ chứa hiển thị cổng 80và cổng 443cho máy chủ. Khi vùng chứa được đưa lên, nó sẽ gắn hai thư mục cục bộ vào /etc/letsencrypt/và các /etc/ssl/thư mục trên vùng chứa tương ứng. Sau đó, lệnh khởi động mặc định ( nginx -g 'daemon off;') được ghi đè để chạy startup.shtệp. Cuối cùng, vùng chứa được định cấu hình để khởi động lại bất cứ khi nào nó hoạt động ngay bây giờ, thông qua restart: alwaysđường truyền.

Dockerfile

FROM nginx:1.13.5-alpine

LABEL maintainer="Forest Hoffman<forestjhoffman@gmail.com>"

##
# setting necessary server configurations
##

# add curl and other necessary packages for openssl and certbot
RUN apk add --update \
                curl \
                bash \
                openssl \
                certbot \
                python \
                py-pip \
        && pip install --upgrade pip \
        && pip install 'certbot-nginx' \
        && pip install 'pyopenssl'

RUN addgroup staff
RUN addgroup www-data
RUN adduser -h /home/dev/ -D -g "" -G staff dev
RUN adduser -S -H -g "" -G www-data www-data
RUN echo dev:trolls | chpasswd

##
# copying nginx configuration file
##

COPY nginx.conf /etc/nginx/nginx.conf
RUN chown root:staff /etc/nginx/nginx.conf

# adds certbot cert renewal job to cron
COPY crontab /tmp/crontab-certbot
RUN (crontab -l; cat /tmp/crontab-certbot) | crontab -

# copies over the startup file which handles initializing the nginx
# server and the SSL certification process (if necessary)
COPY startup.sh /bin/startup.sh
RUN chown root:root /bin/startup.sh
RUN chmod ug+rx /bin/startup.sh
RUN chmod go-w /bin/startup.sh

Dockerfile sẽ bao gồm tất cả các yêu cầu cần thiết để chạy Certbot trong vùng chứa. Nó cũng sẽ thêm một dòng vào cron của vùng chứa sẽ chạy Certbot ở chế độ gia hạn, vào sáng sớm (theo thời gian hệ thống của vùng chứa Docker).

crontab

# Renew Let's Encrypt SSL Certificates that have < 30 days to go,
# in the morning (UTC time).
0 11 * * * /usr/bin/certbot renew --quiet

startup.sh

#!/bin/bash
#
# startup.sh
#

# Startup the nginx server. The server has to be active for the Let's Encrypt Certbot to
# register and install the certificates.
nginx -g "daemon on;"

# Checks that the SSL certificates are installed. If they are, renews any that are old, and
# installs them if not.
if [[ -d "/etc/letsencrypt/live/example.com" ]]; then
        certbot renew --quiet
else
        if ! [[ -d "/etc/letsencrypt/live/example.com" ]]; then
                certbot --nginx -m your-email@ex.com --agree-tos --no-eff-email --redirect --expand -d example.com,www.example.com
        fi
        if ! [[ -f "/etc/ssl/certs/dhparam.pem" ]]; then
                openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
        fi
fi

# Shuts down the daemonized nginx server and fires up one in the foreground.
nginx -s stop && nginx -g 'daemon off;'

Tập startup.shlệnh được thiết kế để chạy bất cứ khi nào vùng chứa được đưa lên (tức là với docker-compose up). Nó sẽ chỉ cố gắng đăng ký các chứng nhận nếu thư mục cho các chứng chỉ chưa có trong /etc/letsencrypt/livethư mục trên vùng chứa. Các đường dẫn vào startup.shphải trùng với các đường dẫn trong tệp cấu hình Nginx. Nói về mà…

nginx.conf

user www-data;
worker_processes 1;
pid /run/nginx.pid;

events {
    worker_connections 1024;
    # multi_accept on;
}

http {
    #sendfile on;

    upstream docker-wordpress {
            server nginx-wordpress:80;
    }

    # listen for HTTPS requests to example domain
    server {
            ssl_dhparam /etc/ssl/certs/dhparam.pem;
            server_name example.com www.example.com;

            listen 443 ssl; # managed by Certbot
            ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
            ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
            include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

            location / {
                    proxy_pass       http://docker-wordpress;
                    proxy_redirect   off;
                    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-Host $server_name;
                    proxy_set_header X-Forwarded-Proto https;
            }
    }

    # handle ACME challenge from Certbot, and send HTTP requests to HTTPS
    server {
            listen 80;
            server_name example.com www.example.com;

            # listen for ACME challenge from Certbot
            location ^~ /.well-known/acme-challenge/ {
                    # No HTTP authentication
                    allow all;

                    default_type "text/plain";
            }

            location = /.well-known/acme-challenge/ {
                    return 404;
            }

            # Redirect other HTTP traffic to HTTPS
            location / {
                    access_log off;
                    return 301 https://$host$request_uri;
            }
    }
}

Điều này cấu hình proxy để lắng nghe các yêu cầu truy cập cổng 443(ví dụ: yêu cầu sử dụng https://*). Nếu các yêu cầu dành cho miền example.comhoặc www.example.comthì yêu cầu sẽ được chuyển đến http://docker-wordpressmáy chủ. Máy http://docker-wordpresschủ “ngược dòng” được định nghĩa là cổng 80của vùng chứa được kết nối nginx-wordpress. Việc kết nối các vùng chứa với nhau được thực hiện bằng cách sử dụng networkskhóa trong docker-compose.ymltệp.

[Đã chỉnh sửa 12/05/17]: Tôi đã cập nhật tệp cấu hình Nginx ở trên để bao gồm một khối máy chủ cho phép proxy vượt qua thử thách ACME của Certbot. Điều này là bắt buộc để gia hạn chứng chỉ.

Mọi yêu cầu chuyển đến cổng 80đều không sử dụng SSL (chỉ bình thường http://*), vì vậy những yêu cầu đó được chuyển hướng đến cổng 443bằng cách buộc sử dụng HTTPS trong url.

Khối này …

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

Cho biết nơi chứng chỉ SSL cho các miền mong muốn sẽ nằm trên vùng chứa proxy.

Các vùng chứa WordPress

Lưu ý rằng tôi đã chia nhỏ các cấu hình vùng chứa trong các phần phụ bên dưới, nhưng chúng thực sự là tất cả từ cùng một docker-compose.ymltệp.

Đây là những gì nó trông giống như tất cả cùng nhau.

docker-compos.yml

version: '3.3'

services:
  nginx:
    container_name: nginx-wordpress
    image: nginx:latest
    ports:
      - '80'
    volumes:
      - ./nginx:/etc/nginx/conf.d
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./logs/nginx:/var/log/nginx
      - ./wordpress:/var/www/html
    depends_on:
      - wordpress
    restart: always
    networks:
      - nginxproxy_default
  mysql:
    container_name: mysql
    image: mariadb
    ports:
      - '3306'
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
    restart: always
    networks:
      - nginxproxy_default
  wordpress:
    container_name: wp
    image: wordpress-prod:4.8.1-php5.6-fpm
    ports:
      - '9000'
    volumes:
      - ./wordpress:/var/www/html
    environment:
      - WORDPRESS_DB_NAME=wordpress
      - WORDPRESS_TABLE_PREFIX=wpprefix_
      - WORDPRESS_DB_HOST=mysql
      - WORDPRESS_DB_PASSWORD=root
    depends_on:
      - mysql
    restart: always
    networks:
      - nginxproxy_default
networks:
  nginxproxy_default:
    external: true

Điều quan trọng cần thấy ở đây là khóa cấp cao nhất networks, cho phép mỗi vùng chứa kết nối với mạng mặc định của proxy . Mạng không được tạo bởi bất kỳ vùng chứa nào trong tệp soạn thảo này, vì vậy nginxproxy_defaultmạng được xác định là mạng bên ngoài qua external: trueđường truyền.

Nginx cho Vùng chứa WordPress

docker-compos.yml

###
  nginx:
    container_name: nginx-wordpress
    image: nginx:latest
    ports:
      - '80'
    volumes:
      - ./nginx:/etc/nginx/conf.d
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./logs/nginx:/var/log/nginx
      - ./wordpress:/var/www/html
    depends_on:
      - wordpress
    restart: always
    networks:
      - nginxproxy_default
###

Máy chủ nginx phía trước vùng chứa WordPress hiển thị cổng 80và gắn bốn thư mục. Hai cái đầu tiên dành cho cấu hình nginx, cái tiếp theo là để bảo toàn nhật ký và cái cuối cùng là để bảo toàn cấu trúc tệp lõi WordPress.

nginx.conf

user www-data;
worker_processes auto;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Đây chỉ là một tệp cấu hình cơ bản bao gồm bất kỳ tệp cấu hình bổ sung nào được gắn vào thư mục /etc/nginx/conf.dvà /etc/nginx/sites-enabled/. Tệp này cũng chỉ định www-datangười dùng là người dùng mà Nginx nên sử dụng khi cố gắng cung cấp tệp. Điều này có nghĩa là cấu trúc tệp của máy chủ (được gắn vào /var/www/html) phải được www-datangười dùng / nhóm có thể truy cập được.

nginx / wordpress.conf

server {
    listen 80;

    root /var/www/html;
    index index.php;

    access_log /var/log/nginx/wp-access.log;
    error_log /var/log/nginx/wp-error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.(png|jpg|jpeg|gif|svg)$ {
        try_files $uri $uri/;
    }

    # Deny access to config.
    location = /wp-config.php {
        deny all;
    }

    # Deny access to htaccess.
    location ~ /\. { 
        deny all;
    }

    # Directly allow access to /wp-admin/admin-ajax.php. This is necessary for
    # WordPress to function on the admin side.
    location ~* ^/wp-admin/admin-ajax.php$ {
        try_files $uri =404;
        fastcgi_intercept_errors on;
        fastcgi_pass wordpress:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Allow access to all other PHP files.
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass wordpress:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

Máy chủ Nginx này đặc biệt phục vụ cho vùng chứa WordPress. Nó lắng nghe các yêu cầu chuyển 80và gửi bất kỳ yêu cầu nào cho các tệp PHP (bao gồm các trang quản trị) đến vùng chứa WordPress trên cổng 9000. Máy chủ nginx này không cần lắng nghe trên cổng 443vì proxy đang xử lý xác thực SSL. Mọi yêu cầu đến đối với tệp trên máy chủ WordPress sẽ được định tuyến thông qua proxy.

Vùng chứa WordPress

docker-compos.yml

###
  wordpress:
    container_name: wp
    image: wordpress-prod:4.8.1-php5.6-fpm
    ports:
      - '9000'
    volumes:
      - ./wordpress:/var/www/html
    environment:
      - WORDPRESS_DB_NAME=wordpress
      - WORDPRESS_TABLE_PREFIX=wpprefix_
      - WORDPRESS_DB_HOST=mysql
      - WORDPRESS_DB_PASSWORD=root
    depends_on:
      - mysql
    restart: always
    networks:
      - nginxproxy_default
###

Vùng chứa WordPress hiển thị cổng 9000. Nó có một ổ đĩa được gắn kết để bảo vệ cấu trúc tệp WordPress. Nó cũng có bốn biến môi trường tương ứng với cơ sở dữ liệu được kết nối. Lưu ý rằng WORDPRESS_DB_HOSTtên giống với tên của vùng chứa mysqlcontainer_name được kết nối .

wordpress / wp-config.php

<?php
###
// 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';

    // Force SSL in admin.
    define('FORCE_SSL_ADMIN', true);
}

/* That's all, stop editing! Happy blogging. */
###

Bỏ qua các cấu hình mặc định, một vài dòng này có thể được đặt trước “dừng chỉnh sửa!” bình luận. Những dòng này buộc WordPress phải thực hiện các yêu cầu nội bộ bằng HTTPS, bao gồm cả phía quản trị viên.

Mariadb (MySQL) cho Vùng chứa WordPress

 

docker-compos.yml

###
  mysql:
    container_name: mysql
    image: mariadb
    ports:
      - '3306'
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
    restart: always
    networks:
      - nginxproxy_default
###

Sự khác biệt giữa vùng chứa Mariadb / MySQL và các vùng khác là mysqlkhối lượng được gắn kết và biến môi trường mật khẩu gốc. Tất cả các cấu hình khác trong khối này rất giống với các thùng chứa trước đó.

Cài đặt chứng chỉ SSL với Certbot

 

Để chạy Certbot trên Nginx Proxy, trước tiên máy chủ phải được thiết lập và chạy. Giả sử rằng các chứng chỉ chưa có trong thư mục cục bộ của chúng ./etc/letsencrypt, việc cố gắng chạy proxy bây giờ sẽ không thành công. Tôi phát hiện ra rằng để proxy có thể chạy, một số điều cần phải xảy ra.

1) nginxproxy_defaultMạng cần được tạo. Nếu proxy chưa từng được chạy trước đó, thì mạng không thể tồn tại. Tạo mạng bằng cách chạy như sau trong một thiết bị đầu cuối:

$ docker network create nginxproxy_default

2) Các vùng chứa WordPress cần phải chạy trước khi proxy có thể bắt đầu. Đầu tiên, hãy điều hướng đến vị trí docker-compose.ymltệp dành cho vùng chứa WordPress. Sau đó, chạy phần sau trong một thiết bị đầu cuối:

$ docker-compose up -d

Lưu ý: -dCờ bắt đầu các vùng chứa ở chế độ không đầu, có nghĩa là bạn sẽ không thấy bất kỳ lỗi nào trừ khi bạn sử dụng lệnh docker-compose logshoặc kiểm tra trạng thái của các vùng chứa thông qua docker ps -a.

3) Các đường dẫn đến chứng chỉ cần được ghi chú trước khi vùng chứa proxy có thể chạy Certbot. Trong proxy, nginx.conftôi đã phải nhận xét khối máy chủ chứa listen 443 ssl;dòng và khối máy chủ xử lý chuyển hướng từ HTTP sang HTTPS. Ở vị trí của họ, tôi tạm thời nhập khối máy chủ này:

server {
    listen 80;
    server_name example.com www.example.com;
    location / {
         proxy_pass       http://docker-wordpress;
         proxy_redirect   off;
         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-Host $server_name;
    }
}

Sau đó, Nginx Proxy có thể được tạo bằng docker-compose up --buildlệnh. Docker-comp khi đó sẽ sử dụng lệnh khởi động không phải mặc định, lệnh này sẽ chạy startup.shtập lệnh trong vùng chứa. Tôi khuyên bạn không nên sử dụng chế độ không đầu khi xây dựng proxy, bằng cách đó bạn có thể chắc chắn rằng Certbot có thể đăng ký chứng chỉ.

Khi Certbot đã tạo thành công chứng chỉ, khối máy chủ tạm thời được thêm vào trong bước 3 ở trên có thể bị xóa và bỏ ghi chú hai khối máy chủ khác. Sau khi thay đổi cấu hình, proxy sẽ cần được tải lại bằng một docker-compose down && docker-compose up -d.

Thực hiện kiểm tra nhanh với docker ps -asẽ hiển thị một cái gì đó dọc theo các dòng sau:

CONTAINER ID  IMAGE                            COMMAND                 CREATED     STATUS        PORTS                                     NAMES
62b3a673f1cb  nginx-proxy:0.0.2                "nginx -g 'daemon ..."  3 days ago  Up 2 minutes  0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp  nginx-proxy
ea4acq9cc868  nginx:latest                     "nginx -g 'daemon ..."  4 days ago  Up 3 minutes  0.0.0.0:8081->80/tcp                      nginx-wordpress
c7badc76c834  wordpress-prod:4.8.1-php5.6-fpm  "docker-entrypoint..."  4 days ago  Up 3 minutes  0.0.0.0:8082->9000/tcp                    wp
2ba321f4afdd  mariadb                          "docker-entrypoint..."  4 days ago  Up 3 minutes  0.0.0.0:8083->3306/tcp                    mysql

Nếu mọi thứ đều ổn, điều hướng đến https://example.com/wp-adminsẽ hiển thị màn hình thiết lập WordPress tốt.

Related Articles

Trả lời

Email của bạn sẽ không được hiển thị công khai.

Back to top button