From e3d8f8a1418e3867a3afeac8343f76cc6b234e9f Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 27 Jun 2026 05:56:54 +0000 Subject: [PATCH] docs: add Caddy deployment guide to README.md and README-en.md Add a dedicated "Production Deployment (Caddy)" section after the FrankenPHP Worker Mode section in both the Chinese and English READMEs. Covers two deployment options: - FrankenPHP + worker.php (persistent-process, recommended) - Caddy + PHP-FPM (standard setup) Each option includes a full Caddyfile example with security headers, internal directory access blocking, static asset serving, and PHP dispatch. Notes on log directory permissions, sub-path (VDNAME) deployment, and environment variable injection are also included. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01NkvcLer1EewaUTWDbujBGD --- README-en.md | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) diff --git a/README-en.md b/README-en.md index 828f9ea..b3b9b29 100644 --- a/README-en.md +++ b/README-en.md @@ -518,6 +518,131 @@ frankenphp php-server --worker public/worker.php --root public/ --- +## Production Deployment (Caddy) + +PlumePHP supports two Caddy deployment modes — choose the one that fits your environment. + +### Option 1: FrankenPHP + Worker Mode (Recommended) + +FrankenPHP embeds PHP directly into Caddy. Combined with `worker.php`'s persistent-process loop, PHP starts only once and all requests reuse the same process — eliminating cold-start overhead for maximum throughput. + +**Caddyfile:** + +```caddyfile +{ + frankenphp + order php_server before file_server +} + +yourdomain.com { + root * /var/www/PlumePHP/public + + tls your@email.com + + header { + X-Frame-Options DENY + X-Content-Type-Options nosniff + X-XSS-Protection "1; mode=block" + Referrer-Policy strict-origin-when-cross-origin + -Server + } + + # Block direct access to internal framework directories + @blocked { + path /library/* /application/* /config/* /storage/* /vendor/* /tests/* + } + respond @blocked 403 + + # Serve static assets directly without involving PHP + @static { + path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot + } + file_server @static + + # PHP worker persistent-process mode + php_server { + worker worker.php + } +} +``` + +**Launch commands:** + +```bash +# Development (traditional mode — PHP restarts per request, no worker overhead) +frankenphp php-server --root public/ + +# Production (worker mode — persistent processes) +frankenphp php-server --worker public/worker.php --root public/ + +# Via Caddyfile +frankenphp run --config /etc/caddy/Caddyfile +``` + +### Option 2: Caddy + PHP-FPM + +Suitable for environments that already run PHP-FPM, or when you prefer not to introduce FrankenPHP. + +**Caddyfile:** + +```caddyfile +yourdomain.com { + root * /var/www/PlumePHP/public + + tls your@email.com + + header { + X-Frame-Options DENY + X-Content-Type-Options nosniff + -Server + } + + # Block direct access to internal framework directories + @blocked { + path /library/* /application/* /config/* /storage/* /vendor/* /tests/* + } + respond @blocked 403 + + # Serve static assets directly without involving PHP + @static { + path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot + } + file_server @static + + # All other requests are dispatched through index.php + php_fastcgi unix//run/php/php8.2-fpm.sock { + index index.php + env HTTP_MOD_REWRITE On + } + + file_server +} +``` + +### Notes + +**Log directory permissions:** + +```bash +mkdir -p storage/log +chown -R www-data:www-data storage/ +chmod -R 755 storage/ +``` + +**Sub-path deployment (virtual directory):** If the app is mounted under a sub-path (e.g. `/app`), set `'VDNAME' => 'app'` in `config/config.php` and add `uri strip_prefix /app` inside the corresponding route block in the Caddyfile. + +**Environment variables:** Database credentials and other config are best supplied via a `.env` file (built-in `PlumeDotEnv` support). In PHP-FPM mode they can also be injected through the `env` directive inside `php_fastcgi`. + +**Comparison:** + +| | FrankenPHP + worker.php | Caddy + PHP-FPM | +|---|---|---| +| PHP startup cost | Once (process persists) | Per request (depends on FPM config) | +| Deployment complexity | Low (single binary) | Medium (two services) | +| Best for | High concurrency, low latency | Stable, general-purpose | + +--- + ## Global Helper Functions | Function | Purpose | diff --git a/README.md b/README.md index 1e3bde8..af6a7da 100644 --- a/README.md +++ b/README.md @@ -478,6 +478,131 @@ frankenphp php-server --worker public/worker.php --root public/ --- +## 生产部署(Caddy) + +PlumePHP 支持两种 Caddy 部署模式,按需选择。 + +### 方案一:FrankenPHP + Worker 模式(推荐) + +FrankenPHP 将 PHP 嵌入 Caddy,结合 `worker.php` 常驻进程,PHP 只启动一次,请求复用同一进程,无冷启动开销,性能最优。 + +**Caddyfile:** + +```caddyfile +{ + frankenphp + order php_server before file_server +} + +yourdomain.com { + root * /var/www/PlumePHP/public + + tls your@email.com + + header { + X-Frame-Options DENY + X-Content-Type-Options nosniff + X-XSS-Protection "1; mode=block" + Referrer-Policy strict-origin-when-cross-origin + -Server + } + + # 禁止直接访问框架内部目录 + @blocked { + path /library/* /application/* /config/* /storage/* /vendor/* /tests/* + } + respond @blocked 403 + + # 静态资源直接服务,不经 PHP + @static { + path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot + } + file_server @static + + # PHP Worker 常驻进程模式 + php_server { + worker worker.php + } +} +``` + +**启动命令:** + +```bash +# 开发(无 worker,每请求启动一次 PHP) +frankenphp php-server --root public/ + +# 生产(worker 常驻进程) +frankenphp php-server --worker public/worker.php --root public/ + +# 通过 Caddyfile 启动 +frankenphp run --config /etc/caddy/Caddyfile +``` + +### 方案二:Caddy + PHP-FPM + +适合已有 PHP-FPM 环境,或不想引入 FrankenPHP 的场景。 + +**Caddyfile:** + +```caddyfile +yourdomain.com { + root * /var/www/PlumePHP/public + + tls your@email.com + + header { + X-Frame-Options DENY + X-Content-Type-Options nosniff + -Server + } + + # 禁止直接访问框架内部目录 + @blocked { + path /library/* /application/* /config/* /storage/* /vendor/* /tests/* + } + respond @blocked 403 + + # 静态资源直接服务,不经 PHP + @static { + path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2 *.ttf *.eot + } + file_server @static + + # 所有其他请求经 index.php 调度 + php_fastcgi unix//run/php/php8.2-fpm.sock { + index index.php + env HTTP_MOD_REWRITE On + } + + file_server +} +``` + +### 注意事项 + +**日志目录权限:** + +```bash +mkdir -p storage/log +chown -R www-data:www-data storage/ +chmod -R 755 storage/ +``` + +**虚拟目录(子路径部署):** 若部署在子路径(如 `/app`),需在 `config/config.php` 设置 `'VDNAME' => 'app'`,并在 Caddyfile 中对应路由块内添加 `uri strip_prefix /app`。 + +**环境变量注入:** 数据库等配置推荐通过 `.env` 文件传入(`PlumeDotEnv` 内置支持);也可在 PHP-FPM 模式下通过 `php_fastcgi` 的 `env` 指令注入。 + +**两种方案对比:** + +| | FrankenPHP + worker.php | Caddy + PHP-FPM | +|---|---|---| +| PHP 启动开销 | 一次(进程常驻) | 每请求(取决于 FPM 配置) | +| 部署复杂度 | 低(单二进制) | 中(两个服务) | +| 适用场景 | 高并发、低延迟 | 稳健通用 | + +--- + ## 全局辅助函数 | 函数 | 说明 |