介绍
LEMP 软件堆栈是一组软件,可用于提供用 PHP 编写的动态网页和 Web 应用程序。这是一个首字母缩略词,描述Linux操作系统,带有 Nginx(发音为“ Engine -X”)Web 服务器。后端数据存储在MySQL数据库中,动态处理由PHP处理。
本指南演示如何在 Ubuntu 服务器上安装 LEMP 堆栈。Ubuntu 操作系统负责堆栈的 Linux 部分。我们将介绍如何启动和运行其余组件。
先决条件
要完成本教程,您需要以普通非root sudo
用户身份访问 Ubuntu 服务器,并在服务器上启用防火墙。要进行设置,您可以按照我们的Ubuntu 初始服务器设置指南进行操作。
第 1 步 – 安装 Nginx Web 服务器
为了向网站访问者显示网页,您将使用高性能 Web 服务器 Nginx。您将使用 APT 包管理器来获取此软件。
由于这是您第一次使用apt
此会话,请首先更新服务器的包索引:
sudo apt update
接下来运行apt install
安装Nginx:
sudo apt install nginx
出现提示时,按Y
和ENTER
确认您要安装 Nginx。安装完成后,Nginx Web 服务器将在您的 Ubuntu 服务器上激活并运行。
如果您已ufw
启用防火墙(如我们的初始服务器设置指南中所建议),则需要允许连接到 Nginx。Nginx 在安装时会注册几个不同的 UFW 应用程序配置文件。要检查哪些 UFW 配置文件可用,请运行:
sudo ufw app list
Output
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
建议您启用最严格的配置文件,这样仍可以允许您所需的流量。由于您尚未在本指南中为您的服务器配置 SSL,因此您只需要在端口上允许常规 HTTP 流量80
。
通过运行以下命令启用此功能:
sudo ufw allow 'Nginx HTTP'
您可以通过检查状态来验证更改:
sudo ufw status
此输出显示现在允许 HTTP 流量:
Output
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
添加新的防火墙规则后,您可以通过在 Web 浏览器中访问服务器的域名或公共 IP 地址来测试服务器是否启动并运行。
如果您没有指向服务器的域名并且不知道服务器的公共 IP 地址,则可以通过运行以下任一命令来找到它:
ip addr show
hostname -I
这将打印出几个 IP 地址。您可以在 Web 浏览器中依次尝试每个 IP 地址。
另外,您也可以从互联网上的其他位置检查哪个 IP 地址是可访问的:
curl -4 icanhazip.com
在 Web 浏览器中输入您收到的地址,它将带您进入 Nginx 的默认登录页面:
http://server_domain_or_IP
如果您收到此页面,则表示您已成功安装 Nginx 并为您的 Web 服务器启用 HTTP 流量。
第2步 – 安装MySQL
现在您已启动并运行 Web 服务器,您需要安装数据库系统来存储和管理站点的数据。MySQL 是 PHP 环境中常用的数据库管理系统。
再次使用apt
获取并安装该软件:
sudo apt install mysql-server
出现提示时,按Y
,然后按确认安装ENTER
。
安装完成后,建议您运行 MySQL 预装的安全脚本。此脚本将删除一些不安全的默认设置并锁定对数据库系统的访问。通过运行以下命令启动交互式脚本:
sudo mysql_secure_installation
系统将提示您一个问题,询问您是否要配置VALIDATE PASSWORD PLUGIN
。
注意:启用此功能需要一定的判断。如果启用,不符合指定条件的密码将被 MySQL 拒绝并显示错误。禁用验证是安全的,但您应始终使用强而独特的密码作为数据库凭据。
回答Y
是,或者回答其他任何内容以继续而不启用:
Output
VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?
Press y|Y for Yes, any other key for No:
如果您回答“是”,系统会要求您选择密码验证级别。请记住,如果您输入2
最强级别,则在尝试设置任何不包含数字、大小写字母和特殊字符的密码时,您将收到错误:
Output
There are three levels of password validation policy:
LOW Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary file
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 1
无论您是否选择设置VALIDATE PASSWORD PLUGIN
,服务器都会要求您选择并确认 MySQL根用户的密码。请不要将其与系统根用户混淆。数据库根用户是具有数据库系统全部权限的管理用户。尽管 MySQL 根用户的默认身份验证方法不需要使用密码,但即使设置了密码,您也应该在此处定义一个强密码作为额外的安全措施。我们稍后会讨论这个问题。
如果您启用了密码验证,您将看到您输入的 root 密码的密码强度,并且您的服务器将询问您是否要继续使用该密码。如果您对当前密码满意,请Y
在提示符下按“是”:
Output
Estimated strength of the password: 100
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
对于其余的问题,请在每次提示时按下Y
并按下ENTER
键。这将删除一些匿名用户和测试数据库,禁用远程 root 登录,并加载这些新规则,以便 MySQL 立即遵守您所做的更改。
完成后,测试您是否能够登录到 MySQL 控制台:
sudo mysql
这将以管理数据库用户root 的身份连接到 MySQL 服务器,您应该收到以下输出:
Output
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.28-0ubuntu4 (Ubuntu)
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
要退出 MySQL 控制台,请写入以下内容:
mysql>exit
请注意,即使您在运行脚本时定义了密码,您也不需要提供密码即可以rootmysql_secure_installation
用户身份进行连接。这是因为,在 Ubuntu 上安装时,管理 MySQL 用户的默认身份验证方法是auth_socket
,而不是使用密码的方法。乍一看,这似乎是一个安全问题,但它使数据库服务器更安全,因为唯一允许以root MySQL 用户身份登录的用户是具有sudo
从控制台或通过以相同权限运行的应用程序连接的权限的系统用户。实际上,这意味着您将无法使用管理数据库root用户从 PHP 应用程序进行连接。
为了提高安全性,最好为每个数据库设置具有较少权限的专用用户帐户,特别是当您计划在服务器上托管多个数据库时。
注意:某些较旧的原生 MySQL PHP 库版本
mysqlnd
不支持caching_sha2_authentication
,这是 MySQL 8 中创建用户的默认身份验证方法。因此,在 MySQL 8 上为 PHP 应用程序创建数据库用户时,您可能需要确保将其配置为使用。我们将在第 6 步mysql_native_password
中演示如何执行此操作。
您的 MySQL 服务器现已安装并保护。接下来,您将安装 PHP,这是 LEMP 堆栈中的最后一个组件。
第 3 步 – 安装 PHP
您已安装 Nginx 来提供内容,并安装 MySQL 来存储和管理数据。现在您可以安装 PHP 来处理代码并为 Web 服务器生成动态内容。
虽然 Apache 在每个请求中嵌入了 PHP 解释器,但 Nginx 需要一个外部程序来处理 PHP 处理并充当 PHP 解释器本身和 Web 服务器之间的桥梁。这可以使大多数基于 PHP 的网站获得更好的整体性能,但需要额外的配置。您需要安装php8.1-fpm
,它代表“PHP fastCGI 进程管理器”并使用当前版本的 PHP(在撰写本文时),以告诉 Nginx 将 PHP 请求传递给此软件进行处理。此外,您还需要php-mysql
,这是一个允许 PHP 与基于 MySQL 的数据库通信的 PHP 模块。核心 PHP 包将自动作为依赖项安装。
要安装php8.1-fpm
和php-mysql
包,请运行:
sudo apt install php8.1-fpm php-mysql
出现提示时,按Y
和ENTER
确认安装。
现在您已安装 PHP 组件。接下来,您将配置 Nginx 以使用它们。
第4步 – 配置Nginx以使用PHP处理器
使用 Nginx Web 服务器时,我们可以创建服务器块(类似于 Apache 中的虚拟主机)来封装配置详细信息并在单个服务器上托管多个域。在本指南中,我们将使用your_domain作为示例域名。
在 Ubuntu 上,Nginx 默认启用了一个服务器块,并配置为从 目录中提供文档/var/www/html
。虽然这对于单个站点来说效果很好,但如果您托管多个站点,管理起来可能会很困难。我们不会修改,而是在your_domain网站/var/www/html
内创建一个目录结构,如果客户端请求与其他任何站点都不匹配,则保留该目录作为要提供的默认目录。/var/www/var/www/html
为your_domain创建根 Web 目录,如下所示:
sudo mkdir /var/www/your_domain
接下来,使用环境变量分配目录的所有权$USER
,该变量将引用您当前的系统用户:
sudo chown -R $USER:$USER /var/www/your_domain
sites-available
然后,使用您喜欢的命令行编辑器在 Nginx 的目录中打开一个新的配置文件。在这里,我们将使用nano
:
sudo nano /etc/nginx/sites-available/your_domain
这将创建一个新的空白文件。插入以下基本配置:
server {
listen 80;
server_name your_domain www.your_domain;
root /var/www/your_domain;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
每个指令和位置块的作用如下:
listen
— 定义 Nginx 将监听哪个端口。在本例中,它将监听端口80
,即 HTTP 的默认端口。root
— 定义存储此网站提供的文件的文档根目录。index
— 定义 Nginx 将按何种顺序优先处理此网站的索引文件。通常的做法是列出index.html
优先级高于其他index.php
文件的文件,以便在 PHP 应用程序中快速设置维护登录页面。您可以调整这些设置以更好地满足您的应用程序需求。server_name
— 定义此服务器块应响应哪些域名和/或 IP 地址。将此指令指向您的服务器的域名或公共 IP 地址。location /
— 第一个 location 块包含一个try_files
指令,用于检查是否存在与 URL 请求匹配的文件或目录。如果 Nginx 找不到相应的资源,它将返回 404 错误。location ~ \.php$
fastcgi-php.conf
— 此位置块通过将 Nginx 指向配置文件和文件来处理实际的 PHP 处理php8.1-fpm.sock
,该文件声明了与哪个套接字关联php8.1-fpm
。location ~ /\.ht
— 最后一个 location 块处理.htaccess
Nginx 不处理的文件。通过添加该deny all
指令,如果任何.htaccess
文件碰巧进入文档根目录,则不会将其提供给访问者。
编辑完成后,保存并关闭文件。如果您使用的是nano
,您可以按CTRL+X
,然后按Y
和ENTER
确认。
通过链接到 Nginxsites-enabled
目录的配置文件来激活您的配置:
sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
然后,从目录中取消链接默认配置文件/sites-enabled/
:
sudo unlink /etc/nginx/sites-enabled/default
注意:如果您需要恢复默认配置,可以通过重新创建符号链接来实现,如下所示:
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/
这将告诉 Nginx 在下次重新加载时使用该配置。您可以通过运行以下命令来测试配置是否存在语法错误:
sudo nginx -t
如果报告任何错误,请返回配置文件检查其内容,然后再继续。
准备就绪后,重新加载 Nginx 以应用更改:
sudo systemctl reload nginx
您的新网站现已启用,但网站根目录仍为空。在该位置创建一个文件,以便您可以测试新的服务器块是否按预期工作:/var/www/your_domain
/index.html
nano /var/www/your_domain/index.html
在此文件中包括以下内容:/var/www/your_domain/index.html
<html>
<head>
<title>your_domain website</title>
</head>
<body>
<h1>Hello World!</h1>
<p>This is the landing page of <strong>your_domain</strong>.</p>
</body>
</html>
现在转到您的浏览器并访问您的服务器的域名或 IP 地址,如server_name
服务器块配置文件中的指令所列:
http://server_domain_or_IP
如果您收到此页面,则表示您的 Nginx 服务器块正在按预期工作。
您可以将此文件保留为应用程序的临时登录页面,直到您设置一个index.php
文件来替换它。完成后,请记住从文档根目录中删除或重命名该文件,因为默认情况下index.html
它将优先于文件。index.php
您的 LEMP 堆栈现已完全配置。在下一步中,您将创建一个 PHP 脚本来测试 Nginx 是否能够处理.php
新配置的网站中的文件。
第 5 步 – 使用 Nginx 测试 PHP
您的 LEMP 堆栈现在应该已完全设置完毕。您可以测试它以验证 Nginx 是否可以正确地将.php
文件传递给您的 PHP 处理器。
您可以通过在文档根目录中创建一个测试 PHP 文件来执行此操作。使用info.php
您喜欢的文本编辑器在文档根目录中打开一个名为的新文件:
nano /var/www/your_domain/info.php
将以下几行添加到新文件中。这是有效的 PHP 代码,它将返回有关您的服务器的信息:
<?php
phpinfo();
完成后,保存并关闭文件。
现在,您可以通过访问在 Nginx 配置文件中设置的域名或公共 IP 地址,在 Web 浏览器中访问此页面,然后执行以下操作/info.php
:
http://server_domain_or_IP/info.php
您将收到一个包含有关您的服务器的详细信息的网页:
通过该页面检查了有关您的 PHP 服务器的相关信息后,最好删除您创建的文件,因为它包含有关您的 PHP 环境和 Ubuntu 服务器的敏感信息。您可以使用以下命令rm
删除该文件:
sudo rm /var/www/your_domain/info.ph
如果您以后需要,您可以随时重新生成此文件。
第 6 步 – 从 PHP 测试数据库连接(可选)
如果您想测试 PHP 是否能够连接到 MySQL 并执行数据库查询,您可以创建一个包含虚拟数据的测试表,然后从 PHP 脚本查询其内容。在此之前,您需要创建一个测试数据库和一个正确配置以访问该数据库的新 MySQL 用户。
注意:某些较旧的本机 MySQL PHP 库版本
mysqlnd
不支持caching_sha2_authentication
MySQL 8 的默认身份验证方法,您可能需要确保它们已配置为使用mysql_native_password
。
我们将创建一个名为example_database 的数据库和一个名为example_user 的用户,但您可以用不同的值替换这些名称。
首先,使用root帐户连接到 MySQL 控制台:
sudo mysql
要创建新数据库,请从 MySQL 控制台运行以下命令:
CREATE DATABASE example_database;
现在您可以创建一个新用户并授予他们您所创建的自定义数据库的全部权限。
以下命令将创建一个名为 的新用户example_user
,使用mysql_native_password
为默认身份验证方法。我们将此用户的密码定义为password
,但您应该用自己选择的安全密码替换此值。
CREATE USER 'example_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
现在我们需要授予该用户对example_database
数据库的权限:
GRANT ALL ON example_database.* TO 'example_user'@'%';
这将赋予example_user用户对example_database数据库的完全权限,同时阻止该用户在您的服务器上创建或修改其他数据库。
现在使用以下命令退出 MySQL shell:
exit
您可以通过再次登录 MySQL 控制台来测试新用户是否具有适当的权限,这次使用自定义用户凭据。请注意-p
此命令中的标志,它将提示您输入创建example_user用户时使用的密码:
mysql -u example_user -p
登录MySQL控制台后,确认您有权访问example_database数据库:
SHOW DATABASES;
这将返回以下输出:
Output+--------------------+
| Database |
+--------------------+
| example_database |
| information_schema |
+--------------------+
2 rows in set (0.000 sec)
接下来,我们将创建一个名为todo_list的测试表。从 MySQL 控制台运行以下语句:
CREATE TABLE example_database.todo_list (
item_id INT AUTO_INCREMENT,
content VARCHAR(255),
PRIMARY KEY(item_id)
);
在测试表中插入几行内容。您可能需要使用不同的值重复执行下一个命令几次:
INSERT INTO example_database.todo_list (content) VALUES ("My first important item");
要确认数据已成功保存到表中,请运行:
SELECT * FROM example_database.todo_list;
您的输出应显示如下:
Output+---------+--------------------------+
| item_id | content |
+---------+--------------------------+
| 1 | My first important item |
| 2 | My second important item |
| 3 | My third important item |
| 4 | and this one more thing |
+---------+--------------------------+
4 rows in set (0.000 sec)
确认测试表中有有效数据后,可以退出 MySQL 控制台:
exit
现在您可以创建连接到 MySQL 并查询内容的 PHP 脚本。使用您喜欢的编辑器在您的自定义 Web 根目录中创建一个新的 PHP 文件。我们将使用nano
它:
nano /var/www/your_domain/todo_list.php
以下 PHP 脚本连接 MySQL 数据库并查询todo_list
表的内容,以列表形式显示结果。如果数据库连接出现问题,则会抛出异常。
将以下内容添加到您的todo_list.php
脚本中:/var/www/your_domain/todo_list.php
<?php
$user = "example_user";
$password = "password";
$database = "example_database";
$table = "todo_list";
try {
$db = new PDO("mysql:host=localhost;dbname=$database", $user, $password);
echo "<h2>TODO</h2><ol>";
foreach($db->query("SELECT content FROM $table") as $row) {
echo "<li>" . $row['content'] . "</li>";
}
echo "</ol>";
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
编辑完成后保存并关闭文件。
您现在可以在 Web 浏览器中访问此页面,方法是访问为您的网站配置的域名或公共 IP 地址,然后执行以下操作/todo_list.php
:
http://server_domain_or_IP/todo_list.php
您应该收到如下所示的页面,显示您在测试表中插入的内容:
这意味着您的 PHP 环境已准备好连接并与您的 MySQL 服务器交互。
结论
在本指南中,您构建了一个灵活的基础,用于为访问者提供 PHP 网站和应用程序,使用 Nginx 作为 Web 服务器,使用 MySQL 作为数据库系统。