这个系列走到第五篇终于要聊到把Web服务真正拉起来这件事了。虽然前面铺垫了不少Linux基础但到了Apache安装这一步很多人依然会卡在各种细节上装是装上了服务起不来默认页打不开防火墙一通乱配最后SSH都断了。这篇就以Ubuntu 18.04标题里的Ubuntu 18基本都指这个LTS版本为例把Apache从安装、核心配置、虚拟主机到常见故障排查完整过一遍。无论你是刚入门的运维新人还是想自己捣鼓一台网站服务器的技术爱好者这篇文章能当一份直接照着操作的手册来用。1. 为什么还在用Apache——安装前的选型思考1.1 Apache与Nginx先想明白为什么选它很多新手一搜“Web服务器”满屏都是Nginx高并发、轻量级。没错Nginx在静态资源和反向代理场景下确实有优势这也让不少人对Apache产生误解觉得它是不是已经被淘汰了。我实际接触到的项目里Apache不仅没过时存量市场还非常大。尤其是那些跑了很多年的PHP项目、虚拟主机商的客户站点、企业OA系统后面对接的几乎都是Apache。原因也很简单.htaccess目录级配置这种机制对传统PHP应用的伪静态、目录访问控制、防盗链来说实在太方便了。你不需要改主配置扔一个.htaccess到目录里就能生效。这里放一张对比表大家根据场景去权衡对比项ApacheNginx并发模型进程/线程模型稳定但内存开销相对大事件驱动模型高并发下资源占用更低模块管理支持动态加载a2enmod即可启用多数模块需编译时选定后期调整麻烦目录级配置支持.htaccess目录独立规则灵活不支持目录级动态配置所有规则在server/location里定义新手友好度默认配置就能跑资料和踩坑记录极多配置层级较多对新手有一定门槛两者并不是二选一的关系生产环境里Apache和Nginx并存也很常见Nginx在前面处理静态文件和负载均衡Apache在背后跑动态业务。但既然本系列的主题是Apache我们就先把这一条链路走通走扎实。1.2 Ubuntu 18环境准备与安装规划很多人安装失败根本不是命令敲错而是环境压根没想好。Ubuntu 18.04在2018年发布属于非常经典的LTS版本虽说现在看稍微有点年头但在很多企业内部服务器上依然大量存在。它的软件管理走的是apt体系跟Debian同源日常操作习惯和20.04、22.04并没有本质区别。装上Apache之前我建议先做三件小事确认系统版本。执行cat /etc/os-release看清楚到底是Ubuntu还是Debian版本号是多少。不同版本包名和默认配置可能有细微差别比如CentOS用的是httpdUbuntu则叫apache2这里就体现得很明显。刷新软件源缓存。sudo apt update这步不能省。新机器或者长时间没维护过的系统本地软件包列表可能很旧直接install可能拿到过时版本甚至找不到包。更新一下让系统知道从哪里下载最新版本。确认网络连通性。apt要访问Ubuntu官方软件源如果服务器在内网或者公司有专门的apt内网源提前把/etc/apt/sources.list配置好可以省掉大量外网延迟。这三步做完再执行sudo apt upgrade把系统基础包升一遍。当然如果是生产环境升级系统包要格外谨慎防止升级完内核或关键库导致服务异常。新装的实验环境就没这么多顾虑升一下更稳妥。另外建议在动手之前先想好目录规划。Apache默认会把站点文件放到/var/www/html但实践里我更推荐在/var/www下为每个站点单独建目录比如/var/www/mysite然后在虚拟主机配置里单独指向。为什么这么干因为默认目录如果直接被业务占用后面加站点、做隔离、改权限都会很别扭尤其是多站点共享一台服务器的时候目录混乱几乎必然引来权限问题。2. 核心实操在Ubuntu 18上安装Apache2.1 安装命令与版本确认安装这条路其实很简单核心就两条命令sudo apt update sudo apt install apache2 -y-y参数表示遇到询问自动确认免去手动交互。如果你是在自己电脑的虚拟机上实验不加也没问题就是中途需要按一次回车。装完后不要急着去做别的事先验证它到底装没装上。我最常用的命令是apache2 -v它能输出版本信息。Ubuntu 18.04自带的Apache版本一般是2.4.29左右这是非常经典且稳定的一个发行版版本。如果提示command not found说明安装没成功或者PATH有问题这时候回过头去检查apt安装过程有没有报错。再看服务状态systemctl status apache2正常情况下输出里会有一行active (running)代表systemd已经接管了Apache进程。Ubuntu的Apache包默认就写好了自启动规则开机自动拉起来不需要你额外配置rc.local。这一点对于从源码编译安装过Apache的人来说会直观感受到差距发行版包管理真的香。最后顺手看一下端口监听ss -tulpn | grep :80看到LISTEN并且地址是0.0.0.0:80或:::80说明Apache已经正常绑定在80端口上了。这里插一句很多人习惯用老的netstat命令但Ubuntu 18上ss才是御用工具参数类似输出更清晰建议直接改用它。2.2 服务管理与启动验证流程安装完不是终点还得确认它确实能对外服务。我习惯分两步验证第一步本机自测curl -I http://127.0.0.1能看到HTTP/1.1 200 OK说明Apache进程本身没有问题监听和默认站点都正常。第二步查看本机IP然后浏览器访问hostname -I浏览器输入http://服务器IP如果看到“Apache2 Ubuntu Default Page”或者类似说“It works”的默认页面说明对外访问链路是通的。这里有个小彩蛋Ubuntu默认页面里藏着很多实用提示不仅有安装路径说明、常用配置指引还告诉你静态文件目录在哪。我当年第一次见到这个页面的时候还以为是某个教程写的后来才发现就是Apache包自带的欢迎页完全可以当成本地文档用。不过生产环境里这个默认页建议尽早换掉换成自己的维护页面省得暴露过多环境信息。顺利走到这里说明服务状态、端口监听、本机访问、外部访问全部正常。接下来才是真正开始“用”Apache的时候。2.3 核心目录结构装完后先看懂“地图”Apache装好之后会生成一整套目录结构。很多人在网上搜索教程照着改某一个文件出了问题就不知道去哪里查。这里先把目录地图摊开目录/文件作用/etc/apache2/apache2.conf全局主配置文件进程属主、全局权限、日志格式等都在这里/etc/apache2/ports.conf端口监听配置文件默认监听80端口/etc/apache2/sites-available/所有可用站点的配置模板存放处/etc/apache2/sites-enabled/真正生效的站点软链目录/etc/apache2/mods-available/可安装的模块列表/etc/apache2/mods-enabled/当前生效的模块软链/var/www/html/默认站点根目录/var/log/apache2/access.log访问日志/var/log/apache2/error.log错误日志sites-enabled和mods-enabled这两个目录的精髓在于里面的文件都是软链指向../sites-available/xxx.conf这种。这种设计的好处是你只管在available里放配置用a2ensite或a2enmod来“启停”不用手动去改太多东西。我之前见过有人直接编辑sites-enabled下的软链文件一保存整个配置文件就变成普通文本了逻辑瞬间失效这是个很低级但很容易犯的错。记住改配置永远去available目录改然后用命令去启停。2.4 为什么选apt安装而不是源码编译不少教程会教你从官网下载源码手动./configure、make、make install。这种装法不是不行而是对新手来说坑太深。编译过程中需要自行解决一堆依赖库装完还得自己写systemd服务单元、设置日志轮转、配置用户权限稍有不慎就留一身烂摊子。用apt install apache2的优势在于依赖自动解决apt会把需要的库一并装上。目录结构和配置体系统一符合Debian系的运维习惯。自带systemd服务文件启停、开机自启都帮你配好了。安全补丁能通过apt upgrade直接升级源码安装反而要手工维护版本。自带logrotate日志轮转配置不会出现日志把磁盘撑爆这种低级事故。老运维常挂在嘴边的一句话是能用包管理器软件包解决的问题尽量不要自己编译。这个原则放到Apache这个场景上依然适用。除非你确实需要某个官方包没有的特殊模块或者定制编译参数那时候才建议源码安装但那是进阶话题这里不展开。3. 深入配置让Apache真正开始工作3.1 防火墙规则别让80端口被堵住安装成功但外部访问不了多数情况和Linux自身防火墙或者云平台安全组有关。Ubuntu 18自带UFW防火墙但默认是未启用状态。问题来了有些人直接从网上抄命令先sudo ufw enable再添加规则结果把自己SSH连接掐断了。正确的顺序一定是先把必要端口放行最后再启用防火墙。常用的放行命令sudo ufw allow OpenSSH sudo ufw allow Apache Full sudo ufw enableApache Full是UFW里现成的应用规则会一次放行80和443两个端口。如果你暂时不打算上HTTPS也可以只放行80sudo ufw allow 80/tcpsudo ufw enable之后再用sudo ufw status确认规则生效。这里提醒一句云服务器厂商在控制台还有一套安全组规则服务器内部防火墙放行了云平台安全组没放行外面照样进不来。这种双层防火墙模型经常让新手原地发懵排查时一定要两头都看。另外如果你只是想在虚拟机里做测试UFW完全可以用但不强制开很多人也选择不开系统防火墙直接靠云安全组做访问控制这也是常见做法。3.2 虚拟主机配置一个服务器跑多个站点安装完成后默认站点指向/var/www/html但真实业务里很少会直接往里塞东西。更规范的做法是建虚拟主机。我这里给出一套可以直接抄的流程第一步创建站点目录并放一个测试文件sudo mkdir -p /var/www/mysite echo h1My Site/h1 | sudo tee /var/www/mysite/index.html第二步复制默认配置作为模板sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/mysite.conf复制一份再改比手写整个VirtualHost靠谱因为默认配置里的语法结构、缩进风格都是现成的不容易出错。第三步编辑mysite.conf重点确认这几个参数VirtualHost *:80 ServerName mysite.example.com ServerAdmin webmasterexample.com DocumentRoot /var/www/mysite ErrorLog ${APACHE_LOG_DIR}/mysite_error.log CustomLog ${APACHE_LOG_DIR}/mysite_access.log combined /VirtualHostServerName填你解析好的域名如果只是测试环境直接用服务器IP填进去也行。DocumentRoot必须指向你刚才建的站点目录这是整个配置的灵魂。日志建议单独设置文件这样不同站点的日志能分开排查比混着看全局日志舒服太多。第四步启用站点并重载配置sudo a2ensite mysite.conf sudo systemctl reload apache2注意这里我用的是reload而不是restart。两者区别很值得记住reload是平滑重载配置不会中断正在处理的请求restart是全部杀掉再启动生产环境会造成瞬时断连。绝大部分配置变更场景用reload就足够。第五步验证curl -H Host: mysite.example.com http://127.0.0.1如果配置正确你会看到自己写的h1My Site/h1内容。浏览器访问时只要域名解析到服务器IP也能看到同样页面。这里必须单独提醒一个高频错误目录权限。如果站点目录放在/var/www下面默认的继承权限通常没问题因为apache2.conf里已经对/var/www授予了Require all granted。但如果你把站点目录放在其他位置比如某个用户的/home/user/site下就必须在配置里手动加一段Directory /home/user/site Options Indexes FollowSymLinks AllowOverride All Require all granted /Directory不加这段的典型后果是访问时返回403 Forbidden。这也是虚拟主机配置新手的头号拦路虎。3.3 启用常用模块rewrite、ssl、headersApache的模块化机制用好了能解决大量实际需求。日常我至少会开这几个模块sudo a2enmod rewrite sudo a2enmod ssl sudo a2enmod headers sudo a2enmod expiresrewriteURL重写很多框架的路由规则、伪静态都依赖它。ssl启用HTTPS的基础后面配证书时会用到。headers可以自定义HTTP响应头比如跨域、缓存策略。expires给静态资源设置过期时间对页面性能优化作用明显。开完模块之后同样执行sudo systemctl reload apache2生效。a2enmod会在mods-enabled下自动生成软链所以你可以随时用ls /etc/apache2/mods-enabled确认当前开了哪些模块。关于模块还有一个常见问题是不是把所有模块都开上更省事我的建议是不要。模块开多了内存占用和处理开销都会变大某些调试模块还可能暴露内部信息。更糟糕的是模块之间可能存在依赖关系出现冲突时排查难度直线上升。我的习惯是“需要什么开什么”保持最小化这样以后排查问题时范围能控制在很小。4. 常见问题排查与避坑指南4.1 80端口被占用Apache起不来的头号原因Apache装的没问题但systemctl status apache2一看是failed十有八九是80端口被抢了。我在实际环境里见过抢端口的选手不少有Nginx、有Java后端服务、有Squid代理、还有别的web容器。定位命令sudo ss -tulpn | grep :80加上sudo才能看到PID和进程名称否则输出会缺少关键信息。确认占用进程后二选一要么停掉对方要么让Apache改用其他端口。如果决定让Apache监听8080记住改两处/etc/apache2/ports.conf里的Listen 80改成Listen 8080同时站点配置里VirtualHost *:80也要改成VirtualHost *:8080。漏改任何一处都会出现“服务起来了但监听的不是你以为的端口”这种怪象。4.2 默认页面打不开三层排查法外网访问不了Apache默认页本机却正常这时候我一般按三层顺序来查本机自测curl -I http://127.0.0.1先行。本机都不通说明问题出在服务本身往下查日志本机通继续看防火墙。防火墙排查sudo ufw status看服务器内部防火墙再登录云平台控制台检查安全组是否放行80端口。这个双层防火墙模型我前面已经强调过很多网页打不开的问题都卡在这里。监听地址检查sudo ss -tulpn | grep :80看Apache是监听0.0.0.0:80还是127.0.0.1:80。如果只监听在回环地址上外部自然永远无法访问。默认配置是监听所有地址但如果你自己改过ports.conf这一步不能漏。这套排查流程在实践中大约能解决八成以上的“打不开”问题而且每一步耗时都在十几秒内非常值得养成习惯。4.3 403权限问题与目录配置要点配置虚拟主机后访问返回403 Forbidden的场景太常见了。原因基本可以归为两类第一类目录权限不足。Apache进程以www-data用户运行它需要能读取站点文件。文件至少是644权限目录至少是755权限。很多人把站点文件放在用户家目录下权限还是700那Apache自然什么都读不到。解决办法是chmod 755 /var/www/mysite chmod 644 /var/www/mysite/index.html如果目录确实在用户家目录这种权限敏感区更省事的方案是直接把站点目录建到/var/www下从根源上规避权限问题。第二类Directory指令没配置好。如果你的站点目录不在/var/www下又没有给对应目录写Require all grantedApache默认会拒绝访问。这块容易和第一种情况混淆排查时可以先看error.log权限问题通常会有Permission denied或client denied by server configuration这样的关键字。还有一个隐蔽场景目录下有Options Indexes时如果存在index.html正常显示页面一旦没有索引文件Apache会把整个目录结构列出来这在生产环境既不好看也不安全。建议把Options Indexes FollowSymLinks里的Indexes去掉或者改成Options -Indexes。4.4 日志、备份与安全加固建议Apache的日志是排查问题的第一手资料。/var/log/apache2/error.log记录后端错误access.log则能看到所有访问请求。我习惯在改动配置或站点上线时用tail -f实时观察日志这个习惯帮忙定位过不少奇怪问题比如某个静态资源配置路径不对、某个目录权限被篡改、甚至还能看到被扫描工具探测的痕迹。安全方面有几件事装完Apache就顺手做了成本很低但收益很大隐藏版本号在/etc/apache2/apache2.conf里加上ServerTokens Prod避免响应头直接暴露完整版本信息。关闭目录列表确认站点配置里没有启用Indexes避免目录索引直接裸露给外部。确认日志轮转生效/etc/logrotate.d/apache2是系统自带的确认它存在日志就不会无限膨胀挤爆磁盘。定期备份配置sudo cp -r /etc/apache2 /etc/apache2.bak_$(date %F)改动任何配置前先备份。看似麻烦关键时刻能救命我确实见过有人把配置改坏又没备份最后只能凭记忆一点点恢复的场景。最后再分享一个经验技巧改完任何Apache配置先别急着reload跑一遍sudo apache2ctl configtest。它会帮你做语法检查输出Syntax OK才代表没有低级拼写错误。我每次配置站点、启停虚拟主机前后都会执行一下配合reload而不是restart这套组合拳用了很久基本没有因为配置语法错误把线上服务搞挂过。装完Apache只是第一步能把它配置成一台可以稳定服务业务的Web服务器才算是真正把这篇内容吃透了。