Nginx结合Certbot SSL证书配置指南 (Ubuntu 24.04)

本文档旨在提供一个全面的指南,介绍如何在 Ubuntu 24.04 服务器上使用 Nginx 设置反向代理(以 Emby 为例),并通过 Certbot 获取和管理 Let’s Encrypt 免费 SSL 证书,实现 HTTPS 安全访问。

1.1 前提条件

  • Ubuntu 24.04 LTS 服务器: 拥有 sudo 权限。

  • 域名: 拥有一个域名,并且其 DNS A 或 AAAA 记录已指向服务器公网 IP 地址。

  • 防火墙配置: 服务器防火墙(如 ufw)已允许外部访问 TCP 端口 80 (HTTP) 和 443 (HTTPS)。

    1
    2
    sudo ufw allow 'Nginx Full' # 或者分别允许 80 和 443
    sudo ufw reload

1.1.1 步骤一:安装 Nginx

1
sudo apt update && sudo apt install nginx

目前通过该方式安装 Nginx,Nginx 配置默认都是采用配置分离的方式,即 Nginx 推荐的最佳实践。我们只需要在 /etc/nginx/sites-available/ 中新增自己的站点配置,并建立软链接到 /etc/nginx/sites-enabled/ 即可。

1.1.2 Nginx 配置分离介绍

为了便于管理,Nginx 配置通常采用分离的方式。主配置文件 nginx.conf (通常在 /etc/nginx/) 会通过 include 指令加载其他目录下的配置文件。常见的做法有:

  • /etc/nginx/conf.d/*.conf: 任何在此目录下的 .conf 文件都会被加载。
  • /etc/nginx/sites-available//etc/nginx/sites-enabled/:
    • sites-available/ 中创建站点配置文件。

    • 通过在 sites-enabled/ 中创建指向 sites-available/ 中文件的符号链接来启用站点。

      1
      sudo ln -s /etc/nginx/sites-available/your-site.conf /etc/nginx/sites-enabled/your-site.conf

1.2 步骤二:安装 Certbot 及 Nginx 插件

1
2
3
4
sudo apt update && sudo apt install certbot python3-certbot-nginx

# 检查安装是否成功
certbot --version

1.3 步骤三:为域名申请证书

1.3.1 还没进行 Nginx 配置

1
sudo certbot --nginx -d emby.yourdomain.com --cert-name yourdomain.com
  • --nginx: 使用 Nginx 插件进行验证和安装。
  • -d emby.yourdomain.com: 指定要为其申请证书的域名。
  • --cert-name yourdomain.com: 关键参数。告诉 Certbot 使用或创建一个名为 yourdomain.com 的证书。这样,证书文件会存放在 /etc/letsencrypt/live/yourdomain.com/,与 Nginx 配置匹配。

回车后,Certbot 会引导:

  1. 输入邮箱地址。
  2. 同意服务条款。
  3. 选择是否将 HTTP 流量自动重定向到 HTTPS (推荐)。

过程中,Certbot 会:

  1. 检查名为 yourdomain.com 的证书是否存在。
  2. 确保 emby.yourdomain.com 被包含在该证书中(如果不存在则添加,如果证书本身不存在则创建)。
  3. 通过 Nginx 插件进行域名验证。
  4. 成功后,将证书文件保存在 /etc/letsencrypt/live/yourdomain.com/
  5. 自动更新 Nginx 配置中开放了 80 端口的站点配置中的 443 Server,并设置自动续期。即如果是刚安装的 Nginx,那么默认会更新 /etc/nginx/sites-available/default

执行完 Certbot 命令后,证书已经保存下来,最后根据模板对自己需要的站点配置进行定制即可。可以结合被自动修改过的 /etc/nginx/sites-available/default

建议让 AI 协助生成和优化,非常方便。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# /etc/nginx/sites-available/emby.conf

server {
listen 80;
listen [::]:80;
server_name emby.yourdomain.com;

# Let's Encrypt 续期验证需要
location /.well-known/acme-challenge/ {
root /var/www/html;
}

location / {
return 301 https://$host$request_uri;
}
}

# 3. HTTPS 服务配置
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name emby.yourdomain.com;

# SSL 证书路径 (由 Certbot 自动生成)
ssl_certificate /etc/letsencrypt/live/emby.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/emby.yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf; # Certbot 推荐的 SSL 安全配置
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Certbot 推荐的 DH 参数

# 其他配置...
}

1.3.2 已有 Nginx 配置

如果已经有 Nginx 配置了,那么需要在对应的站点配置上确保有如下监听 80 端口的 Server,例如:/etc/nginx/sites-available/emby.conf 中确保有以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# /etc/nginx/sites-available/emby.conf

server {
listen 80;
listen [::]:80;
server_name emby.yourdomain.com;

# Let's Encrypt 续期验证需要
location /.well-known/acme-challenge/ {
root /var/www/html;
}

location / {
return 301 https://$host$request_uri;
}
}

接着再执行 Certbot 命令:

1
sudo certbot --nginx -d emby.yourdomain.com --cert-name yourdomain.com

执行后,Certbot 会自动在 站点配置中的 443 Server 中生成例如以下的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# /etc/nginx/sites-available/emby.conf

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name emby.yourdomain.com;

# SSL 证书路径 (由 Certbot 自动生成)
ssl_certificate /etc/letsencrypt/live/emby.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/emby.yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf; # Certbot 推荐的 SSL 安全配置
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Certbot 推荐的 DH 参数

# 其他配置。。。
}

1.3.3 完整的配置示例:Emby

假设 Emby 运行在 http://127.0.0.1:8096,期望通过 https://emby.yourdomain.com 访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# /etc/nginx/sites-available/emby.conf

# HTTP 重定向到 HTTPS
server {
listen 80;
listen [::]:80;
server_name emby.yourdomain.com; ## 需要修改 ##: 替换为你的域名

# Certbot ACME challenge
location ~ /.well-known/acme-challenge/ {
allow all;
root /var/www/html; # Certbot 默认的 webroot 或你指定的路径
}

location / {
return 301 https://$host$request_uri;
}
}

# HTTPS & 反向代理配置
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name emby.yourdomain.com; ## 需要修改 ##: 替换为你的域名

# SSL 证书配置 (Certbot 会自动管理)
ssl_certificate /etc/letsencrypt/live/emby.yourdomain.com/fullchain.pem; ## 需要修改 ##
ssl_certificate_key /etc/letsencrypt/live/emby.yourdomain.com/privkey.pem; ## 需要修改 ##
include /etc/letsencrypt/options-ssl-nginx.conf; # Certbot 推荐的 SSL 安全配置
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

# 增强 SSL 安全性
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# 日志
access_log /var/log/nginx/emby.access.log;
error_log /var/log/nginx/emby.error.log;

location / {
proxy_pass http://127.0.0.1:8096; ## 需要修改 ##: Emby 实际 IP 和 HTTP 端口

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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;

# WebSocket 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

proxy_buffering off;
proxy_connect_timeout 300;
proxy_send_timeout 3600s;
proxy_read_timeout 3600s;
send_timeout 3600s;
client_max_body_size 0;
}
}

启用配置:

1
sudo ln -s /etc/nginx/sites-available/emby.conf /etc/nginx/sites-enabled/

1.3.4 理解 SSL 证书与 Certbot

1.3.4.1 如何确认是否使用了 Certbot?

  1. 检查 Certbot 命令: certbot --versionwhich certbot
  2. 检查 Let’s Encrypt 目录: ls -l /etc/letsencrypt/。如果存在 live, archive, renewal 等子目录,则很可能使用 Certbot。
  3. 检查 Nginx 配置: ssl_certificatessl_certificate_key 指令是否指向 /etc/letsencrypt/live/yourdomain.com/fullchain.pemprivkey.pem
  4. 检查自动续期任务:
    • Systemd Timers: systemctl list-timers | grep certbot
    • Cron Jobs: ls -l /etc/cron.d/certbotsudo crontab -l

1.3.4.2 SSL 证书一般放置位置

  • /etc/letsencrypt/ (由 Certbot 管理):
    • live/yourdomain.com/fullchain.pem: 完整的证书链(推荐使用)。
    • live/yourdomain.com/privkey.pem: 私钥。
    • live 目录下的文件是符号链接,指向 archive 目录中的最新版本。
  • /etc/ssl/certs//etc/ssl/private/ (Debian/Ubuntu 传统位置): 用于非 Certbot 管理的证书。
  • /etc/pki/tls/certs//etc/pki/tls/private/ (RHEL/CentOS 传统位置)。

始终通过检查 Nginx 配置文件中的 ssl_certificatessl_certificate_key 指令来确定实际使用的证书路径。

1.4 步骤四:验证与维护

1.4.1 测试 Nginx 配置

1
sudo nginx -t

确保输出 syntax is oktest is successful

1.4.2 重载 Nginx 服务

1
sudo systemctl reload nginx

1.4.3 验证 Certbot 自动续期

Certbot 包通常会自动设置 systemd timer 或 cron job 来处理续期。

模拟续期(不会真正续期,仅测试配置):

1
sudo certbot renew --dry-run

查看 systemd timer:

1
systemctl list-timers | grep certbot

1.5 步骤五:安全增强 (HSTS)

在确认 HTTPS 完全正常工作后,可以考虑在 Nginx 的 HTTPS server 块中添加 HSTS (HTTP Strict Transport Security) 头,强制浏览器始终使用 HTTPS 访问:

1
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

注意: 启用 HSTS 后,如果 SSL 配置出现问题,用户可能在 max-age 时间内无法通过 HTTP 访问你的站点。请谨慎操作,并确保 SSL 证书自动续期正常工作。