docker使用certbot获取证书(后续尝试定时续期)

背景

没啥背景,就是需要搞证书,花钱的证书买不起,就只能白嫖了,白嫖肯定就只有let‘s encrypt,没啥说的直接开干。

我准备了三个域名,www.xxx.com,api.xxx.com和admin.xxx.com,

zerossl

差了let‘s encrype的官方文档。有很多的acme的客户端。因为我基本都会优先考虑容器,发现docker哪里有个zerossl,然后也去研究了一下,zerossl的官网(https://zerossl.com/)也提供了很多关于证书的相关接口,对接他的接口我觉得应该也可以。但是我没有,因为我觉得都是ACME的客户端实现,我为啥还要再去实现一遍。没必要。然后就去研究了一下zerossl的docker容器。搜索引擎关于zerossl的容器资料特别少,它的官方主页(https://hub.docker.com/r/zerossl/client/)也写的有点复杂,反正我没时间出来,(总是会提示method not allowed),所以最终还是放弃了,回到最原始的certbot

以上是一堆废话,下面开始正文

certbot

certbot其实也有对应的docker容器(https://hub.docker.com/r/certbot/certbot)版本,这也是我后面才发现的,因为他官方文档写的docker客户端是zerossl。

certbot使用docker的文档地址:https://certbot.eff.org/docs/install.html#running-with-docker

不说废话了,直接拉取镜像,然后使用命令查看帮助信息

docker run -it --rm certbot/certbot --help

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...

Certbot can obtain and install HTTPS/TLS/SSL certificates.  By default,
it will attempt to use a webserver both for obtaining and installing the
certificate. The most common SUBCOMMANDS and flags are:

obtain, install, and renew certificates:
    (default) run   Obtain & install a certificate in your current webserver
    certonly        Obtain or renew a certificate, but do not install it
    renew           Renew all previously obtained certificates that are near
expiry
    enhance         Add security enhancements to your existing configuration
   -d DOMAINS       Comma-separated list of domains to obtain a certificate for

  (the certbot apache plugin is not installed)
  --standalone      Run a standalone webserver for authentication
  (the certbot nginx plugin is not installed)
  --webroot         Place files in a server‘s webroot folder for authentication
  --manual          Obtain certificates interactively, or using shell script
hooks

   -n               Run non-interactively
  --test-cert       Obtain a test certificate from a staging server
  --dry-run         Test "renew" or "certonly" without saving any certificates
to disk

manage certificates:
    certificates    Display information about certificates you have from Certbot
    revoke          Revoke a certificate (supply --cert-name or --cert-path)
    delete          Delete a certificate (supply --cert-name)

manage your account:
    register        Create an ACME account
    unregister      Deactivate an ACME account
    update_account  Update an ACME account
  --agree-tos       Agree to the ACME server‘s Subscriber Agreement
   -m EMAIL         Email address for important account notifications

More detailed help:

  -h, --help [TOPIC]    print this message, or detailed help on a topic;
                        the available TOPICS are:

   all, automation, commands, paths, security, testing, or any of the
   subcommands or plugins (certonly, renew, install, register, nginx,
   apache, standalone, webroot, etc.)
  -h all                print a detailed help page including all topics
  --version             print the version number
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Certbot获取争取有好几种方式,主要就是验证域名是不是你的。

一种就是在你的站点下放一个/.well-known/acme-challenge,在里面创建一个文件然后let‘s encrypt会去请求整个文件,这种方式就是官网的Webroot的方式

第二种:就是通过DNS的查找方式取验证,具体我就不知道了,我看到有个大佬用这种方式成功了(https://soulteary.com/2018/08/30/use-docker-certbot-to-obtain-ssl-certificates.html)括号里就是大佬的链接,有兴趣可以试试,我说说我用这种方式遇到的坑。

 开始我对这种方式也很感兴趣,因为看文档说这事唯一方式去获取通配符域名的证书,官方文档提供了很多DNS的插件(https://certbot.eff.org/docs/using.html#dns-plugins),我按博客里的选择了cloudflare(文档地址:https://certbot-dns-cloudflare.readthedocs.io/en/stable/),他会让你去他的网址注册账号,然后验证你的域名,这个过程说实话我觉得还是比较漫长的,最后还不知道要加什么,我是没成功,算了放弃了。所以最后我又回到了第一种方式,至于官网上的其他什么Nginx、Standalone等等我就没实践了。反正第一种方式(也就是webroot)我走通了,本来我主要就是实践,解决问题,并不计划进行科研

webroot方式因为要访问你的站点目录,所以certbot的容器呀开放站点目录的读写权限,当然首先容器肯定要映射站点目录,执行docker的命令如下

docker run -it --rm   -v /home/docker-nginx/certs/www.xxx.com:/etc/letsencrypt  -v /home/docker-nginx/certs/www.xxx.com:/var/lib/letsencrypt \-v /home/docker-nginx/certs/www.xxx.com:/var/log/letsencrypt  \-v /home/docker-app/webapp/app:/data/letsencrypt \certbot/certbot certonly  --webroot --agree-tos --webroot-path=/data/letsencrypt -m [email protected] -d www.xxx.com

解释一下

--rm,容器执行完以后删除

-v 映射容器目录

前三个主要映射证书的存储路径,因为官方文档说明了证书存储在容器里的/etc/letsencrypt目录下,为了保存证书,我所以我映射到了服务器的物理路径下。

最后一个目录就是映射我的站点目录,因为certbot验证是需要往你的站点目录写东西供他访问,所以我要做这一步。

certonly,帮助上说的很清楚了,只获取争取不安装

--webroot:验证方式使用webroot

--agree-tos:统一他的协议

--webroot-path:站点目录,这里写的是容器内的目录,要与上面映射的目录一致

-m:邮箱,说是要过期了会通知到该邮箱

-d 域名,如果有多个域名,好像说是可以接多个-d,我没试过。

第一次执行会咨询你是否确定什么的,具体忘记,反正输入一个Y就行了

说一下我在这里遇到的坑,前面说我准备了三个域名,www.xxx.com,api.xxx.com,admin.xxx.com,其中www和admin两个域名我是放静态文件的,api是我的接口站点使用asp.netcore写的webapi,www和admin我使用的就是Nginx做web服务器。api就只官网的方式,然后对外使用一个Nginx就分流。前两个www和admin获取证书都没有问题,另一个api验证失败,错误信息大概就是请求我api站点目录下的/.well-known/acme-challenge下的文件404。所以我开始怀疑是不是没有权限写,但是我检查了我整个wwwroot目录,甚至我把权限改成了777都没有效果,找不到原因。

没办法,只能想办法绕过去。后面想到,既然nginx的证书没问题,干脆我用分流的Nginx来验证我的api,然后我就在我的分流Nginx目录下放建了一个目录。修改Nginx关于api的配置

server 
    {
        listen       80;        #监听端口    
        listen       443 ssl;
        server_name api.xxxx.top;
        location ~/.well-known/acme-challenge/ {
            root /home/app;
        }
        
        #默认请求设置
        location / {
            proxy_pass http://webapi;    #转向.netcore处理

            proxy_set_header Host $proxy_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Via "nginx";

        }
    }

主要没加什么,添加了一个location,把所有有/.well-known/acme-challenge/的请求都转到/root/app上去,主语两个location的顺序,然后在Nginx容器的目录映射到物理主机上然后再执行命令

docker run -it --rm -v /home/docker-nginx/certs/api.xxx.com :/etc/letsencrypt -v /home/docker-nginx/certs/api.xxx.com :/var/lib/letsencrypt -v /home/docker-nginx/certs/api.xxx.com :/var/log/letsencrypt -v /home/docker-nginx/rootd:/data/letsencrypt certbot/certbot certonly --webroot --agree-tos --webroot-path=/data/letsencrypt -m  -d api.xxx.com

看到成功的那一刻,内心真的无比激动。

证书已经获取到对应的目录下了,然后就是配置对应的站点证书了。

贴一个server就行了,其他配置都一模一样的。

server
    {
        listen     80;
        listen     443 ssl;
        server_name www.wenwangjiegua.top;

        ssl_certificate       /home/certs/www.xxx.com/live/www.xxx.com/fullchain.pem;          #证书里面,必须是包含两套完整的-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----        ssl_certificate_key  /home/certswww.xxx.com/live/www.xxx.com/privkey.pem;         #证书密钥文件
        location / {

            proxy_set_header Host $proxy_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Via "nginx";
            proxy_pass http://webapp;    #转向.netcore处理
        }
    }

这个配置是同时存在http和https请求,Nginx的302跳转百度一下就行了。

说一下我在这步犯下的一个错误,记录一下,这里我犯了一个错误,我上面的配置都完成了,但是一直用https请求都不成功,找了半天,发现原来的我的Nginx的docker没有对外开放443端口,打开就好了。这个问题真的是查了半天。傻逼了,傻逼了。

https://hub.docker.com/r/certbot/certbot

相关推荐