Ubuntu 系统系列 | 第 16 天:Web 服务器搭建——Nginx/Apache 安装配置与反向代理

第 16/30 天

引言

Web 服务器是互联网的基础设施,无论是搭建个人博客、企业官网,还是部署微服务 API,都离不开 Web 服务器。在 Ubuntu 生态中,Nginx 和 Apache 是最主流的两个选择——它们各有优势,适用于不同的场景。

今天,我们将从零开始在 Ubuntu 上搭建 Nginx 和 Apache,深入配置虚拟主机、SSL 证书,并实战反向代理——这是现代 Web 架构中最核心的部署模式之一。无论你是运维新手还是后端开发者,掌握这些技能都是通往生产环境的必经之路。


一、Nginx vs Apache:选型对比

在动手安装之前,先了解两者的核心差异:

特性 Nginx Apache
架构模型 事件驱动(异步非阻塞) 进程/线程模型(每个连接一个进程)
并发处理 极高,单进程处理数千连接 中等,依赖 MPM 模式
静态文件性能 极优(自带高效静态文件服务) 良好
动态内容 通过 FastCGI 代理(PHP-FPM) 原生支持(mod_php)
配置复杂度 简洁清晰 功能丰富但配置繁重
模块系统 编译时静态模块 动态加载模块(DSO)
反向代理 原生支持,性能极佳 通过 mod_proxy 实现
适用场景 高并发、反向代理、静态资源、负载均衡 传统 LAMP 栈、.htaccess 重度用户

我的建议: 新项目首选 Nginx——性能更好、配置更简洁、反向代理能力更强。Apache 适合需要大量 .htaccess 覆盖或兼容老项目的场景。


二、安装 Nginx

2.1 从官方仓库安装

Ubuntu 官方源自带 Nginx,但版本可能较旧。推荐添加 Nginx 官方源获取最新稳定版:

# 安装依赖
sudo apt update
sudo apt install -y curl gnupg2 ca-certificates lsb-release

# 添加 Nginx 官方签名密钥
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg

# 添加 Nginx 稳定版源
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list

# 安装
sudo apt update
sudo apt install -y nginx

2.2 验证安装

# 检查版本
nginx -v
# 输出: nginx version: nginx/1.26.x

# 检查服务状态
sudo systemctl status nginx

# 启动并设置开机自启
sudo systemctl start nginx
sudo systemctl enable nginx

此时访问 http://你的服务器IP,应该看到 Nginx 的默认欢迎页面。

2.3 Nginx 目录结构

了解 Nginx 的核心目录结构至关重要:

/etc/nginx/
├── nginx.conf          # 主配置文件
├── conf.d/             # 全局配置片段
├── sites-available/    # 可用站点配置(虚拟主机)
├── sites-enabled/      # 已启用站点(软链接到 sites-available)
├── modules-available/  # 可用模块
└── modules-enabled/    # 已启用模块

/var/log/nginx/
├── access.log          # 访问日志
└── error.log           # 错误日志

/var/www/html/          # 默认网站根目录
/usr/share/nginx/html/  # 部分发行版的默认根目录

三、安装 Apache

3.1 安装 Apache2

sudo apt update
sudo apt install -y apache2

3.2 验证并启动

# 检查版本
apache2 -v
# 输出: Server version: Apache/2.4.62 (Ubuntu)

# 启动服务
sudo systemctl start apache2
sudo systemctl enable apache2

3.3 Apache 目录结构

/etc/apache2/
├── apache2.conf        # 主配置文件
├── ports.conf          # 端口配置
├── sites-available/    # 可用站点配置
├── sites-enabled/      # 已启用站点(软链接)
├── mods-available/     # 可用模块
├── mods-enabled/       # 已启用模块
└── conf-available/     # 可用配置片段

/var/www/html/          # 默认网站根目录
/var/log/apache2/       # 日志目录

四、配置虚拟主机(Virtual Hosts)

虚拟主机让一台服务器托管多个网站,是 Web 服务器的核心功能。

4.1 Nginx 虚拟主机配置

创建第一个站点配置文件:

# 创建网站目录
sudo mkdir -p /var/www/example.com/html
sudo chown -R $USER:$USER /var/www/example.com/html
sudo chmod -R 755 /var/www/example.com

# 创建测试页面
cat > /var/www/example.com/html/index.html << 'HTML'
<!DOCTYPE html>
<html>
<head><title>Welcome to Example</title></head>
<body>
<h1>Hello from Nginx on Ubuntu!</h1>
<p>This is a virtual host example.</p>
</body>
</html>
HTML

创建 Nginx 站点配置:

# /etc/nginx/sites-available/example.com
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com/html;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    # 静态文件缓存
    location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # 日志配置
    access_log /var/log/nginx/example_access.log;
    error_log  /var/log/nginx/example_error.log;
}

启用站点:

# 创建软链接到 sites-enabled
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

# 测试配置语法
sudo nginx -t

# 重载 Nginx
sudo systemctl reload nginx

4.2 Apache 虚拟主机配置

# 创建网站目录
sudo mkdir -p /var/www/example2.com/html
sudo chown -R $USER:$USER /var/www/example2.com/html

# 创建测试页面
cat > /var/www/example2.com/html/index.html << 'HTML'
<!DOCTYPE html>
<html>
<head><title>Welcome to Example2</title></head>
<body>
<h1>Hello from Apache on Ubuntu!</h1>
<p>This is an Apache virtual host example.</p>
</body>
</html>
HTML

创建 Apache 站点配置:

# /etc/apache2/sites-available/example2.com.conf
<VirtualHost *:80>
    ServerAdmin admin@example2.com
    ServerName example2.com
    ServerAlias www.example2.com

    DocumentRoot /var/www/example2.com/html

    <Directory /var/www/example2.com/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example2_error.log
    CustomLog ${APACHE_LOG_DIR}/example2_access.log combined
</VirtualHost>

启用站点:

# 启用站点
sudo a2ensite example2.com.conf

# 禁用默认站点(可选)
sudo a2dissite 000-default.conf

# 测试配置
sudo apache2ctl configtest

# 重载 Apache
sudo systemctl reload apache2

五、反向代理实战

反向代理是 Nginx 最强大的功能之一——它接收客户端请求,转发给后端服务器(应用服务器、API 服务等),再将结果返回给客户端。这实现了负载均衡、安全隔离、SSL 终结等高级功能。

5.1 反向代理架构示意图

Client ──► Nginx (反向代理) ──► Backend Server (Node.js/Python/Java)
                                        │
                                        ├── App 1 (port 3000)
                                        ├── App 2 (port 3001)
                                        └── App 3 (port 3002)

5.2 使用 Nginx 反向代理 Node.js 应用

假设你有一个运行在 localhost:3000 的 Node.js 应用:

# /etc/nginx/sites-available/node-app
server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }

    # 限制请求体大小(API 上传文件时很重要)
    client_max_body_size 50M;
}

5.3 使用 Nginx 反向代理 PHP(PHP-FPM)

Nginx 不自带 PHP 处理能力,需要通过 FastCGI 代理到 PHP-FPM:

server {
    listen 80;
    server_name blog.example.com;
    root /var/www/blog;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

5.4 基于路径的反向代理(多服务聚合)

一个域名下代理多个后端服务,通过路径区分:

server {
    listen 80;
    server_name app.example.com;

    # API 服务 — 转发到 Go 后端
    location /api/ {
        proxy_pass http://127.0.0.1:8080/;
        proxy_set_header Host $host;
    }

    # 前端静态文件 — 直接由 Nginx 服务
    location /static/ {
        alias /var/www/frontend/dist/;
        expires 30d;
    }

    # WebSocket 支持
    location /ws/ {
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

5.5 Apache 反向代理配置

Apache 通过 mod_proxy 实现反向代理:

# 启用必要模块
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
sudo systemctl restart apache2

配置反向代理:

<VirtualHost *:80>
    ServerName proxy.example.com

    # 反向代理到后端
    ProxyPass /app1 http://127.0.0.1:3000/
    ProxyPassReverse /app1 http://127.0.0.1:3000/

    ProxyPass /app2 http://127.0.0.1:5000/
    ProxyPassReverse /app2 http://127.0.0.1:5000/

    # 负载均衡(多台后端)
    <Proxy "balancer://mycluster">
        BalancerMember http://127.0.0.1:3000
        BalancerMember http://127.0.0.1:3001
        ProxySet lbmethod=byrequests
    </Proxy>

    ProxyPass /balancer balancer://mycluster/
    ProxyPassReverse /balancer balancer://mycluster/
</VirtualHost>

六、SSL 证书配置(HTTPS)

6.1 使用 Certbot 自动获取 Let’s Encrypt 证书

# 安装 Certbot
sudo apt install -y certbot python3-certbot-nginx

# 自动获取证书并配置 Nginx
sudo certbot --nginx -d example.com -d www.example.com

# 测试自动续期
sudo certbot renew --dry-run

6.2 Nginx SSL 配置最佳实践

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;

    # SSL 证书路径
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # 安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # HSTS(HTTP Strict Transport Security)
    add_header Strict-Transport-Security "max-age=63072000" always;

    root /var/www/example.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

# HTTP → HTTPS 重定向
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

七、常见问题与排查

Q1: Nginx 配置测试报错如何排查?

# 检查语法
sudo nginx -t

# 检查具体错误行
sudo nginx -T 2>&1 | grep -i error

# 查看错误日志
sudo tail -f /var/log/nginx/error.log

Q2: 端口被占用怎么办?

# 查看端口占用
sudo netstat -tlnp | grep -E ':80|:443'

# 或使用 ss
sudo ss -tlnp | grep -E ':80|:443'

# 如果有其他程序占用了 80 端口,停止它
sudo systemctl stop apache2  # 如果 Apache 占用 80

Q3: Apache 和 Nginx 能否共存?

可以,但不能同时监听相同端口。一个方案是让 Nginx 监听 80/443,Apache 监听其他端口(如 8080),Nginx 反向代理到 Apache:

# Nginx 监听 80,转发动态请求到 Apache:8080
location ~ .php$ {
    proxy_pass http://127.0.0.1:8080;
}

Q4: 修改配置后访问仍然是旧页面?

# 清空浏览器缓存
# 或者强制重载 Nginx/Apache
sudo systemctl reload nginx
# 或
sudo systemctl reload apache2

Q5: 反向代理返回 502 Bad Gateway?

# 检查后端服务是否正常运行
curl http://127.0.0.1:3000/health

# 检查 Nginx 错误日志
sudo tail -f /var/log/nginx/error.log

# 常见原因:后端服务未启动、防火墙阻挡、socket 路径错误

八、性能调优建议

Nginx 核心调优参数

# /etc/nginx/nginx.conf 中的核心优化
worker_processes auto;               # 自动匹配 CPU 核心数
worker_connections 1024;             # 每个 worker 最大连接数
keepalive_timeout 65;                # 长连接超时
client_max_body_size 100M;           # 上传文件大小限制
sendfile on;                         # 高效文件传输
tcp_nopush on;                       # 优化网络包
gzip on;                             # 启用压缩
gzip_types text/plain text/css application/json application/javascript;

Apache 性能调优

# 切换到事件 MPM(多处理模块)
sudo a2dismod mpm_prefork
sudo a2enmod mpm_event
sudo systemctl restart apache2

总结

今天我们深入学习了 Ubuntu 上 Web 服务器的搭建与配置:

技能点 掌握程度
Nginx 安装与基础配置 ✅ 实战
Apache 安装与虚拟主机 ✅ 实战
反向代理配置(Nginx + Apache) ✅ 实战
SSL 证书自动配置(Certbot) ✅ 实战
多站点虚拟主机管理 ✅ 掌握
性能调优基础 ✅ 了解

下期预告: 第 17 天我们将进入数据库的世界——在 Ubuntu 上部署 MySQL/MariaDB/PostgreSQL,从安装到调优,掌握生产级数据库配置的全部要点。


系列目录

天数 文章标题 链接
第 1 天 Ubuntu 简介与版本选择 阅读
第 2 天 手把手安装 Ubuntu 阅读
第 3 天 Ubuntu 桌面环境初探 阅读
第 4 天 Ubuntu 终端基础 阅读
第 5 天 用户与权限管理 阅读
第 6 天 软件包管理 阅读
第 7 天 文件与文本操作 阅读
第 8 天 系统服务管理 阅读
第 9 天 磁盘与文件系统管理 阅读
第 10 天 网络配置与管理 阅读
第 11 天 进程管理与监控 阅读
第 12 天 计划任务与自动化 阅读
第 13 天 备份与恢复策略 阅读
第 14 天 系统更新与升级管理 阅读
第 15 天 SSH 远程管理与安全加固 阅读
第 16 天 Web 服务器搭建 👉 本文
第 17 天 数据库服务器部署 敬请期待
第 18 天 Docker 容器化 敬请期待
第 19 天 文件共享服务 敬请期待
第 20 天 监控与告警系统 敬请期待
第 21 天 邮件服务器基础 敬请期待
第 22 天 系统安全加固 敬请期待
第 23 天 性能调优与内核参数 敬请期待
第 24 天 虚拟化技术 敬请期待
第 25 天 容器编排入门 敬请期待
第 26 天 高可用与负载均衡 敬请期待
第 27 天 Ubuntu 自动部署 敬请期待
第 28 天 故障排查实战 敬请期待
第 29 天 Ubuntu 社区与文档 敬请期待
第 30 天 30 天回顾总结 敬请期待
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容