Ubuntu 搭建 LEMP 环境:一份详尽的 Nginx, MySQL, PHP 指南

本文将手把手教你在 Ubuntu 服务器上搭建 LEMP 技术栈,包括安装配置 Nginx、MySQL、PHP-FPM,并完成防火墙设置、虚拟主机配置和数据库连接测试,为部署高性能 PHP 应用打下坚实基础。

阅读时长: 7 分钟
共 3051字
作者: eimoon.com

搭建 Web 服务器是每个后端开发者的基础课。LEMP 技术栈——即 Linux、Nginx (Engine-X)、MySQL 和 PHP 的组合,因其出色的性能和稳定性,成为了托管动态网站和应用(尤其是 PHP 应用)的主流选择之一。Nginx 的事件驱动架构在高并发场景下表现尤其亮眼。

这篇指南会带你一步步在 Ubuntu 服务器上把 LEMP 环境从零搭建起来。我们会覆盖从安装各个组件到配置它们协同工作的全过程。

版本说明: 本文主要基于 Ubuntu 22.04 LTSPHP 8.1。如果你正在使用最新的 Ubuntu 24.04 LTS,PHP 版本会是 8.3。操作时请注意将 php8.1-fpm 相关的命令和路径替换为 php8.3-fpm(例如,Nginx 配置中的 socket 路径应为 /run/php/php8.3-fpm.sock)。

准备工作

在开始之前,确保你已经准备好以下环境:

  • 一台 Ubuntu 服务器。
  • 一个拥有 sudo 权限的非 root 用户。
  • UFW 防火墙已启用。

如果你是刚拿到一台全新的服务器,可以先参考 Ubuntu 初始服务器设置指南 完成基础配置。

第一步:安装 Nginx Web 服务器

Nginx 是整个技术栈的门户,负责接收和处理来自用户的 HTTP 请求。我们用 apt 包管理器来安装它。

首先,更新一下包列表,确保我们能拿到最新的软件版本:

sudo apt update

然后,安装 Nginx:

sudo apt install nginx

安装过程中,系统会提示你确认,按 Y 回车即可。安装完成后,Nginx 服务会自动启动。可以用 systemctl 来检查一下它的状态:

sudo systemctl status nginx

如果看到 Active: active (running) 的字样,说明 Nginx 已经成功运行了。

接下来,我们需要配置防火墙,放行 Web 流量。Nginx 在安装时会自动向 UFW 注册几个应用配置文件,我们可以看看有哪些可用的:

sudo ufw app list

输出大概是这样:

Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
  • Nginx Full: 同时开放 80 (HTTP) 和 443 (HTTPS) 端口。
  • Nginx HTTP: 只开放 80 端口。
  • Nginx HTTPS: 只开放 443 端口。

因为我们还没配置 SSL 证书,所以先只开放 HTTP 流量就够了,这也是最安全的做法。

sudo ufw allow 'Nginx HTTP'

检查一下防火墙状态,确保规则已经生效:

sudo ufw status

你应该能看到 Nginx HTTP 已经被 ALLOW

现在,打开浏览器,访问你的服务器 IP 地址(如果不知道 IP,可以在服务器上运行 hostname -Icurl -4 icanhazip.com 来查看)。如果一切顺利,你会看到 Nginx 的默认欢迎页面。

Nginx 默认欢迎页

看到这个页面,就说明 Nginx 已经装好了,并且能对外提供服务了。

第二步:安装 MySQL 数据库

动态网站的数据通常需要一个地方来存放,MySQL 就是这个角色。它是一个非常成熟且广泛使用的关系型数据库管理系统。

同样,使用 apt 来安装:

sudo apt install mysql-server

安装完成后,建议立即运行 MySQL 自带的安全脚本。这个脚本会帮你处理一些不安全的默认设置,比如移除测试数据库、禁止 root 用户远程登录等。

sudo mysql_secure_installation

脚本会问你一系列问题。第一个是关于是否启用“密码验证插件”(VALIDATE PASSWORD PLUGIN)。这个插件可以强制要求密码符合一定的复杂度。启用它是个好习惯,但不是必须的。如果你选择启用,建议选择中等(MEDIUM)强度,也就是 1

接下来,脚本会让你为 MySQL 的 root 用户设置密码。注意,这里的 root 是数据库的超级管理员,和系统的 root 用户不是一回事。尽管在 Ubuntu 上,默认的 auth_socket 认证方式让你可以通过 sudo 无密码登录 MySQL,但设置一个强密码仍然是一个好的安全习惯。

对于剩下的问题,一路按 Y 回车就行了。

完成后,我们可以试试能不能登录 MySQL 控制台:

sudo mysql

因为 auth_socket 插件的存在,当你在服务器上以 sudo 权限执行 mysql 命令时,它会直接认证你为 MySQL 的 root 用户,无需输入密码。这在本地管理时非常方便且安全。

要退出 MySQL 控制台,输入 exit 即可。

第三步:安装 PHP

现在轮到技术栈里的 “P” 了。Nginx 本身不能执行 PHP 代码,它需要一个外部程序来处理。我们用 php-fpm (FastCGI Process Manager) 来做这件事。php-fpm 是一个高效的 PHP FastCGI 管理器,也是目前 Nginx + PHP 架构的的的事实标准。

我们还需要 php-mysql 扩展,这样 PHP 代码才能连接到 MySQL 数据库。

# 对于 Ubuntu 22.04
sudo apt install php8.1-fpm php-mysql

# 对于 Ubuntu 24.04,请使用以下命令
# sudo apt install php8.3-fpm php-mysql

安装完成后,php-fpm 服务也会自动启动。可以检查一下它的状态:

# 检查 Ubuntu 22.04 的 PHP 8.1
sudo systemctl status php8.1-fpm

确认服务 active (running) 后,我们的 LEMP 栈所有组件就都安装完毕了。

第四步:配置 Nginx 与 PHP-FPM 协同工作

万事俱备,只欠东风。现在我们需要告诉 Nginx,当遇到 .php 文件请求时,应该把它交给 PHP-FPM 来处理,而不是当成静态文件下载。

这个配置是通过 Nginx 的 “server block”(服务块)来完成的,它类似于 Apache 里的 “virtual host”(虚拟主机),允许你在同一台服务器上托管多个网站。

首先,为你的网站创建一个根目录。我们约定使用域名来命名,例如 your_domain

sudo mkdir /var/www/your_domain

然后,把这个目录的所有权交给当前用户,方便我们之后上传和编辑文件。

sudo chown -R $USER:$USER /var/www/your_domain

接下来,创建一个新的 Nginx 配置文件。所有的站点配置都放在 /etc/nginx/sites-available/ 目录下。

sudo nano /etc/nginx/sites-available/your_domain

在这个新文件里,粘贴以下基础配置。记得把 your_domain 替换成你自己的域名或服务器 IP。

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;
        # 确保这里的 socket 路径和你的 PHP 版本匹配
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
}

简单解释一下这段配置:

  • listen 80: 监听 80 端口的 HTTP 请求。
  • root: 指定网站文件的根目录。
  • index: 定义默认的索引文件类型和查找顺序。
  • server_name: 定义这个 server block 应该响应哪个域名。
  • location /: 处理常规的静态文件请求。try_files 会尝试按顺序查找文件,如果都找不到就返回 404。
  • location ~ \.php$: 这是核心部分。它匹配所有以 .php 结尾的请求,然后通过 fastcgi_pass 指令,将请求通过一个 Unix socket 文件转发给 PHP-FPM 进程。
  • location ~ /\.ht: 阻止访问 .htaccess 文件,因为 Nginx 不使用它,暴露出来有安全风险。

保存并关闭文件。

为了让这个配置生效,我们需要在 /etc/nginx/sites-enabled/ 目录里创建一个指向它的符号链接(软链接)。

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/

同时,最好把 Nginx 自带的默认配置给禁用掉,避免冲突。

sudo unlink /etc/nginx/sites-enabled/default

在重启 Nginx 之前,先检查一下配置文件有没有语法错误,这是一个非长重要的好习惯。

sudo nginx -t

如果看到 syntax is oktest is successful 的信息,就说明没问题。然后,平滑地重载 Nginx 服务来应用新配置:

sudo systemctl reload nginx

第五步:测试 PHP 处理能力

现在,整个技术栈的连接已经打通。我们来创建一个简单的 PHP 文件测试一下。在你的网站根目录里创建一个 info.php 文件:

nano /var/www/your_domain/info.php

写入以下内容:

<?php
phpinfo();

phpinfo() 是一个 PHP 内置函数,它会输出当前 PHP 环境的详细信息。

保存文件后,在浏览器里访问 http://your_domain/info.php。如果你看到一个包含 PHP 版本、模块信息等内容的页面,恭喜你,LEMP 环境已经成功搭建并正常工作了!

PHP Info 页面

重要提示:这个 info.php 文件暴露了太多服务器的敏感信息。测试成功后,一定要马上删除它!

sudo rm /var/www/your_domain/info.php

第六步:测试数据库连接 (可选)

最后一步,我们来验证一下 PHP 是否能成功连接到 MySQL 数据库。

首先,我们需要创建一个新的数据库和一个专用的数据库用户。直接用 root 用户去连数据库是一个非常糟糕的实践。

再次进入 MySQL 控制台:

sudo mysql

执行以下 SQL 命令来创建数据库和用户。记得把 example_databaseexample_userpassword 替换成你自己的。

-- 创建数据库
CREATE DATABASE example_database;

-- 创建用户,并指定使用 mysql_native_password 认证方式(对某些旧 PHP 客户端兼容性更好)
CREATE USER 'example_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';

-- 授予用户对该数据库的所有权限
GRANT ALL ON example_database.* TO 'example_user'@'%';

-- 刷新权限
FLUSH PRIVILEGES;

-- 退出
EXIT;

现在,在你的网站根目录创建一个新的 PHP 文件,比如 todo_list.php

nano /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>"; 
  // 简单创建一个表并插入数据
  $db->exec("CREATE TABLE IF NOT EXISTS $table (item_id INT AUTO_INCREMENT, content VARCHAR(255), PRIMARY KEY(item_id))");
  $db->exec("INSERT INTO $table (content) VALUES ('My first important item')");
  $db->exec("INSERT INTO $table (content) VALUES ('My second important item')");
  
  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();
}

保存文件,然后在浏览器访问 http://your_domain/todo_list.php。如果你看到了一个包含 “My first important item” 列表的页面,那就说明 PHP 和 MySQL 之间的连接也完全没问题了。

到这里,一个功能完备、性能出色的 LEMP 服务器环境就搭建完成了。你可以开始部署你的 PHP 项目了。

关于

关注我获取更多资讯

公众号
📢 公众号
个人号
💬 个人号
使用 Hugo 构建
主题 StackJimmy 设计