#需求拆解

个人博客,日均几百 PV,偶尔发个技术文章带点图。需求非常朴素:

  • 能跑起来,不折腾
  • 打开要快
  • 别三天两头挂

按这个标准,配置可以很克制。

#服务器选型

最终选了 2 核 2G,理由不是"够用",而是过剩的部分没有意义:

项 需要的 实际开销
Nginx 静态服务 < 20MB 约 12MB
构建产物(静态文件) 0 内存 占用磁盘
系统 + SSH 约 120MB 120MB

也就是说,2G 内存里有 1.8G 是空着的。但空着不花钱,翻倍要钱,这个账很好算。

#内存优化:Swap 是必需品

2G 物理内存跑 Ubuntu,建议加 2GB Swap:

fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

它不是拿来当内存用的,是防止突发占用直接触发 OOM Killer 把服务杀掉 —— 宁可慢,别挂。

#Nginx 配置要点

静态站 + 反向代理后端,核心就四块:

server {
    listen 80;
    server_name sqhstudio.com.cn www.sqhstudio.com.cn;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name sqhstudio.com.cn www.sqhstudio.com.cn;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/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_session_cache   shared:SSL:10m;

    gzip on;
    gzip_types text/css application/javascript application/json image/svg+xml;
    gzip_min_length 1k;

    root /var/www/sqhstudio;
    index index.html;

    location / {
        try_files $uri $uri/ $uri.html /index.html;
        expires 7d;
    }

    # 带 hash 的资源可以长期缓存
    location ~* \.(js|css|woff2|jpg|png|svg|webp)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

几个容易踩的点:

  1. try_files 末尾要兜底到 /index.html —— 前端路由刷新时不加这行会 404
  2. gzip 别把图片也压了 —— 白费 CPU
  3. 静态资源长缓存 + HTML 不缓存 —— 否则更新了前端用户看不到

#HTTPS 证书

用 Let's Encrypt 的 Certbot,三分钟搞定:

certbot certonly --standalone -d sqhstudio.com.cn -d www.sqhstudio.com.cn

certbot 会自动写好续期定时任务,只要在续期前后跑一次 nginx -s reload 即可。

cat > /etc/cron.d/certbot-renew <<'EOF
0 3 * * 0 root certbot renew --quiet --post-hook "systemctl reload nginx"
EOF

#目录权限

mkdir -p /var/www/sqhstudio
chown -R www-data:www-data /var/www/sqhstudio
chmod -R 755 /var/www/sqhstudio

不要给 777。 静态文件是只读的,网站进程能读就够。

#部署流程定型

最后固化成三条命令:

node build.js              # 本地构建
rsync -avz --delete dist/ user@host:/var/www/sqhstudio/   # 同步
ssh user@host 'nginx -t && systemctl reload nginx'        # 重载

--delete 保证服务器上不会有残留的旧文件 —— 这是最容易被忽略但最容易出「幽灵 bug」的地方。

#收尾检查清单

  • 域名 A 记录指向服务器公网 IP
  • 安全组只放行 22 / 80 / 443
  • SSH 禁用密码登录,改用密钥
  • 配置 Swap
  • 开启 gzip
  • 证书签发成功,HTTPS 正常
  • www 301 跳转到主域名
  • 页面在手机上看排版正常
  • RSS 订阅能正常拉到内容

这个清单每次上线前过一遍,能省掉很多「上线后才发现」的问题。