从 Azure 到 HTTPS:用 Nginx、PW DNS 和 Certbot 搭建个人网站
这篇文章记录一套可复用的搭建思路:一台 Azure Linux 虚拟机负责运行 Nginx,PW DNS 提供域名解析,Hugo 生成静态网页,Certbot 申请并自动续期 Let’s Encrypt 证书。 它适合博客、作品集和文档站。全站没有数据库和常驻应用进程,对小内存服务器很友好。
这篇文章记录一套可复用的搭建思路:一台 Azure Linux 虚拟机负责运行 Nginx,PW DNS 提供域名解析,Hugo 生成静态网页,Certbot 申请并自动续期 Let’s Encrypt 证书。
它适合博客、作品集和文档站。全站没有数据库和常驻应用进程,对小内存服务器很友好。
最终架构
浏览器
↓ HTTPS :443
example.com
↓ A 记录
Azure 公网 IPv4
↓
Azure NSG + Linux 防火墙
↓
Nginx → /srv/blog/public(Hugo 静态文件)本文统一使用示例域名 example.com 与示例目录 /srv/blog/public,发布前请替换为你自己的真实配置。
1. 创建 Azure 虚拟机并收紧入口
在 Azure Portal 创建 Ubuntu LTS 虚拟机后,分配一个静态公网 IPv4。动态 IP 变更会让 A 记录失效;静态 IP 更适合个人网站。
网络安全组(NSG)至少应明确配置:
| 用途 | 协议/端口 | 来源 |
|---|---|---|
| HTTP | TCP 80 | Internet |
| HTTPS | TCP 443 | Internet |
Azure 的 NSG 会先过滤到达虚拟机的流量;如果同时给子网和网卡绑定了 NSG,流量必须通过两边的规则。
登录服务器后,先更新系统并安装 Nginx:
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y nginx
sudo systemctl enable --now nginx2. 使用 Hugo 生成静态网站
Hugo 只在构建时消耗资源,Nginx 最终只是读取 HTML、CSS 和图片。以当前目录为例:
cd ~/blog
hugo --minify构建产物在 ~/blog/public。每次更新文章或主题后,都重新执行一次 hugo --minify 即可。
3. 在 PW DNS 添加 A 记录
在 PW DNS 的域名控制台中添加记录:
| 字段 | 根域名示例 |
|---|---|
| 所属域名 | example.com |
| 记录类型 | A |
| 主机记录 | @ |
| 记录值 | Azure VM 的公网 IPv4 |
| TTL | 300 秒 |
@ 表示根域名本身,也就是 example.com。如果填写 blog,最终访问地址会是 blog.example.com。
这台服务器使用固定公网 IP,因此不需要 DDNS 客户端或 API Token。只有公网 IP 会经常变化时,才需要 DDNS 自动更新 A 记录。DNS Token 应视为密码:不要放进文章、脚本仓库或截图;如果曾泄露,立即在平台撤销并重新生成。
等待解析后可检查:
getent ahostsv4 example.com输出应为你的 Azure 公网 IP。
4. 先让 Nginx 通过 HTTP 提供网站
在 /etc/nginx/sites-available/blog 创建站点配置:
server {
listen 80;
listen [::]:80;
server_name example.com;
root /srv/blog/public;
index index.html;
autoindex off;
location / {
try_files $uri $uri/ =404;
}
}启用并检查配置:
sudo ln -s /etc/nginx/sites-available/blog /etc/nginx/sites-enabled/blog
sudo nginx -t
sudo systemctl reload nginx此时 http://你的域名 必须能从公网访问。Let’s Encrypt 的 HTTP 校验需要 80 端口可达;如果打不开,先检查 NSG、Linux 防火墙、DNS 和 Nginx 根目录。
5. 使用 Certbot 申请免费 HTTPS 证书
Certbot 官方推荐通过 Snap 安装:
sudo snap install certbot --classic
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot申请证书。下面使用 webroot 方式,不让 Certbot 自动改写 Nginx 配置:
sudo certbot certonly --webroot \
-w /srv/blog/public \
-d example.com根据提示填写邮箱并同意条款。成功后,证书通常位于:
/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/privkey.pem6. 将 Nginx 切换为 HTTPS,并保留续期校验路径
将 Nginx 配置更新为下面的形式:
server {
listen 80;
listen [::]:80;
server_name example.com;
location /.well-known/acme-challenge/ {
root /srv/blog/public;
}
location / {
return 301 https://example.com$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com;
root /srv/blog/public;
index index.html;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
location / {
try_files $uri $uri/ =404;
}
}重新加载前务必检查语法:
sudo nginx -t && sudo systemctl reload nginx现在访问 https://example.com,浏览器应显示正常锁标识。
7. 验证自动续期
Let’s Encrypt 证书有效期较短,但 Certbot 会安装定时续期任务。不要只相信“已安装”,应立即做一次模拟验证:
sudo certbot renew --dry-run看到所有模拟续期成功,才说明 DNS、80 端口和 ACME challenge 路径都正确。
8. 基础防护与 DDoS 边界
Nginx 可以降低单 IP 刷请求的影响,例如设置每 IP 请求速率与并发连接上限:
# http 上下文
limit_req_zone $binary_remote_addr zone=per_ip:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=per_ip:10m;
# HTTPS server 上下文
limit_req zone=per_ip burst=30 nodelay;
limit_conn per_ip 20;
client_max_body_size 1m;这类规则能缓解应用层恶意请求,但不能抵御耗尽服务器带宽的大型 DDoS。要获得更强防护,应在 Azure Front Door / Application Gateway WAF 或可信 CDN 前置代理后,再用 NSG 仅允许代理节点访问源站 80/443。
发布清单
- A 记录已解析到固定公网 IP
- Azure NSG 仅放行必要端口
- HTTP 80 可访问,HTTPS 443 可访问
-
nginx -t成功 -
certbot renew --dry-run成功 - 每次更新内容后执行
hugo --minify
完成这些步骤后,你就有了一个资源占用很低、可自动续期 HTTPS 的个人静态网站。