如何让docker 部署的nginx上通过acme.sh安装ssl/https 证书

发布于 2020-02-26 13:00:05

本篇文章是教大家如何在docker部署的nginx上通过acme.sh安装ssl/https 证书。

由于文中例子是通过acme.sh的http验证方式生成证书,所以在此之前,必须保证你的网站能通过http访问。

目录&流程

1.服务器环境介绍

首先介绍我当前的服务器环境。

1) 阿里云ecs,系统:centos 7

2) 使用docker-compose 配置的php+mysql+nginx环境,nginx直接拉取官方最新版本。
image.png

其中nginx容器向外映射
端口:80(http)、443(https)

路径:

- /home/www:/var/www/html   (项目文件路径)
- /home/docker/lnmp/nginx/conf:/etc/nginx/conf.d (配置文件)
- /home/docker/lnmp/nginx/ssl:/etc/nginx/ssl。(存放ssl证书路径)
- /home/docker/lnmp/nginx/log:/var/log/nginx。 (日志路径)

3) 域名:nuomiphp.com,http能正常访问。

以上配置只是作为参考,原理都一样,请大家因地制宜,不一定要跟我的配置相同。

2.准备工作

2.1 开通阿里云端口

默认情况下,阿里云服务器的80(http)、443(https)端口是关闭。需要在安全组和系统防火墙开启。
具体可参考文章

新买的阿里云服务器 centos7 如何开放80、3360端口

2.2 映射容器端口

将本地 80、3306 端口映射到nginx容器内部的 80、3306端口

2.3 挂载容器目录 (选配)

将主机中项目的目录ssl挂载nginx容器的/etc/nginx/ssl,用于存放ssl证书。如:

- /home/docker/lnmp/nginx/ssl:/etc/nginx/ssl。(存放ssl证书路径)
- /home/docker/lnmp/nginx/log:/var/log/nginx。 (日志路径,方便调试)

2.4 配置顶级域名的解析

由于acme.sh的http认证过程,需要访问配置域名的顶级域名。如www.nuomiphp.com 会访问nuomiphp.com这个顶级域名。所以需要在阿里云设置顶级域名的解析。如图:
image.png

3.使用acme.sh生成证书

acme.sh有http 和 dns 两种验证安装,本文使用的是http安装。相关资料可参考acme.sh介绍

3.1 安装 acme.sh

1) 安装很简单, 一个命令:

curl  https://get.acme.sh | sh

注意:如果遇到:Failed connect to raw.githubusercontent.com:443; 拒绝连接 参照这个解决点击
2) 把 acme.sh 安装到你的 home 目录下:

~/.acme.sh/

并创建 一个 bash 的 alias, 方便你的使用: alias acme.sh=~/.acme.sh/acme.sh

3.2 生成证书

acme.sh  --issue  -d mydomain.com -d www.mydomain.com  --webroot  /home/wwwroot/mydomain.com/

注意:
1) 本文使用的是http方式验证生成。
2) 假设你的域名是nuomiphp.com,那边必须保证nuomiphp.com和www.nuomiphp.com能通过浏览器正常访问,因为在acme.sh认证过程中,会在网站目录下生成验证文件,格式类似:http://nuomiphp.com/.well-known/acme-challenge/_sw4yO3tQM11kAmppJaGPuZwuW4xUFlHfva5-VVgqtQ 必须保证这样的路径能访问。

成功后的截图:

image.png

3.3 copy/安装 证书

前面证书生成以后, 接下来需要把证书 copy 到真正需要用它的地方.

注意, 默认生成的证书都放在安装目录下: ~/.acme.sh/, 请不要直接使用此目录下的文件, 例如: 不要直接让 nginx/apache 的配置文件使用这下面的文件. 这里面的文件都是内部使用, 而且目录结构可能会变化.

正确的使用方法是使用 --installcert 命令,并指定目标位置, 然后证书文件会被copy到相应的位置,
例如:

acme.sh  --installcert  -d  <domain>.com   \
        --key-file   /etc/nginx/ssl/<domain>.key \
        --fullchain-file /etc/nginx/ssl/fullchain.cer \
        --reloadcmd  "service nginx force-reload"

前面这几段是官方的说明,但由于我们的nginx是docker里的,配置有稍微不同。

1) 前面说了,主机映射到容器的目录是/home/docker/lnmp/nginx/ssl,所以copy的证书应该都放到这都这个目录西下。

2) reloadcmd命令是设置acme.sh自动续费后重启nginx用的,由于我们的nignx是docker里运行的,需要改成docker restart lnmp_nginx_1,其中lnmp_nginx_1是容器名称,通过docker ps可查看得到

最后,修改后的命令应该是这样:

acme.sh  --installcert  -d  nuomiphp.com  \
        --key-file    /home/docker/lnmp/nginx/ssl/nuomiphp/nuomiphp \
        --fullchain-file  /home/docker/lnmp/nginx/ssl/nuomiphp/fullchain.cer \
        --reloadcmd "docker restart lnmp_nginx_1"

注意:这里ssl/nuomiphp是考虑到一个服务器可能有多个域名,所以我在ssl目录另建nuomiphp目录。

4.检查nginx是否安装ssl模块

由于我拉取的是官方最新nginx镜像,默认是已安装ssl模块。
大家不确定的话,可以通过docker exec it 容器ID /bin/bash进入nginx容器

然后输入命令nginx -V 查看
如果发现含有onfigure arguments:里含有 http_ssl_module说明已安装ssl模块

5.配置nginx

5.1 备份原配置

如果原来有网站的话,可以通过cp xxx.conf xxx.bx 备份

5.2 配置nginx

开启ssl

listen       443 ssl;
        server_name   nuomiphp.com www.nuomiphp.com ww.nuomiphp.com;
        root  /var/www/html/nuomiphp/public;
        index index.html index.htm index.php default.html default.htm default.php;
        ssl_certificate      /etc/nginx/ssl/nuomiphp/fullchain.cer;
        ssl_certificate_key  /etc/nginx/ssl/nuomiphp/nuomiphp.key;
        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_session_timeout  5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers  on;

其中 ssl_certificate、ssl_certificate_key 对应上一步骤copy过来的cer和key

这是完整配置,可作参考

server {
        #开启ssl
        listen       443 ssl;
        server_name   nuomiphp.com www.nuomiphp.com ww.nuomiphp.com;
        root  /var/www/html/nuomiphp/public;
        index index.html index.htm index.php default.html default.htm default.php;
        ssl_certificate      /etc/nginx/ssl/nuomiphp/fullchain.cer;
        ssl_certificate_key  /etc/nginx/ssl/nuomiphp/nuomiphp.key;
        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_session_timeout  5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        ssl_prefer_server_ciphers  on;
        
        #开启gzip压缩
        gzip  on;
        gzip_min_length  1k;
        gzip_buffers     4 16k;
        gzip_http_version 1.1;
        gzip_comp_level 9;
        gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;
        gzip_disable "MSIE [1-6]\.";
        gzip_vary on;
        
        #日志
        access_log  /var/log/nginx/nuomiphp.access.log  main;
        error_log /var/log/nginx/nuomiphp.error.log error;
        
        #隐藏index.php
        location / {
                index  index.html index.htm index.php;
                    #主要是这一段一定要确保存在
                   if (!-e $request_filename) {
                      rewrite  ^(.*)$  /index.php?s=/$1  last;
                      break;
                    }
                    #结束
                #autoindex  on;
         }
    #php解析配置     
    location ~ \.php(.*)$ {
                fastcgi_pass   php:9000;
                fastcgi_index  index.php;
                fastcgi_split_path_info  ^((?U).+\.php)(/?.+)$;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                fastcgi_param  PATH_INFO  $fastcgi_path_info;
                fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info;
                include        fastcgi_params;
    }
    #error_page  404              /404.html;
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

#对http请求重定向到https
server {
 listen 80;
 server_name nuomiphp.com  www.nuomiphp.com ww.nuomiphp.com;  
 rewrite ^(.*)$ https://$host$1 permanent;
 location / {
    index index.html index.htm;
  }
}

配置完后,重启nginx,这是如果能通过https访问网站,则代表配置成功。

6.总结

总的来讲,由于acme.sh自动化配置,配置下来并没有复杂的操作。

主要多注意些细节,比如:
1) 443端口忘了开放
1) 顶级域名忘了解析
1) 等等等

运用点小技巧,比如

1) 在配置nginx过程中,可能需要频繁的重启nginx。这时可以通过docker exec -it 容器ID /bin/bash 命令进入容器,通过nginx -s reload来快速刷新nginx配置,好处就是快速,并且哪怕配置错了,也不会影响之前的已生效的配置。

最后,感想letsencrypt 和 acme.sh ~!为我们提供了免费的ssl方案!:clap:

0 条评论

发布
问题