Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions README-en.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
125 changes: 125 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 配置) |
| 部署复杂度 | 低(单二进制) | 中(两个服务) |
| 适用场景 | 高并发、低延迟 | 稳健通用 |

---

## 全局辅助函数

| 函数 | 说明 |
Expand Down
Loading