安装 Nginx,启用Brotli压缩+FastCGI缓存+静态资源expires
bash
sudo apt install -y nginx
sudo systemctl enable nginx
备份Nginx配置
bash
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
编辑 Nginx 主配置(加载 Brotli 模块)
sudo nano /etc/nginx/nginx.conf在http { ... }块内添加以下内容(放在include /etc/nginx/sites-enabled/*;上方):
bash
# Brotli核心配置
brotli on; # 开启Brotli压缩
brotli_comp_level 6; # 压缩级别1-11,6兼顾速度和压缩率(推荐)
brotli_buffers 16 8k; # 压缩缓冲区大小
brotli_min_length 20; # 小于20字节的文件不压缩(无意义)
brotli_types # 需压缩的文件类型(覆盖常见动态/静态资源)
text/plain
text/css
text/javascript
application/javascript
application/x-javascript
text/xml
application/xml
application/xml+rss
text/html
application/json
image/svg+xml
font/ttf
font/otf
application/font-woff
application/font-woff2;
brotli_vary on; # 配合CDN时返回Vary: Accept-Encoding(可选)
配置 FastCGI 缓存(加速 PHP 动态页面,如 WordPress)
bash
# 创建缓存目录(自定义路径,如/var/nginx/cache)
sudo mkdir -p /var/nginx/cache
# 设置Nginx运行用户(www-data)为目录所有者
sudo chown -R www-data:www-data /var/nginx/cache
sudo chmod -R 700 /var/nginx/cache # 仅限www-data访问,增强安全
在/etc/nginx/nginx.conf的http { ... }中添加
bash
# FastCGI缓存全局配置
fastcgi_cache_path /var/nginx/cache levels=1:2 keys_zone=WORDPRESS_CACHE:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri"; # 缓存唯一标识(避免冲突)
fastcgi_cache_valid 200 301 302 60m; # 200/301/302状态码缓存60分钟
fastcgi_cache_valid 404 1m; # 404页面仅缓存1分钟
fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;
fastcgi_cache_bypass $cookie_nocache $arg_nocache $arg_comment; # 这些参数跳过缓存(如WP后台)
fastcgi_no_cache $cookie_nocache $arg_nocache $arg_comment $request_method = POST; # POST请求不缓存(如表单提交)
fastcgi_ignore_headers Cache-Control Expires Set-Cookie; # 忽略PHP返回的缓存头,以Nginx配置为准
编辑你的 WordPress 站点配置(如/etc/nginx/sites-available/default),在 location ~ \.php$ { ... } 块内添加:
bash
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.4-fpm.sock; # 替换为你的PHP版本(如php7.4-fpm.sock)
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 启用FastCGI缓存(关键)
fastcgi_cache WORDPRESS_CACHE;
fastcgi_cache_status on; # 可选,添加X-Cache响应头(方便调试)
add_header X-Cache $upstream_cache_status; # 响应头显示缓存状态(HIT/MISS/EXPIRED)
# 新增:避免缓存WordPress后台/登录/表单提交
fastcgi_cache_bypass $cookie_wordpress_logged_in $cookie_nocache $arg_nocache $arg_comment;
fastcgi_no_cache $cookie_wordpress_logged_in $cookie_nocache $arg_nocache $arg_comment $request_method = POST;
}
配置静态资源 Expires(浏览器本地缓存,减少重复请求)
bash
sudo nano /etc/nginx/sites-available/default
编辑你的 WordPress 站点配置(如/etc/nginx/sites-available/default),在server { ... }块内添加静态资源规则
bash
server {
# 其他配置(listen/root/server_name等)已省略
# 静态资源Expires配置
location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|avif)$ {
expires 30d; # 图片缓存30天
add_header Cache-Control "public, max-age=2592000"; # 30天=2592000秒
add_header X-Content-Type-Options nosniff; # 安全头(可选)
access_log off; # 关闭静态资源访问日志(减少磁盘IO)
}
location ~* \.(css|js)$ {
expires 7d; # CSS/JS缓存7天(更新频率比图片高)
add_header Cache-Control "public, max-age=604800"; # 7天=604800秒
access_log off;
}
location ~* \.(ttf|otf|woff|woff2|eot)$ {
expires 90d; # 字体文件缓存90天(极少更新)
add_header Cache-Control "public, max-age=7776000"; # 90天=7776000秒
add_header Access-Control-Allow-Origin "*"; # 解决跨域加载字体(可选)
access_log off;
}
# 修复WordPress固定链接的核心规则
location / {
try_files $uri $uri/ /index.php?$args;
}
# 取消注释
location ~ /\.ht {
deny all;
}
验证配置并重启 Nginx
bash
sudo nginx -t
2025/12/14 13:03:32 [emerg] 2194#2194: unknown directive "brotli" in /etc/nginx/nginx.conf:19
nginx: configuration file /etc/nginx/nginx.conf test failed
再次尝试安装Nginx
以下是一份"踩坑全集"式经验文档,专为 树莓派 4B + Debian GNU/Linux 13 (trixie) 手写编译 Nginx 1.27.0 并启用 Brotli 压缩 + FastCGI 缓存 + 静态资源 30 天 expires
1 目标与最终效果
| 功能 | 验证方式 |
|---|---|
| Brotli 动态压缩 | curl -H "Accept-Encoding: br" -I localhost 看到 content-encoding: br |
| FastCGI 缓存 | curl -I localhost/test.php 看到 X-FastCGI-Cache: HIT |
| 静态资源 30 天 expires | curl -I localhost/style.css 看到 Cache-Control: max-age=2592000 |
| libpcre2-dev 支持 | 编译参数 --with-pcre-jit 通过且 nginx -V 含 pcre-jit |
2 全程速览(copy & run)
bash
# 0 卸载旧 Nginx 并装编译依赖
sudo apt remove --purge -y nginx*
sudo apt update && sudo apt install -y build-essential libpcre2-dev zlib1g-dev \
libssl-dev libgd-dev libxslt1-dev uuid-dev ca-certificates git
# 1 拉源码
mkdir -p ~/build && cd ~/build
wget https://nginx.org/download/nginx-1.27.0.tar.gz
tar -xf nginx-1.27.0.tar.gz
git clone --recurse-submodules -j8 https://github.com/google/ngx_brotli.git
# 2 生成 Makefile(含 Brotli + PCRE2-JIT)
cd nginx-1.27.0
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-threads \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-stream_realip_module \
--add-module=../ngx_brotli
# 3 编译 & 安装
make -j$(nproc)
sudo make install
# 4 systemd 服务
sudo tee /etc/systemd/system/nginx.service <<'EOF'
[Unit]
Description=Nginx - high performance web server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now nginx
# 5 PHP-FPM(Debian 13 单元名带版本)
sudo apt install -y php8.4-fpm
sudo systemctl enable --now php8.4-fpm
# 6 缓存 & expires 目录
sudo mkdir -p /var/cache/nginx/fastcgi_cache
sudo chown -R www-data:www-data /var/cache/nginx
# 7 配置片段(一次性写入 /etc/nginx/nginx.conf http{} 段)
sudo tee -a /etc/nginx/nginx.conf <<'EOF'
# Brotli
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml;
brotli_static on;
# FastCGI cache
fastcgi_cache_path /var/cache/nginx/fastcgi_cache levels=1:2 keys_zone=fcgi:10m inactive=60m max_size=1g;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
# expires map
map $sent_http_content_type $expires {
default 1h;
text/html epoch;
text/css 30d;
application/javascript 30d;
~image/ 30d;
}
expires $expires;
EOF
# 8 虚拟主机(/etc/nginx/sites-enabled/default.conf)
sudo mkdir -p /var/www/rpi.local /etc/nginx/sites-enabled
sudo tee /etc/nginx/sites-enabled/default.conf <<'EOF'
server {
listen 80;
server_name localhost;
root /var/www/rpi.local;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_cache fcgi;
fastcgi_cache_valid 200 302 1h;
fastcgi_cache_valid 404 1m;
fastcgi_cache_use_stale error timeout updating;
fastcgi_cache_min_uses 1;
add_header X-FastCGI-Cache $upstream_cache_status; # 可视化缓存状态
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
EOF
# 9 放测试文件
echo "<?php echo time(); ?>" | sudo tee /var/www/rpi.local/test.php
echo "body { color: red; }" | sudo tee /var/www/rpi.local/style.css
sudo chown -R www-data:www-data /var/www/rpi.local
# 10 重载 & 验证
sudo nginx -t && sudo systemctl reload nginx
curl -H "Accept-Encoding: br" -I localhost/style.css | grep content-encoding
curl -I localhost/test.php | grep -E "X-FastCGI-Cache|Cache-Control"
3 踩坑全景图(按报错时间序)
| 报错现象 | 根因 | 解决命令 |
|---|---|---|
./configure: error: Brotli library is missing from ../ngx_brotli/deps/brotli/c |
没拉子模块 | cd ../ngx_brotli && git submodule update --init |
fatal error: pcre.h: No such file or directory |
系统只有 PCRE2,文件名不同 | sudo ln -s /usr/include/pcre2.h /usr/include/pcre.h |
unknown type name 'pcre_extra' |
Nginx 源码仍用 PCRE-1 API | 用系统头文件即可,不要 再 --with-pcre=../pcre2-10.44;保留 --with-pcre-jit |
user directive is not allowed here |
user 写进 server{} |
挪到最顶层:user www-data; |
502 Bad Gateway |
php-fpm 监听 socket,Nginx 仍写 127.0.0.1:9000 | 改 fastcgi_pass unix:/run/php/php8.4-fpm.sock; |
connect() failed (13: Permission denied) |
Nginx worker 是 nobody,不在 www-data 组 |
顶层写 user www-data; |
mail: invalid option -- 's' |
默认 mail 是 msmtp,不支持 -s |
`printf "Subject: test\n\nbody" |
sites-available 目录不存在 |
源码安装只生成最简目录 | 手动 mkdir 并在 nginx.conf 末尾加 include /etc/nginx/sites-enabled/*.conf; |
4 最终验证(一次性通过)
bash
# Brotli 动态压缩
curl -H "Accept-Encoding: br" -I localhost/style.css
→ content-encoding: br
# FastCGI 缓存
curl -I localhost/test.php
→ X-FastCGI-Cache: HIT / MISS
→ Cache-Control: max-age=2592000 (若把 PHP map 也设 30d)
# 静态 30 天 expires
curl -I localhost/style.css
→ Cache-Control: max-age=2592000
5 操作
自动备份:cron + tar 整站 /var/www + 数据库
1 创建备份脚本
bash
sudo tee /usr/local/bin/backup.sh <<'EOF'
#!/bin/bash
# === 配置区 ===
WEB_DIR="/var/www"
DB_USER="root"
DB_PASS="你的数据库密码"
BACKUP_DIR="/mnt/backup_disk" # 可用 U 盘或移动硬盘
DATE=$(date +%F_%H-%M)
# === 执行区 ===
mkdir -p $BACKUP_DIR
# 1. 打包整站
tar -czf $BACKUP_DIR/www_${DATE}.tar.gz -C $WEB_DIR .
# 2. 导出所有库
mysqldump -u${DB_USER} -p${DB_PASS} --all-databases | gzip > $BACKUP_DIR/db_${DATE}.sql.gz
# 3. 清理 7 天前旧档
find $BACKUP_DIR -name "*.tar.gz" -o -name "*.sql.gz" -mtime +7 -delete
EOF
sudo chmod +x /usr/local/bin/backup.sh
2 加入系统定时任务(每天 03:00 执行)
bash
echo "0 3 * * * root /usr/local/bin/backup.sh" | sudo tee /etc/cron.d/backup
首次手动跑一次看日志:
bash
sudo /usr/local/bin/backup.sh && ls -lh /mnt/backup_disk
二、Let's Encrypt 证书:certbot + Nginx
1 装 certbot 及 Nginx 插件
bash
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
2 申请并自动配置(以 rpi.local 为例)
bash
sudo certbot --nginx -d rpi.local -d www.rpi.local
交互过程:
-
输入邮箱 → 同意协议 → 选择 自动把 HTTP 重定向到 HTTPS
完成后会提示:Congratulations! Your certificate has been successfully installed.
证书路径:
/etc/letsencrypt/live/rpi.local/fullchain.pem
/etc/letsencrypt/live/rpi.local/privkey.pem
Nginx 已自动被改好 443 监听与重定向 。
3 自动续期(已内置)
bash
sudo certbot renew --dry-run # 测试续期流程
系统自带 systemd timer,每天两次检查 ,无需手动加 cron;
若一定要用 cron:
bash
sudo crontab -e
# 每天 04:00 续期 & 重载 nginx
0 4 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
证书到期前 30 天会自动续期 。
三、Nginx 无缝升级:保留 ./configure 参数
1 记录当前参数
bash
nginx -V 2>&1 | tee ~/nginx-build-args.txt
输出示例:
configure arguments: --prefix=/etc/nginx ... --add-module=../ngx_brotli
2 升级日操作(以 1.28.0 为例)
bash
cd ~/build
wget https://nginx.org/download/nginx-1.28.0.tar.gz
tar -xf nginx-1.28.0.tar.gz
cd nginx-1.28.0
# 用旧参数重新配置
./configure $(cat ~/nginx-build-args.txt | sed -e 's/.*configure arguments://')
make -j$(nproc)
# 热替换二进制(零停机)
sudo systemctl reload nginx # 先让 worker 用旧文件
sudo cp objs/nginx /usr/sbin/nginx
sudo systemctl reload nginx # 新 master 用新二进制
验证:
bash
nginx -v # 应显示 1.28.0
旧配置、旧模块全部保留,服务不中断。
四、常见坑速查表
| 现象 | 原因 | 一行解决 |
|---|---|---|
| certbot 续期失败 | 80/443 被防火墙拦 | sudo ufw allow 80,443 或开放云安全组 |