本教程适用于以下操作系统版本

  • Debian 12(Bookworm)
  • Debian 11(Bullseye)
  • Debian 9(Stretch)
  • Debian 8(Jessie)
  • Debian 6(Squeeze)
  • Debian 5(Lenny)

本页内容

  • 准备工作
  • 第 1 步 - 配置防火墙
  • 第 2 步 - 安装 PHP
  • 第 3 步 - 安装 MariaDB
  • 第 4 步 - 配置 MariaDB
  • 第 5 步 - 安装 Nginx
  • 第 6 步 - 配置 PHP-FPM
  • 第 7 步 - 安装 phpMyAdmin
  • 第 8 步 - 配置 phpMyAdmin
  • 第 9 步 - 配置 Opcache
  • 第 10 步 - 安装用于 SSL 的 Certbot
  • 第 11 步 - 测试演示站点 创建站点 创建 SSL 证书 配置 Nginx
  • 总结
  • 创建站点
  • 创建 SSL 证书
  • 配置 Nginx

Linux LEMP 技术栈是一套用于 Web 应用开发和托管的流行软件组合。它由四个关键组件组成:Linux、Nginx(读作 "Engine-X")、MySQL 或 MariaDB(关系型数据库)以及 PHP(一种流行的 Web 编程语言)。在该架构中,Linux 是操作系统,Nginx 是负责处理 HTTP 请求并提供图片、.css 文件等静态内容的 Web 服务器。MySQL(在本教程中即 MariaDB)用作数据库系统。PHP 是用于动态生成 Web 内容并与数据库交互的脚本语言。这些组件共同构成了一个稳健且可扩展的环境,用于构建和部署网站及 Web 应用。

本指南将教你如何在几天前发布的 Debian 12(bookworm)服务器上安装 LEMP 技术栈。你还将学习如何安装 phpMyAdmin 等应用。

准备工作

  • 一台运行 Debian 12 的服务器。
  • 一个具有 sudo 权限的非 root 用户。
  • 一个指向该服务器的完全限定域名(FQDN),例如 example.com。
  • Uncomplicated Firewall(UFW)已启用并正在运行。
  • 所有软件包均已更新。$ sudo apt update && sudo apt upgrade
  • 系统所需的几个软件包。$ sudo apt install wget curl nano ufw software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release debian-archive-keyring unzip -y 其中部分软件包可能已在你的系统上安装。

一台运行 Debian 12 的服务器。

一个具有 sudo 权限的非 root 用户。

一个指向该服务器的完全限定域名(FQDN),例如 example.com。

Uncomplicated Firewall(UFW)已启用并正在运行。

所有软件包均已更新。

$ sudo apt update && sudo apt upgrade

系统所需的几个软件包。

$ sudo apt install wget curl nano ufw software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release debian-archive-keyring unzip -y

其中部分软件包可能已在你的系统上安装。

第 1 步 - 配置防火墙

在安装任何软件包之前,第一步是配置防火墙以允许 HTTP 和 HTTPS 连接。

检查防火墙状态。

$ sudo ufw status

你应该会看到类似以下内容。

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

允许 HTTP 和 HTTPS 端口。

$ sudo ufw allow http
$ sudo ufw allow https

再次检查状态以确认。

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)

第 2 步 - 安装 PHP

Debian 12 默认自带 PHP 8.2。你可以运行以下命令来安装它。

$ sudo apt install php-fpm php-cli php-mysql php-mbstring php-xml php-gd

我们已安装 PHP 的 MySQL、CLI、GD、Mbstring 和 XML 扩展。你可以根据自身需求安装其他扩展。

若要始终使用最新版本的 PHP,或想安装多个版本的 PHP,请添加 Ondrej 的 PHP 软件源。

首先,导入 Sury 软件源的 PHP GPG 密钥。

$ sudo curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg

添加 Ondrej Sury 的 PHP 软件源。

$ sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'

更新系统软件源列表。

$ sudo apt update	

现在,你可以安装任意版本的 PHP。

$ sudo apt install php8.1-fpm php8.1-cli

检查已安装的 PHP 版本。

$ php --version
PHP 8.2.7 (cli) (built: Jun  9 2023 19:37:27) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.7, Copyright (c), by Zend Technologies

第 3 步 - 安装 MariaDB

Debian 12 默认不随附 MySQL,官方也尚未发布对应的软件包。因此,我们将使用 MariaDB 来替代。MariaDB 同样没有针对 Debian 12 的官方软件包,但 Debian 自带了该软件。因此,请使用以下命令安装它。

$ sudo apt install mariadb-server

检查 MySQL 版本。

$ mysql --version
mysql  Ver 15.1 Distrib 10.11.3-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper

运行 MariaDB 安全安装脚本。

$ sudo mysql_secure_installation

系统会要求输入 root 密码。直接按回车,因为我们还没有为其设置任何密码。

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none):

接下来,系统会询问是否切换到 Unix socket 认证方式。unix_socket 插件允许你使用操作系统凭据连接到 MariaDB 服务器。由于你已经拥有一个受保护的 root 账户,请输入 n 继续。

OK, successfully used password, moving on...

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] n

接下来,系统会询问是否要更改 root 密码。在 Debian 12 中,root 密码与系统自动维护紧密相关,因此不应改动。输入 n 继续。

 ... skipping.

You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n] n

接下来,系统会提出一些问题以增强 MariaDB 安全性。输入 Y 以删除匿名用户、禁止 root 远程登录、删除测试数据库并重新加载权限表。

 ... skipping.

By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

你可以在命令行中输入 sudo mysql 或 sudo mariadb 进入 MariaDB 命令行。

第 4 步 - 配置 MariaDB

登录 MariaDB 命令行。

$ sudo mysql

创建一个示例数据库。

MariaDB> CREATE DATABASE exampledb;

创建一个 SQL 用户账户。

MariaDB> CREATE USER 'exampleuser'@'localhost' IDENTIFIED BY 'YourPassword2!';

将该数据库的所有权限授予该用户。

MariaDB> GRANT ALL PRIVILEGES ON exampledb.* TO 'exampleuser'@'localhost';

由于我们没有修改 root 用户,你应该创建另一个使用密码认证、用于执行管理任务的 SQL 用户。请为其设置一个强密码。

MariaDB> GRANT ALL ON *.* TO 'navjot'@'localhost' IDENTIFIED BY 'Yourpassword32!' WITH GRANT OPTION;

刷新用户权限。

MariaDB> FLUSH PRIVILEGES;

退出命令行。

MariaDB> exit

让我们使用新创建的用户再次登录 MySQL 命令行。

$ sudo mysql -u exampleuser -p

创建一个测试表。

MariaDB> CREATE TABLE exampledb.name_list ( sno INT AUTO_INCREMENT, content VARCHAR(255), PRIMARY KEY(sno) );

插入测试数据。

MariaDB> INSERT INTO exampledb.name_list (content) VALUES ("Navjot");

多次重复上述命令以添加更多记录。运行以下命令查看表的内容。

MariaDB> SELECT * FROM exampledb.name_list;

你将收到如下输出。

+-----+---------+
| sno | content |
+-----+---------+
|   1 | Navjot  |
|   2 | Adam    |
|   3 | Josh    |
|   4 | Peter   |
+-----+---------+
4 rows in set (0.00 sec)

退出 MySQL 命令行。

MariaDB> exit

第 5 步 - 安装 Nginx

Debian 12 自带较旧版本的 Nginx。要安装最新版本,你需要下载官方的 Nginx 软件源。

导入 Nginx 的签名密钥。

$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

添加 Nginx 稳定版的软件源。

$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/debian `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

更新系统软件源。

$ sudo apt update

安装 Nginx。

$ sudo apt install nginx

验证安装。在 Debian 系统上,以下命令需要配合 sudo 才能运行。

$ sudo nginx -v
nginx version: nginx/1.24.0

启动 Nginx。

$ sudo systemctl start nginx

检查服务状态。

$ sudo systemctl status nginx
? nginx.service - nginx - high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Thu 2023-06-15 16:33:46 UTC; 1s ago
       Docs: https://nginx.org/en/docs/
    Process: 2257 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
   Main PID: 2258 (nginx)
      Tasks: 2 (limit: 1108)
     Memory: 1.8M
        CPU: 6ms
     CGroup: /system.slice/nginx.service
             ??2258 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             ??2259 "nginx: worker process"

第 6 步 - 配置 PHP-FPM

打开 php.ini 进行编辑。

$ sudo nano /etc/php/8.2/fpm/php.ini

要设置文件上传大小,请修改 upload_max_filesize 和 post_max_size 变量的值。

upload_max_filesize = 50M
...
post_max_size = 50M

根据你的服务器资源和需求配置 PHP 的内存限制。

memory_limit = 256M

按 Ctrl + X 保存文件,并在提示时输入 Y。

你也可以不使用编辑器打开文件,而是用以下命令完成修改。

$ sudo sed -i 's/post_max_size = 8M/post_max_size = 50M/' /etc/php/8.2/fpm/php.ini
$ sudo sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 50M/' /etc/php/8.2/fpm/php.ini
$ sudo sed -i 's/memory_limit = 128M/memory_limit = 256M/' /etc/php/8.2/fpm/php.ini

打开文件 /etc/php/8.0/fpm/pool.d/www.conf 。

$ sudo nano /etc/php/8.2/fpm/pool.d/www.conf

我们需要将 PHP 进程的 Unix 用户/组设置为 nginx。在文件中找到 user=www-data 和 group=www-data 两行,并将它们改为 nginx。

...
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = nginx
group = nginx
...

此外,在文件中找到 listen.owner=www-data 和 listen.group=www-data 两行,并将它们改为 nginx。

listen.owner = nginx
listen.group = nginx

按 Ctrl + X 保存文件,并在提示时输入 Y。

重启 PHP-fpm 进程。

$ sudo systemctl restart php8.2-fpm

第 7 步 - 安装 phpMyAdmin

下载英文版的 phpMyAdmin 归档文件。从 phpMyAdmin 下载页面获取最新版本的链接。

$ wget https://files.phpmyadmin.net/phpMyAdmin/5.2.1/phpMyAdmin-5.2.1-english.tar.gz

为站点创建公开目录。

$ sudo mkdir /var/www/html/example.com -p

将归档文件解压到公开目录。

$ sudo tar -xzf phpMyAdmin-5.2.1-english.tar.gz -C /var/www/html/example.com

切换到公开目录。

$ cd /var/www/html/example.com

将解压后的目录重命名为一个不常见的名称以提高安全性。

$ sudo mv phpMyAdmin-5.2.1-english sm175

第 8 步 - 配置 phpMyAdmin

复制示例配置文件。

$ sudo cp sm175/config.sample.inc.php sm175/config.inc.php

打开配置文件进行编辑。

$ sudo nano sm175/config.inc.php

找到 $cfg['blowfish_secret'] = ''; 这一行,并输入一个 32 字符的随机字符串用于基于 Cookie 的认证。

你可以使用 phpSolved 的在线 blowfish 生成器,或通过命令行来完成。

复制该值并按图示粘贴。

$cfg['blowfish_secret'] = 'Tc/HfLPBOAPxJ-rhQP}HJoZEK69c3j:m';

按 Ctrl + X 保存文件,并在提示时输入 Y。

将站点和 phpMyAdmin 的所有权更改为 Nginx 服务器。

$ sudo chown -R nginx:nginx /var/www/html/example.com

删除 phpMyAdmin 的安装目录。

$ sudo rm -rf /var/www/html/example.com/sm175/setup

第 9 步 - 配置 Opcache

Opcache 是 PHP 的缓存系统。其工作原理是将预编译的脚本字节码保存在内存中,因此每当用户访问页面时,加载速度会更快。Opcache 默认已安装。要验证,请检查 PHP 版本。

$ php --version
PHP 8.2.7 (cli) (built: Jun  9 2023 19:37:27) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.7, Copyright (c), by Zend Technologies

这表明 Opcache 已安装并可用。如果此处没有显示,你可以运行以下命令手动安装。

$ sudo apt install php-opcache

要修改 Opcache 设置,请打开文件 /etc/php/8.2/fpm/conf.d/10-opcache.ini 进行编辑。

$ sudo nano /etc/php/8.2/fpm/conf.d/10-opcache.ini

以下设置可以帮助你开始使用 Opcache,通常也推荐用于获得良好的性能。你可以在文件末尾添加以下几行来启用它。

opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60

按 Ctrl + X 保存文件,并在提示时输入 Y。

重启 PHP-FPM。

$ sudo systemctl restart php8.2-fpm

第 10 步 - 安装用于 SSL 的 Certbot

我们需要安装 Certbot 来生成 Let's Encrypt 提供的免费 SSL 证书。

你可以使用 Debian 自带的软件源安装 Certbot,也可以通过 Snapd 工具获取最新版本。我们将使用 Snapd 版本。

Debian 12 默认未安装 Snapd。请安装 Snapd 软件包。

$ sudo apt install snapd

运行以下命令以确保你的 Snapd 版本是最新的。

$ sudo snap install core
$ sudo snap refresh core

安装 Certbot。

$ sudo snap install --classic certbot

使用以下命令,通过创建指向 /usr/bin 目录的符号链接,确保可以运行 Certbot 命令。

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

验证 Certbot 是否正常工作。

$ certbot --version
certbot 2.6.0

第 11 步 - 测试演示站点

创建站点

创建并打开一个测试页面进行编辑。

$ sudo nano /var/www/html/example.com/index.php

在其中粘贴以下代码。

<?php
$user = "exampleuser";
$password = "YourPassword2!";
$database = "exampledb";
$table = "name_list";

try {
    $db = new PDO("mysql:host=localhost;dbname=$database", $user, $password);
    echo "<h2>Members List</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();
}

按 Ctrl + X 保存文件,并在提示时输入 Y。

创建 SSL 证书

运行以下命令以生成 SSL 证书。

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m 
[email protected]
 -d example.com

上述命令会将证书下载到服务器上的 /etc/letsencrypt/live/example.com 目录。

生成 Diffie-Hellman 组证书。

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

检查 Certbot 续期调度服务。

$ sudo systemctl list-timers

你会发现 snap.certbot.renew.service 是计划运行的服务之一。

NEXT                        LEFT          LAST                        PASSED        UNIT                      ACTIVATES
.....
Sun 2023-02-26 06:32:00 UTC 9h left       Sat 2023-02-25 18:04:05 UTC 2h 59min ago  snap.certbot.renew.timer  snap.certbot.renew.service
Sun 2023-02-26 06:43:20 UTC 9h left       Sat 2023-02-25 10:49:23 UTC 10h ago       apt-daily-upgrade.timer   apt-daily-upgrade.service
Sun 2023-02-26 09:00:06 UTC 11h left      Sat 2023-02-25 20:58:06 UTC 5min ago      apt-daily.timer           apt-daily.service

对流程进行一次空运行,以检查 SSL 续期是否正常工作。

$ sudo certbot renew --dry-run

如果没有看到错误,说明一切就绪。你的证书将自动续期。

配置 Nginx

创建并打开文件 /etc/nginx/conf.d/example.conf 进行编辑。

$ sudo nano /etc/nginx/conf.d/example.conf

在其中粘贴以下代码。

server {
    listen       443 ssl http2;
    listen       [::]:443 ssl http2;
    server_name  example.com;

    access_log  /var/log/nginx/example.com.access.log;
    error_log   /var/log/nginx/example.com.error.log;

    ssl_certificate      /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

    ssl_session_timeout  5m;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;

    root /var/www/html/example.com;

    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Pass PHP Scripts To FastCGI Server
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock; #depends on PHP versions
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

# enforce HTTPS
server {
    listen       80;
    listen       [::]:80;
    server_name  example.com;
    return 301   https://$host$request_uri;
}

按 Ctrl + X 保存文件,并在提示时输入 Y。

打开文件 /etc/nginx/nginx.conf 进行编辑。

$ sudo nano /etc/nginx/nginx.conf

在 include /etc/nginx/conf.d/*.conf; 这一行之前添加以下行。

server_names_hash_bucket_size  64;

按 Ctrl + X 保存文件,并在提示时输入 Y。

验证你的 Nginx 配置。

$ sudo nginx -t

如果没有看到错误,说明可以正常进行。启动 Nginx 服务器。

$ sudo systemctl start nginx

在浏览器中访问 https://example.com 加载你的网站,你将看到以下页面。

如何在 Debian 12 上安装 LEMP 技术栈(Nginx、PHP 和 MariaDB)

你可以通过在浏览器中访问 https://example.com/sm175 来使用你安装的 phpMyAdmin。你可以输入你之前创建的管理用户或普通用户进行登录。

总结

本教程到此结束,你学习了如何在 Debian 12 服务器上搭建 LEMP 技术栈并创建了一个演示站点。如果你有任何问题,请在下方评论区留言。