apache配置文件单域名多入口
Apache 的配置 VirtualHost 配置里,一个 ServerName 后面跟多个 DocumentRoot 入口,文件这事听起来简单,单域实际踩坑的名多人不少。上周帮朋友迁移一个老项目,入口就遇到这个问题:域名是配置 app.example.com,但用户访问 / 要进前台页面,文件访问 /admin 要进后台管理系统,单域两个目录完全独立,名多代码也不在一起。入口
最直接的配置想法是在 Apache 里配两个 VirtualHost,都绑定同一个域名。文件但 Apache 对同名 ServerName 的单域处理方式是——谁先匹配到谁生效,后面的名多直接忽略。所以这条路走不通。入口
Alias 是最省事的做法
如果两个入口的物理路径不同,Alias 指令几乎是最快能跑通的方式。比如前台在 /var/www/frontend,后台在 /var/www/adminpanel:
<VirtualHost *:80> ServerName app.example.com DocumentRoot /var/www/frontend Alias /admin /var/www/adminpanel <Directory /var/www/adminpanel> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> <Directory /var/www/frontend> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> </VirtualHost>
这样 app.example.com/ 走前台,app.example.com/admin 走后台。配置改完 apachectl configtest 检查一下语法,没问题就 reload。
但这里有个细节容易被忽略:Alias 是路径前缀匹配,/admin 会匹配到 /admin、/admin/、/adminanything。如果后台程序内部有自己的一套路由,比如它期望的入口是 /admin/index.php,那 Alias 到目录层面通常没问题。但如果后台代码里写死了 $_SERVER['DOCUMENT_ROOT'] 来做文件包含,Alias 不会改变 DOCUMENT_ROOT 的值,程序可能找不到文件。这种情况就得靠 RewriteBase 或者干脆上反向代理。
RewriteRule 更灵活,但别写太绕
另一个常见场景是两个入口在同一个 DocumentRoot 下,只是入口文件不同。比如 Laravel 项目里前台走 index.php,后台走 admin.php。这种用 mod_rewrite 更自然:
RewriteEngine On RewriteBase / RewriteRule ^admin(/.*)?$ admin.php [L,QSA] RewriteRule ^(?!admin).*$ index.php [L,QSA]
注意第二条规则里的负向断言 (?!admin),不加的话 /admin 会被第二条规则也匹配到,虽然 [L] 标记会阻止继续处理,但规则顺序和标记配合不好就容易出现 500 或者无限循环。我见过有人在规则里写 RewriteCond %{ REQUEST_URI} !^/admin 来做条件判断,效果一样,但可读性差一些。
RewriteRule 的好处是路径可以完全重写,不依赖物理目录结构。坏处是调试麻烦,LogLevel alert rewrite:trace3 打开日志才能看清每一步怎么跳的。
ProxyPass 适合前后端分离的架构
现在很多项目前台是静态站或者 Node 服务,后台是 PHP 或者 Java。这种异构入口用 Alias 和 Rewrite 都别扭,反向代理最干净:
ProxyPreserveHost On ProxyPass /api http://127.0.0.1:3000/ ProxyPassReverse /api http://127.0.0.1:3000/ ProxyPass /admin http://127.0.0.1:8080/ ProxyPassReverse /admin http://127.0.0.1:8080/
这样 /api 转发到本地 3000 端口的 Node 服务,/admin 转发到 8080 端口的后台应用。Apache 只做入口网关,具体业务逻辑由后端服务处理。这种配置在容器化部署里特别常见,因为每个服务可以独立扩缩容,Apache 层几乎不用改。
有个坑要注意:ProxyPass 的路径末尾有没有斜杠,行为不一样。ProxyPass /admin http://127.0.0.1:8080/ 会把 /admin/foo 映射成 http://127.0.0.1:8080/foo,而 ProxyPass /admin http://127.0.0.1:8080 会映射成 http://127.0.0.1:8080/admin/foo。差一个字符,后端收到的路径完全不同。
选哪种取决于入口之间的关系
我的判断标准很简单:如果两个入口共享同一个物理目录树,RewriteRule 最合适;如果目录完全独立但还在同一台机器上,Alias 够用;如果入口背后是不同的服务进程,直接上 ProxyPass。别为了“统一配置风格”硬用一种方案,Apache 提供了这些指令就是让它们各司其职的。
最后提一句,改完配置记得用 curl -I 分别测两个入口的响应头,确认状态码和 Content-Type 都符合预期。浏览器缓存有时候会骗你,命令行更可靠。









