我的多个网站(产品官网、博客、作品集)均采用 OBS 静态托管 + ECS Nginx 反向代理方案。本文分享完整部署流程,包括 OBS 桶配置、Nginx 反代去 Content-Disposition 头、HTTPS 证书和多站点配置。

一、架构设计

用户 → DNS解析 → ECS公网IP:443 → Nginx反向代理
                                        ↓
                                    OBS桶(静态文件)
                                        
Nginx 职责:
  1. HTTPS 终结(SSL证书)
  2. 反向代理到 OBS 桶
  3. 去掉 OBS 返回的 Content-Disposition 头
  4. 多站点 server_name 分发
💡
为什么需要 Nginx?OBS 静态托管默认给文件加 Content-Disposition: attachment 头,导致浏览器下载而非直接展示。Nginx 反代时剥离该头,让浏览器正常渲染 HTML。

二、OBS 桶配置

2.1 创建桶

  1. 登录华为云控制台 → 对象存储服务 OBS → 创建桶
  2. 桶名:如 blog-guidl-top(全局唯一)
  3. 区域:选离用户最近的区域(如华北-北京四)
  4. 桶策略:公共读(允许匿名读取对象)

2.2 上传网站文件

# 用 obsutil 批量上传
obsutil cp ./Z_2\ Blog-技术博客blog.guidl.top/ obs://blog-guidl-top/ -r -f

# 关键:设置正确的 Content-Type
# HTML  → text/html; charset=utf-8
# CSS   → text/css; charset=utf-8
# JS    → application/javascript; charset=utf-8
# 图片  → image/png / image/jpeg / image/svg+xml
⚠️
易错点:OBS 默认可能将 .html 的 Content-Type 设为 application/octet-stream,导致浏览器下载。上传后需检查并修正 Content-Type。

三、ECS Nginx 配置

3.1 安装 Nginx

# ECS 上安装 Nginx(CentOS)
yum install -y nginx
systemctl enable nginx
systemctl start nginx

# 安装 certbot 申请 Let's Encrypt 证书
yum install -y certbot python3-certbot-nginx

3.2 多站点反向代理配置

每个站点一个 server 块,通过 server_name 分发。以博客站为例:

# /etc/nginx/conf.d/blog-guidl-top.conf

server {
    listen 80;
    server_name blog.guidl.top;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name blog.guidl.top;

    ssl_certificate     /etc/letsencrypt/live/blog.guidl.top/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/blog.guidl.top/privkey.pem;

    location / {
        proxy_pass /blog/.obs.cn-north-4.myhuaweicloud.com;
        proxy_set_header Host blog-guidl-top.obs.cn-north-4.myhuaweicloud.com;
        
        # 关键:去掉 OBS 的 Content-Disposition 头
        proxy_hide_header Content-Disposition;
        
        # 修正 Content-Type(OBS 有时设错)
        proxy_set_header Accept-Encoding "";
        sub_filter_types text/html text/css application/javascript;
    }
}

3.3 多站点统一管理

我的4个子站点都在同一台 ECS 上,每个站点一个 conf 文件(隐私政策已并入各站 /policy 路径):

/etc/nginx/conf.d/
├── netlab-guidl-top.conf    # 产品官网 netlab.guidl.top
├── www-guidl-top.conf       # 作品集 www.guidl.top
├── blog-guidl-top.conf      # 博客 blog.guidl.top
└── lab-guidl-top.conf       # 资源站 lab.guidl.top

# 重载配置
nginx -t && nginx -s reload

四、HTTPS 证书配置

# 用 certbot 自动申请+配置 Let's Encrypt 证书
certbot --nginx -d blog.guidl.top -d netlab.guidl.top -d www.guidl.top

# 自动续期(certbot 默认已设置 systemd timer)
certbot renew --dry-run  # 测试续期

也可以用华为云 SCM(证书管理服务)申请免费DV证书,部署到 ECS 上。

五、域名解析

域名记录类型值
netlab.guidl.topAECS公网IP
www.guidl.topAECS公网IP
blog.guidl.topAECS公网IP
lab.guidl.topAECS公网IP
guidl.topCNAMEwww.guidl.top

所有子域都指向同一台 ECS 的公网 IP,Nginx 通过 server_name 分发到不同 OBS 桶。

六、自动化部署脚本

#!/bin/bash
# deploy-blog.sh - 一键部署博客到 OBS

SITE="Z_2 Blog-技术博客blog.guidl.top"
BUCKET="blog-guidl-top"

echo ">>> 上传到 OBS..."
obsutil cp "./$SITE/" "obs://$BUCKET/" -r -f -u

echo ">>> 修正 Content-Type..."
obsutil config -i=AK -k=SK -e=obs.cn-north-4.myhuaweicloud.com
# 批量设置 HTML 文件类型
for f in $(find "./$SITE/" -name "*.html"); do
    key="${f#./$SITE/}"
    obsutil obsutil set-meta "obs://$BUCKET/$key" "Content-Type:text/html;charset=utf-8"
done

echo ">>> 重载 Nginx..."
ssh ecs "nginx -t && nginx -s reload"

echo ">>> 部署完成!"
echo "访问: /blog/"

七、常见问题排查

  • 页面下载而非展示:检查 Nginx 是否 proxy_hide_header Content-Disposition
  • CSS/JS 不加载:检查 OBS 上文件的 Content-Type 是否正确
  • 404:检查 OBS 桶策略是否为公共读,proxy_pass URL 是否正确
  • 混合内容警告:确保页面内所有资源链接都用 https://
  • 证书过期:检查 certbot 续期 timer 是否正常运行

八、小结

  • OBS 静态托管 + Nginx 反代是低成本高可靠的静态站方案
  • 核心难点是去 Content-Disposition 头和修正 Content-Type
  • 多站点共用一台 ECS,Nginx server_name 分发,运维成本低
  • 自动化部署脚本让更新发布只需一条命令