老门轴的博客● 统计中…
← 返回文章列表

从 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)至少应明确配置:

用途协议/端口来源
HTTPTCP 80Internet
HTTPSTCP 443Internet

Azure 的 NSG 会先过滤到达虚拟机的流量;如果同时给子网和网卡绑定了 NSG,流量必须通过两边的规则。

登录服务器后,先更新系统并安装 Nginx:

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y nginx
sudo systemctl enable --now nginx

2. 使用 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
TTL300 秒

@ 表示根域名本身,也就是 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.pem

6. 将 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 的个人静态网站。

参考资料