使用 acme.sh 从 Let’ s Encrypt 生成免费的通配符 SSL 证书

准备内容

  • 域名一个
  • 阿里云账号一个
  • 系统 CentOS7 (其他系统请自行测试)

开始表(zhuang)演(bi)了

1.安装 acme.sh ,中文说明点这里

# 安装
$ curl https://get.acme.sh | sh
.
.
.
[Sat Mar 16 18:22:28 CST 2019] Good, bash is found, so change the shebang to use bash as preferred.
[Sat Mar 16 18:22:29 CST 2019] OK
[Sat Mar 16 18:22:29 CST 2019] Install success!

# 让环境变量生效
$ source ~/.bashrc

2.生成证书

  • acme.sh 实现了 acme 协议支持的所有验证协议。 一般有两种方式验证:HTTP 验证和 DNS 验证。

  • 这里我们是用 DNS 验证方式。DNS 方式,需要手动在域名上添加一条 txt 解析记录,验证域名所有权。为了避免每次都需要手动解析验证域名所有权,我们使用域名解析商提供的 api 自动添加 txt 记录完成验证,acme.sh 目前支持数十种解析商的自动集成,其中包含阿里云。以阿里云为例,你需要先登录到阿里云账号,生成你自己的 api id 和 api key,它是免费的(建议开启阿里云【RAM 访问控制】,只给 AliyunDNSFullAccess 权限策略,这样做更安全)。然后执行下面的命令:

export Ali_Key="xxx" && export Ali_Secret="xxx"

# 因为生成的通配符域名证书中并不包含根域名证书,所以我们要指定根域名。
acme.sh --issue --dns dns_ali -d example.com -d *.example.com
.
.
.
[Mon Mar 25 11:28:48 CST 2019] Your cert is in  /home/user/.acme.sh/example.com/example.com.cer 
[Mon Mar 25 11:28:48 CST 2019] Your cert key is in  /home/user/.acme.sh/example.com/example.com.key 
[Mon Mar 25 11:28:48 CST 2019] The intermediate CA cert is in  /home/user/.acme.sh/example.com/ca.cer 
[Mon Mar 25 11:28:48 CST 2019] And the full chain certs is there:  /home/user/.acme.sh/example.com/fullchain.cer
.
.
.

# 创建放置证书的文件夹
mkdir -p /data/certs/com.example/

# 前面证书生成以后,,需要把证书 copy 到真正需要用它的地方。
acme.sh --install-cert -d example.com -d *.example.com \
--key-file "/data/certs/com.example/com.example.key" \
--fullchain-file "/data/certs/com.example/fullchain.cer" \
--reloadcmd "service nginx force-reload"

3.nginx 配置

# 创建证书文件夹的软连接
ln -s /data/certs /etc/nginx/certs
  • /etc/nginx/nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;

    # localhost 转发到 https://www.example.com
    server {
        listen       80;
        server_name  localhost;

        charset utf-8;

        location / {
            rewrite ^(.*)$ https://www.example.com$1 permanent;
        }
    }

    include /etc/nginx/conf.d/*.conf;
}
  • /etc/nginx/conf.d/com.example.www.conf
# HTTP
server {
    listen      80;
    server_name example.com www.example.com;

    charset utf-8;

    location / {
        rewrite ^(.*)$ https://www.example.com$1 permanent;
    }
}

# HTTPS
server {
    listen      443;
    server_name example.com;

    charset utf-8;

    ssl                       on;
    ssl_certificate           certs/com.example/fullchain.cer;
    ssl_certificate_key       certs/com.example/com.example.key;
    ssl_session_timeout       5m;
    ssl_ciphers               ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    location / {
        rewrite ^(.*)$ https://www.example.com$1 permanent;
    }
}

server {
    listen      443;
    server_name www.example.com;

    charset utf-8;

    ssl                       on;
    ssl_certificate           certs/com.example/fullchain.cer;
    ssl_certificate_key       certs/com.example/com.example.key;
    ssl_session_timeout       5m;
    ssl_ciphers               ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;

    root  /data/wwwroot/com.example.www/public;
    index index.html index.php;

    # laravel 优雅链接,将所有请求都引导到 index.php 前端控制器。
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        root          /data/wwwroot/com.example.www/public;
        fastcgi_pass  127.0.0.1:9999;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

注意:请将 example.com 改为你自己的域名。

如有错误,请批评改正。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4

@mayingbiao89 那就来一个定时器,你看多方便~

while (true) {
    sleep('我要睡一年');
    exec('shell是时候续期了', $result, $status);
}

不要打我、O(∩_∩)O哈哈~

5年前 评论

阿里云和腾云都有免费的(一年期),LE有一个好处可以一键续签,我觉得个人或者测试就好。

5年前 评论

@AlicFeng 一年一换也感觉麻烦,不如这个让它在那里“自生自灭”。 :joy:

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!