很多人配置Apache虚拟主机,只盯着ServerName和DocumentRoot参数,修改配置重启服务,访问页面直接弹出403 Forbidden。排查很久才发现,目录权限没有配套设置。DocumentRoot仅用来告诉Apache网站文件存放路径,Apache能不能读取目录、是否允许目录内启用.htaccess、是否开放目录列表浏览,这些权限都写在
先理清主站点定义。Apache体系内,主站点是访问请求无法匹配任何虚拟主机ServerName时,用来兜底响应的站点,也就是Apache安装完成后默认展示的页面。Debian、Ubuntu系统,对应配置文件路径 /etc/apache2/sites-available/000-default.conf,文件内包含一段,DocumentRoot默认指向 /var/www/html。CentOS、RHEL系统,主站点配置直接写在 /etc/httpd/conf/httpd.conf,DocumentRoot默认同样是 /var/www/html。

问题根源大多在目录权限。打开Ubuntu系统的 /etc/apache2/apache2.conf,能看到全局配置段,里面包含Options Indexes FollowSymLinks,AllowOverride None,Require all granted。这段配置管控/var/www/下全部子目录,/var/www/html自动继承这套权限。如果修改主站点DocumentRoot为 /srv/mysite,这个路径不在/var/www/目录下,没有任何Directory配置覆盖,Apache默认拒绝访问,403报错就会出现。解决办法,要么在apache2.conf新增配置段,或者直接写在主站点的VirtualHost内部。
把Directory写在虚拟主机配置文件内,是更干净的方案。举个例子,主站点配置文件 /etc/apache2/sites-available/000-default.conf,参考写法如下:
<VirtualHost *:80>
ServerName [example.com](https://link.wtturl.cn/?target=https%3A%2F%2Fexample.com&scene=im&aid=497858&lang=zh)
DocumentRoot /srv/mysite
<Directory /srv/mysite>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
各行参数含义:Options 用来控制目录特性,Indexes 在首页文件缺失时展示目录文件列表,FollowSymLinks 允许 Apache 读取符号链接。AllowOverride All 开启目录下.htaccess 文件覆盖配置,部署 WordPress、Laravel 项目一般需要开启这项。Require all granted 是 Apache2.4 的语法,代表放行全部访问请求;2.2 版本的 Order allow,deny、Allow from all 已经淘汰,新旧语法混用容易引发异常。主站点目录配置还有不少细节。000-default.conf文件名排序靠前,一般作为兜底站点。修改主站点 DocumentRoot,但000-default.conf里面 Directory 没有同步修改,所有无法匹配域名的访问请求都会触发 403。CentOS 的逻辑大体一致,仅文件路径不同。主配置文件 /etc/httpd/conf/httpd.conf,默认就在这个文件。新增虚拟主机,通常在 /etc/httpd/conf.d/ 创建.conf文件,单个文件写一组。想要该虚拟主机独立目录权限,就在 VirtualHost 内部增加配置。不单独配置的话,会继承 httpd.conf 里/var/www/html的全局权限,前提是 DocumentRoot 放在/var/www/html路径下。修改完配置不要直接重载服务。执行 apachectl configtest 或是 apache2ctl configtest,校验语法错误。确认无误再执行 systemctl reload apache2 或者 systemctl reload httpd。如果页面依旧返回 403,检查 Linux 系统目录文件权限,Apache 运行用户一般是 www-data 或者 apache,至少要拥有目录读、执行权限。CentOS 默认开启 SELinux,非标准目录访问会被拦截,ls -Z查看安全上下文,异常时使用 chcon 或者 semanage 调整。目录权限配置正常不会有提示,一旦写错直接抛出 403,没有中间状态。