🧩 第02章 · 上线一个新网站
域名→DNS→证书→Nginx→systemd→MySQL
上线一个新网站¶
以 bangdream.xyz 为例,把「一个域名 + 一个 Node.js 后端 + 一个 MySQL 数据库」从零跑成一个公网可访问的 HTTPS 网站。这条链路是把上一章的裸机接上互联网的第一次实战。
本章目标:域名 → DNS → 证书 → Nginx → systemd → MySQL → 定时任务,每一步都有命令、验证点和易错点。
0. 准备:确认你已经有的¶
# 服务器公网 IP(假设 192.168.1.100)
ip -4 addr | grep 'inet ' | grep -v '127.0.0.1'
# 确认已经初始化(上一章内容)
sudo ls /var/www/sites-available
1. 域名解析(DNS)¶
在域名注册商后台,把 bangdream.xyz 添加 A 记录指向服务器 IP。
| 记录类型 | 主机记录 | 指向值 | TTL |
|---|---|---|---|
| A | @ | 192.168.1.100 | 600 |
| A | www | 192.168.1.100 | 600 |
等 DNS 生效后本地验证:
# 用系统解析查询(dig/nslookup 需先装 dnsutils)
dig +short bangdream.xyz
# 或用 nslookup
nslookup bangdream.xyz | grep Address
⚠️ 易错:DNS 缓存。改了记录立即
dig可能还是旧 IP,CDN/递归服务器有 TTL 缓存,等几分钟或用dig @8.8.8.8 bangdream.xyz强制走公共 DNS 验证。
2. 云防火墙放行 80/443¶
服务器内的 ufw 是一层,云控制台安全组是另一层,两层都要放行。
# 服务器内防火墙
sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw status
🔒 安全:云安全组没放行 80/443,
curl就会Connection refused或timeout——这是新站最常见「为什么访问不了」的原因之一。先把安全组放行再排查。
3. 安装 Nginx 并写站点配置¶
sudo apt update && sudo apt install -y nginx
sudo systemctl enable --now nginx && systemctl status nginx --no-pager | head -5
⚠️ 易错:Ubuntu 默认就启用了
/etc/nginx/sites-enabled/default,会抢占 80 端口。新站点配好后应rm /etc/nginx/sites-enabled/default(或保留默认但确保 server_name 不冲突)。
写站点配置文件:
# /etc/nginx/sites-available/bangdream.xyz.conf
server {
listen 80;
listen [::]:80;
server_name bangdream.xyz www.bangdream.xyz;
# 跳转 HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name bangdream.xyz www.bangdream.xyz;
# 证书路径(certbot 会填这里,见第 4 步)
ssl_certificate /etc/letsencrypt/live/bangdream.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bangdream.xyz/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# 静态资源或 Node 后端,统一走反向代理到 127.0.0.1:3000
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
}
# 软链到 sites-enabled 并测试语法
sudo ln -s /etc/nginx/sites-available/bangdream.xyz.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
⚠️ 易错:改完 Nginx 配置必须
nginx -t通过再reload。写错一个分号或括号,reload会导致 Nginx 全站服务中断甚至起不来。
4. 用 certbot 签发 HTTPS 证书¶
sudo apt install -y certbot python3-certbot-nginx
# 先确保 80 端口正常响应,再签证书(自动改 nginx 配置)
sudo certbot --nginx -d bangdream.xyz -d www.bangdream.xyz --email admin@bangdream.xyz --agree-tos --no-eff-email
| 验证点 | 命令 | 预期 |
|---|---|---|
| 证书到期 | sudo certbot certificates |
显示 90 天有效期 |
| 自动续期 | sudo certbot renew --dry-run |
成功续约 |
| HTTPS 可达 | curl -I https://bangdream.xyz |
HTTP/2 200 |
⚠️ 易错:
--nginx模式会自动改你的站点配置并可能覆盖手写内容。若证书签发失败常见原因是「80 端口 443 端口没通」或「DNS 未指向本机」。续期依赖 80/443 可达,别为了省事关掉 80。
5. 用 systemd 托管 Node.js 后端¶
假设你已经把 server.js 放到 /opt/apps/site。
sudo mkdir -p /opt/apps/site
# 示例: 你的 Node 应用入口 /opt/apps/site/server.js,监听 127.0.0.1:3000
# /etc/systemd/system/bangdream-site.service
[Unit]
Description=BangDream site backend
After=network.target mysql.service
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/apps/site
ExecStart=/usr/local/bin/node server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now bangdream-site
systemctl status bangdream-site --no-pager
# 本机验证后端可直接响应
curl -I http://127.0.0.1:3000
⚠️ 易错:
ExecStart要写绝对路径(/usr/local/bin/node),WorkingDirectory决定node server.js找文件的位置。用Restart=always后进程崩溃会自动拉起,但要验证journalctl -u bangdream-site -f看真实报错。
6. 建 MySQL 数据库和用户¶
sudo apt install -y mysql-server
sudo systemctl enable --now mysql
# 以 root 进入(新装默认 auth_socket,可无密码 sudo mysql)
sudo mysql
CREATE DATABASE bangdream DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'bangdream_app'@'localhost' IDENTIFIED BY '强密码';
GRANT ALL PRIVILEGES ON bangdream.* TO 'bangdream_app'@'localhost';
FLUSH PRIVILEGES;
SHOW DATABASES;
| 验证点 | 命令 | 预期 |
|---|---|---|
| 数据库存在 | mysql -e "SHOW DATABASES" |
含 bangdream |
| 用户可连 | mysql -u bangdream_app -p -e "SELECT 1" |
成功返回 |
| 应用连接 | 后端测试查询 | 正常读写 |
🔒 安全:应用用专用低权限用户(只对
bangdream.*授权),不要用 root。数据库只监听127.0.0.1(bind-address),不要暴露到公网。
7. 定时任务:备份与巡检¶
用 cron 每天备份数据库并做一个简单巡检。
crontab -e
# 每天 02:30 备份数据库
30 2 * * * /usr/local/bin/backup-db.sh >> /var/log/cron-backup.log 2>&1
# 每 10 分钟探活一次网站并记录结果
*/10 * * * * curl -sf https://bangdream.xyz > /dev/null || echo "$(date) DOWN" >> /var/log/site-health.log
# 写一个最小备份脚本
sudo tee /usr/local/bin/backup-db.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
DB=bangdream; DIR=/srv/backup/db
mkdir -p "$DIR"
mysqldump -u bangdream_app -p'强密码' "$DB" | gzip > "$DIR/${DB}-$(date +%F).sql.gz"
find "$DIR" -name "*.sql.gz" -mtime +7 -delete
EOF
sudo chmod +x /usr/local/bin/backup-db.sh
# 手动触发一次并验证备份文件生成
sudo /usr/local/bin/backup-db.sh && ls -lh /srv/backup/db/
8. 上线完成清单¶
| # | 验证点 | 命令 | 预期 |
|---|---|---|---|
| 1 | DNS 已解析 | dig bangdream.xyz |
返回服务器 IP |
| 2 | 防火墙放行 | curl -I http://bangdream.xyz |
可见 nginx |
| 3 | HTTPS 证书 | curl -I https://bangdream.xyz |
HTTP/2 200 |
| 4 | 后端存活 | systemctl status bangdream-site |
active (running) |
| 5 | 数据库连通 | 应用正常读写 | 无报错 |
| 6 | 定时任务 | crontab -l |
两条任务在列 |
| 7 | 备份成功 | ls /srv/backup/db |
当天 .sql.gz 存在 |
一条命令总验证:
curl -sI https://bangdream.xyz | head -3 \
&& systemctl is-active bangdream-site \
&& ls /srv/backup/db | tail -1 \
&& sudo certbot certificates | grep 'VALID'
bangdream.xyz 已上线——域名、证书、Nginx、后端、数据库、定时任务全部打通。下一章在这个基础上搭建自托管 GitLab(gitlab.bangdream.xyz)。