账单应用域名与 HTTPS 配置教程
把现有账单应用接入新域名,让浏览器通过 HTTPS 直接访问,并让证书自动续期。
https://bill.lzlee.xyz/DNS 不保存网页端口。浏览器省略端口时,HTTP 使用 80、HTTPS 使用 443,再由 Nginx 转发到应用的 3000 端口。
| 参数 | 本次使用的值 |
|---|---|
| 主域名 / 子域名 | lzlee.xyz / bill.lzlee.xyz |
| ECS 公网 IP / 地域 | 8.163.117.252 / 广州(cn-guangzhou) |
| 应用目录 / 进程名 | /opt/bills / bills-app |
| 后端配置 / 数据 | /opt/bills/backend/.env/opt/bills/backend/data/db.json |
| Nginx 新站点 | /etc/nginx/sites-available/bill.lzlee.xyz |
| 本次备份目录 | /opt/bills-backups/domain-bill-20261015-122600/ |
连接服务器,检查服务并备份
打开 Windows PowerShell,使用本机已有密钥连接。本次使用的是 bills_ecs.pem;换电脑时应改成你自己的密钥路径。
ssh -i "C:\Users\Lee\.ssh\bills_ecs.pem" root@8.163.117.252登录后执行以下检查。后文标为“服务器”的命令都在这个 SSH 窗口中运行。
pm2 status
curl -fsS http://127.0.0.1:3000/api/health
nginx -t
ss -lntp | grep -E ':(80|443|3000)\b'确认 bills-app 为 online,健康接口返回 "status":"ok"。本机 Nginx 已安装;新服务器如果没有 Nginx,需先安装并启动,再继续配置。
先备份,再修改配置
BACKUP_DIR="/opt/bills-backups/domain-bill-$(date +%Y%m%d-%H%M%S)"
install -d -m 700 "$BACKUP_DIR"
cp -p /opt/bills/backend/.env "$BACKUP_DIR/backend.env"
cp -p /opt/bills/backend/data/db.json "$BACKUP_DIR/db.json"
tar -czf "$BACKUP_DIR/nginx-before.tar.gz" -C /etc nginx
sha256sum /opt/bills/backend/data/db.json "$BACKUP_DIR/db.json"
printf '备份目录:%s\n' "$BACKUP_DIR"两份数据库的校验值应一致;记下输出的备份路径。配置过程中暂停写入新账单,可避免复制文件时数据仍在变化。数据库备份仅作保障,域名切换不需要导入或覆盖数据库。
/opt/bills-backups/domain-bill-20261015-122600/ 内保存了 db.json、backend.env、nginx-before.tar.gz,以及申请证书前的 nginx-before-https.conf。环境配置备份可能含密码,应保留在受限目录。添加 bill 子域名解析
- 登录阿里云控制台,打开“云解析 DNS”,进入
lzlee.xyz的解析设置。 - 选择“添加记录”,按照下表填写,再点击“确定”。
- 新增后检查记录状态为启用,主机记录确实为
bill。
| 填写项 | 填写内容 | 作用 |
|---|---|---|
| 记录类型 | A | 指向 IPv4 地址 |
| 主机记录 | bill | 组合成 bill.lzlee.xyz |
| 解析请求来源 | 默认 / 默认 | 使用默认解析线路 |
| 记录值 | 8.163.117.252 | 本次 ECS 公网 IP |
| TTL | 默认,本次为 600 秒 | 解析缓存时间 |
| 状态 | 启用 | 让记录生效 |
@ 代表根域名 lzlee.xyz,不会生成 bill.lzlee.xyz。应新增主机记录 bill,无需为了添加子域名去修改原来的 @ 记录;记录值也不要填写 http:// 或 :3000。Resolve-DnsName bill.lzlee.xyz -Type A
Resolve-DnsName bill.lzlee.xyz -Type A -Server dns29.hichina.com应看到地址 8.163.117.252。第二条直接查询本域名的阿里云权威 DNS,适合区分“记录填错”和“本地缓存尚未更新”。换域名时应使用该域名自己的权威 DNS。TTL 600 秒不代表所有网络一定恰好十分钟更新完毕。
字段解释参考:阿里云 DNS 记录参数说明。
在 ECS 安全组放行 80 和 443
打开“云服务器 ECS”,切换到广州,找到公网 IP 为 8.163.117.252 的实例。进入该实例实际关联的安全组,在入方向添加规则。
| 填写项 | 本次正确设置 |
|---|---|
| 授权策略 / 优先级 | 允许 / 1 |
| 协议类型 | 自定义 TCP |
| 访问来源 | IPv4:0.0.0.0/0(公开网站允许任意来源访问) |
| 访问目的端口 | HTTP(80) 与 HTTPS(443) |
如果界面一次只能添加一个端口,就分别添加两条允许规则。你提供的下面这张图填写正确,点击“确定”保存即可。
本次服务器的 UFW 为未启用状态,没有改动系统防火墙。以后遇到服务器已启用 UFW 时,先检查状态,再按需允许这两个端口;不需要关闭防火墙。
ufw status仅当 UFW 已启用且未允许网页端口时执行
ufw allow 80/tcp
ufw allow 443/tcp保留已有 SSH 管理规则,避免影响后续登录。
控制台路径与端口说明:阿里云:使用安全组。本次新入口需要 80 / 443,未调整原有 3000 端口的开放情况。
新增 Nginx 站点,转发到原应用
为新域名单独创建一个站点文件,保留服务器原有站点。以下是申请证书前的 HTTP 初始配置。
nano /etc/nginx/sites-available/bill.lzlee.xyz将下方内容粘贴进编辑器,按 Ctrl+O、回车保存,再按 Ctrl+X 退出。
server {
listen 80;
server_name bill.lzlee.xyz;
client_max_body_size 50m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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_read_timeout 310s;
proxy_send_timeout 310s;
}
}server_name 对应新域名,proxy_pass 对应应用实际监听地址。本项目由后端一并提供前端页面和 /api 接口,因此整个站点转发到 3000 即可。
ln -s /etc/nginx/sites-available/bill.lzlee.xyz /etc/nginx/sites-enabled/bill.lzlee.xyz
nginx -t && systemctl reload nginx
curl -fsS -H "Host: bill.lzlee.xyz" http://127.0.0.1/api/health如果提示符号链接已存在,先用 ls -l /etc/nginx/sites-enabled/bill.lzlee.xyz 确认它指向正确文件,不必重复创建。nginx -t 必须成功后才能重载;不要把备份文件放在 sites-enabled 目录,以免被当作有效站点重复加载。
http://bill.lzlee.xyz/api/health 应返回正常状态。先打通 HTTP,再进入第 06 步申请证书。配置语法参考:Nginx 官方反向代理文档。
补充本项目的允许来源
本项目通过后端 .env 中的 FRONTEND_URL 维护允许来源列表。编辑该文件,在原值末尾补充新地址,使用英文逗号分隔,不要覆盖文件内其他设置。
nano /opt/bills/backend/.env下面是本次最终保留的完整来源值。其中包含此前已有的历史地址;以后部署其他应用时,保留该应用自己的原值,再添加新域名的 HTTP / HTTPS 来源即可。
FRONTEND_URL=http://localhost:5173,http://8.163.128.126:3000,http://bill.lzlee.xyz,https://bill.lzlee.xyz,http://bill.lzlee.xyz:3000,http://lzlee.xyz:3000pm2 restart bills-app --update-env
pm2 status本次前端接口地址使用相对路径 /api,无需重新构建前端。如果其他项目把旧 IP 或域名写死在前端配置里,则需要同时修改接口地址并重新构建。FRONTEND_URL 是本项目的变量名,不是所有程序都通用。
同源访问通常不依赖跨域放行,但本次仍同步补全项目的来源配置,以保持跨域调用的响应一致;允许来源不代替账号登录验证。
申请 HTTPS 证书并自动跳转
开始前确认新域名已经指向本服务器,公网 80 端口可达,Nginx 的 server_name 正确。这里使用 Certbot 的 Nginx 插件完成证书验证和站点配置。
cp -p /etc/nginx/sites-available/bill.lzlee.xyz "$BACKUP_DIR/nginx-before-https.conf"BACKUP_DIR 由第 01 步创建。若重新打开了 SSH 窗口,先将它重新设为当次实际备份目录。
apt-get update
apt-get install -y --no-install-recommends certbot python3-certbot-nginx以后自行配置时,建议用交互方式申请;按提示填写你自己的联系邮箱、同意服务条款。
certbot --nginx --cert-name bill.lzlee.xyz -d bill.lzlee.xyz --redirect--redirect 会启用 HTTP 到 HTTPS 的跳转。成功后 Certbot 会修改已有站点,添加 443 监听及证书路径,保留到 127.0.0.1:3000 的转发配置。
查看这次实际使用的非交互申请命令
这次没有配置联系邮箱,使用了下面的命令;下次自行配置推荐使用上面的交互方式。
certbot --nginx --cert-name bill.lzlee.xyz -d bill.lzlee.xyz --non-interactive --agree-tos --register-unsafely-without-email --redirect| 生成内容 | 本次路径 |
|---|---|
| 证书链 | /etc/letsencrypt/live/bill.lzlee.xyz/fullchain.pem |
| 证书私钥 | /etc/letsencrypt/live/bill.lzlee.xyz/privkey.pem |
| 续期配置 | /etc/letsencrypt/renewal/bill.lzlee.xyz.conf |
申请、Nginx 插件与续期说明:Certbot 官方使用文档。
从公网和浏览器确认结果
回到 Windows PowerShell,依次检查跳转、证书与接口。这里使用 curl.exe,避免 Windows 中同名命令别名带来的差异。
curl.exe -I http://bill.lzlee.xyz/
curl.exe -I https://bill.lzlee.xyz/
curl.exe https://bill.lzlee.xyz/api/health
curl.exe -i -H "Origin: https://bill.lzlee.xyz" https://bill.lzlee.xyz/api/health| 检查项 | 正确结果 |
|---|---|
| HTTP 首页 | 301,Location 指向 HTTPS |
| HTTPS 首页 | 正常响应,证书校验无报错;本项目页面可能进一步跳转到登录页 |
| 健康接口 | HTTP 200,JSON 含 "status":"ok" |
| 来源响应 | Access-Control-Allow-Origin: https://bill.lzlee.xyz |
| 浏览器页面 | 最终进入 https://bill.lzlee.xyz/login,输入框、样式、按钮正常 |
本次已经完成的验证
桌面 1366 × 900 与手机 390 × 844 两种窗口都能进入登录页。证书校验、健康接口、来源响应正常,页面未出现 JavaScript 错误。
域名改变后,原网站的登录状态不会自动转移。使用原账号在新域名重新登录即可。
本次检查到登录页面和接口为止,没有使用真实账号提交登录,也没有新增或修改账单。右侧是迁移完成后的手机页面截图。
你以后复现时的验收清单
检查证书自动续期
本次已确认 certbot.timer 为启用且运行状态,续期配置使用 Nginx 插件。无需再额外添加一套重复的定时任务。
certbot certificates
systemctl is-enabled certbot.timer
systemctl is-active certbot.timer
systemctl list-timers --all certbot.timer预期可看到证书信息、enabled、active 和下次触发时间。如果定时器尚未启用,再执行 systemctl enable --now certbot.timer。
以后可补做一次续期模拟
certbot renew --dry-run这条命令用测试环境检查续期流程,不会替换当前正式证书。本次没有运行续期模拟;“定时器已启用”与“未来每一次续期都成功”是两个不同的检查结果。
certbot certificates 的实时结果为准。维护时保留域名正确解析和公网 80 端口可达,便于当前验证方式继续工作。journalctl -u certbot.service --since "7 days ago" --no-pager
tail -n 80 /var/log/letsencrypt/letsencrypt.log
tail -n 80 /var/log/nginx/error.log
pm2 logs bills-app --lines 60 --nostream打不开时,按现象定位
| 现象 | 优先检查 | 下一步 |
|---|---|---|
| 找不到域名 / IP 错误 | 主机记录是否填成 @、记录是否启用、本地是否有缓存 | 查询普通 DNS 和权威 DNS;必要时更新本机 DNS 缓存 |
| 连接一直超时 | 正确实例的安全组、系统防火墙、80 / 443 是否监听 | 云端规则和服务器本机检查结合判断,不只看 DNS |
| 显示 Nginx 默认页 | server_name、启用链接、重复站点 | 用带 Host 的本机请求验证,查看有效配置后重载 |
| 502 Bad Gateway | 3000 端口、PM2 状态、后端健康接口 | 先让 127.0.0.1:3000 正常,再查代理 |
| 页面有但接口报错 | 接口是否仍写死旧地址、来源配置、应用日志 | 检查浏览器网络请求,区分跨域错误、404 和后端错误 |
| 证书验证失败 | 域名是否指对 IP、80 是否可达、Nginx 是否命中正确站点 | 先完成普通 HTTP 的外网验证,再申请证书 |
| 申请时 ACME 连接超时 | 服务器访问签发机构的出站网络 | 检查 ACME 接口连通后重试,避免连续重复签发 |
| 新域名要求重新登录 | 域名更换后的正常登录状态隔离 | 使用原账号登录,不要因此重建数据库 |
DNS 还没更新,先测服务器本身
curl.exe --resolve bill.lzlee.xyz:80:8.163.117.252 -I http://bill.lzlee.xyz/
curl.exe --resolve bill.lzlee.xyz:443:8.163.117.252 https://bill.lzlee.xyz/api/health第二条需要已经签发匹配域名的证书。--resolve 仅对本次请求指定 IP,不修改电脑的 DNS;证书仍照常校验。
服务器端进一步检查
nginx -t
ls -l /etc/nginx/sites-enabled/
ss -lntp | grep -E ':(80|443|3000)\b'
curl -fsS http://127.0.0.1:3000/api/health
curl -I --connect-timeout 5 --max-time 10 https://acme-v02.api.letsencrypt.org/directory本次申请证书曾出现一次 ACME 请求超时,后续重试成功;没有通过关闭证书校验来绕过问题。
只回退相关配置,保留账单数据
本次采用独立站点文件,原有 Nginx 站点仍保留。若要撤销这次新增入口,可以停用新站点,再恢复本次备份的后端环境配置。
BACKUP_DIR="/opt/bills-backups/domain-bill-20261015-122600"
test -f "$BACKUP_DIR/backend.env" && echo "环境配置备份存在"
ls -l /etc/nginx/sites-enabled/bill.lzlee.xyz确认文件存在、上述链接指向本次新站点后,再按顺序执行:
unlink /etc/nginx/sites-enabled/bill.lzlee.xyz
cp -p "$BACKUP_DIR/backend.env" /opt/bills/backend/.env
pm2 restart bills-app --update-env
nginx -t && systemctl reload nginx这不会删除证书、应用或数据库。若只是申请证书失败、准备继续使用普通 HTTP,可以在备份路径确认正确的前提下,将 nginx-before-https.conf 恢复到对应站点文件,再校验并重载 Nginx。
DNS 是控制台中的独立设置;是否恢复旧域名解析,要另外检查原记录。最终检查时 lzlee.xyz 根域名已没有返回 A 记录,因此不能假定旧网址此刻仍可直接访问。
db.json。覆盖旧数据库可能丢失备份之后新增的账单。换一个域名,重点替换这些值
| 项目 | 当前示例 | 下次怎么改 |
|---|---|---|
| 完整域名 | bill.lzlee.xyz | 同步修改 DNS、server_name、允许来源、证书命令和验证地址 |
| DNS 主机记录 | bill | 只填子域名前缀;主域名在对应解析区域中选择 |
| 服务器 IP | 8.163.117.252 | 使用目标实例当前公网 IP;确认地域和安全组 |
| 应用端口 | 3000 | 改为程序实际监听端口,同时更新 proxy_pass 和本机检查 |
| 应用路径 / 进程名 | /opt/bills / bills-app | 使用实际目录、环境文件、数据文件和 PM2 进程 |
| SSH 密钥 / 备份 | 本机 pem / 当次时间戳目录 | 使用自己的密钥,并为每次操作新建备份 |
推荐顺序:确认应用正常 → 备份 → 添加解析 → 放行 80 / 443 → 配置 HTTP 转发 → 更新应用来源 → 确认 HTTP 可达 → 申请 HTTPS → 验证页面与接口 → 检查自动续期。
如果只是给现有账单应用换一个入口,通常无需重装 Node、重新创建数据库或重新部署整个前端。若是另一套应用,应先完成它自己的部署,再套用域名入口配置。