在阿里云ECS上部署个人博客记录
1227 字
7 分钟
| 配置项 | 说明 |
|---|---|
| 操作系统 | Ubuntu 24.04 LTS |
| Git |
安装命令:sudo apt install git -y验证安装: git --version
|
| Node.js |
安装命令:curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install -y nodejs验证安装: node -v 和 npm -v
|
| pnpm |
安装命令:npm install -g pnpm验证安装: pnpm -v
|
| Nginx |
安装命令:sudo apt install nginx -y启动Nginx: sudo systemctl start nginx开机自启: sudo systemctl enable nginx验证安装:访问服务器IP地址,看到Nginx欢迎页面 |
如果是私有仓库,使用SSH方式克隆:
ssh-keygen -t ed25519 -C "your_email@example.com"# 将 ~/.ssh/id_ed25519.pub 添加到 GitHub SSH Keysgit clone git@github.com:your-username/your-blog-repo.git构建博客:
cd your-blog-repopnpm installpnpm build将构建输出目录(通常是 dist 或 build)复制到Nginx的根目录:
sudo cp -r dist/* /var/www/html/编辑Nginx配置文件:
sudo nano /etc/nginx/sites-available/astro-blog添加以下内容,注意替换域名和路径:
server { listen 80; listen [::]:80;
# 替换为你的域名(或公网 IP) server_name your-domain.com www.your-domain.com;
# Astro 构建输出目录(与部署脚本中的 WEB_ROOT 一致) root /var/www/html; index index.html;
# 开启 gzip 压缩(可选但推荐) gzip on; gzip_vary on; gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml application/rss+xml image/svg+xml;
# 支持 SPA / 静态路由(Astro 默认是静态页面,但若用了客户端路由需此配置) location / { try_files $uri $uri/ =404; }
# 安全:隐藏 Nginx 版本号(可选) server_tokens off;}启用配置并重启Nginx:
# 创建符号链接以启用站点sudo ln -s /etc/nginx/sites-available/astro-blog /etc/nginx/sites-enabled/# 删除默认配置以避免冲突sudo rm /etc/nginx/sites-enabled/default# 测试配置是否正确sudo nginx -t# 重启 Nginx 以应用更改sudo systemctl restart nginx此时,访问你的域名或公网IP地址,应该能看到你的博客页面。(注意调整阿里云安全组规则,开放80端口)
购买域名后,在域名服务商处将域名解析到ECS实例的公网IP地址。
使用Certbot获取免费的SSL证书:
sudo apt install certbot python3-certbot-nginx -ysudo certbot --nginx -d your-domain.com -d www.your-domain.comCertbot会自动设置续期任务,但可以手动测试续期:
sudo certbot renew --dry-run使用GitHub Webhooks和一个简单的部署脚本,实现代码更新后自动部署:(使用 Node.js 和 Express)
# 选择一个目录存放部署脚本# 安装必要的包pnpm add express body-parser# 创建 deploy.js 文件nano deploy.js创建 deploy.js 文件,内容如下:
const express = require('express');const crypto = require('crypto');require('dotenv').config();const { exec } = require('child_process');
const app = express();const PORT = process.env.PORT || 3333; // 监听端口const SECRET = 'secreforwebhook'; // 替换为你的 Webhook 密钥const REPO_PATH = '/home/rinne/blog'; // 替换为你的博客仓库路径const BRANCH = 'main';
app.use(express.raw({ type: 'application/json' }));
app.post('/webhook', (req, res) => { const signature = req.headers['x-hub-signature-256']; const payload = req.body; // 这是 Buffer
if (!signature) { return res.status(400).send('Missing signature'); }
const expectedSignature = 'sha256=' + crypto.createHmac('sha256', SECRET) .update(payload) .digest('hex');
if (signature !== expectedSignature) { console.log('❌ 签名无效'); return res.status(401).send('Unauthorized'); }
let event; try { event = JSON.parse(payload.toString()); } catch (e) { return res.status(400).send('Invalid JSON'); }
if (event.ref === `refs/heads/${BRANCH}`) { console.log('✅ 触发部署...'); exec(`cd ${REPO_PATH} && ./deploy.sh`, (error, stdout, stderr) => { if (error) { console.error('部署失败:', stderr); return res.status(500).send('Deploy failed'); } console.log('部署成功:', stdout); res.status(200).send('OK'); }); } else { res.status(200).send('Ignored'); }});
app.get('/', (req, res) => { res.send('Webhook service OK');});
app.listen(PORT, '0.0.0.0', () => { console.log(`🚀 Webhook 服务运行在 http://0.0.0.0:${PORT}`);});启动服务(建议用 PM2 守护):
pnpm add -g pm2pm2 start deploy.js --name "blog-webhook"pm2 startuppm2 save使用 Nginx 反向代理部署脚本:
sudo nano /etc/nginx/sites-available/webhook添加以下内容:
server { listen 3333; server_name your-domain.com; # 👈 替换成你的域名
# 禁止直接访问根路径(可选) location = / { return 403; }
# Webhook 路由 location /webhook { proxy_pass http://localhost:3333; # 转发到你的 Node.js 服务 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; }
# 可选:隐藏服务器信息 server_tokens off;}在GitHub仓库中设置Webhook,指向 http://your-domain.com/deploy,选择 application/json 作为内容类型。
完成以上步骤后,每次推送代码到GitHub时,ECS实例上的博客将自动更新。
# 启动 Nginxsudo systemctl start nginx# 停止 Nginxsudo systemctl stop nginx# 重启 Nginxsudo systemctl restart nginx# 重新加载配置(不停止服务)sudo systemctl reload nginx# 查看 Nginx 状态sudo systemctl status nginx# 测试 Nginx 配置是否正确sudo nginx -tNginx 配置文件路径:/etc/nginx/available/ 和 /etc/nginx/sites-enabled/,分别是可用站点和已启用站点的配置目录。
# 启动应用pm2 start app.js --name "my-app"# 停止应用pm2 stop my-app# 重启应用pm2 restart my-app# 查看应用状态pm2 status# 查看应用日志pm2 logs my-app# 设置开机自启pm2 startup# 保存当前进程列表pm2 save# 删除应用pm2 delete my-app