使用 acme.sh 申请 IP 证书并部署到 Caddy

本文记录一套可复用流程:用 acme.sh 申请 Let’s Encrypt IP 证书,并在 Caddy 中加载使用
适合没有域名、直接用公网 IP 提供 HTTPS 的场景。


零. 前置说明

  • 系统:Debian/Ubuntu(其他 Linux 同理)
  • ACME 客户端:acme.sh
  • Web 服务:Caddy
  • 验证方式:http-01(80 端口必须公网可达)
  • 证书类型:ECC(--ecc

一、先明确 4 个关键事实(避免方向错)

  1. Let’s Encrypt 默认 profile 不支持 IP 证书
    直接用默认参数会报:
    Default profile does not permit IP address identifiers

  2. 申请 IP 证书时,要显式指定支持 IP 的 profile(如 shortlived):

    • --certificate-profile shortlived --days 6
  3. --issue 命令必须指定验证方式之一:

    • --standalone / --alpn / -w / --dns
      否则会报:Please specify at least one validation method
  4. Caddy 启动失败最常见不是语法,而是私钥权限

    • open /etc/ssl/ip.key: permission denied

二、环境准备

1
2
3
curl https://get.acme.sh | sh
source ~/.bashrc
acme.sh --register-account --server letsencrypt

三、申请 IP 证书(生产可用命令)

以下示例以 127.0.0.1 为例;IPv6 写法后面单独给。

方案 A:HTTP-01(standalone,走 80 端口)

1
2
3
4
5
6
7
acme.sh --issue -d 127.0.0.1 \
--standalone \
--server letsencrypt \
--certificate-profile shortlived \
--days 6 \
--ecc \
--debug 2

前提:

  • 80 端口公网可达
  • 申请时 80 端口不能被 Caddy/Nginx 占用

若被占用(常见):

1
2
3
systemctl stop caddy
# 再执行 issue
systemctl start caddy

方案 B:TLS-ALPN-01(–alpn,走 443 端口)

当 80 被封禁但 443 可用时,优先用它:

1
2
3
4
5
6
7
acme.sh --issue -d 127.0.0.1 \
--alpn \
--server letsencrypt \
--certificate-profile shortlived \
--days 6 \
--ecc \
--debug 2

前提:

  • 443 端口公网可达
  • 申请时 443 端口不能被 Caddy 占用

四、安装证书到固定路径(不要直接用 ~/.acme.sh)

1
2
3
4
5
acme.sh --install-cert -d 127.0.0.1 --ecc \
--key-file /etc/ssl/ip.key \
--cert-file /etc/ssl/ip.crt \
--fullchain-file /etc/ssl/ip.fullchain.crt \
--reloadcmd "systemctl reload caddy"

五、修正文件权限

Caddy 以 caddy 用户运行,默认可能读不到 /etc/ssl/ip.key

1
2
3
chown root:caddy /etc/ssl/ip.key /etc/ssl/ip.fullchain.crt /etc/ssl/ip.crt
chmod 640 /etc/ssl/ip.key
chmod 644 /etc/ssl/ip.fullchain.crt /etc/ssl/ip.crt

若不做这步,常见报错:
loading certificates: open /etc/ssl/ip.key: permission denied


六、Caddyfile 正确写法

1)IPv4 示例

1
2
3
4
5
6
7
8
http://127.0.0.1 {
redir https://127.0.0.1{uri} 308
}

https://127.0.0.1 {
tls /etc/ssl/ip.fullchain.crt /etc/ssl/ip.key
reverse_proxy 127.0.0.1:15001
}

2)IPv6 示例(必须加中括号)

1
2
3
4
https://[::1] {
tls /etc/ssl/ip.fullchain.crt /etc/ssl/ip.key
reverse_proxy 127.0.0.1:15001
}

七、上线前检查命令

caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
systemctl restart caddy