介绍
LEMP 软件堆栈是一组软件,可用于为用 PHP 编写的动态网页和 Web 应用程序提供服务。这是一个描述一个缩写大号inux下操作系统,与Nginx的(发音如“ é ngine-X”)的web服务器。后端数据被存储在中号ySQL数据库和动态处理是通过处理P HP。
本指南演示了如何在 Ubuntu 20.04 服务器上安装 LEMP 堆栈。Ubuntu 操作系统满足第一个要求。我们将描述如何启动和运行其余的组件。
先决条件
为了完成本教程,您需要以普通的非 rootsudo
用户身份访问 Ubuntu 20.04 服务器,并在您的服务器上启用防火墙。要进行设置,您可以按照我们针对 Ubuntu 20.04 的初始服务器设置指南进行操作。
步骤 1 – 安装 Nginx Web 服务器
为了向我们的网站访问者显示网页,我们将使用 Nginx,一个高性能的网络服务器。我们将使用apt
包管理器来获取此软件。
由于这是我们第一次使用apt
此会话,首先更新服务器的包索引。之后,您可以使用apt install
来安装 Nginx:
- sudo apt update
- sudo apt install nginx
出现提示时,输入Y
以确认您要安装 Nginx。安装完成后,Nginx Web 服务器将处于活动状态并在您的 Ubuntu 20.04 服务器上运行。
如果您ufw
按照我们的初始服务器设置指南中的建议启用了防火墙,您将需要允许连接到 Nginx。Nginx 在安装时会注册一些不同的 UFW 应用程序配置文件。要检查哪些 UFW 配置文件可用,请运行:
- sudo ufw app list
OutputAvailable applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
建议您启用仍然允许您需要的流量的最严格的配置文件。由于您没有在本指南中为您的服务器配置 SSL,您只需要允许端口上的常规 HTTP 流量80
。
通过键入以下内容启用此功能:
- sudo ufw allow 'Nginx HTTP'
您可以通过运行来验证更改:
- sudo ufw status
此命令的输出将显示现在允许 HTTP 流量:
OutputStatus: 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 eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'
这将打印出一些 IP 地址。您可以在 Web 浏览器中依次尝试每一个。
作为替代方案,您可以检查从 Internet 上的其他位置查看哪些 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
是,或其他任何不启用就继续的问题。
VALIDATE PASSWORD PLUGIN 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 plugin?
Press y|Y for Yes, any other key for No:
如果您回答“是”,系统会要求您选择密码验证级别。请记住,如果您输入2
最强级别,则在尝试设置任何不包含数字、大小写字母和特殊字符或基于常用词典单词的密码时,您将收到错误消息。
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 root用户的密码。这不要与系统 root混淆。该数据库根用户是在数据库系统完全权限的管理用户。尽管 MySQL root 用户的默认身份验证方法不使用密码,即使设置了密码,您也应该在此处定义强密码作为额外的安全措施。稍后我们将讨论这个问题。
如果您启用了密码验证,您将看到您刚刚输入的 root 密码的密码强度,您的服务器将询问您是否要继续使用该密码。如果您对当前密码感到满意,请Y
在提示处输入“是”:
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 服务器,这是通过sudo
运行此命令时的使用推断出来的。你应该看到这样的输出:
OutputWelcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 8.0.19-0ubuntu5 (Ubuntu)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
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 控制台,请键入:
- exit
请注意,即使您在运行脚本时定义了密码,也无需提供密码即可以root用户身份进行连接mysql_secure_installation
。那是因为管理 MySQL 用户的默认身份验证方法unix_socket
不是password
. 尽管这起初看起来像是一个安全问题,但它使数据库服务器更加安全,因为唯一允许以根MySQL 用户身份登录的用户是具有 sudo 权限的系统用户,这些用户从控制台或通过运行在相同的特权。实际上,这意味着您将无法使用管理数据库root用户从 PHP 应用程序进行连接。为root设置密码MySQL 帐户可作为保护措施,以防默认身份验证方法从 更改unix_socket
为password
。
为了提高安全性,最好为每个数据库设置具有较少扩展权限的专用用户帐户,特别是如果您计划在您的服务器上托管多个数据库。
注意:在撰写本文时,本机 MySQL PHP 库mysqlnd
不支持 caching_sha2_authentication
,这是 MySQL 8 的默认身份验证方法。因此,在 MySQL 8 上为 PHP 应用程序创建数据库用户时,您需要确保他们’被配置为使用mysql_native_password
。我们将在步骤 6 中演示如何做到这一点。
您的 MySQL 服务器现已安装并受到保护。接下来,我们将安装 PHP,这是 LEMP 堆栈中的最后一个组件。
第 3 步 – 安装 PHP
您已经安装了 Nginx 来为您的内容提供服务,并安装了 MySQL 来存储和管理您的数据。现在您可以安装 PHP 来处理代码并为 Web 服务器生成动态内容。
虽然 Apache 在每个请求中嵌入了 PHP 解释器,但 Nginx 需要一个外部程序来处理 PHP 处理并充当 PHP 解释器本身和 Web 服务器之间的桥梁。这允许在大多数基于 PHP 的网站中获得更好的整体性能,但它需要额外的配置。您需要安装php-fpm
,它代表“PHP fastCGI 进程管理器”,并告诉 Nginx 将 PHP 请求传递给该软件进行处理。此外,您还需要php-mysql
一个 PHP 模块,它允许 PHP 与基于 MySQL 的数据库进行通信。核心 PHP 包将自动安装为依赖项。
要安装php-fpm
和php-mysql
软件包,请运行:
- sudo apt install php-fpm php-mysql
出现提示时,键入Y
和ENTER
以确认安装。
您现在已经安装了 PHP 组件。接下来,您将配置 Nginx 以使用它们。
第 4 步 – 配置 Nginx 以使用 PHP 处理器
在使用 Nginx Web 服务器时,我们可以创建服务器块(类似于 Apache 中的虚拟主机)来封装配置细节,并在一台服务器上托管多个域。在本指南中,我们将使用your_domain作为示例域名。要了解有关使用 DigitalOcean 设置域名的更多信息,请参阅我们对 DigitalOcean DNS的介绍。
在 Ubuntu 20.04 上,Nginx 默认启用一个服务器块,并配置为从/var/www/html
. 虽然这适用于单个站点,但如果您托管多个站点,则可能会变得难以管理。而不是修改的/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/php7.4-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
以下是每个指令和位置块的作用:
listen
— 定义 Nginx 将侦听的端口。在这种情况下,它将侦听 port80
,这是 HTTP 的默认端口。root
— 定义存储此网站提供的文件的文档根目录。index
— 定义 Nginx 将以此网站的索引文件的优先顺序。通常的做法是列出index.html
优先级高于index.php
文件的文件,以便在 PHP 应用程序中快速设置维护登录页面。您可以调整这些设置以更好地满足您的应用需求。server_name
— 定义此服务器块应响应的域名和/或 IP 地址。将此指令指向您服务器的域名或公共 IP 地址。location /
— 第一个位置块包含一个try_files
指令,用于检查是否存在与 URI 请求匹配的文件或目录。如果 Nginx 找不到合适的资源,它将返回 404 错误。location ~ \.php$
— 此位置块通过将 Nginx 指向fastcgi-php.conf
配置文件和php7.4-fpm.sock
文件来处理实际的 PHP 处理,该文件声明了与php-fpm
.location ~ /\.ht
— 最后一个位置块处理.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
在此文件中包含以下内容:
<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();
完成后,通过键入CTRL
+X
和y
和ENTER
确认保存并关闭文件。
现在,您可以通过访问您在 Nginx 配置文件中设置的域名或公共 IP 地址,在 Web 浏览器中访问此页面,后跟/info.php
:
http://server_domain_or_IP/info.php
您将看到一个包含有关您的服务器的详细信息的网页:
通过该页面检查有关您的 PHP 服务器的相关信息后,最好删除您创建的文件,因为它包含有关您的 PHP 环境和您的 Ubuntu 服务器的敏感信息。您可以使用rm
删除该文件:
- sudo rm /var/www/your_domain/info.php
如果以后需要,您可以随时重新生成此文件。
步骤 6 — 从 PHP 测试数据库连接(可选)
如果您想测试 PHP 是否能够连接到 MySQL 并执行数据库查询,您可以创建一个带有虚拟数据的测试表并从 PHP 脚本中查询其内容。在我们这样做之前,我们需要创建一个测试数据库和一个正确配置的新 MySQL 用户来访问它。
在撰写本文时,本机 MySQL PHP 库mysqlnd
不支持 caching_sha2_authentication
MySQL 8 的默认身份验证方法。我们需要使用mysql_native_password
身份验证方法创建一个新用户,以便能够从以下位置连接到 MySQL 数据库PHP。
我们将创建一个名为数据库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 控制台来测试新用户是否具有适当的权限,这次使用自定义用户凭据:
- mysql -u example_user -p
请注意-p
此命令中的标志,它会提示您输入创建example_user用户时使用的密码。登录 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
脚本中:
<?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();
}
完成编辑后保存并关闭文件。
您现在可以通过访问为您的网站配置的域名或公共 IP 地址,然后在您的 Web 浏览器中访问此页面/todo_list.php
:
http://server_domain_or_IP/todo_list.php
您应该会看到一个这样的页面,其中显示了您插入到测试表中的内容:
这意味着您的 PHP 环境已准备好连接您的 MySQL 服务器并与之交互。
结论
在本指南中,我们为向访问者提供 PHP 网站和应用程序构建了一个灵活的基础,使用 Nginx 作为 Web 服务器,使用 MySQL 作为数据库系统。