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

这次在师兄的帮助下,注册了github student pack,然后花了5$Digital Ocean买了一台国外服务器(ubuntu server)。于是,干脆把博客从github pages搬到服务器上去了。接下来干了3件事: - 建立git脚本 - 构建nginx转发 - 颁发https证书

0 建立ssh免验证

建立好Droplets后,你邮件里面应该会收到一封来自Digital Ocean的邮件。它会告诉你root账户的随机密码是多少(一般是20位左右的数字、字母混合体),如果没收到邮件,可以在网页上点击你的Droplets,然后点击Access,接着Reset Root Password,这样你就会又收到一封root密码邮件。

使用它登录即可(第一次会强制要求,重置密码):

$ ssh root@128.64.32.16

Last login: Tue Mar 12 06:43:45 2019 from 124.16.141.63
Changing password for root.
(current) UNIX password:
Enter new UNIX password:
Retype new UNIX password:

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

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

1 创建博客目录

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

# mkdir -p /var/www/blog

2 配置git hooks

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

2.1 创建--bare裸库

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

# mkdir ~/blog.git && cd ~/blog.git
# git init --bare

2.2 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

记得附加可执行权限,修改权限为rwxr-xr-x也就是755

# chmod 755 ~/blog.git/hooks/post-receive

2.3 配置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

3 Nginx转发

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

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

这里.conf的命名随意,只需要保证后缀为.conf即可,因为Nginx默认会加载conf.d/目录下的所有后缀为.conf的文件。 ## 3.1 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来验证。

3.2 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;
}
}

3.3 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;
}
}

4 https证书

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

# apt install certbot
# certbot --version
certbot 0.23.0

4.1 生成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!就代表成功了。

4.2 https证书自动续期

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

# /usr/bin/certbot renew

运行之后记得reload nginx,可以先使用nginx -t测试一下.conf是否有问题。

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# nginx -s reload

网上搜索到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

4.3 验证自动续期命令

手动执行/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.

2019/7/2 根据实际效果来看,我的网站在3个月后,https证书到期了。效果如同没有自动续期。后来分析其原因,发现证书确实自动续期了,但是需要重新运行一次nginx -s reload命令。

4.4 删除证书

certbot提供了删除证书的命令:delete,选择你需要删除的域名即可。特别是有时候生成了xxx-0001xxx-002之类的证书,看着不好看,那就直接删除。

# certbot delete
Saving debug log to /var/log/letsencrypt/letsencrypt.log

Which certificate(s) would you like to delete?
-------------------------------------------------------------------------------
1: qingdujun.com
-------------------------------------------------------------------------------
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1

番外, 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 [6] https://www.4spaces.org/lets-encrypt-certbot-remove-revoke/