强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Certbot 证书自动化教程 / 第 3 章:Standalone 模式

第 3 章:Standalone 模式

3.1 Standalone 模式概述

Standalone(独立)模式是 Certbot 最简单的验证方式。Certbot 自身启动一个临时的 HTTP 服务器监听 80 端口,用于完成 ACME HTTP-01 验证挑战。

工作原理

┌───────────────────────┐
│     Certbot 进程       │
│                       │
│  临时 HTTP 服务器      │
│  (监听 80 端口)       │
│                       │
│  /.well-known/        │
│  acme-challenge/      │
│  └── <token>          │
└───────────┬───────────┘
            │
            │ Let's Encrypt 服务器请求验证
            │ GET http://example.com/.well-known/acme-challenge/<token>
            │
            ▼
    验证通过 → 签发证书

适用场景

场景是否适合原因
首次申请证书✅ 非常适合无需现有 Web 服务器
服务器尚未部署✅ 非常适合Certbot 自带 HTTP 服务器
Nginx/Apache 未运行✅ 适合不依赖现有服务
Nginx/Apache 正在运行❌ 不适合80 端口冲突
防火墙封锁 80 端口❌ 不适合无法接收验证请求

3.2 基本使用

前提条件

# 确认 80 端口未被占用
sudo ss -tlnp | grep :80

# 如果 Nginx 或 Apache 正在运行,需要先停止
sudo systemctl stop nginx
# 或
sudo systemctl stop apache2

# 确认防火墙允许 80 端口
sudo ufw allow 80/tcp

申请单域名证书

sudo certbot certonly --standalone \
  -d example.com \
  --agree-tos \
  --email admin@example.com \
  --non-interactive

申请多域名证书

sudo certbot certonly --standalone \
  -d example.com \
  -d www.example.com \
  -d api.example.com \
  --agree-tos \
  --email admin@example.com \
  --non-interactive

交互式申请

# 不加 --non-interactive 参数,Certbot 会交互式引导
sudo certbot certonly --standalone

# 运行后会提示:
# 1. 输入邮箱地址
# 2. 同意服务条款
# 3. 选择要申请证书的域名
# 4. 输入域名(如 example.com)

命令参数详解

参数说明示例
certonly仅获取证书,不安装-
--standalone使用独立模式-
-d指定域名-d example.com
--agree-tos同意服务条款-
--email注册邮箱--email admin@example.com
--non-interactive非交互模式-
--staging使用测试环境-
--http-01-port指定监听端口--http-01-port 8080
--dry-run模拟运行(不实际申请)-

3.3 端口配置

默认端口

Standalone 模式默认使用 80 端口。这是 Let’s Encrypt HTTP-01 验证的标准端口。

自定义端口(不推荐)

# 使用非标准端口(需要在服务器前端做端口转发)
sudo certbot certonly --standalone \
  -d example.com \
  --http-01-port 8080

警告: Let’s Encrypt 服务器始终向 80 端口发起验证请求。使用非标准端口时,需要在前端路由器或负载均衡器上配置端口转发(80 → 8080),否则验证会失败。

端口冲突处理

# 查看占用 80 端口的进程
sudo lsof -i :80

# 或者
sudo ss -tlnp | grep :80

# 常见的 80 端口占用者
# - nginx
# - apache2 / httpd
# - caddy
# - 其他 web 服务

临时停止 Nginx/Apache

# 临时停止 Nginx
sudo systemctl stop nginx

# 申请证书
sudo certbot certonly --standalone -d example.com

# 申请完成后重启 Nginx
sudo systemctl start nginx

使用 Hook 自动处理

# 使用 pre-hook 和 post-hook 自动停止/启动 Web 服务器
sudo certbot certonly --standalone \
  -d example.com \
  --pre-hook "systemctl stop nginx" \
  --post-hook "systemctl start nginx"

3.4 高级用法

指定证书存储路径

# 使用 --cert-path 指定输出路径
sudo certbot certonly --standalone \
  -d example.com \
  --cert-path /etc/ssl/certs/example.com.crt \
  --key-path /etc/ssl/private/example.com.key \
  --fullchain-path /etc/ssl/certs/example.com.fullchain.pem \
  --chain-path /etc/ssl/certs/example.com.chain.pem

使用 RSA 密钥

# 默认使用 EC 密钥,如需 RSA 密钥
sudo certbot certonly --standalone \
  -d example.com \
  --key-type rsa \
  --rsa-key-size 4096

使用 EC 密钥

# 使用 ECDSA 密钥(默认,推荐)
sudo certbot certonly --standalone \
  -d example.com \
  --key-type ecdsa \
  --elliptic-curve secp384r1

Dry Run 测试

# 模拟申请,不实际签发证书
sudo certbot certonly --standalone \
  -d example.com \
  --dry-run

# 输出示例:
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Processing /etc/letsencrypt/renewal/example.com.conf
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Simulating a certificate request for example.com
# The dry run was successful.

提示: 在生产环境申请证书前,务必先使用 --dry-run 测试,避免消耗速率限制。

3.5 使用 Staging 环境

# 使用 staging 环境测试
sudo certbot certonly --standalone \
  --staging \
  -d example.com \
  --agree-tos \
  --email admin@example.com

# 测试成功后,删除 staging 证书
sudo certbot delete --cert-name example.com

# 再使用 production 环境正式申请
sudo certbot certonly --standalone \
  -d example.com \
  --agree-tos \
  --email admin@example.com

验证 staging 证书

# 查看 staging 证书
sudo certbot certificates --cert-name example.com

# staging 证书的签发者通常是:
# "Fake LE Intermediate X1" 或类似名称

3.6 证书申请完整流程示例

场景:为新服务器首次申请证书

#!/bin/bash
# file: request-cert.sh
# 描述:Standalone 模式申请证书的完整流程

DOMAIN="example.com"
EMAIL="admin@example.com"

echo "=== Step 1: 环境检查 ==="
# 检查 80 端口
if ss -tlnp | grep -q ":80 "; then
    echo "错误: 80 端口已被占用"
    ss -tlnp | grep ":80 "
    exit 1
fi

# 检查域名解析
RESOLVED_IP=$(dig +short "$DOMAIN" A | head -1)
SERVER_IP=$(curl -s ifconfig.me)
if [ "$RESOLVED_IP" != "$SERVER_IP" ]; then
    echo "警告: 域名 $DOMAIN 解析到 $RESOLVED_IP,本机 IP 为 $SERVER_IP"
    read -p "是否继续? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        exit 1
    fi
fi

echo "=== Step 2: 申请证书 ==="
sudo certbot certonly --standalone \
  -d "$DOMAIN" \
  --agree-tos \
  --email "$EMAIL" \
  --non-interactive

if [ $? -eq 0 ]; then
    echo "=== 证书申请成功 ==="
    sudo certbot certificates --cert-name "$DOMAIN"
else
    echo "=== 证书申请失败 ==="
    echo "查看日志: /var/log/letsencrypt/letsencrypt.log"
    exit 1
fi

3.7 验证过程排错

常见错误及解决方案

错误 1:端口占用

Problem binding to port 80: Could not bind to IPv4 or IPv6.

解决方案:

# 找到占用 80 端口的进程
sudo lsof -i :80
# 停止该进程
sudo systemctl stop nginx

错误 2:防火墙阻止

Timeout during connect (likely firewall problem).

解决方案:

# 检查防火墙规则
sudo ufw status
# 允许 80 端口
sudo ufw allow 80/tcp

错误 3:域名解析不正确

DNS problem: NXDOMAIN looking up A for example.com

解决方案:

# 检查域名解析
dig +short example.com A
# 确认域名已正确指向服务器 IP

错误 4:速率限制

Too many certificates already issued for example.com

解决方案:

# 使用 --staging 测试
sudo certbot certonly --standalone --staging -d example.com
# 等待限制重置(通常一周)

3.8 Standalone 与其他模式对比

特性StandaloneWebrootNginx 插件DNS 验证
需要 80 端口
需要 Web 服务器
停机时间短暂
通配符支持
自动配置服务器
复杂度
适用场景首次申请已有 Web 服务器Nginx 用户通配符

3.9 最佳实践

  1. 首次使用 staging: 先用 --staging 测试,确认无误后再正式申请
  2. 配合 pre/post-hook: 使用 --pre-hook--post-hook 自动管理 Web 服务器
  3. 不要长时间占用 80 端口: Standalone 服务器仅在验证期间运行,不需要长期运行
  4. 记录申请日志: 保留 /var/log/letsencrypt/letsencrypt.log 便于排错
  5. dry-run 测试续期: 定期使用 --dry-run 测试续期是否正常
# 测试续期是否正常
sudo certbot renew --dry-run

注意事项

  1. 端口 80 必须可达: Standalone 模式依赖 80 端口接收 Let’s Encrypt 的验证请求
  2. 验证期间有短暂停机: 如果已有 Web 服务器运行在 80 端口,需要临时停止
  3. 不适合 CDN 后端: 如果站点在 CDN 后面,验证请求可能到达 CDN 而非你的服务器
  4. IPv6 支持: Certbot 默认同时监听 IPv4 和 IPv6,确保两者都可达

扩展阅读