作者 | Nickhopps
LEMP 代表的是(L:Linux OS,E:Nginx,M:MySQL/MariaDB, P:PHP),與之對應的是 LAMP(唯一不同的是 A,代表 Apache 網路伺服器),由於Nginx輕量、高效的特性,LEMP 在近來的 Web 服務中的出鏡率越來越高。
為了追隨潮流,在之前 LAMP 搭建 WordPress[1] 的基礎上,我又嘗試了使用 Nginx 作為 WordPress 的網路伺服器,儘管遇到了各種各樣的問題,但是取得了不錯的效果。由於 Nginx 的配置比較複雜,於是有很多需要註意的地方。
常見網路伺服器的優缺點
1. Nginx
Nginx 是十分輕量級的 HTTP 伺服器,是一個高效能的 HTTP 和反向代理伺服器,Nginx 以事件驅動的方式編寫,所以有非常好的效能,同時也是一個非常高效的反向代理、負載平衡。其擁有匹敵 Lighttpd 的效能,同時還沒有 Lighttpd 的記憶體洩漏問題。
2. Apache
Apache 是世界使用排名第一的 Web 伺服器軟體。它可以執行在幾乎所有廣泛使用的計算機平臺上,由於其跨平臺和安全性被廣泛使用,是最流行的 Web 伺服器端軟體之一。但是對於那些需要更強大的 Web 應用伺服器(比如大小、可定製、響應速度、可擴充套件性等方面)的人而言,Apache 明顯不符合他們的要求。
3. Lighttpd
Lighttpd 是一個具有非常低的記憶體開銷,CPU 佔用率低,效能好,以及豐富的模組等特點。Lighttpd 是眾多 開源的輕量級的網路伺服器中較為優秀的一個。支援 FastCGI、 CGI、 Auth、 輸出壓縮、URL 重寫、Alias 等重要功能。
如果考慮網站的綜合狀況的話,比較理想的做法是用 Nginx 做高併發、快取、代理前端內容,而使用 Apache 處理後臺動態內容。不過如果只是驅動 WordPress,單獨使用 Nginx 就夠了。
安裝 LEMP
安裝過程和 LAMP 差不多,只是幾個地方稍微不同。
安裝 Nginx
# 安裝Nginx
sudo apt install nginx
# 檢查Nginx執行狀況
sudo systemctl status nginx.service
安裝 PHP7
# 安裝PHP7和PHPFastCGI管理器PHP-FPM
sudo apt install php7.0 php7.0-fpm
安裝 MariaDB 資料庫
# 安裝MariaDB sudo apt install mariadb-server mariadb-client php7.0-mysql # 重啟PHP-FPM服務以便使用MySQL模組與資料庫通訊 sudo systemctl restart php7.0-fpm.service
為了安全加固 MariaDB,執行來自 Ubuntu 軟體倉庫中的二進位制包提供的安全指令碼,這會詢問你設定一個 root 密碼,移除匿名使用者,禁用 root 使用者遠端登入,移除測試資料庫等。
# 使用安全指令碼 sudo mysql_secure_installation # 配置MariaDB以便普通使用者能夠不使用root許可權來訪問資料庫 sudo mysql MariaDB> use mysql; MariaDB> update user set plugin='' where User='root'; MariaDB> flush privileges; MariaDB> exit # 然後使用如下命令執行資料庫命令 mysql -u root -p -e 'show databases'
安裝其他模組
還有一些 WordPress 會用到的模組,比如 mcrypt、mbstring,安裝完後需要重啟 PHP-FPM。
# 其他模組 sudo apt install php7.0-mcrypt php7.0-mbstring
到這裡 LEMP 的安裝工作就已經基本搞定了,接下來是最重要的配置環節。
配置 Nginx
主配置
首先是主配置檔案 /etc/nginx/nginx.conf
:
# Set user and group. user www-data www-data; # Usually equal to number of CPUs you have. worker_processes 1; # Global error log [ debug | info | notice | warn | error | crit ]. error_log /var/log/nginx/error.log warn; # Pid file pid /run/nginx.pid; events { worker_connections 1024; } http { ### Basic Settings ### include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 60; client_max_body_size 15m; # Limit the max size of plugin in WordPress. ### 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; ### FastCGI Settings ### fastcgi_cache_path /tmp/wpcache levels=1:2 keys_zone=WORDPRESS:250m inactive=1d max_size=1G; fastcgi_temp_path /tmp/wpcache/temp; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_essay-header http_500; fastcgi_ignore_essay-headers Cache-Control Expires Set-Cookie; ### Virtual Host Configs ### include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
子配置
然後是 WordPress 的配置檔案 /etc/site-enabled/wordpress.conf
:
server { listen 80 default_server; listen [::]:80 default_server; root /home/ubuntu/wordpress; index index.html index.php; server_name www.infiniture.cn; access_log /var/log/nginx/infiniture.com.access.log; error_log /var/log/nginx/infiniture.com.error.log; # Managed by Certbot listen 443 ssl; ssl_certificate /etc/letsencrypt/live/www.infiniture.cn/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.infiniture.cn/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; if ($scheme != "https") { return 301 https://$host$request_uri; } # Add rewrite support for wordpress location / { try_files $uri $uri/ /index.php?$args; rewrite /wp-admin$ $scheme://$host$uri/ permanent; } # Cache strategy set $no_cache 0; # POST requests and urls with a query string should always go to PHP if ($request_method = POST) { set $no_cache 1; } if ($query_string != "") { set $no_cache 1; } # Don't cache uris containing the following segments if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") { set $no_cache 1; } # Don't use the cache for logged in users or recent commenters if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { set $no_cache 1; } location ~ /wp-admin { location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; # Making the updates in WordPress real time. fastcgi_buffering off; add_essay-header X-Accel-Buffering "no"; } } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; fastcgi_connect_timeout 600; fastcgi_send_timeout 600; fastcgi_read_timeout 600; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; fastcgi_cache_bypass $no_cache; fastcgi_no_cache $no_cache; fastcgi_cache WORDPRESS; fastcgi_cache_valid 200 301 302 1d; add_essay-header X-Cache "$upstream_cache_status From $host"; } # Purge cache(Nginx Helper Purge Method: Using a Get) location ~ /purge(/.*) { allow 127.0.0.1; allow 182.254.246.42; deny all; fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1"; } # 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 sub-directory installs and also in multisite network # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban) location ~* /(?:uploads|files)/.*\.php$ { deny all; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; access_log off; } }
配置說明
以上配置中,需要說明的幾個:
client_max_body_size 15m;
因為 WordPress 裡很多外掛的體積比較大,如果不設定這個值的大小,會導致外掛或者主題安裝失敗。fastcgi_cache_path /tmp/wpcache levels=1:2 keys_zone=WORDPRESS:250m inactive=1d max_size=1G;
這個包括下麵的所有內容都是為了使 Nginx 快取動態檔案,引數對應的是快取位置,快取級別,快取標識及大小,有效期,最大容量。.htaccess
檔案,因此無法使用 WordPress 自帶的地址重寫功能,需要自己新增相應的功能。# Add rewrite support for wordpress location / { try_files $uri $uri/ /index.php?$args; rewrite /wp-admin$ $scheme://$host$uri/ permanent; }
fastcgi_buffering off;
這個選項預設是開啟的,它會把 FastCGI 傳回的內容快取起來,直到快取空間滿了之後一併輸出,這會導致 WordPress 下更新時不會實時顯示,而是更新完成後全部一起顯示。關掉這個選項即可解決這個問題。fastcgi_connect_timeout 600; fastcgi_send_timeout 600; fastcgi_read_timeout 600;
# Purge cache(Nginx Helper Purge Method: Using a Get)
location ~ /purge(/.*) {
allow 127.0.0.1;
allow xxx.xxx.xxx.xxx; # 你的伺服器地址
deny all;
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
總結
這樣就在 LEMP 平臺上搭建好了 WordPress 站點。