备案期用 ECS + Nginx 部署静态站
2026-06-22 更新:Emo 已迁至
emo.icemelt.fun,
www.icemelt.fun/emo/ 现 301 跳转。完整迁移步骤见
备案后 Emo 从 /emo/ 子路径迁到子域名。
下文保留备案期子路径方案作历史记录。
上一篇写了 OSS 静态站 的坑。备案材料要求「域名能打开网站首页」,但 CDN 加速域名也要备案 — 审核前往往外网 403,形成「打不开 → 审不过」的死循环。
我买了一台阿里云 ECS,在备案完成前用 Nginx 直接托管静态文件,DNS 用 A 记录指到公网 IP。博客和 Emo 应用都跑起来了,HTTPS 用 Let's Encrypt 免费证书。下文是实操记录,供同类场景参考。
整体架构
| 访问地址 | 服务器目录 | 项目 |
|---|---|---|
https://www.icemelt.fun |
/var/www/icemelt-blog |
备案首页 / 本博客 |
https://www.icemelt.fun/emo/ |
/var/www/emo-world-map(与博客同级) |
Emo 世界地图 Web 版 |
系统:Alibaba Cloud Linux 3.2104(类 CentOS,用 dnf 装软件)。
备案通过后仍可继续用 ECS,也可以再迁回 OSS+CDN。
为什么不用 CDN 等备案
OSS 文件可以照常上传当备份,但对外解析在审核期应指 ECS,不要 CNAME 到未备案的 CDN。
审核员要能打开你填的首页 URL(我填的是 https://www.icemelt.fun/)。
安全组入方向放行:22(SSH)、80、443。
DNS:A 记录,不是 CNAME
@→ A → ECS 公网 IPwww→ A → 同上
子域名 emo.icemelt.fun 在未备案时会被阿里云拦截(外网 403,页面标题
Non-compliance ICP Filing),Let's Encrypt 也无法验证。所以 Emo 先挂在
www.icemelt.fun/emo/,共用主域名的备案与 HTTPS 证书。
服务器装 Nginx(Workbench 可复制)
SSH 可用阿里云 Workbench,不必强求本机 ssh。在服务器上执行:
dnf -y update
dnf -y install nginx rsync || {
tee /etc/yum.repos.d/nginx.repo <<'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=https://nginx.org/packages/centos/8/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
dnf -y install nginx rsync
}
mkdir -p /var/www/icemelt-blog /var/www/emo-world-map
chown -R nginx:nginx /var/www/icemelt-blog /var/www/emo-world-map
mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak 2>/dev/null || true
systemctl enable --now nginx
ACL 的配置目录是 /etc/nginx/conf.d/*.conf,不是 Ubuntu 的
sites-enabled。站点配置里给博客根目录加一段
location /emo/ 做 SPA 回退 /emo/index.html。
本机上传:Mac 用 rsync,别在服务器上 scp 自己
常见误会:已经 Workbench 登录进服务器(提示符像 root@iZbp**********,你的实例主机名),却在服务器里执行
scp ~/Projects/icemelt-blog/... root@公网IP:/root/
服务器上没有 Mac 的项目路径,且 SSH 连自己还要密钥,会 Permission denied (publickey)。
上传应在 Mac 终端做,或在 Workbench 里直接粘贴安装命令 / 上传文件。
Mac 首次连接需在 ECS 绑定 SSH 公钥,或 Workbench 里把 id_rsa.pub 写入
~/.ssh/authorized_keys。
# 博客
cd ~/Projects/icemelt-blog
export DEPLOY_HOST=你的ECS公网IP
./deploy/server-sync.sh
# Emo(构建时带 baseUrl /emo/)
cd ~/Projects/emo-world-map
./deploy/server-deploy.sh
免费 HTTPS:certbot
备案首页能打开后,在服务器上:
dnf -y install certbot python3-certbot-nginx
certbot --nginx -d www.icemelt.fun -d icemelt.fun
按提示选强制跳转 HTTPS。证书自动续期可用
certbot renew --dry-run 检查。
emo.icemelt.fun 的子域证书要等该域名入备案后再申请;备案期用
/emo/ 子路径即可,高德 Web Key 白名单填 www.icemelt.fun。
Expo Web 挂子路径 /emo/
子路径部署要在构建时设 EXPO_PUBLIC_BASE_PATH=/emo(或
app.config.js 里 experiments.baseUrl),否则 JS 仍请求
/_expo/... 会 404。 构建产物上传到 /var/www/emo-world-map/(与博客同级),Nginx 用
alias 把 /emo/ 指过去;不要把 Emo 文件放进博客目录里。
和 OSS 方案如何衔接
- 审核中:DNS → ECS,Nginx 提供页面,备案材料填该 URL。
- 审核通过:可继续 ECS;若迁 OSS+CDN,把 A 记录改成 CNAME,并刷新 CDN 缓存。
- 构建产物:仍可
ossutil上传到桶作备份或多地发布。
踩坑小结
- CDN 未备案 → 外网打不开 → 别在审核期当主入口。
- 未备案子域 → 403 拦截 → 应用先挂
/emo/或等备案。 - 在服务器里 scp 到本机公网 IP → 路径和密钥都不对。
- 地图首次无 pin → 高德异步加载与 React effect 竞态,需等
mapReady再画标记(已修)。
仓库里保留了 deploy/server-sync.sh、server-bootstrap-acl3.sh 和
nginx-icemelt.fun.conf,换机器可复用。更完整的命令清单见项目内
deploy/SERVER.md。