随着CentOS7的终结日渐临近,升级或替换系统终于也被提上日程了。在虚拟机上测试过从CentOS7转换到AlmaLinux或RockyLinux,但情况并非很理想。
Oneinstack和LNMP的自动化脚本又频频传出挂马的消息,至于宝塔这种可视化界面又存在这样那样的问题(见《这次被宝塔面板给坑苦了——数据库被删除》、《宝塔面板不执行计划任务》)还对系统性能要求颇高,所以干脆学习一下如何手动安装服务器的应用程序。
本文中的安装方法主要参考自《How to Install LEMP Stack (Nginx, PHP and MariaDB) on Debian 12》一文。
准备工作
首先将系统及所有程序都升级到最新版
$ 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
有些程序已经默认安装在系统中,还有些可以根据自己的需要增添。
配置防火墙
在开始安装前,需对防火墙进行一下配置,如不需要可以跳过本步骤。
首先查看一下UFW的运行状况
$ sudo ufw status
你可能会看到如下的内容:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
如果防火墙没有运行的话,会显示Status: inactive
。因为是远程服务器,所以在开启UFW前要确保SSH已被允许,否则就无法远程连接到服务器了,运行以下命令:
$ sudo ufw allow ssh
然后运行:
$ sudo ufw enable
开启过程会提示可能会中断SSH操作并询问是否继续,输入Y
即可。再次检验UFW运行状态,应该就能看到如上所示的信息了。
接下来添加HTTP和HTTPS的端口:
$ sudo ufw allow http
$ sudo ufw allow https
再次检验UFW状态,如下所示:
$ 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)
安装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 --version
PHP 8.2.26 (cli) (built: Nov 25 2024 17:21:51) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.26, Copyright (c) Zend Technologies
with Zend OPcache v8.2.26, Copyright (c), by Zend Technologies
如果想始终使用最新版本的PHP,或者如果想安装多个版本的PHP,可以添加Ondrej的PHP存储库。
首先,导入Sury的repo 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了,比如8.1:
$ sudo apt install php8.1-fpm php8.1-cli
安装数据库程序MariaDB或MySQL
Debian 12中并不包含MySQL软件包,其已经被MariaDB替换,所以可以通过以下命令进行安装:
$ sudo apt install mariadb-server
安装完毕后,检查一下版本:
$ mysql --version
mysql Ver 15.1 Distrib 10.11.16-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套接字身份验证方法。unix套接字插件允许你使用操作系统凭据连接到MariaDB服务器。由于你已经有一个受保护的根帐户,请输入n继续(如果搞不清楚的话输入y也可以)。
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密码。 这里输入y,然后再输入想修改的新密码。
... skipping.
You already have your root account protected, so you can safely answer 'n'.
Change the root password? [Y/n] y
接下来,系统会问你一些问题,以提高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!
注意:MariaDB可能会因为出现缺少字符集的问题而出现导入错误(详见《Mariadb导入数据表时发生“Unknown collation: 'utf8mb4_0900_ai_ci'”错误》一文)而又懒得折腾,或者就是偏好使用MySQL,那么只能下载安装包进行安装了。
首选,进入MySQL存储库下载页面,下载最新软件包。也可以在命令界面下使用wget命令下载最新的发行包。
wget https://repo.mysql.com/mysql-apt-config_0.8.33-1_all.deb
其次,下载完成后,使用如下命令进行安装。
sudo dpkg -i mysql-apt-config_0.8.33-1_all.deb
执行如上命令后,你会看到如下的MySQL配置安装界面,默认为8.4长期维护版本,如果需要切换则按回车键进行选择(下图为Ubuntu在虚拟机中的演示效果,Debian 12同理)。
使用以下命令更新软件包,并安装MySQL。
sudo apt update
sudo apt install mysql-server
安装过程中将会要求设置root密码,这一步先不设置,Tab键切换到 “OK” 继续,然后在后期通过安全安装脚本进行配置。最后同样检验一下版本以及测试数据库运行。
可以通过在命令行中输入sudo mysql
或sudo MariaDB
进入数据库控制台。
设置MariaDB
登录MariaDB shell:
$ 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;
退出shell:
MariaDB> exit
让我们使用新创建的用户再次登录到MySQL shell:
$ 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)
退出shell:
MariaDB> exit
安装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
验证安装:
$ sudo nginx -v
nginx version: nginx/1.26.2
启动Nginx:
$ sudo systemctl start nginx
验证服务状态:
$ systemctl status nginx
● nginx.service - nginx - high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Sat 2025-01-04 14:39:57 CST; 5s ago
Docs: https://nginx.org/en/docs/
Process: 18225 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
Main PID: 18226 (nginx)
Tasks: 3 (limit: 4420)
Memory: 2.9M
CPU: 15ms
CGroup: /system.slice/nginx.service
├─18226 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
├─18227 "nginx: worker process"
└─18228 "nginx: worker process"
配置PHP-FPM
打开配置文件php.ini
进行编辑:
$ sudo nano /etc/php/8.2/fpm/php.ini
根据服务器资源和需求配置PHP的内存限制,比如:
memory_limit = 256M
还有上传文件的大小限制:
upload_max_filesize = 50M
...
post_max_size = 50M
保存并退出。
也可以不打开文件,而直接使用如下的命令:
$ 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
我们需要将UNIX用户/PHP流程组设置为NGINX。在文件中找到用户= 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
保存并退出。
重启PHP-fpm进程:
$ sudo systemctl restart php8.2-fpm
如果希望修改上述的用户名(比如www用户)则需要先创建用户,否则重启进程会提示错误。
安装phpMyAdmin
下载phpMyAdmin的文件包。可从phpMyAdmin下载页面中获取最新版本。
$ wget https://files.phpmyadmin.net/phpMyAdmin/5.2.1/phpMyAdmin-5.2.1-all-languages.tar.gz
为网站创建一个目录:
$ sudo mkdir /var/www/html/example.com -p
解压缩文档到站点目录下:
$ sudo tar -xzf phpMyAdmin-5.2.1-all-languages.tar.gz -C /var/www/html/example.com
切换到站点目录:
$ cd /var/www/html/example.com
将提取的目录重命名为比较模糊的名称以提高安全性,比如:
$ sudo mv phpMyAdmin-5.2.1-all-languages ms175
设置phpMyAdmin
复制示例配置文件:
$ sudo cp ms175/config.sample.inc.php ms175/config.inc.php
打开配置文件并编辑:
$ sudo nano sm175/config.inc.php
查找$cfg['blowfish secret'] = ";
并输入一个32个字符的随机字符串,用于基于cookie的认证。
你可以使用phpSolved的在线生成器,也可以通过命令行完成。
复制黏贴生成的值,如下所示:
$cfg['blowfish_secret'] = 'Tc/HfLPBOADxJ-rhQP}HJoZEK69c3j:m';
保存并退出。
删除phpMyAdmin的setup目录:
$ sudo rm -rf /var/www/html/example.com/ms175/setup
设置Opcache
Opcache是PHP的缓存系统。它的工作原理是将预编译的脚本字节码保存在内存中,这样用户每次访问页面时,加载速度都会加快。Opcache默认已安装(见PHP安装部分中检验版本的结果,其中带有with Zend 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
保存并退出。
重新启动PHP-FPM:
$ sudo systemctl restart php8.2-fpm
安装SSL证书
如果只希望使用Let's Encrypt的证书,那么可以安装Certbot证书脚本工具,如果希望有多个证书选择可以使用acme脚本(具体见《使用acme脚本申请免费ssl证书》一文)。以下是Certbot的安装和使用过程。
你可以使用Debian的存储库安装Certbot,也可以使用Snapd工具(一种全新的软件包管理工具)获取最新版本。在本安装中,将使用Snapd版本。Debian 12并没有安装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
示例网站测试
创建并打开一个测试页面:
$ 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();
}
保存并退出。
生成SSL证书
执行如下命令生成SSL证书:
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m name@example.com -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是计划运行的服务之一。
试运行流程,检查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;
}
保存并退出。
打开/etc/nginx/nginx.conf
文件进行编辑:
$ sudo nano /etc/nginx/nginx.conf
在include /etc/nginx/conf.d/*.conf;
这一行前添加以下内容:
server_names_hash_bucket_size 64;
保存并退出。
验证Nginx配置:
$ sudo nginx -t
如果没有错误,就说明可以开始了。启动Nginx服务器:
$ sudo systemctl start nginx
如果出现警告的话,比如:
nginx: [warn] the "listen ... http2" directive is deprecated, use the "http2" directive instead in /etc/nginx/conf.d/example.conf:2
则可以将开头几行修改为:
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.com;
……
在浏览器中访问https://example.com,加载网站后将看到以下页面。
你可以通过浏览器访问https://example.com/ms175来访问phpMyAdmin。输入管理用户或之前创建的用户进行登录。
其他参考资料
https://www.cnblogs.com/linux265/p/17974348
https://www.cyberciti.biz/faq/set-up-a-firewall-with-ufw-on-debian-12-linux/