Let’s Encrypt!ubuntu获取https证书及Nginx反向代理实战

这次在师兄的帮助下,注册了github student pack,然后花了5$Digital Ocean买了一台国外服务器(ubuntu server)。于是,干脆把博客从github pages搬到服务器上去了。接下来干了3件事:

  • 建立git脚本
  • 构建nginx转发
  • 颁发https证书

建立ssh免验证

ssh-copy-id命令可以把本地主机的公钥复制到远程主机的authorized_keys文件上,ssh-copy-id命令也会给远程主机的用户主目录(home)和~/.ssh, 和~/.ssh/authorized_keys设置合适的权限。

$ ssh-copy-id ~/.ssh/id_rsa.pub root@68.183.*.*

创建博客目录

在远程服务器上创建一个目录(位置随意),用来接收git提交上来的数据。注意,此时你只需要创建该目录即可,不需要scp文件。
e.g.

# mkdir -p /var/www/blog

配置git hooks

git能在特定的重要动作发生时触发自定义脚本。这些都要归功于git hookgit钩子)。目前我们只需要实现一个功能——将git提交的内容放置于/var/www/blog目录下。

  • 创建--bare裸库
    由于是用于转发,这里只需要使用--bare创建一个git裸库(位置随便),也就是说不包含任何源文件的拷贝。
    e.g.

    # mkdir ~/blog.git && cd ~/blog.git
    # git init --bare
  • post-receive脚本
    .git/hooks/...下有文本脚本的sample其中就有一个叫post-receive-sample,在此基础上,拷贝一份,重命名为post-receive(必须)。脚本非常简单,删除原有的/var/www/blog目录,然后从blog.git仓库clone新的博客静态文件。

    # vim ~/blog.git/hooks/post-receive
    #!/bin/bash
    rm -rf /var/www/blog
    git clone /root/blog.git /var/www/blog
  • 配置hexo _config.yml
    这里注意填写正确的用户名(如root)、IP地址以及git的路径。我的路径为/root/blog.git,由于ssh默认根路径为/home(比如root账户登录即为/root),这里可以省略写成blog.git,当然也可以写成~/blog.git
    e.g.

    deploy:
    - type: git
    repo: root@68.183.*.*:blog.git

Nginx转发

我将域名添加了3个A记录,分别为@wwwblog,这样对应着写上3个配置文件(其实一个就可以搞定),分别为default.confwww.confblog.conf

# cd /etc/nginx/conf.d
# ls
blog.conf default.conf www.conf

这里.conf的命名随意,只需要保证后缀为.conf即可,因为Nginx默认会加载conf.d/目录下的所有后缀为.conf的文件。

  • default.conf
    default.conf正则匹配所有前缀的域名,主要功能为:监听80端口,去^~ /.well-known/acme-challenge/目录下验证证书。这里再添加一个,location / 将所有的http请求,永久性的重定向(301)到https

    server {
    listen 80;
    server_name *.qingdujun.com;

    location ^~ /.well-known/acme-challenge/ {
    default_type "type/plain";
    root /var/www/html;
    }

    location / {
    return 301 https://$host$request_uri;
    }
    }

    需要注意的是,域名下的\.well-know\acme-challenge\目录下的文件必须要可以访问。这个是Let’s Encrypt用于验证域名所有权的。它会在上面-w参数设置的目录下建立临时文件,然后通过http访问,比如上面的设置就会新建诸如/var/www/html/.well-known/acme-chanllenge/xxxxxxx(xxxxxxx是随机字符),然后通过http://example.com/.well-known/acme-chanllenge/xxxxxxx来验证。

  • www.conf
    www.conf监听https 443端口,并指定fullchain.pem(包括上面的服务器证书和其他证书)、privkey.pem(私钥)。指定博客根目录root /var/www/blog;、指定主页index index.html index.htm;

    server {
    listen 443 ssl;
    server_name qingdujun.com www.qingdujun.com;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/qingdujun.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/qingdujun.com/privkey.pem;

    location / {
    root /var/www/blog;
    index index.html index.htm;
    }
    }
  • blog.conf
    blog.conf内容与www.conf几乎一致,唯一的差别在于server_name。其实如果在www.conf中增加blog.qingdujun.com将不再需要blog.conf了,话又说回来,如果在default.conf中增加多个server配置将不再需要www.confblog.conf了。

    server {
    listen 443 ssl;
    server_name blog.qingdujun.com;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/qingdujun.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/qingdujun.com/privkey.pem;

    location / {
    root /var/www/blog;
    index index.html index.htm;
    }
    }

https证书

这里使用certbot来生成证书。查看是否已经安装了该软件(certbot --version)。如果未安装,请使用apt install certbot安装。

# apt install certbot
# certbot --version
certbot 0.23.0

  • 生成https证书

    certbot certonly --email qdujun@gmail.com --webroot -w /var/www/html \
    -d qingdujun.com \
    -d www.qingdujun.com \
    -d blog.qingdujun.com

    其中,certonly 表示只颁发证书。--email 指定邮箱。如果没指定的话,后面要求主动输入。--webroot 用于自动验证域名。-w 指定网站的目录。-d 指定目录对应的域名。

    这里域名所有权验证目录/var/www/html和博客的位置/var/www/blog没有关系。但是建议不要指定在博客目录下,因为git hook中每次都会删除博客,重新生成,这样就会造成^~ /.well-known/acme-challenge/目录的丢失。

    出现Congratulations!就代表成功了。

  • https证书自动续期
    certbot证书默认只有90天的有效期,到期之后将不再有效,需要手动运行renew命令续期。运行之后记得reload

    # /usr/bin/certbot renew

    网上搜索到ubuntu上有一个软件cron用于执行定时任务。一般服务器都自带该软件的(可以先运行service cron status查看是否安装了),如果没有请安装它。

    # apt install cron
    # service cron start
    # service cron status
    ● cron.service - Regular background program processing daemon
    Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled)
    Active: active (running) since Mon 2018-10-29 10:25:34 UTC; 20h ago
    Docs: man:cron(8)
    Main PID: 774 (cron)
    Tasks: 1 (limit: 1152)
    CGroup: /system.slice/cron.service
    └─774 /usr/sbin/cron -f

    使用crontab命令,设置定时任务。其中,m 分钟、h 小时、dom 日期、mon 月份、dow 星期、command 执行的命令。那么,以下内容就是:

    每个月的28号凌晨3:01自动续期https证书,凌晨3:06使其对Nginx生效。

    # crontab -e

    01 3 28 * * /usr/bin/certbot renew >> /var/log/ssl-renew.log
    06 3 28 * * /usr/sbin/nginx -s reload
  • 验证自动续期命令
    手动执行/usr/bin/certbot renew命令,可以看到Cert not yet due for renewal(证书尚未到期)。

    # /usr/bin/certbot renew >> /var/log/ssl-renew.log
    Saving debug log to /var/log/letsencrypt/letsencrypt.log
    Cert not yet due for renewal

    # cat /var/log/ssl-renew.log
    Processing /etc/letsencrypt/renewal/qingdujun.com.conf
    The following certs are not due for renewal yet:
    /etc/letsencrypt/live/qingdujun.com/fullchain.pem expires on 2019-01-27 (skipped)
    No renewals were attempted.

番外, github student pack完成学生认证之后,送100$代金券,可以使用它们的云服务。还有个好处就是在github上可以免费创建私有仓库。

References:
[1] https://www.hrwhisper.me/install-lets-encrypt-ssl-centos-nginx/
[2] http://man.linuxde.net/ssh-copy-id
[3] https://www.cnblogs.com/fundebug/p/6873913.html
[4] https://blog.csdn.net/kangear/article/details/80546945
[5] https://blog.csdn.net/a295277302/article/details/78143010