CentOS、Nginx、MySQL、PHP,由 LNMP 一键脚本安装,具体参见 lnmp.org 。
ThinkPHP5 在经过重构之后,入口文件改为了 /public/index.php
。在添加站点后(lnmp vhost add
),访问站点就需要加个二级目录,如 https://example.com/public
。
如何在将 ThinkPHP5 部署在 LNMP 环境中时,去掉 public 及 index.php ,让 url 变得更加友好。下面是解决方案。
由于 LNMP 是用于生产环境的,默认关闭了 PHP 的错误提示,这就导致如果页面出错会直接返回服务器 500 错误,而不会显示具体错误信息。所以我们需要修改下,打开 /usr/local/php/conf
下的 php.ini 文件,搜索 display_errors ,把 Off 修改为 On ,这样出错时,页面会提示具体错误信息。
打开 /usr/local/nginx/conf/vhost/example.com.conf
文件,
vim /usr/local/nginx/conf/vhost/example.com.conf
将内容
root /home/wwwroot/example.com;
修改为:
root /home/wwwroot/example.com/public;
修改之后问题来了,由于 lnmp 环境考虑到虚拟站点各自的访问目录权限问题,在 /usr/local/nginx/conf/fastcgi.conf
里面有如下配置:
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";
每个站点的访问权限就限制在了 $document_root
里了,上面我们修改了 example.com.conf
文件,将 root 的路径加了 /public
,所以限制了只能访问 public 目录下的文件,而 ThinkPHP 需要加载 public 同级目录下的 application 等目录下的文件,这样就有问题了。
现在要做的是:
既需要 root /home/wwwroot/example.com/public;
这个配置,又要让虚拟站点有 /home/wwwroot/example.com
目录的访问权限。
那么可以修改 /usr/local/nginx/conf/fastcig.conf
配置文件:
在内容
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";
后面添加一行:
fastcgi_param PHP_ADMIN_VALUE $basedir if_not_empty;
$basedir
变量可以在 /usr/local/nginx/conf/vhost/example.com.conf
配置文件里面的 include enable-php.conf
前赋值就行了:
set $basedir "open_basedir=/home/wwwroot/example.com/:/tmp/:/proc/";
这样,既满足了部署要求,又不影响其他一般站点的使用,因为 $basedir
可以根据站点需要自行设定。
可以在 set $basedir
后面添加或者引入 ThinkPHP5 的伪静态规则。
set $basedir "open_basedir=/home/wwwroot/example.com/:/tmp/:/proc/";
include thinkphp.conf
伪静态规则如下:
location / {
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php?s=/$1 last;
break;
}
}
最后,别忘了把 php.ini
文件里的 display_errors
的值由 On
改回 Off
。
添加 301 将HTTP 重定向到 HTTPS。
server
{
listen 80;
#listen [::]:80;
server_name www.example.com;
return 301 https://$server_name$request_uri;
}
最后要注意一点,LNMP 采用自动化颁发和续期 HTTPS 证书策略,在颁发证书之前会验证服务器的有效性,通过 HTTP 访问网站根目录下的 .well-known
目录下的验证文件,请求地址形如 https://domain.com/.well-known/xxx
。所以如果是像 ThinkPHP、Laravel 这样 web 目录不是根目录的,需要修改域名对应的配置文件,确保网站根目录对应到域名,不然可能由于无法获取到验证文件的内容,而导致证书生成失败。另外域名对应的 SSL 证书配置文件里的根目录也要和实际目录一致,以确保证书续期成功。