强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Apache HTTP Server 完全指南 / 生产最佳实践

生产最佳实践

本章总结 Apache 在生产环境中的安全基线、运维 SOP、备份策略和团队管理规范。

1. 安全基线

1.1 安全配置清单

检查项配置优先级
隐藏版本信息ServerTokens Prod
关闭签名ServerSignature Off
禁用目录列表Options -Indexes
保护敏感文件<FilesMatch "^\.">
启用 HTTPSSSLEngine on
禁用弱协议SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
启用 HSTSHeader set Strict-Transport-Security
安全头配置X-Frame-Options, X-XSS-Protection
访问控制Require ip / Require user
ModSecurityWAF 规则
日志审计完整的日志记录
定期更新安全补丁及时应用

1.2 安全基线配置

# /etc/apache2/conf-available/security-baseline.conf

# 1. 版本信息
ServerTokens Prod
ServerSignature Off

# 2. 目录安全
<Directory />
    Options -Indexes -FollowSymLinks -Includes
    AllowOverride None
    Require all denied
</Directory>

<Directory "/var/www/html">
    Options -Indexes +FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

# 3. 敏感文件保护
<FilesMatch "^\.">
    Require all denied
</FilesMatch>

<FilesMatch "\.(conf|log|bak|sql|sh|env|git|htaccess|htpasswd)$">
    Require all denied
</FilesMatch>

# 4. 安全头
<IfModule mod_headers.c>
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always unset Server
    Header always unset X-Powered-By
</IfModule>

# 5. 请求限制
<IfModule mod_reqtimeout.c>
    RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
</IfModule>

# 6. HTTP 方法限制
<LimitExcept GET POST HEAD OPTIONS>
    Require all denied
</LimitExcept>

1.3 SSL 基线

# /etc/apache2/conf-available/ssl-baseline.conf

<IfModule mod_ssl.c>
    # 仅允许安全协议
    SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
    
    # 强密码套件
    SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
    SSLHonorCipherOrder off
    
    # 会话安全
    SSLSessionTickets off
    
    # 压缩
    SSLCompression off
    
    # OCSP Stapling
    SSLUseStapling on
    SSLStaplingCache shmcb:/var/run/ocsp(128000)
</IfModule>

<IfModule mod_headers.c>
    # HSTS
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
</IfModule>

2. 运维 SOP

2.1 日常运维检查表

#!/bin/bash
# daily-check.sh - 每日检查脚本

echo "=== Apache 每日检查 $(date +%Y-%m-%d) ==="

# 1. 服务状态
echo "1. 服务状态:"
systemctl is-active apache2

# 2. 配置语法
echo "2. 配置语法:"
apachectl configtest 2>&1

# 3. 进程数
echo "3. 进程数:"
ps aux | grep httpd | wc -l

# 4. 错误日志统计
echo "4. 最近 24 小时错误:"
grep "$(date -d yesterday +%Y-%m-%d)" /var/log/apache2/error.log | wc -l

# 5. 磁盘空间
echo "5. 磁盘空间:"
df -h | grep -E '/$|/var|/tmp'

# 6. SSL 证书到期
echo "6. SSL 证书到期检查:"
for cert in /etc/letsencrypt/live/*/fullchain.pem; do
    EXPIRY=$(openssl x509 -enddate -noout -in "$cert" | cut -d= -f2)
    DAYS_LEFT=$(( ($(date -d "$EXPIRY" +%s) - $(date +%s)) / 86400 ))
    echo "  $(dirname $cert): $EXPIRY ($DAYS_LEFT 天)"
done

# 7. 内存使用
echo "7. 内存使用:"
free -h

# 8. 负载
echo "8. 系统负载:"
uptime

echo "=== 检查完成 ==="

2.2 变更管理流程

变更请求 → 评审 → 测试 → 备份 → 实施 → 验证 → 记录
#!/bin/bash
# change-apache-config.sh

CONFIG_FILE=$1
CHANGE_DESC=$2

# 1. 备份当前配置
BACKUP_DIR="/backup/apache/$(date +%Y%m%d_%H%M%S)"
mkdir -p $BACKUP_DIR
cp /etc/apache2/apache2.conf $BACKUP_DIR/
cp -r /etc/apache2/sites-enabled $BACKUP_DIR/
echo "配置已备份到: $BACKUP_DIR"

# 2. 测试新配置
cp $CONFIG_FILE /etc/apache2/apache2.conf
if ! apachectl configtest; then
    echo "配置测试失败,恢复原配置"
    cp $BACKUP_DIR/apache2.conf /etc/apache2/
    exit 1
fi

# 3. 重新加载配置
systemctl reload apache2
if [ $? -ne 0 ]; then
    echo "重载失败,恢复原配置"
    cp $BACKUP_DIR/apache2.conf /etc/apache2/
    cp -r $BACKUP_DIR/sites-enabled /etc/apache2/
    systemctl reload apache2
    exit 1
fi

# 4. 验证
sleep 5
if curl -s -o /dev/null -w "%{http_code}" http://localhost/ | grep -q "200\|301\|302"; then
    echo "变更成功: $CHANGE_DESC"
else
    echo "验证失败,恢复原配置"
    cp $BACKUP_DIR/apache2.conf /etc/apache2/
    cp -r $BACKUP_DIR/sites-enabled /etc/apache2/
    systemctl reload apache2
    exit 1
fi

# 5. 记录变更
echo "$(date) - $CHANGE_DESC" >> /var/log/apache2-changes.log

2.3 版本升级流程

#!/bin/bash
# upgrade-apache.sh

# 1. 记录当前版本
echo "当前版本:" > /tmp/upgrade.log
apachectl -v >> /tmp/upgrade.log
apachectl -V >> /tmp/upgrade.log

# 2. 备份配置和网站
BACKUP_DIR="/backup/apache/pre-upgrade-$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
tar -czf $BACKUP_DIR/apache-config.tar.gz /etc/apache2/
tar -czf $BACKUP_DIR/apache-www.tar.gz /var/www/
cp /etc/apache2/mods-enabled/*.load $BACKUP_DIR/
cp /etc/apache2/mods-enabled/*.conf $BACKUP_DIR/

# 3. 检查新版本
apt update
apt list --upgradable | grep apache

# 4. 执行升级
apt upgrade apache2

# 5. 测试配置
if ! apachectl configtest; then
    echo "升级后配置测试失败"
    echo "请检查配置并手动修复"
    exit 1
fi

# 6. 重启服务
systemctl restart apache2

# 7. 验证
sleep 5
if curl -s -o /dev/null -w "%{http_code}" http://localhost/ | grep -q "200\|301\|302"; then
    echo "升级成功"
    apachectl -v >> /tmp/upgrade.log
else
    echo "升级后验证失败,请检查"
    exit 1
fi

echo "升级完成,详细日志: /tmp/upgrade.log"

3. 备份与恢复

3.1 完整备份脚本

#!/bin/bash
# backup-apache-full.sh

BACKUP_BASE="/backup/apache"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_BASE/$DATE"
RETENTION_DAYS=30

mkdir -p $BACKUP_DIR

# 1. 配置文件
echo "备份配置文件..."
tar -czf $BACKUP_DIR/apache-config.tar.gz \
    /etc/apache2/ \
    /etc/php/ \
    2>/dev/null

# 2. 网站文件
echo "备份网站文件..."
tar -czf $BACKUP_DIR/apache-www.tar.gz \
    /var/www/ \
    2>/dev/null

# 3. SSL 证书
echo "备份 SSL 证书..."
tar -czf $BACKUP_DIR/apache-ssl.tar.gz \
    /etc/letsencrypt/ \
    /etc/ssl/ \
    2>/dev/null

# 4. 日志(最近 7 天)
echo "备份日志..."
find /var/log/apache2/ -mtime -7 -type f -exec tar -czf $BACKUP_DIR/apache-logs.tar.gz {} + 2>/dev/null

# 5. 生成清单
echo "生成备份清单..."
{
    echo "=== Apache 备份清单 ==="
    echo "日期: $DATE"
    echo "主机: $(hostname)"
    echo "Apache 版本: $(apachectl -v | head -1)"
    echo ""
    echo "备份内容:"
    ls -lh $BACKUP_DIR/
} > $BACKUP_DIR/manifest.txt

# 6. 清理旧备份
echo "清理 ${RETENTION_DAYS} 天前的备份..."
find $BACKUP_BASE -type d -mtime +$RETENTION_DAYS -exec rm -rf {} +

# 7. 计算备份大小
BACKUP_SIZE=$(du -sh $BACKUP_DIR | cut -f1)
echo "备份完成: $BACKUP_DIR ($BACKUP_SIZE)"

3.2 恢复脚本

#!/bin/bash
# restore-apache.sh

BACKUP_DIR=$1

if [ -z "$BACKUP_DIR" ]; then
    echo "用法: $0 <backup-directory>"
    echo "可用备份:"
    ls -d /backup/apache/*/ | tail -10
    exit 1
fi

echo "=== 恢复 Apache 配置 ==="
echo "备份目录: $BACKUP_DIR"
echo ""

read -p "确认恢复?这将覆盖当前配置 (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "已取消"
    exit 0
fi

# 1. 停止服务
echo "停止 Apache..."
systemctl stop apache2

# 2. 备份当前配置(以防恢复失败)
CURRENT_BACKUP="/backup/apache/before-restore-$(date +%Y%m%d_%H%M%S)"
mkdir -p $CURRENT_BACKUP
cp -r /etc/apache2/ $CURRENT_BACKUP/

# 3. 恢复配置
echo "恢复配置文件..."
tar -xzf $BACKUP_DIR/apache-config.tar.gz -C /

# 4. 恢复网站文件
echo "恢复网站文件..."
tar -xzf $BACKUP_DIR/apache-www.tar.gz -C /

# 5. 测试配置
echo "测试配置..."
if ! apachectl configtest; then
    echo "配置测试失败,恢复到恢复前状态"
    cp -r $CURRENT_BACKUP/apache2/* /etc/apache2/
    systemctl start apache2
    exit 1
fi

# 6. 启动服务
echo "启动 Apache..."
systemctl start apache2

# 7. 验证
sleep 5
if curl -s -o /dev/null -w "%{http_code}" http://localhost/ | grep -q "200\|301\|302"; then
    echo "恢复成功"
else
    echo "恢复后验证失败,请检查"
fi

3.3 定期备份 Cron

# /etc/cron.d/apache-backup

# 每天凌晨 2 点备份
0 2 * * * root /usr/local/bin/backup-apache-full.sh >> /var/log/apache-backup.log 2>&1

# 每周日凌晨 3 点完整备份(包含日志)
0 3 * * 0 root /usr/local/bin/backup-apache-full.sh --include-logs >> /var/log/apache-backup.log 2>&1

# 每月 1 日备份 SSL 证书
0 4 1 * * root tar -czf /backup/apache/ssl-$(date +\%Y\%m\%d).tar.gz /etc/letsencrypt/ /etc/ssl/

4. 监控告警规范

4.1 告警级别

级别条件响应时间通知方式
P0-严重服务不可用5 分钟电话+短信+邮件
P1-紧急性能严重下降15 分钟短信+邮件
P2-警告资源使用偏高1 小时邮件
P3-通知信息性事件下一工作日邮件

4.2 告警规则

# Prometheus 告警规则
groups:
  - name: apache_alerts
    rules:
      # P0 - 服务不可用
      - alert: ApacheDown
        expr: up{job="apache"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Apache 服务停止"
          description: "Apache 服务已停止超过 1 分钟"
      
      # P1 - 高错误率
      - alert: ApacheHighErrorRate
        expr: rate(apache_accesses_total{code=~"5.."}[5m]) > 10
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Apache 5xx 错误率过高"
      
      # P1 - 证书即将过期
      - alert: ApacheCertExpiring
        expr: (ssl_certificate_expiry - time()) / 86400 < 7
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "SSL 证书将在 7 天内过期"
      
      # P2 - 高负载
      - alert: ApacheHighLoad
        expr: apache_cpu_load > 80
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Apache CPU 负载过高"
      
      # P2 - 磁盘空间
      - alert: ApacheDiskSpaceLow
        expr: (node_filesystem_avail_bytes{mountpoint="/var/log"} / node_filesystem_size_bytes{mountpoint="/var/log"}) * 100 < 20
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "日志分区空间不足"

4.3 Grafana 仪表板

{
  "dashboard": {
    "title": "Apache 生产监控",
    "panels": [
      {
        "title": "服务状态",
        "type": "stat",
        "targets": [{
          "expr": "up{job='apache'}",
          "legendFormat": "状态"
        }]
      },
      {
        "title": "每秒请求",
        "type": "timeseries",
        "targets": [{
          "expr": "rate(apache_accesses_total[5m])",
          "legendFormat": "RPS"
        }]
      },
      {
        "title": "响应时间",
        "type": "timeseries",
        "targets": [{
          "expr": "rate(apache_duration_seconds_sum[5m]) / rate(apache_duration_seconds_count[5m])",
          "legendFormat": "平均响应时间"
        }]
      },
      {
        "title": "工作线程",
        "type": "gauge",
        "targets": [{
          "expr": "apache_busy_workers / (apache_busy_workers + apache_idle_workers) * 100",
          "legendFormat": "使用率 %"
        }]
      },
      {
        "title": "错误率",
        "type": "timeseries",
        "targets": [{
          "expr": "rate(apache_accesses_total{code=~'5..'}[5m]) / rate(apache_accesses_total[5m]) * 100",
          "legendFormat": "错误率 %"
        }]
      }
    ]
  }
}

5. 性能优化规范

5.1 环境参数标准

参数开发环境测试环境生产环境
MPMeventeventevent
MaxRequestWorkers100250400+
KeepAliveTimeout1553
MaxKeepAliveRequests100100100
ServerTokensFullProdProd
LogLeveldebugwarnwarn
错误显示OnOffOff

5.2 缓存策略标准

资源类型max-age策略
HTML0no-cache
CSS/JS (带哈希)1 年immutable
CSS/JS (无哈希)1 天必须验证
图片1 年public
字体1 年immutable
API 响应0no-store
静态文件1 月public

5.3 压缩配置标准

# 压缩配置
<IfModule mod_deflate.c>
    DeflateCompressionLevel 6
    
    # 压缩类型
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE image/svg+xml
    
    # 排除已压缩内容
    SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|zip|gz|bz2|rar|mp[34]|avi|wmv|flv)$ no-gzip dont-vary
</IfModule>

6. 文档与培训

6.1 运维文档结构

docs/
├── architecture/
│   ├── 系统架构图.md
│   ├── 网络拓扑图.md
│   └── 数据流图.md
├── operations/
│   ├── 日常运维手册.md
│   ├── 变更管理流程.md
│   ├── 故障处理手册.md
│   └── 应急预案.md
├── security/
│   ├── 安全基线文档.md
│   ├── 安全事件响应.md
│   └── 审计报告模板.md
├── deployment/
│   ├── 部署流程.md
│   ├── 回滚流程.md
│   └── 灰度发布.md
└── maintenance/
    ├── 备份恢复手册.md
    ├── 性能调优指南.md
    └── 升级指南.md

6.2 事故报告模板

# 事故报告

## 基本信息
- **事故编号**: INC-YYYY-MMDD-XXX
- **报告时间**: YYYY-MM-DD HH:MM:SS
- **报告人**: 
- **事故等级**: P0/P1/P2/P3

## 事故描述
- **影响范围**: 
- **持续时间**: 
- **影响用户数**: 
- **业务损失**: 

## 事故经过
1. YYYY-MM-DD HH:MM:SS - 发现问题
2. YYYY-MM-DD HH:MM:SS - 开始排查
3. YYYY-MM-DD HH:MM:SS - 定位原因
4. YYYY-MM-DD HH:MM:SS - 修复完成
5. YYYY-MM-DD HH:MM:SS - 验证恢复

## 根本原因
- **直接原因**: 
- **根本原因**: 

## 处理措施
- **临时措施**: 
- **永久措施**: 

## 改进计划
- [ ] 
- [ ] 
- [ ] 

## 经验教训
- 
- 

6.3 培训计划

主题对象频率方式
Apache 基础新员工入职培训面授
安全意识全体运维季度在线
故障处理运维团队月度演练
性能调优高级运维季度工作坊
新版本特性全体运维版本发布时分享会

7. 容量规划

7.1 容量评估

#!/bin/bash
# capacity-planning.sh

echo "=== Apache 容量评估 ==="

# 当前使用情况
echo "1. 当前负载:"
echo "   CPU: $(top -bn1 | grep 'Cpu(s)' | awk '{print $2}')%"
echo "   内存: $(free | grep Mem | awk '{print $3/$2 * 100.0}')%"
echo "   磁盘: $(df / | tail -1 | awk '{print $5}')"

# 连接数
echo "2. 连接数:"
echo "   当前: $(ss -tlnp | grep ':80 ' | wc -l)"
echo "   最大: $(grep MaxRequestWorkers /etc/apache2/mods-enabled/mpm_*.conf | awk '{print $2}')"

# 请求量
echo "3. 请求量 (最近 24 小时):"
echo "   总请求: $(wc -l < /var/log/apache2/access.log)"
echo "   每秒请求: $(tail -10000 /var/log/apache2/access.log | wc -l | awk '{print $1/86400}')"

# 带宽
echo "4. 带宽使用:"
echo "   日均: $(awk '{sum+=$10} END {print sum/1024/1024 " MB"}' /var/log/apache2/access.log)"

# 预测
echo "5. 建议:"
echo "   根据当前使用情况,建议:"
echo "   - MaxRequestWorkers: $(ps aux | grep httpd | wc -l | awk '{print int($1*1.5)}')"
echo "   - 内存预留: $(free -m | grep Mem | awk '{print int($2*0.2) " MB"}')"

7.2 扩展策略

负载增加
├── 垂直扩展(Scale Up)
│   ├── 增加 CPU
│   ├── 增加内存
│   └── 优化 MPM 参数
├── 水平扩展(Scale Out)
│   ├── 添加后端服务器
│   ├── 配置负载均衡
│   └── 使用 CDN
└── 架构优化
    ├── 启用缓存
    ├── 压缩优化
    └── 数据库优化

8. 高可用方案

8.1 主备架构

                ┌─────────────┐
                │  负载均衡器  │
                │  (keepalived)│
                └──────┬──────┘
                       │
         ┌─────────────┼─────────────┐
         │                           │
┌────────┴────────┐         ┌────────┴────────┐
│   Apache 主     │         │   Apache 备     │
│   (MASTER)      │         │   (BACKUP)      │
│   优先级 100    │         │   优先级 90     │
└────────┬────────┘         └────────┬────────┘
         │                           │
         └─────────┬─────────────────┘
                   │
           ┌───────┴───────┐
           │  共享存储      │
           │  (NFS/GlusterFS)│
           └───────────────┘

8.2 Keepalived 配置

# /etc/keepalived/keepalived.conf (主)
vrrp_script check_apache {
    script "/usr/local/bin/check_apache.sh"
    interval 2
    weight 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass apache_ha
    }
    
    virtual_ipaddress {
        192.168.1.100/24
    }
    
    track_script {
        check_apache
    }
    
    notify_master "/usr/local/bin/notify_master.sh"
    notify_backup "/usr/local/bin/notify_backup.sh"
}
#!/bin/bash
# check_apache.sh
if ! pgrep -x apache2 > /dev/null; then
    exit 1
fi
curl -sf http://localhost/ > /dev/null || exit 1
exit 0

9. 安全合规

9.1 PCI DSS 要求

要求Apache 配置
2.2 配置标准安全基线配置
4.1 传输加密SSL/TLS 配置
6.2 安全补丁定期更新
6.5 安全编码ModSecurity WAF
10.2 审计日志完整日志记录
11.2 漏洞扫描定期安全扫描

9.2 GDPR 合规

# 日志匿名化(不记录 IP)
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined_anon

# 或使用哈希处理
LogFormat "ANONYMIZED %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" gdpr

# Cookie 安全
Header always set Set-Cookie "Path=/; HttpOnly; Secure; SameSite=Strict"

10. 注意事项

  1. 定期演练:备份恢复、故障处理定期演练
  2. 文档更新:配置变更后及时更新文档
  3. 安全审计:定期进行安全审计和漏洞扫描
  4. 性能测试:定期进行压力测试和性能优化
  5. 团队协作:建立有效的沟通和协作机制

11. 扩展阅读

12. 总结

生产环境 Apache 运维需要:

  • 安全基线:建立和执行安全配置标准
  • 运维规范:制定和遵循 SOP 流程
  • 备份策略:定期备份,定期验证
  • 监控告警:建立完善的监控和告警体系
  • 持续改进:定期评估、优化和改进

遵循最佳实践可以确保 Apache 服务稳定、安全、高效运行。