LEMP代表的是(L:Linux OS,E:Nginx,M:MySQL/MariaDB, P:PHP),与之对应的是LAMP(唯一不同的是A,代表Apache网络服务器),由于Nginx轻量、高效的特性,LEMP在近来的WEB服务中的出镜率越来越高。为了追随潮流,在之前LAMP搭建Wordpress的基础上,我又尝试了使用Nginx作为Wordpress的网络服务器,尽管遇到了各种各样的问题,但是取得了不错的效果。由于Nginx的配置十分复杂,于是有很多需要注意的地方。

常见网络服务器的优缺点

1. Nginx

Nginx是十分轻量级的HTTP服务器,是一个高性能的HTTP和反向代理服务器,Nginx以事件驱动的方式编写,所以有非常好的性能,同时也是一个非常高效的反向代理、负载平衡。其拥有匹配Lighttpd的性能,同时还没有Lighttpd的内存泄漏问题。

  • 优点

    • 轻量级,处理请求异步非阻塞,抗并发,高度模块化,有着Lighttpd的性能,且更稳定。
  • 缺点

    • Nginx在处理动态请求方面不如Apache。

2. Apache

Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。但是对于那些需要更强大的Web应用服务器(比如大小、可定制、响应速度、可扩展性等方面)的人而言,Apache明显不符合他们的要求。

  • 优点

    • 兼容性和稳定性强,处理动态请求能力好。
  • 缺点

    • 体量大,在速度、性能不及其他轻量级WEB服务器,并且消费内存较高。

3. Lighttpd

Lighttpd是一个具有非常低的内存开销,cpu占用率低,效能好,以及丰富的模块等特点。lighttpd是众多OpenSource轻量级的web server中较为优秀的一个。支持FastCGI, CGI, Auth, 输出压缩(output compress), URL重写, Alias等重要功能。

  • 优点

    • 轻量级,CPU占用低,效能好,模块丰富,对fastcgi支持非常好,比Apache性能更高。
  • 缺点

    • 稳定性没有Apache和Nginx好。

如果考虑网站的综合状况的话,比较理想的做法是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会用到的模块,比如phpmyadmin和xmlrpc,安装完后需要重启PHP-FPM。

# 其他模块
sudo apt install php7.0-mcrypt php7.0-mbstring php7.0-xml php7.0-xmrpc

到这里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_header http_500;
	fastcgi_ignore_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 localhost;

	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/localhost/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/localhost/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_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_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 缓存动态文件,参数对应的是缓存位置,缓存级别,缓存标识及大小,有效期,最大容量。

  • 由于 Nginx 不支持 Apache 的 .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 的读写等待时长,很容易导致安装或者更新失败,因此需要设置如下内容。

fastcgi_connect_timeout 600;
fastcgi_send_timeout 600;
fastcgi_read_timeout 600;
  • 为了更好管理动态文件缓存,我用了一个名为“Nginx hleper”的插件,为此增加了如下配置。
# 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";
}


Linux  

LEMP Wordpress

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!