其实一直一来早都想把环境切换到 Nginx ,因为即使 Apache 运行在 event 模式下,受限于自身的架构,其性能的表现和资源占用的情况依旧无法和 Nginx 站在同一基准线上。而促使我做这件事的原因很简单,Let's Encrypt的证书过期了,厌倦了每三个月去 manual renew 证书一次,遂将证书的管理转到 Acme.sh, 后者支持阿里云的 DNS api,可以方便的自动 renew 证书。证书的生成和配置很简单,然而却出现了另外一个问题,Apache 无法支持 ACME 获得证书,这里大概是因为证书使用了另外一种加密方式,而 Apache 无法 Cipher。我没有纠结于证书的类型和加密方式,对我来说自动续签更加重要。既然 Apache 不行,正好借此机会换到 Nginx。
由于以前的 LAMP 早已安装和配置好,这里需要做的工作就是安装 Nginx 和配置就好。Nginx 的安装就不说了,现在 Reposity 的源本身已经很安全,个人不必再迷信手动编译,因此我全部用的都是官网的包安装的,快速方便。PHP 我这里用的是 7.2版本。 以下就直接贴出配置文件。
php-fpm + php pool
# 查看 php-fpm 配置
# cat /etc/php/7.2/fpm/php-fpm.conf | grep -v "^;" | grep -v '^$'
[global]
pid = /run/php/php7.2-fpm.pid
error_log = /var/log/php7.2-fpm.log
include=/etc/php/7.2/fpm/pool.d/*.conf
# 查看 Pool 的配置
# cat /etc/php/7.2/fpm/pool.d/site-name.conf | grep -v "^;" | grep -v '^$'
[site-name]
user = www-data
group = www-data
listen = /run/php/site-name.sock
listen.owner = www-data
listen.group = www-data
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
request_terminate_timeout = 300s
request_slowlog_timeout = 10s
chdir = /var/www/html/site-name.com/public_html
slowlog = /var/www/html/site-name.com/logs/$pool.log.slow
php_flag[display_errors] = off
php_admin_value[display_errors]=0
php_admin_value[display_startup_errors]=0
php_admin_value[html_errors]=0
php_admin_value[define_syslog_variables]=0
php_admin_flag[file_uploads]=1
php_admin_flag[log_errors] = on
php_admin_value[log_errors]=1
php_admin_value[upload_tmp_dir]="/var/tmp"
php_admin_value[upload_max_filesize]="4M"
php_value[max_input_time]="120"
php_admin_value[max_input_time]=120
php_value[max_execution_time]="300"
php_admin_value[post_max_size]="4M"
php_value[session.gc_maxlifetime]=3600
php_admin_value[session.gc_probability]=1
php_admin_value[session.gc_divisor]=100
php_admin_value[error_log] = /var/log/fpm-php/site-name.log
php_admin_value[memory_limit] = 64M
php_admin_value[disable_functions] = exec,passthru,shell_exec,system
php_admin_flag[allow_url_fopen] = off
php_admin_value[magic_quotes_gpc]=0
php_admin_value[register_globals]=0
php_admin_value[session.auto_start]=0
php_admin_value[mbstring.http_input]="pass"
php_admin_value[mbstring.http_output]="pass"
php_admin_value[mbstring.encoding_translation]=0
php_admin_value[expose_php]=0
php_admin_value[allow_url_fopen]=1
php_admin_value[safe_mode]=0
php_admin_value[cgi.fix_pathinfo]=1
php_admin_value[cgi.discard_path]=0
# Nginx 的配置分为 2 部分,Nginx全局环境 + Vhost 配置
# Nginx 全局配置
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
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_min_length 1100;
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 font/truetypef font/opentype application/vnd.ms-fontobject text/x-component image/svg+xml;
gzip_static on;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
# Nginx - 针对 Drupal 站点的 vhost 配置
server {
listen 80;
server_name www.site-name.com site-name.com;
add_header Strict-Transport-Security max-age=15768000;
#永久重定向到 https 站点
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name www.site-name.com site-name.com;
root /var/www/html/site-name.com/public_html;
keepalive_timeout 120;
#证书文件
ssl_certificate /etc/certs/site-name.com/fullchain.pem;
#私钥文件
ssl_certificate_key /etc/certs/site-name.com/key.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
access_log /var/www/html/site-name.com/logs/access.log;
error_log /var/www/html/site-name.com/logs/error.log;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Very rarely should these ever be accessed outside of your lan
location ~* \.(txt|log)$ {
allow 192.168.0.0/16;
deny all;
}
location ~ \..*/.*\.php$ {
return 403;
}
location ~ ^/sites/.*/private/ {
return 403;
}
# Block access to scripts in site files directory
location ~ ^/sites/[^/]+/files/.*\.php$ {
deny all;
}
# Allow "Well-Known URIs" as per RFC 5785
location ~* ^/.well-known/ {
allow all;
}
# Block access to "hidden" files and directories whose names begin with a
# period. This includes directories used by version control systems such
# as Subversion or Git to store control files.
location ~ (^|/)\. {
return 403;
}
location / {
# try_files $uri @rewrite; # For Drupal <= 6
try_files $uri /index.php?$query_string; # For Drupal >= 7
}
location @rewrite {
rewrite ^/(.*)$ /index.php?q=$1;
}
# Don't allow direct access to PHP files in the vendor directory.
location ~ /vendor/.*\.php$ {
deny all;
return 404;
}
location ~ '\.php$|^/update.php' {
# Ensure the php file exists. Mitigates CVE-2019-11043
try_files $uri =404;
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
include fastcgi_params;
# Block httpoxy attacks. See https://httpoxy.org/.
fastcgi_param HTTP_PROXY "";
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param QUERY_STRING $query_string;
fastcgi_intercept_errors on;
fastcgi_pass unix:/run/php/site-name.sock;
}
location ~ ^/sites/.*/files/styles/ { # For Drupal >= 7
try_files $uri @rewrite;
}
location ~ ^(/[a-z\-]+)?/system/files/ { # For Drupal >= 7
try_files $uri /index.php?$query_string;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
try_files $uri @rewrite;
expires max;
log_not_found off;
}
# # Enforce clean URLs
# Removes index.php from urls like www.example.com/index.php/my-page --> www.example.com/my-page
# Could be done with 301 for permanent or other redirect codes.
if ($request_uri ~* "^(.*/)index\.php(.*)") {
return 307 $1$2;
}
}