void linux 安装 laravel 9 出错主因是 php 版本(默认 7.4)与扩展(如 mbstring、xml、tokenizer)缺失,且 musl+seccomp 默认拦截 proc_open,open_basedir 配置不当也会导致 autoload.php 加载失败。

Void Linux 安装 Laravel 9 出错,核心原因不是 Void 本身不兼容,而是它默认不预装 PHP 扩展、禁用部分系统调用,且包管理器(xbps)的 PHP 版本策略与 Laravel 9 要求存在断层:Laravel 9 需 PHP ≥ 8.0,而 Void 的 php 主包在稳定仓库中仍为 7.4(截至 2026 年 9 月),且关键扩展如 mbstring、xml、tokenizer 默认未启用。
PHP 版本和扩展缺失是首要拦路虎
Void Linux 的 xbps-install php 安装的是 PHP 7.4,运行 php -v 即可确认。Laravel 9 明确拒绝低于 8.0 的版本,Composer 会在 create-project 阶段直接报错:Your requirements could not be resolved to an installable set of packages.
即使手动编译 PHP 8.0+,也必须显式启用以下扩展(它们不在默认构建中):
-
mbstring:用于多字节字符串处理,Laravel 的Str工具类强依赖 -
xml和dom:Eloquent 模型序列化、Blade 编译器内部使用 -
tokenizer:Artisan 命令行解析、模板编译必需 -
ctype和json:基础验证与 API 响应支撑
安装方式不是 apt-get 或 yum,而是用 xbps 安装对应扩展包,例如:sudo xbps-install php82-mbstring php82-xml php82-tokenizer(注意版本号要匹配你实际安装的 PHP 主版本)。
proc_open 被 musl libc + seccomp 默认拦截
Void 使用 musl libc 和严格的 seccomp 过滤器,默认禁止 proc_open 系统调用。Laravel 的 php artisan key:generate、队列启动、甚至 composer install 中某些插件都会触发该函数,报错为:Call to undefined function proc_open() 或静默卡死。
解决路径只有两条:
- 临时放宽限制(仅开发环境):
sudo sysctl kernel.unprivileged_userns_clone=1,并确保 PHP 不运行在unshare --user环境下 - 更稳妥的做法:改用
php -d disable_functions=""启动 Artisan,例如:php -d disable_functions="" artisan key:generate;但需确认你的 PHP ini 文件中未硬编码禁用proc_open
open_basedir 和 chroot 导致 vendor/autoload.php 加载失败
Void 上常用 runit 或自定义服务脚本启动 PHP-FPM,部分配置会默认加 open_basedir 限制(尤其配合 chroot 部署时)。错误现象是 Nginx 返回 500,日志里出现:require(): open_basedir restriction in effect. File(/var/www/myapp/vendor/autoload.php) is not within the allowed path(s)。
关键点在于:Laravel 的 public/index.php 在子目录,而 vendor/ 在父级。open_basedir 必须包含两者共同根目录,例如:/var/www/myapp/:/tmp/:/dev/urandom —— 注意末尾冒号和显式列出 /dev/urandom(musl 下 session 启动需要)。
若用 chroot /var/www/myapp,则 open_basedir 必须写成相对 chroot 根的路径:/:/tmp/:/dev/urandom,否则 autoload.php 永远找不到。
Void Linux 的精简哲学让它对“默认开箱即用”不友好,Laravel 9 的依赖链又恰好踩在 musl + seccomp + xbps 分离式扩展包的几个缝隙上。最易被忽略的是:你以为改了 php.ini 就完事,其实 php-fpm.d/www.conf 里的 php_admin_value[disable_functions] 和 php_admin_value[open_basedir] 是独立覆盖层,不查这个,问题永远在原地打转。











