本文是一篇大纲,罗列常用 Linux 服务器软件的配置,主要是个人使用和配置过程中的一些备忘和错误记录。算是之前的一篇 《Linode VPS 的一些基本设置》的升级篇。

注1:里面提到的各个服务的安装以及配置均为个人作为初学者的折腾和摸索,仅供自己参考、备忘,不属于教程,也谈不上最佳实践。

注2:本文所列命令有的是 Ubuntu 的,有的是 Fedora 的,而且时间跨度很大,有的是多年前的,有的是最近的,这个从命令里面能看出来。

设置时区

# 查看时区列表
timedatectl list-timezones
# 设定时区,比如 Asia/Taipei
[email protected]:~$ sudo timedatectl set-timezone Asia/Taipei

[[email protected] ~]$ timedatectl
                   Local time: Sat 2023-09-30 20:10:21 CST
               Universal time: Sat 2023-09-30 12:10:21 UTC
                     RTC time: Sat 2023-09-30 12:10:21
                    Time zone: Asia/Taipei (CST, +0800)
    System clock synchronized: yes
                  NTP service: active
              RTC in local TZ: no

安装 Nginx

安装最新版 Nginx

【2023.07.25】注意,Fedora 不需要添加 nginx.repo,它自带的就是最新的,但是需要更改一下配置,使用 mailline 版,否则,它默认安装的是 stable 版。

dnf module list nginx

运行上面命令,可以查看自带的 nginx 仓库所提供的版本,目前有 mainline 和 1.20,默认是安装 1.20,我们可以运行下面命令,改成默认安装 mainline 版

sudo dnf module enable nginx:mainline

运行后,查看,可以看到,已经改成了 mainline 版

[[email protected] yum.repos.d]$ dnf module list nginx
Last metadata expiration check: 0:04:00 ago on Tue 25 Jul 2023 10:59:55 AM CST.
Fedora Modular 38 - x86_64
Name                     Stream                          Profiles                               Summary
nginx                    mainline [e]                    common [d], minimal                    nginx webserver
nginx                    1.20                            common, minimal                        nginx webserver

Fedora Modular 38 - x86_64 - Updates
Name                     Stream                          Profiles                               Summary
nginx                    mainline [e]                    common [d], minimal                    nginx webserver
nginx                    1.20                            common, minimal                        nginx webserver

Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled

【👇❗注意,要安装最新版 nginx 不再需要额外的仓库,依据 nginx 官网上的安装提示即可安装到最新版的 nginx】

https://nginx.org/en/linux_packages.html

安装 Nginx 后必要的修改

注意,安装完 nginx 后,有两个必要的修改:

一、隐藏 nginx 的版本号,修改这个文件,

sudo vi /etc/nginx/nginx.conf

把里面的 server_tokens off; 这一行的注释去掉就可以了,没有这一行的话,自己加上。注意是在 http block 里。

二、禁止 IP 直接访问,禁止未绑定的域名直接访问

如果不禁止的话,访问服务器 IP 或者访问 nginx 里未绑定,但是域名却指向服务器 IP 的域名,都会加载 nginx 默认页,/usr/share/nginx/html/index.html,这都不是我们想要的。

这个nginx自己有一个专门的配置,代码 444,如下,这个是目前 Fedora 的配置,

server {
    listen       80 default_server;
    listen       [::]:80 default_server ipv6only=on;
    return       444;
    # root       /home/coke/www/1984;
    # index      index.html;
    # access_log /var/log/nginx/host.access.log  main;
    # error_page 500 502 503 504  /50x.html;

    # location = /50x.html {
    #     root   /usr/share/nginx/html;
    # }
}

配置文件在 /etc/nginx/default.d/default.conf ,这个配置文件是我自己加上的。

之前 Ubuntu 版本是默认有这个文件,而 Fedora 版是把 sever 部分也写在了 /etc/nginx/nginx.conf 文件里,个人觉得这样不方便,还是按照 Ubuntu 的方式来,把它独立出来比较好。

关于 nginx 生成的 off 文件

【2023.08.02】关于 nginx 生成的 off 文件:

今天有时间研究,于是又开启了 SELinux,不出所料,重启之后,nginx 没能启动。
查看 audit 日志,发现是与 off 文件权限有关,心想,肯定是因为 nginx 配置里面 access_log off; 这一行引起的,因为网上也都说,这样是不对的,nginx 依然会生成 off 文件并存放 access log,我们应该写成 access_log /dev/null;
于是把几个网站的 access log 都改成了 /dev/null,也没测试,心想这次一定没问题了,于是直接重启了服务器。
重启后发现 nginx 依然不能启动,也就是说依然有错,真是奇了怪了,于是又使用 ripgrep 搜索 nginx 配置文件找 off 字眼,发现很多个 log_not_found off;,于是我又自以为是地把这些 off 也全改成了 /dev/null,而且有个网站下面的 error_log 也是 off,我也改了🤣。
看似一切都没问题了,这次改好后没有直接重启,而是命令行测试了一下,然后命令行启动 nginx,哈哈,运行启动命令后,发现依然出错,怎么搞的??因为是运行的 nginx 启动命令,所以 nginx 也给出提示查看 nginx 错误信息,这一看明了了,原来不是自己一开始以为的那样,而是因为在 /usr/share/nginx 目录下有一个 off 文件,nginx 无法启动是因为 SELinux 规则阻止了 nginx 读取这个文件,这个文件的 context 明显不对。
按理说这个 off 文件应该属于 log 属性,不应该是 httpd 属性,也不应该是 usr 属性。因为我忘记了当时查看这个文件时系统显示的属性,所以暂时就这么记录着吧,可以确定,肯定是由于 context 不对而被阻止的。

[[email protected] audit]# systemctl start nginx
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.


[[email protected] audit]# cat audit.log | audit2why
type=AVC msg=audit(1690936372.283:212): avc:  denied  { append } for  pid=1190 comm="nginx" name="off" dev="sda5" ino=87165 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:usr_t:s0 tclass=file permissive=0

        Was caused by:
                Missing type enforcement (TE) allow rule.

                You can use audit2allow to generate a loadable module to allow this access.


[[email protected] audit]# systemctl status nginx.service
× nginx.service - The nginx HTTP and reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/system/service.d
             └─10-timeout-abort.conf
             /etc/systemd/system/nginx.service.d
             └─php-fpm.conf
     Active: failed (Result: exit-code) since Wed 2023-08-02 08:32:52 CST; 30s ago
    Process: 1189 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
    Process: 1190 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
        CPU: 63ms

Aug 02 08:32:52 coke.im systemd[1]: Starting nginx.service - The nginx HTTP and reverse proxy server...
Aug 02 08:32:52 coke.im nginx[1190]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
Aug 02 08:32:52 coke.im nginx[1190]: nginx: [emerg] open() "/usr/share/nginx/off" failed (13: Permission denied)
Aug 02 08:32:52 coke.im nginx[1190]: nginx: configuration file /etc/nginx/nginx.conf test failed
Aug 02 08:32:52 coke.im systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Aug 02 08:32:52 coke.im systemd[1]: nginx.service: Failed with result 'exit-code'.
Aug 02 08:32:52 coke.im systemd[1]: Failed to start nginx.service - The nginx HTTP and reverse proxy server.
[[email protected] audit]#

上面是相关查错提示,这里也得提醒自己,很明显 nginx 提示的更具体,一眼就看到了问题所在,而 audit 日志那个提示实在是太模糊了,没有说 off 文件在哪里,是不能写这个文件,还是不能读这个文件。搞得人一头雾水,既然 nginx 有错误提示,为什么一开始不查看 nginx 的错误提示,而是去看 audit 的呢?这个处理问题的思路很明显有问题。所以要记住,往后查看错误日志,尽可能看服务本身的日志或提示,然后再去看 audit 或者 messages 里面的日志。 ❗❗❗

这也是为什么我浏览各个网站的 log 目录时,从未发现有 off 文件,所以得出的结论是 nginx 想往里面写 off 文件而没权限所以失败,而实际情况不是我想的那样。实际上是因为上面提到的那个网站的配置 error_log off; ,这么一个配置,在 nginx 看来,它会把错误日志写到默认的 /usr/share/nginx 下面,而不会写到网站自己的 log 目录下,仔细想想,是不是如此???所以,正是因为这个配置导致 nginx 在默认目录下生成了 off 文件(这个文件应该也是在刚开始那会儿 SELinux 处于关闭状态时生成的),没有启用 SELinux 时是没问题的,而启用 SELinux 后 nginx 访问不了这个文件。

写到这里,又意识到一个问题,那就是这个 off 文件记录的全是上面提到的网站的错误日志,里面貌似没有 access 日志,那么回过头来再看前面说的,好像又不对了,因为如果在 SELinux 关闭那段时间里,按照我们每个网站的配置,access log 也同样不会写到每个网站的 log 目录,而是应该都写到 nginx 默认目录的 off 文件,那么怎么这个 off 文件里没有大量的 access 日志呢??

所以,上面的结论再次被推翻了,实际上,access_log off; 是可以这么写的,而且这样写后,不会如网上说的把 access 日志写到 off 文件里,只有 error_log off; 如此,access log 如果这么写,那就是真的关闭了 access 日志。写到这儿,我立即开始怀疑自己当时看网上的回答时应该是看错了,没有细看,于是回头再翻看了下相关回答,是的,我确实看错了,人家网上说的很清楚的,是我自己看错了

有图有真相:👇 可以看出,人家写的很明白的,这个答案的评论 13 和 5 个赞的是对的,中间 9 个赞的那个评论是错的。至此,一切都明了了。唉,实在是佩服自己啊,看个答案都能看错!!!不应该!

Stackoverflow 网站里面相关回答的截图

于是,我又回过头来,把几个网站的配置都写成了 access_log off; 😂

关于 nginx 的 fallback 机制

【2023.07.27】关于 nginx 的 fallback 机制:

经过我的深度测试,nginx 应该是尽可能的提供给网络请求以应答,它的最终处理过程就是把所有配置文件综合到一起,也就是 nginx -T 后我们看到的,这是它运行时的一个真正的配置参照,也就是说,但凡任何一个 server block 里面有 listen 80listen 443 ssl ,也就是说,但凡有 listen,nginx 就会过一遍这个总配置,尽可能给你最相应的应答,如果它找不到匹配的,它会找默认,还是尽可能给你应答。

可以这么理解,我们平时配置各个 server(virtual host),把它们单独放在 sites-available 里面等等类似这种吧,其实是为了我们容易理解,一看就明白各个域名的配置在哪,而对于 nginx 来说,它其实是不在乎的,它最终都会根据 nginx.conf 里面那些个 include ,把各处的配置综合到一起来参照,也就是说,如果不是为了好看,我们也完全可以把所有的站点配置包括 php-fpm 的配置,全部都写到 nginx.conf 里,这对 nginx 来说,没啥两样,但是我们阅读和查找起来就会非常麻烦,所以我们分开配置,并在 nginx.conf 里面用 include 调用。

上面啰嗦这些是前提。

然后我们就好理解了,刚才的深度测试为什么是那样的结果,其实也是验证了 nginx 官网里 How nginx processes a request: https://nginx.org/en/docs/http/request_processing.html 这篇文档里所做的说明。

不过有一点,官网没有提,那就是,至少在目前 Fedora 38 上是如此,即使没有任何的配置,但是只要你有 listen 某个端口,比如某个 server block 里面有一条 listen 80,无论它属于哪个域名的配置,只要出现过一次 listen 80,nginx 就会竭尽所能的给你应答,哪怕是只有这么一行配置,root 没有,index 也没有,location 也没有,所有其他的全都没有配置,nginx 还是会跑到 /usr/share/nginx/html 里给你拉取 index.html 来显示,这就是困扰了我两天的那个问题的原因所在。也就是说,但凡 nginx 能运行,哪怕只有一个 server block,里面只写一行,listen 80;,只要你访问指向你 IP 的域名,或者直接访问 IP 地址,当然是 80 端口的,nginx 就会给出应答,给你展示 /usr/share/nginx/html 里面的 index.html 文件(也就是默认的欢迎页面)。

给个具体例子,下面的配置文件,而且 nginx 就只有这一个配置文件,那么它也是可以运行的,无论你是什么请求,即使是没有绑定的域名,只要 DNS 指向服务器 IP,那么最终,都会显示 nginx 的欢迎页面。

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    server_tokens       off;
    tcp_nopush          on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

server {
    listen 80;
}

}

可以看出,上面配置里,仅仅在 server block 里加了一个 listen 80; 即便这样,如果你访问 IP 地址,同样会加载默认页面,如果有某个域名比如 abcd.efgh.com 它 DNS 指向了服务器 IP,那么浏览器访问这个域名,也同样会加载欢迎页面。https 请求也同样的道理,但凡有个 listen 443,nginx 也会给出默认页,哪怕咱压根就没有配置,它也没读取到包含 /usr/share/nginx/html 的配置,所以,可以得出结论,nginx 有个硬编码的配置,也就是有个 hardcoded 指令,遇到找不到的,最后都 fallback 到默认页,当然前提是得有 listen,如果 listen 都没有,也就无所谓请求和应答了。

这个困扰我两天的问题,我还试图向人工智能提问,提问过好多个模型,貌似只有 ChatGPT 给出了可以接受的答案,看下面第 5 条,大致也是这个意思。不过我也不确定 ChatGPT 是真的有铁证才这么说还是它一本正经的编的。但确实是在看了它给出的提示后,我才开始深度测试的,事实证明,就是有个写死的 fallback 机制,如上面所说,只能这么理解,否则解释不了我测试的结果。

There could be several reasons why you’re still seeing the Nginx welcome page. Here are a few things you could check:

1.Nginx Configuration: Make sure that the configuration files are correctly set up. You might have removed the default server block, but it’s possible that there’s another configuration file which is serving the welcome page. Nginx includes all configuration files from the /etc/nginx/conf.d/ and /etc/nginx/sites-enabled/ directories by default, so check these locations for any unexpected configuration files.

2.Browser Cache: Your browser might have cached the Nginx welcome page. Try clearing your browser cache or use a different browser or a private/incognito window to test if this is the case.

3.Nginx Service Restart: After making changes to the Nginx configuration, it’s necessary to reload or restart the Nginx service. Use sudo systemctl reload nginx or sudo service nginx reload on Linux. If you didn’t do this, the old configuration is still in effect.

4.Server Block Priority: Nginx processes server blocks in a specific order. If there’s no server block that matches the incoming request, Nginx will use the first server block in its configuration. Make sure that your intended server block is specified before any other that might be serving the welcome page.

5.Default Index File: If you’ve removed the default server block but haven’t specified a new one to replace it, Nginx might be falling back to serving the default index.html file in its document root (/usr/share/nginx/html/ by default). Check if this file is the welcome page you’re seeing.

To troubleshoot, you can use the nginx -t command to test your configuration files for syntax errors. You can also check the Nginx error logs for any issues — these are typically located at /var/log/nginx/error.log on Linux.

关于 nginx 的 HTTP/2

【2023.07.27】关于 nginx 的 HTTP/2:

nginx 在 1.9.5 之后的版本,要开启 HTTP/2 支持,只需要单独一个 http2 命令,不用再把 http2 参数加到 listen 后面,如下:

server {
    listen 443 ssl;

    http2 on;

    ssl_certificate server.crt;
    ssl_certificate_key server.key;
}

1.9.5 版本之前的 nginx 开启 HTTP/2 需要写成下面这样:

server {
    listen 443 ssl http2;

    ssl_certificate server.crt;
    ssl_certificate_key server.key;
}

另外,能不能单独在 80 端口启用 HTTP/2?也就是 H2C(HTTP2 Over Cleartext),再直白说就是 HTTP/2 without TLS,我问 ChatGPT-3.5 能不能写成 listen 80 http2; 这样子,它说可以,我就这么写了,然后网址打不开了。实际上这么写会出错,相关问题参见: https://stackoverflow.com/questions/46788904/why-do-web-browsers-not-support-h2c-http-2-without-tls

安装 PHP

Ubuntu 上安装最新版 PHP

Ubuntu 自带的 PHP 版本往往不是最新的,只是较新的,如果想要安装最新版的 PHP,或者选择安装特定版本的 PHP,都建议使用下面这个源。以安装目前最新版 PHP 8.2 为例:

sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php8.2-fpm

下面是一些常用的 PHP 模块,多数情况下我们都是顺带把下面这些一起安装上,如果确定自己不需要,当然也可以不安装。如果想安装其他版本的 PHP,同理,指定版本号就行了。

sudo apt install php8.2-fpm php8.2-opcache php8.2-mysql php8.2-gd php8.2-mbstring php8.2-curl php8.2-xml php8.2-zip

安装完成后,可以 php -v 查看版本号,php -m 查看已经安装的扩展模块。另外 sudo systemctl enable php8.2-fpm 让它开机自启。

安装完 PHP 后要做的修改

安装完 PHP 后,需要做几处修改,涉及安全性、用户、可上传大小等。

从小白刚开始折腾时基本就是这样,安装完,然后找到 php.ini 在哪,直接修改 php.ini 里面相关的配置,然后保存并重启 php-fpm,很多教程就是这么写的。但是这个凭直觉就感觉是不对的,因为 Linux 里面各种设置一般都是拿自己的来覆盖默认的,而不是直接修改程序本来的配置,因为这样很不好,修改多了就乱了,而且程序更新时,如果新版本带来了配置文件的变更,是覆盖还是不覆盖?都是问题。

所以,不建议这么粗暴的修改软件默认的配置文件,想变更什么配置,我们用自己的配置文件来覆盖软件自带的默认配置

Ubuntu(至少最近几年比较新的 Ubuntu)上 PHP 的配置文件在 /etc/php/8.2/fpm 下面,注意我这里的版本号是 8.2,如果是别的版本,比如 7.x 版,那就是 /etc/php/7.x/fpm,我们可以看到它下面还有两个目录 conf.dpool.d,它们分别对应的是什么?这里直接引用 ChatGPT 的解释:

在 PHP 的配置文件目录中,conf.dpool.d 分别保存的是不同类型的配置。

  1. conf.d 目录

    • 在 PHP 中,conf.d 目录通常包含各种 PHP 模块(扩展)的配置文件。
    • 每个模块(例如 opcache、mysqli、gd 等)通常会有一个单独的配置文件,这些文件以 .ini 结尾。
    • 这些配置文件包含了特定模块的相关配置选项。当您启用某个 PHP 扩展时,它通常会在 conf.d 中创建相应的配置文件,并在其中设置默认的配置值。这些配置可以被用户修改以满足特定需求。
  2. pool.d 目录

    • pool.d 目录通常与 PHP-FPM(FastCGI Process Manager)相关。
    • 在 PHP-FPM 中,每个运行的网站或应用程序都有一个独立的进程池(pool),这些池的配置可以在 pool.d 目录中找到。
    • 每个池都有一个配置文件,通常以 .conf 结尾,例如 www.conf
    • 这些配置文件包含了与 PHP-FPM 进程池相关的配置选项,例如进程数、用户和组设置、监听地址和端口等。这些配置允许您调整 PHP-FPM 进程池的行为,以便更好地适应您的服务器环境和应用程序需求。

请注意,具体的目录结构和文件命名可能因 PHP 版本和操作系统发行版而异,上述描述是基于一般惯例的概述。在您的系统上,实际的目录和文件名可能会有所不同。

所以,我们要覆盖默认配置的话,也很简单,在对应的目录下面新建一个自己的配置文件,把自己想要修改的部分写到这个文件里面就可以了,需要注意的是,文件名称是有讲究的,因为 PHP 在加载配置文件时也是有顺序的,比如下面的 zz-nginx.conf,如果写成 nginx.conf 或者 0-nginx.conf 就不管用了,因为它们最终还是会被 www.conf 所覆盖。

还有,我们也可以把自定义配置文件写在别的地方,不放在 PHP 配置文件目录里面,此时需要在 php.ini 里面插入一行引用的命令,另外还要注意文件的权限,得确保 PHP 程序有权限读取这个配置文件才行。

我选择直接把自定义配置文件也放到 PHP 配置文件目录下,下面的 90-override.inizz-nginx.conf 就是我用来覆盖默认配置的。修改好之后记得重启 php-fpm。

[email protected]:/etc/php/8.2/fpm$ ls
conf.d  php-fpm.conf  php.ini  pool.d

[email protected]:/etc/php/8.2/fpm$ ls conf.d/
10-mysqlnd.ini   20-ctype.ini  20-fileinfo.ini  20-mbstring.ini   20-readline.ini   20-sysvsem.ini    20-xsl.ini
10-opcache.ini   20-curl.ini   20-ftp.ini       20-mysqli.ini     20-shmop.ini      20-sysvshm.ini    20-zip.ini
10-pdo.ini       20-dom.ini    20-gd.ini        20-pdo_mysql.ini  20-simplexml.ini  20-tokenizer.ini  90-override.ini
15-xml.ini       20-exif.ini   20-gettext.ini   20-phar.ini       20-sockets.ini    20-xmlreader.ini
20-calendar.ini  20-ffi.ini    20-iconv.ini     20-posix.ini      20-sysvmsg.ini    20-xmlwriter.ini
# 注意,除了我添加的那个,上面数字开头的这些其实不是文件,而是软连接,它们指向对应模块目录下实际的配置文件

[email protected]:/etc/php/8.2/fpm$ ls pool.d/
www.conf  zz-nginx.conf

上面罗嗦了很多怎么覆盖默认配置,那么自定义的配置文件里怎么写?很简单,自己想修改哪个配置,直接写上自己想要的值就可以了。

90-override.ini 文件内容👇:

cgi.fix_pathinfo = 0
upload_max_filesize = 10M
post_max_size = 10M

zz-nginx.conf 文件内容👇,注意要写上 [www] 块:

[www]
user = nginx
group = nginx
listen.owner = nginx
listen.group = nginx

Fedora 上安装最新版 PHP

Fedora 因其本身性质,它使用的软件包几乎都是最新的,PHP 包也是,直接 sudo dnf install php php-fpm 安装就行了,即使小版本号稍微落后一点,一般过几天也能跟上。

另外,安装下常用的扩展,比如 xml、zip、json、mysql、curl 等,注意,下面这个命令,不一定正确,因为有些模块是包含在 php-common 里面的。

sudo dnf install php-common php-opcache php-mysqlnd php-gd php-xml

在安装扩展时我发现 Fedora 自己的 @updates 包不全,有些 PHP 扩展没有,所以又改成了使用 remi 包。
还有一点要注意,和 Ubuntu 上的不一样,Fedora 上的 php-mysql 扩展叫 php-mysqlnd,所以是 sudo dnf install php-mysqlnd

Fedora 上安装完 PHP 需要注意的地方

另外,Fedora 上安装完 PHP 后,/var/lib/php 这个目录里有几个目录(opcache、session、wsdlcache)默认是 apache 用户组,而我一般用 Nginx,所以用户组需要改成 nginx,否则 PHP 在读写这几个目录时会因为没有权限而出错。

drwxr-xr-x. 1 root root     86 Jul 28 21:07 peclxml
drwxrwx---. 1 root apache    0 Jul  5 08:00 opcache
drwxrwx---. 1 root apache 1.6K Jul  5 08:00 session
drwxrwx---. 1 root apache    0 Jul  5 08:00 wsdlcache

把它们的用户组由 apache 👆 修改成 nginx 👇

drwxr-xr-x. 1 root root    86 Jul 28 21:07 peclxml
drwxrwx---. 1 root nginx    0 Jul  5 08:00 opcache
drwxrwx---. 1 root nginx 1.6K Jul  5 08:00 session
drwxrwx---. 1 root nginx    0 Jul  5 08:00 wsdlcache

这个好像是 Fedora 特有的情况,而且即使改了,在下次 PHP 版本更新后,会再次变成 apahce,这个与服务器上是否安装有 apache 无关,与是否有 apache 用户或者用户组也无关。总之,它就是这么任性地做。StackOverflow 里面有个关于这个问题的探讨: https://stackoverflow.com/a/50519674/5492955,可以参考下。

所以,为了不每次在 PHP 更新后都出错,我和那个回答里的做法一样,把 nginx 加入了 apache 用户组,然后记得重启 php-fpm 服务才能生效。另外,还要注意 Fedora 和 Ubuntu 不一样的一点,或者说是 Ubuntu 和 RedHat 系不一样的一点,Ubuntu 里的权限是 775 和 664,也就是用户和用户组一样,而 Feodra 是经典的 755 和 644 权限,所以,只是把 nginx 加入 apache 用户组依然是不行的,显然 nginx 依然没有写入权限,所以得把这几个目录的权限改成 775 才行。

Fedora 上 PHP 配置文件路径与覆盖

同样,我们用自己的配置文件来覆盖默认的配置,原理上都是一样的,只是 Fedora 上 PHP 的配置文件路径和 Ubuntu 上稍有区别,Fedora 上 PHP 的配置文件在 /etc/php.d/,php-fpm 配置文件在 /etc/php-fpm.d/

具体写法可参见上面 Ubuntu 部分 安装完 php 后要做的修改

安装 MariaDB

安装 acme.sh 配置 SSL

安装 acme.sh

acme.sh 超级方便和简单,按照官网上的说明操作即可。需要注意的是,我这里是以 root 用户来安装和操作的,官网也是建议使用 root,当然也可以非 root 用户,但是可能会因为某些目录的权限导致不能完成整个流程,尤其如果还开启了 SELinux 的话。

安装:

curl https://get.acme.sh | sh -s email=[email protected]

安装后在 root 目录下有个 .acme.sh 文件夹,acme.sh 的配置和域名配置信息等都是在这个文件夹里,acme.sh 命令也是调用的这个目录下的 acme.sh。

[[email protected] ~]# which acme.sh
alias acme.sh='/root/.acme.sh/acme.sh'
        /root/.acme.sh/acme.sh

另外,需要注意的是,安装完成后,在当前的 shell 下 acme.sh 命令还未生效,需要重开一下 shell 才能读取更新后的环境变量,可以运行一下 bash,或者 exit 然后再次切换到 root 用户就可以了。往后,需要运行 acme.sh 命令,也同样切换到 root 用户来操作。

另外,安装完成后,acme.sh 已经自动在 root 用户的 crontab 里创建了一个定时任务,每天检查是否有证书需要更新,如果证书的日期临近了,它会自动运行更新来生成新的证书文件。

申请证书

申请证书的流程已经很熟悉了,需要注意的是我们申请的是强度更高的的 ECC 证书,而且,是 wildcard 证书,所以,需要额外的验证(如果只是申请单个域名,比如 www.domain.tld,就不需要更进一步的验证,只需要验证这一个域名即可),这里我们使用 Cloudflare API 的方式来验证,将来自动更新时比较省事儿。API 从 Cloudflare 那里获得,然后,申请之前,先执行下面的三行命令把从 Cloudflare 官网获取的 token 等加到环境变量里,接下来运行 acme.sh 时它会读取到并把这些参数保存,以备下次更新证书时再次使用。

export CF_Token="_R8888888888888888888888888888"
export CF_Account_ID="388888888888888888887cc"
export CF_Zone_ID="6b999999999999999999999ce"

旧版本的 acme.sh 是把这几个参数保存在 account.conf 文件里面,新版本更加清晰了,是单独保存在对应站点目录下面的配置文件里,比如 .acme.sh/domain.tld_ecc/domain.tld.conf

申请 ECC 证书命令 👇,注意,这里用的是 384,具体支持情况,参考 acme.sh 官网文档

acme.sh --issue --dns dns_cf -d domain.tld -d '*.domain.tld' --keylength ec-384

安装证书命令 👇

acme.sh --install-cert -d domain.tld -d *.domain.tld --ecc --key-file /etc/pki/nginx/domain.tld/key.pem --fullchain-file /etc/pki/nginx/domain.tld/cert.pem

上面只是安装证书,在实际使用中,我们往往还得重启 nginx 或者 apache 服务来重新读取新的证书,我们可以在后面加一个 reload 命令,另外,这个 reload 命令后面可以跟多条命令,只要使用 ; 隔开即可,例如 👇:

acme.sh --install-cert -d domain.tld -d *.domain.tld --ecc --key-file /etc/pki/nginx/domain.tld/key.pem --fullchain-file /etc/pki/nginx/domain.tld/cert.pem --reloadcmd "sudo systemctl reload nginx; sudo systemctl restart v2ray"

acme.sh 同样会把安装目录、reloadcmd(reloadcmd 现在已经改成使用 Base64 编码保存 👉 Le_ReloadCmd='__ACME_BASE64__START_c3lzdGVtY3RsIHJlbG9hZCBuZ2lueA==__ACME_BASE64__END_') 等信息保存到 domain.tld.conf 配置文件里,下次更新时就不用我们操心了。

安装 Matrix-Synapse

安装 PostgreSQL

# 在 Fedora 上安装
sudo dnf install postgresql-server postgresql-contrib

# 安装后初始化
sudo postgresql-setup --initdb

下面是常用命令,注意,创建数据库是针对 Synapse 的。

## 切换到 postgres (用户),个人感觉直接切换到 popstgres 比 sudo -u postgres ... 方便些
sudo su - postgres

## 创建用户 newuser,--pwprompt 选项会在创建过程中让你输入用户的密码
[[email protected] ~]$ createuser --pwprompt newuser

## 创建数据库 newuserdb,分配给 newuser,注意多个 --参数
[[email protected] ~]$ createdb --encoding=UTF8 --locale=C --template=template0 --owner=newuser newuserdb

## 切换到 psql 命令行操作
[[email protected] ~]$ psql
psql (15.1)
Type "help" for help.

postgres=#

## 显示 hba_file 路径
postgres=# show hba_file;
            hba_file
---------------------------------
  /var/lib/pgsql/data/pg_hba.conf
(1 row)

postgres=#

注意:Synapse 使用 postgres 数据库时我们需要编辑 /var/lib/pgsql/data/pg_hba.conf,加上下面高亮的这行,而且位置有要求,紧挨着 IPv6 部分的上面,IPv4 部分的下面。

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# synapse local connections:
host    synapsedb       synapseuser     ::1/128                 md5
# IPv6 local connections:
host    all             all             ::1/128                 ident
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            ident
host    replication     all             ::1/128                 ident

安装 Postfix

安装 Go

安装 Go 也很简单,go.dev 官网里有详细说明,下面是命令,注意,替换版本号

## 下载最新版
curl -LO https://go.dev/dl/go1.20.7.linux-amd64.tar.gz
## 比较官网的 Hash 值,确保正确
sha256sum go1.20.7.linux-amd64.tar.gz
## 注意权限,我们用 sudo 来安装,否则目标目录无法删除和写入
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.20.7.linux-amd64.tar.gz

/etc/profile 文件底部加上下面这行(这么做是让 go 命令成为全局变量)

export PATH=$PATH:/usr/local/coke/bin
## 检查版本号
go version
## 删除前面下载的安装包
rm go1.20.7.linux-amd64.tar.gz

查看系统开机自启的服务

目前 Ubuntu 和 Feodra 都使用的 systemd 来管理系统,所以查看系统自启服务的命令也是一样的:

systemctl list-unit-files --type=service --state=enabled

关于 SELinux

关于 Cron