mod_macro适用于5个以上结构高度一致的VirtualHost配置场景,通过参数化$domain和$root实现“变与不变”分离,需手动加载模块、定义Macro并用Use调用,不支持默认值或运行时动态逻辑。
在虚拟主机数量多、结构高度一致的场景下(比如 saas 多租户、微前端子域集群、api 网关分组),直接复制粘贴 <virtualhost></virtualhost> 块极易出错且难以维护。mod_macro 的核心价值,就是把“变”的部分抽成参数,“不变”的部分锁死为模板——真正实现配置即代码。
适用前提:确认是否真需要 mod_macro
不是所有重复都值得上宏。只满足以下全部条件时才推荐启用:
- 同一份 Apache 配置中存在 5 个以上结构几乎完全相同的
<virtualhost></virtualhost>块 - 差异点非常固定,例如仅
ServerName、DocumentRoot、日志路径、后端代理地址这几项变化 - 不依赖运行时动态逻辑(如基于请求头或数据库查值),纯静态配置复用
- 团队具备基础 Apache 配置调试能力,能接受额外一个模块依赖
加载模块并验证可用性
mod_macro 不是默认模块,必须显式加载,且顺序不能错:
- 先确认模块文件存在:
ls /usr/lib/apache2/modules/mod_macro.so(Debian/Ubuntu)或ls /usr/lib64/httpd/modules/mod_macro.so(RHEL/CentOS) - 在
httpd.conf或apache2.conf的 最开头模块加载区 添加:LoadModule macro_module modules/mod_macro.so - 执行
apachectl -t -D DUMP_MODULES | grep macro,看到macro_module (shared)才算加载成功 - 再跑一次
apachectl -t确保无语法错误,之后用systemctl reload apache2生效
定义可复用的 VirtualHost 宏
把通用结构封装进 <macro></macro>,变量用 $名称 占位,注意命名清晰、大小写敏感:
<macro vhoststandard><virtualhost>
ServerName $domain
DocumentRoot $root
ErrorLog "$root/../logs/$domain-error.log"
CustomLog "$root/../logs/$domain-access.log" combined
<pre class="brush:php;toolbar:false;"><directory>
Require all granted
AllowOverride None
Options -Indexes
</directory>
# 可统一加的代理规则(如全走 PHP-FPM)
<filesmatch>
SetHandler "proxy:unix:/var/run/php/php8.2-fpm.sock|fcgi://localhost/"
</filesmatch>
这个宏只暴露两个变量:$domain 和 $root,其余全部固化。调用时一行搞定:
Use VHostStandard example.com /var/www/example Use VHostStandard api.example.com /var/www/api Use VHostStandard admin.example.com /var/www/admin
进阶技巧:组合宏与条件逻辑
单一宏不够用?可以嵌套或配合 Apache 原生指令增强灵活性:
- 用
<ifdefine></ifdefine>控制宏是否生效:<ifdefine use_ssl><macro vhostssl>...</macro></ifdefine>,启动时加-D USE_SSL参数启用 - 为不同环境定义多个宏:
VHostStaging自动加Header set X-Env "staging",VHostProd加严格 CSP 头 - 结合
mod_proxy_express或mod_macro+mod_rewrite实现域名前缀自动路由:Use VHostStandard $1.example.com /var/www/$1(需搭配 RewriteRule 提取)
不复杂但容易忽略:宏内不能使用 $ 开头的非参数名(如 $1 在正则上下文外无效),所有变量必须在 Use 行完整传入,不支持默认值或空值跳过。











