PHP 怎么Caddy PHP

wen PHP项目 1

PHP 怎么配 Caddy?一篇搞定现代 PHP 服务器的极简配置与性能调优


目录导读

  1. 为什么抛弃 Nginx/Apache,选择 Caddy?
  2. Caddy 核心优势:自动 HTTPS 与零配置反向代理
  3. PHP-FPM 与 Caddy 的“联姻”:php_fastcgi 指令详解
  4. 实战配置:从单站点到多站点(含 Laravel/WordPress)
  5. 性能与安全调优:缓存、超时、进程池与隐藏版本号
  6. 常见坑与高频问答(FAQ)

为什么抛弃 Nginx/Apache,选择 Caddy?

在 PHP 开发者的圈子里,Nginx 和 Apache 长期占据统治地位,但 Caddy 2 的出现,正在悄悄改变游戏规则。它最大的杀手锏是“自动 HTTPS”——无需手动申请证书、配置续期,Caddy 会免费为你的域名签发并自动续期 Let's Encrypt 证书。 这意味着你彻底告别了 certbot renew 的定时任务。

PHP 怎么Caddy PHP

Caddy 的配置文件(Caddyfile)语法极为简洁,通常只有 Nginx 配置的 1/5 长度,如果你受够了 Nginx 里 location 块的层层嵌套,Caddy 的指令式语法会让你感到“神清气爽”。

Caddy 核心优势:自动 HTTPS 与零配置反向代理

Caddy 的核心是 caddy 命令 + Caddyfile,启动后,它会自动监听 80/443 端口,当你指定一个域名时,它自动完成以下动作:

  • 申请证书
  • 配置 TLS 握手
  • 将 HTTP 请求 301 跳转到 HTTPS
  • 重写请求头(如 X-Forwarded-Proto

对于 PHP 开发,我们并不需要让 Caddy 直接处理 PHP 文件(它不支持 PHP 解释器),而是让它作为一个反向代理,将 *.php 的请求转发给 PHP-FPM 服务。

PHP-FPM 与 Caddy 的“联姻”:php_fastcgi 指令详解

Caddy 2 提供了一个极其便捷的指令:php_fastcgi,这一条指令,相当于 Nginx 中以下几段配置的合集:

  • fastcgi_pass
  • fastcgi_index
  • include fastcgi_params
  • 针对 PHP 文件存在的 try_files 检测

基础语法示例:

example.com {
    root * /var/www/html
    php_fastcgi 127.0.0.1:9000
}

这一行 php_fastcgi 做了什么? 它内部自动实现了:

  1. 如果请求 URI 以 .php 则转发给 0.0.1:9000(默认 PHP-FPM 监听地址)。
  2. 如果请求的文件不存在,自动尝试查找 index.php(这是 try_files 的逻辑)。
  3. 自动设置 SCRIPT_FILENAME 环境变量。

实战配置:从单站点到多站点(含 Laravel/WordPress)

单站点(ThinkPHP / CodeIgniter 传统框架)

:8080 {
    root * /srv/myapp/public
    php_fastcgi unix//run/php/php8.2-fpm.sock
    file_server
}

多站点(Laravel 强制入口 index.php) Laravel 要求所有请求都经过 index.php,我们需要用 try_files 重写:

laravel.example.com {
    root * /var/www/laravel/public
    php_fastcgi unix//run/php/php8.2-fpm.sock
    try_files {path} /index.php?{query}
    file_server
}

注意:这里 php_fastcgi 后面的 try_files 指令,实际上会覆盖 php_fastcgi 内置的默认 try_files 逻辑,因为 Caddy 的指令执行顺序是“靠后覆盖靠前”。

WordPress(固定链接伪静态)

wordpress.example.com {
    root * /var/www/wp
    php_fastcgi unix//run/php/php8.2-fpm.sock
    try_files {path} /index.php?$query_string
    # 静态资源缓存(可选)
    @static {
        file
        path *.css *.js *.png *.jpg *.gif *.svg *.ico
    }
    header @static Cache-Control "public, max-age=2592000"
    file_server
}

性能与安全调优:缓存、超时、进程池与隐藏版本号

关键调优点(必看):

  1. 提升 PHP-FPM 并发: 修改 www.conf 中的 pm.max_childrenpm.max_children = 50,同时调整 Caddy 的反向代理传输大小:

    request_body {
        max_size 20MB
    }
  2. 超时控制: 防止慢 PHP 脚本拖垮服务器。

    reverse_proxy 127.0.0.1:9000 {
        transport fastcgi {
            read_timeout 120s
            write_timeout 120s
        }
    }

    (如果你用 php_fastcgi 简写指令,无法直接设置超时,你需要将其展开为 route 内的 reverse_proxy 才能指定超时。)

  3. 利用 route 指令实现精确匹配: php_fastcgi 是“全局”的,如果你需要对特定路径(如 /api/)单独处理,建议用 route 块:

    route {
        php_fastcgi 127.0.0.1:9000
        # 其他路由规则
    }
  4. 隐藏 PHP 错误日志目录: 禁止外部访问 .env 文件等敏感信息:

    @denied {
        path /.env /.git/*
    }
    respond @denied 404

常见坑与高频问答(FAQ)

问:我用了 php_fastcgi,但打开 PHP 文件变成了下载? 答: 这通常是因为 PHP-FPM 未监听该地址,或未启动,执行 systemctl status php8.2-fpm 检查,如果使用 socket 通信,确保 unix// 前缀后面跟对路径(unix//run/php/php8.2-fpm.sock 注意是两个斜杠)。

问:为什么 Laravel 路由一直返回 404? 答: 核心在于 try_files 顺序,请务必将 php_fastcgi 写在 try_files 之前,Caddy 的指令执行是自上而下,如果先遇到 try_files,它会直接尝试寻找文件,找不到就返回 404,而不会转发给 PHP,正确顺序是:root -> try_files(放在后面) -> php_fastcgi(放前面)或者用 route 包裹。

问:Caddy 是否支持 PHP 8.3 / 8.4? 答: 支持,Caddy 只是代理,它不关心 PHP 版本,只要 PHP-FPM 服务正常工作即可,你甚至可以在同一台机器上配置多个 FPM 实例,通过不同端口区分。

问:如何彻底伪装 PHP 版本号? 答:Caddyfile 中添加:

header {
    -Server
    X-Powered-By "Unknown"
}

但更根本的是修改 php.ini 中的 expose_php = Off


Caddy 的优雅之处在于“约定优于配置”,对于 PHP 开发者而言,迁移到 Caddy 的成本极低,只需保留 PHP-FPM 配置不变,把 Nginx 配置替换成短短的 10 行 Caddyfile,即可获得自动 HTTPS、HTTP/3 支持和简洁的日志格式,如果你还在用宝塔面板手动部署 Nginx,不妨在本地 Docker 环境试一下 Caddy + PHP-FPM,你会发现前所未有的部署快感。

抱歉,评论功能暂时关闭!