恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Ubuntu 18.04 Apache安装与虚拟主机配置实战指南
首页
资讯中心
/
Ubuntu 18.04 Apache安装与虚拟主机配置实战指南
Ubuntu 18.04 Apache安装与虚拟主机配置实战指南
发布时间:2026/10/17 12:10:06
1. 环境准备与安装前置思路写这个系列第五篇的时候我特意回头翻了翻前几篇的内容。前面讲了Ubuntu 18.04的初始化配置、SSH远程连接、基础软件包管理还有LAMP架构里MySQL的部署。这次轮到Apache了但我还是想多说一句很多人觉得Apache安装是个老掉牙的话题apt install apache2一两分钟就能搞定有什么好写的我最初也是这么想的后来在帮几个朋友排查环境问题时发现真正把Apache装好并跑起来的不少但装完能讲清楚目录结构、能配置出多站点、遇到权限和重写问题能快速定位的确实不多。说白了Apache安装这件事门槛不在安装命令本身而在安装之后那一整套配置逻辑。这篇文章我会按实际部署流程往下走覆盖从软件安装、服务管理、核心配置解读到虚拟主机配置、模块启用、性能调优和故障排查的完整链路。Ubuntu 18.04虽然是2018年发布的老版本但至今还有大量服务器跑在上面Apache的配置方式在18.04和20.04、22.04之间并没有天翻地覆的变化所以这篇文章的绝大部分内容对后续版本同样适用。先交代一下本文的适用读者已经完成了Ubuntu 18.04系统基础安装和网络配置准备在这台机器上搭建Web服务的人。如果你计划用的是LAMP组合这篇文章就是为你的Apache环节扫清障碍如果你只是临时需要跑一个静态站点或者做反向代理同样可以按这篇文章的步骤操作。前置知识方面需要了解Linux的基本命令操作比如cd、ls、vim、sudo这些如果还不太熟也没关系文中每一步都会交代清楚命令的作用和执行后应该看到的结果。有一点我在做事前强调的习惯无论装什么软件先确认系统处于什么状态再动手。经常有人在刚执行过apt upgrade的机器上装Apache结果依赖版本冲突折腾半天也有人拿到手的机器网络源都没配置好apt install直接就报错了。我已经踩过太多类似的坑所以在实操之前建议先花一分钟做三件事检查系统版本、确认网络连通性、更新软件包索引。lsb_release -a # 查看当前系统版本 ping -c 4 archive.ubuntu.com # 测试Ubuntu官方源连通性 sudo apt update # 更新软件包索引这三步做完系统状态基本就摸清了。接着就可以正式进入Apache的安装流程。2. 为什么选Apache以及Ubuntu下安装方式的选择在正式执行安装命令之前我想先花点篇幅聊聊两个问题为什么选Apache而不是Nginx以及为什么推荐用apt安装而不是源码编译。这两个问题如果没想清楚后面配置的时候容易心里没底。先说我自己的选择倾向。现在的Web服务器领域Nginx凭借高并发性能和灵活的反向代理配置占据了很大市场份额很多新项目上来就直接套Nginx。但Apache依然有它不可替代的位置尤其在兼容性和灵活性上。Apache的模块化设计非常成熟mod_rewrite、mod_ssl、mod_proxy这些模块经过十几年生产环境检验稳定性和文档丰富度都极高。很多老牌PHP项目、企业内部系统跑在Apache上的比例依然不低。另外.htaccess机制也是Apache的一大特色虽然生产环境里我建议尽量在虚拟主机配置里写规则而不是用.htaccess但不可否认它确实给不拥有服务器根权限的使用者提供了很大的便利。再聊安装方式。Ubuntu的软件源里已经维护好了Apache的二进制包直接apt install就能装上一个开箱即用、文件路径规范、服务管理方式和系统完全集成的Apache。我见过不少人一上来就下载源码包configure、make、make install非要自己折腾一遍才放心其实对于绝大多数Web服务场景完全没有必要。源码编译适合需要定制模块路径、自定义编译参数或者需要最新版本特性的场景而Ubuntu 18.04软件源里的Apache版本虽然不算最新但安全更新和bug修复一直有人维护稳定性是有保障的。生产环境的黄金法则是能用系统包管理器解决的依赖和升级问题就不要自己手动维护一套。省下来的时间可以用来理解配置和服务本身而不是陪编译器较劲。关于Apache在Ubuntu下的包名还有一个历史遗留问题。CentOS等RedHat系发行版里Apache的服务名是httpd包名也是httpd而Debian/Ubuntu系里包名和服务名都是apache2。我第一次从CentOS切到Ubuntu的时候就被这个命名差异坑过习惯性地敲systemctl status httpd结果提示服务不存在。后来才慢慢适应Ubuntu下的Apache配置文件在/etc/apache2/服务名是apache2默认站点目录是/var/www/html/这些都要和CentOS区分开。3. 正式安装Apache全过程3.1 安装命令与版本验证接下来就真正动手了。在Ubuntu 18.04上安装Apache核心命令其实只有一条sudo apt install apache2 -y由于前面已经执行过apt update这里安装过程会比较顺利。安装完成后Apache会作为systemd服务自动注册默认开机自启。你可以用systemctl命令查看服务当前状态sudo systemctl status apache2正常输出会显示Active: active (running)说明Apache已经成功运行。安装完Apache后我习惯顺手确认一下版本号这能帮你判断当前有哪些特性和安全补丁apache2 -v18.04默认源里的Apache版本一般是2.4.29左右。这个版本已经支持HTTP/2协议需要额外启用模块、完整的mod_proxy系列以及完善的SSL配置能力。对于大多数业务场景这个版本完全够用。3.2 防火墙放行Web端口装好Apache之后如果服务器开启了UFW防火墙千万别忘记放行HTTP和HTTPS端口否则浏览器访问会出现连接超时或者拒绝连接但你在服务器本机用curl测又一切正常。这个问题极其常见几乎每个人都会踩一次。Ubuntu 18.04自带的是UFW防火墙管理工具放行Apache端口有两种做法。第一种是直接放行端口号sudo ufw allow 80/tcp sudo ufw allow 443/tcp第二种是利用Apache安装时自动注册的UFW应用配置文件更省事sudo ufw app list这个命令会输出一系列Apache相关条目通常有Apache、Apache Full、Apache Secure三种。Apache对应只放行80端口Apache Secure对应只放行443端口Apache Full则同时放行80和443。一般直接执行sudo ufw allow Apache Full即可如果你需要同时跑HTTP和HTTPS的话。3.3 验证安装结果第一次验证我习惯在服务器本机用命令测试排除网络因素干扰curl -I http://localhost如果返回HTTP/1.1 200 OK说明Apache已经在正常工作了。接下来用浏览器访问服务器的IP地址能看到Apache2 Ubuntu Default Page这个默认页面安装就算正式完成了。从外网访问之前还需要确认一下服务器IP。我常用的命令是hostname -I | awk {print $1}把输出的IP输进浏览器地址栏能看到默认页面就说明一切正常。这里的默认页面其实也是Apache在Ubuntu下的一个特色很多人以为这个页面只是装完后的欢迎页其实它还顺带展示了一些重要配置文件和目录的位置值得花两分钟看一眼。4. 配置文件实战解析从主配置到站点配置4.1 核心目录结构快速上手安装只是开始真正的重头戏是配置文件的理解。我见过太多人把配置改得乱七八糟以后直接在网上提问问“为什么Apache起不来了”一问才知道他们连配置文件在哪里都没搞清楚。所以这一节我会把Ubuntu下Apache的目录结构完整梳理一遍对照着讲清楚每个文件的作用这才是后续一切操作的地基。Ubuntu的Apache把所有配置文件都集中在/etc/apache2/目录下结构非常清晰apache2.conf主配置文件Apache启动时最先读取的全局配置都在这里ports.conf监听端口配置默认监听80端口sites-available/所有可用站点的配置存放目录sites-enabled/实际生效的站点配置目录这里的文件通常是sites-available里配置的符号链接mods-available/可用的模块配置文件目录mods-enabled/已启用的模块配置目录同样是指向mods-available的符号链接conf-available/额外的配置文件目录conf-enabled/已启用的额外配置文件目录envvarsApache环境变量配置文件magicmod_mime_magic模块使用的MIME类型识别文件这套目录结构的设计精髓在于可用配置和生效配置是分开的。你新建一个站点或者启用一个模块不是把配置文件改完就立即生效而是需要在sites-enabled或者mods-enabled里建立符号链接或者用专门的命令来启用。这样做的最大好处是配置变更可以随时回退不会因为一次性改动过多导致服务崩溃后找不到原因。拿站点配置来举例。sites-available目录下默认会有000-default.conf这个文件里面配置了默认虚拟主机。如果你要新增一个站点就在sites-available里新建一个配置文件然后执行sudo a2ensite 站点名.conf来启用它。这个命令本质就是在sites-enabled目录下创建一个指向该配置文件的符号链接。反过来sudo a2dissite 站点名.conf则可以停用站点本质是移除符号链接。4.2 主配置apache2.conf的静态拆分逻辑为了理解这套机制需要看一下apache2.conf编译出来的实际有效内容。配置文件的末尾有一段有趣的逻辑无论你有没有修改过主配置它都会存在。让我在细节上做一点深挖这段配置专门负责按规则加载sites-enabled和conf-enabled中的文件。# Include module configuration: IncludeOptional mods-enabled/*.load IncludeOptional mods-enabled/*.conf # Include all the user configurations: IncludeOptional ports.conf # Include generic snippets of statements IncludeOptional conf-enabled/*.conf # Include the virtual host configurations: IncludeOptional sites-enabled/*.conf这个把配置拆分成多个目录加载的设计我认为是Debian/Ubuntu系Apache做得最优秀的设计之一。如果你去查看CentOS的httpd.conf所有内容堆在一个文件里一改动就得小心翼翼。Ubuntu的做法是让你把不同功能拆开放在不同文件里比如某个域名绑定的ServerName和DocumentRoot放在site配置里某个模块的参数放在mods-available对应的conf文件里互不干扰。主配置文件里还有几个重要的全局配置段稍微留意一下Timeout服务器等待接收请求和响应的时间默认60秒。做过大批量文件上传业务的会把这个值调大。KeepAlive是否启用HTTP持久连接。现代网页往往一个页面几十个资源开启KeepAlive可以减少TCP握手次数明显提升页面加载速度。默认配置是关闭的生产环境建议打开。MaxKeepAliveRequests一个持久连接内允许的最大请求数默认100建议调大到500以上。KeepAliveTimeout持久连接中等待下一个请求的超时时间默认5秒不需要调大5秒足够。User/GroupApache工作进程运行时的系统用户和用户组默认是www-data。权限问题的根源和这两个参数有直接关系。4.3 默认站点与端口配置细节接着看ports.conf这个文件默认内容很简单就一行http监听80端口外加一个NameVirtualHost注释说明。如果你要用SSL在启用mod_ssl之后ports.conf会自动追加Listen 443的配置。这里要提醒一点如果你改了ports.conf里监听的端口记得同时去站点配置里把VirtualHost的端口改成一致否则会出现Apache正常监听但你配置的站点完全不生效的情况。再看默认站点配置文件sites-available/000-default.confVirtualHost *:80 ServerAdmin webmasterlocalhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined /VirtualHost这个文件非常简洁只有一个从任意IP的80端口接收请求的虚拟主机根目录指向/var/www/html。${APACHE_LOG_DIR}这个变量定义在envvars文件里通常指向/var/log/apache2。在实际业务中这个文件往往作为模板你复制一份改成自己的域名和目录就能创建出新的站点。这里有一个关键认知要建立Apache从上到下读取所有启用的虚拟主机配置当一个请求进来时会匹配ServerName字段。如果有多个VirtualHost只有ServerName匹配的那个才会生效。如果没有任何匹配则使用加载顺序中的第一个虚拟主机作为默认站点。所以默认站点配置文件的名称叫000-default.conf是有讲究的000开头的排序让它在没有匹配域名时兜底。这就是为什么如果你买了新域名却忘记修改配置访问IP时看到的还是默认页面因为000-default.conf是第一个被加载的。5. 虚拟主机配置与多站点部署实战5.1 手动创建虚拟主机配置现在开始真正动手配置一个虚拟主机。我自己部署网站服务器时几乎每次都要用到这个流程所以把完整步骤写在这里照着操作即可。假设我要在一个IP上同时跑两个站点域名为test1.example.com和test2.example.com站点目录分别设在/var/www/test1和/var/www/test2。第一步先创建这两个目录并写入测试页面sudo mkdir -p /var/www/test1 sudo mkdir -p /var/www/test2 echo h1Test Site 1/h1 | sudo tee /var/www/test1/index.html echo h1Test Site 2/h1 | sudo tee /var/www/test2/index.html第二步复制默认配置生成两个新配置文件sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/test1.conf sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/test2.conf第三步对test1.conf做修改。用你习惯的编辑器打开配置文件至少需要完成以下几个改动把DocumentRoot改成/var/www/test1把ServerName改成test1.example.com并给日志加上独立的文件名方便后续排查问题时区分两个站点的日志。同样处理test2.conf。改好后测试配置语法确认没有拼写错误sudo apachectl configtest输出Syntax OK说明配置文件全部正常。接着启用这两个站点并重载Apachesudo a2ensite test1.conf sudo a2ensite test2.conf sudo systemctl reload apache2此时如果你在本机的hosts文件里把test1.example.com和test2.example.com指向服务器IP打开浏览器输入这两个域名就能看到各自对应的测试页面。注意为了让两个站点在同一个80端口上共存它们各自的VirtualHost定义里端口都是*:80靠不同的ServerName来区分请求。如果不设置ServerNameApache在启动时会以默认站点方式处理所有请求两个站点就都会显示第一个站点的内容很容易让人误以为配置没生效。5.2 目录访问权限配置的经典坑虚拟主机配置完以后一个极其常见的坑即将出现。当你把DocumentRoot指向一个自己新建的目录比如/var/www/test1却忘记给这个目录配置访问权限时浏览器访问会出现403 Forbidden。原因在于Apache默认的目录权限配置非常严格。看一下apache2.conf里的默认Deny规则就能理解Directory / Options FollowSymLinks AllowOverride None Require all denied /Directory这个配置对根目录做了拒绝一切访问的处理然后各站点目录通过自己的Directory配置段显式放开权限。而你新建的/var/www/test1目录不在任何允许列表里自然会被拦住。解决办法是在虚拟主机配置里显式添加Directory配置段Directory /var/www/test1 Options Indexes FollowSymLinks AllowOverride All Require all granted /Directory这里有几个参数顺便解释一下Options Indexes允许目录索引展示当目录没有index文件时浏览器会看到文件列表。生产环境建议去掉Indexes防止目录结构被随意浏览。FollowSymLinks允许Apache跟随符号链接访问文件如果你在站点目录里做了软链接这个选项是必需的。AllowOverride All允许.htaccess文件覆盖当前目录及子目录的配置。如果你的站点程序依赖.htaccess比如很多PHP开源程序这个选项必须设为All。Require all granted允许所有来源的请求访问该目录。这是Apache 2.4的授权语法完全取代了2.2时代Order Allow,Deny的写法。5.3 启用常见模块与URL重写站点目录配置好之后接下来要考虑模块的启用。Apache的很多功能默认是关闭的最典型的就是mod_rewrite很多程序对URL进行伪静态处理时依赖这个模块。启用命令如下sudo a2enmod rewrite sudo systemctl restart apache2如果你在配置文件中启用了AllowOverride All而在站点目录下放置了.htaccess文件那么这些重写规则会自动生效。不过用户体验更好的方案是直接在虚拟主机配置里写RewriteRule而不是依赖.htaccess文件。原因很简单Apache需要在每个目录里检查是否有.htaccess文件这个行为在AllowOverride All开启时会对每个请求产生额外的文件读取开销。生产环境高并发下这能明显节省性能。但如果你是租用的虚拟主机不能修改Apache主配置那就只能用.htaccess了。如果你需要部署HTTPS还要启用SSL相关模块并配置证书。在Ubuntu 18.04上启用SSL比较简单sudo a2enmod ssl sudo a2ensite default-ssl.conf sudo systemctl restart apache2然后在sites-available/default-ssl.conf里配置证书路径和DocumentRoot即可。当然生产环境用Lets Encrypt免费证书会更方便用certbot配合Apache插件可以自动完成证书申请和配置这里就不展开讲了。5.4 多站点配置过程中的日志观测无论你按上面的步骤配置了多少个站点我建议你在配置完成后打开日志做一次实时观测。我排查问题多年的经验证明日志是最客观的事实来源。Apache的日志位于/var/log/apache2/默认有两个核心文件access.log访问日志和error.log错误日志。启用多站点后同名文件会变多比如test1_error.log、test1_access.log。跟踪错误日志的实时输出可以这样操作sudo tail -f /var/log/apache2/test1_error.log单开一个终端窗口挂着这个命令然后在浏览器里访问test1.example.com任何错误信息都会立刻刷出来。和配置猜测相比日志信息通常直接告诉你问题出在哪一行包括文件权限、配置路径、语法错误、证书问题等等。我把这个习惯养成之后排查故障的速度提升了不止一个档次。6. 性能参数调整与常见故障排查6.1 MPM多进程模块的选择与优化配置层面的问题解决之后聊聊性能调优。Apache 2.4版本在Ubuntu上默认使用MPMMulti-Processing Module来决定如何处理请求。Debian/Ubuntu打包时默认启用的是mpm_event模块同时保留了mpm_prefork和mpm_worker两个备选模块。三者的核心区别和工作原理需要有一点点概念mpm_prefork一个请求由一个进程处理进程之间完全隔离稳定性最好但在高并发下内存占用大。PHP在非线程安全模式下必须使用prefork因为PHP 5.6及更早版本的一些库不是线程安全的。mpm_worker使用进程加线程的混合模式每个进程可以生成多个线程每个线程处理一个请求。并发能力比prefork强很多内存利用更高效。mpm_event基于worker的改进版专门优化了KeepAlive请求处理机制。在KeepAlive连接保持期间event模式不会占用工作线程而是交给专门的事件线程管理所以相同内存下可以支撑更多并发连接。Apache 2.4.29以上的event模式已经非常稳定。在Ubuntu 18.04上切换MPM模式的命令是sudo a2dismod mpm_event sudo a2enmod mpm_prefork sudo systemctl restart apache2注意先禁用旧模块再启用新模块顺序乱了会提示冲突。切换后确认模式生效可以执行apache2ctl -M查看模块列表。如果你的PHP是通过mod_php方式运行的那么务必使用mpm_prefork不能用event或者worker否则会出现Apache进程崩溃或者PHP模块加载失败的情况。这是一个非常基本的合规性问题但踩过这个坑的人不在少数。如果你的PHP是通过PHP-FPM方式运行的那Apache只需要启用mod_proxy_fcgi并配置反向代理到PHP-FPM的socket这种情况下event模式就是最好的选择。我自己部署PHP应用时几乎都采用这种架构并发性能和进程隔离性都很好。相关性能参数的合理配置参考表以比较常见的8核16G服务器和event模式为例参数推荐值说明StartServers4启动时创建的服务器进程数MinSpareThreads25服务器空闲线程最小数量低于此值自动创建MaxSpareThreads75服务器空闲线程最大数量超过此值会回收ThreadsPerChild64每个进程创建的线程数一般不超过64MaxRequestWorkers512最大同时处理的请求数由进程数乘以线程数得出MaxConnectionsPerChild10000每个进程存活期间处理的最大连接数防止内存泄漏修改这些参数需要在/etc/apache2/mods-available/mpm_event.conf里完成。没有绝对的正确答案这些数值和你的业务模式强相关需要监控实内存和连接数后逐步调整。6.2 KeepAlive与超时参数的选择逻辑正常配置好MPM之后还需要回头优化一下KeepAlive相关参数。你可以这样理解KeepAlive机制的意义传统的HTTP请求在每个资源下载后都会断开TCP连接一个包含50个资源的页面就需要50次TCP握手开启KeepAlive后浏览器和服务器之间维持同一个TCP连接来传输多个资源明显减少了握手延迟。KeepAlive涉及三个参数KeepAlive On/Off总开关MaxKeepAliveRequests一个连接内可处理的最大请求数默认100对静态资源较多的网站可以调大到300-500KeepAliveTimeout等待下一个请求的超时时间默认5秒不建议超过10秒如果你在跑高并发业务KeepAliveTimeout要适当压小因为每个空闲连接都在占用服务器的并发连接数。我之前接手过一个流量很大的业务发现连接数一直顶到上限排查了一圈发现KeepAliveTimeout被人调成了30秒大量空闲连接耗尽了MaxRequestWorkers。调整回5秒后问题迎刃而解。Timeout参数也要单独拎出来说。这个参数控制的是收到请求后、发送响应的过程中各个阶段的最大等待时间默认60秒。如果你的站点有上传大文件的需求默认60秒可能不够。我一般把Timeout设置为300秒给大文件上传和慢速客户端预留足够的缓冲。但别把这个值调得太大否则攻击者可以借助大量慢速连接长期占用服务器资源。6.3 高频故障排查速查表多年代理运营经验让我积累了清晰的Apache故障排查路径。下面按发生频率从高到低分享几个经典问题每条附上排查方法故障现象可能原因排查命令/方法浏览器访问超时防火墙未放行80/443端口sudo ufw status检查端口是否allow403 Forbidden目录权限不足或未配置Directory段检查/var/www/test1目录权限是否为755检查VirtualHost里是否有Directory配置块500 Internal Server Error配置语法错误或.htaccess问题sudo apachectl configtesttail -f /var/log/apache2/error.log访问IP显示默认页面ServerName未配置或配置不正确检查站点配置的ServerName是否和访问域名一致a2ensite是否已启用Mod_php与MPM冲突导致Apache崩溃PHP在event模式下不工作切换MPM到prefork或用PHP-FPM方式修改配置不生效忘记reload/restartsystemctl reload apache2优先用reload而不是restart磁盘空间不足导致访问异常日志文件过大挤占空间du -sh /var/log/apache2定期logrotate轮转其中日志文件过大这个问题值得多提一嘴。访问量大的站点access.log一个月就能涨到几个GB。Ubuntu默认配置了logrotate每日轮转日志保留52份基本不需要手动干预。但如果站点访问量异常暴增日志增长会超出logrotate的处理速度还是建议定期检查磁盘空间df -h du -sh /var/log/apache2/*数据无价磁盘满会导致Apache直接拒绝写入日志同时站点访问也可能会出现各种异常。6.4 配置变更的安全回滚习惯最后分享一个我自己的操作习惯。修改任何Apache配置文件之前我都会先把当前生效配置完整复制一份备份有些比较重要的节点还会打上时间戳sudo cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf.bak-20240101修改完执行configtest确认语法无误后再做reload。如果改了配置后Apache启动失败只要把备份文件复制回来再重启服务就能恢复sudo cp /etc/apache2/apache2.conf.bak-20240101 /etc/apache2/apache2.conf sudo systemctl restart apache2这种做法看似多花了几秒钟但服务器出问题时的恢复速度是翻倍的。生产环境的改动安全性和可控性远比改动的速度重要。这套思路不只适用于Apache任何服务器配置变更都应该遵循备份-修改-验证-确认的流程。在Ubuntu 18.04上装了这么多年Apache我的体会是项目初期的稳定基础往往取决于基础服务的细致程度。多站点隔离清楚、模块按需启用、日志整理规范和权限约束到位这些都在为后续开发省时间。文章里提到的每一个坑几乎都是我自己或者身边同事实际踩过的把这些写下来希望各位能少走一些弯路。如果你在部署过程中遇到其他问题最有效的手段是sites的error.log和最经典的apachectl configtest这两个工具总能给你指明方向。