如何在Ubuntu20.04上安装Linux、Nginx、MySQL、PHP(LEMP堆栈)
介绍
LEMP 软件堆栈是一组软件,可用于提供用 PHP 编写的动态网页和 Web 应用程序。 这是描述 Linux 操作系统的首字母缩写词,带有 Nginx(发音为“Engine-X”)Web 服务器。 后端数据存储在MySQL数据库中,动态处理由PHP处理。
本指南演示了如何在 Ubuntu 20.04 服务器上安装 LEMP 堆栈。 Ubuntu 操作系统满足第一个要求。 我们将描述如何启动并运行其余组件。
先决条件
为了完成本教程,您需要以普通的非 root sudo
用户身份访问 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,您只需要允许端口 80
上的常规 HTTP 流量。
通过键入以下内容启用此功能:
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 地址。 您可以在您的网络浏览器中依次尝试它们中的每一个。
作为替代方案,您可以检查从 Internet 上的其他位置查看的 IP 地址是可访问的:
curl -4 icanhazip.com
在您的网络浏览器中输入您收到的地址,它将带您进入 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 用户的密码。 不要与 系统根 混淆。 数据库根 用户是对数据库系统具有完全权限的管理用户。 即使 MySQL 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
请注意,即使您在运行 mysql_secure_installation
脚本时定义了密码,您也无需提供以 root 用户身份连接的密码。 这是因为管理 MySQL 用户的默认身份验证方法是 unix_socket
而不是 password
。 尽管这起初看起来像是一个安全问题,但它使数据库服务器更加安全,因为唯一允许以 root MySQL 用户身份登录的用户是从控制台连接的具有 sudo 权限的系统用户或通过以相同权限运行的应用程序。 实际上,这意味着您将无法使用管理数据库 root 用户从您的 PHP 应用程序进行连接。 为 root MySQL 帐户设置密码可以起到保护作用,以防默认身份验证方法从 unix_socket
更改为 password
。
为了提高安全性,最好为每个数据库设置具有较少扩展权限的专用用户帐户,特别是如果您计划在您的服务器上托管多个数据库。
注意: 在撰写本文时,原生 MySQL PHP 库 mysqlnd
不支持 caching_sha2_authentication
,MySQL 8 的默认身份验证方法. 因此,在 MySQL 8 上为 PHP 应用程序创建数据库用户时,您需要确保将它们配置为使用 mysql_native_password
。 我们将在 Step 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
中为 your_domain 网站创建一个目录结构,而不是修改 /var/www/html
,而将 /var/www/html
保留为默认目录如果客户端请求与任何其他站点不匹配,则提供。
为 your_domain 创建根 Web 目录,如下所示:
sudo mkdir /var/www/your_domain
接下来,使用 $USER 环境变量分配目录的所有权,它将引用您当前的系统用户:
sudo chown -R $USER:$USER /var/www/your_domain
然后,使用您喜欢的命令行编辑器在 Nginx 的 sites-available
目录中打开一个新的配置文件。 在这里,我们将使用 nano
:
sudo nano /etc/nginx/sites-available/your_domain
这将创建一个新的空白文件。 粘贴以下基本配置:
/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 将侦听的端口。 在这种情况下,它将侦听端口80
,这是 HTTP 的默认端口。root
— 定义存储此网站提供的文件的文档根目录。index
- 定义 Nginx 将优先考虑该网站的索引文件的顺序。 通常的做法是列出优先级高于index.php
文件的index.html
文件,以便在 PHP 应用程序中快速设置维护登录页面。 您可以调整这些设置以更好地满足您的应用程序需求。server_name
— 定义该服务器块应响应的域名和/或 IP 地址。 将此指令指向您服务器的域名或公共IP地址。location /
— 第一个位置块包含一个try_files
指令,它检查是否存在与 URI 请求匹配的文件或目录。 如果 Nginx 找不到合适的资源,会返回 404 错误。location ~ \.php$
- 此位置块通过将 Nginx 指向fastcgi-php.conf
配置文件和php7.4-fpm.sock
文件来处理实际的 PHP 处理,该文件声明与 [X194X 关联的套接字]。location ~ /\.ht
- 最后一个位置块处理.htaccess
文件,Nginx 不处理这些文件。 通过添加deny all
指令,如果任何.htaccess
文件碰巧进入文档根目录,它们将不会被提供给访问者。
完成编辑后,保存并关闭文件。 如果您使用的是 nano
,您可以通过键入 CTRL+X
然后 y
和 ENTER
来确认。
通过链接到 Nginx 的 sites-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 代码,它将返回有关您的服务器的信息:
/var/www/your_domain/info.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
身份验证方法创建一个新用户,以便能够从 PHP 连接到 MySQL 数据库。
我们将创建一个名为 example_database 的数据库和一个名为 example_user 的用户,但您可以将这些名称替换为不同的值。
首先,使用 root 帐户连接到 MySQL 控制台:
sudo mysql
要创建新数据库,请从 MySQL 控制台运行以下命令:
CREATE DATABASE example_database;
现在您可以创建一个新用户并授予他们对您刚刚创建的自定义数据库的完全权限。
以下命令使用 mysql_native_password
作为默认身份验证方法创建一个名为 example_user
的新用户。 我们将此用户的密码定义为 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
脚本中:
/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(); }
完成编辑后保存并关闭文件。
您现在可以通过访问为您的网站配置的域名或公共 IP 地址在 Web 浏览器中访问此页面,然后按 /todo_list.php
:
http://server_domain_or_IP/todo_list.php
您应该会看到这样的页面,显示您在测试表中插入的内容:
这意味着您的 PHP 环境已准备好与您的 MySQL 服务器连接和交互。
结论
在本指南中,我们使用 Nginx 作为 Web 服务器和 MySQL 作为数据库系统,为您的访问者提供 PHP 网站和应用程序建立了一个灵活的基础。