2017年11月

已经在树莓派上搭建好了博客,接着就想着目前HTTPS在各大互联网站已经成为标配,在未来肯定是一种趋势,HTTPS的好处有很多,可以防止各种攻击劫持,运营商广告植入,客户传输信息泄露等问题。
通过Google查询发现了一个Let's Encrypt项目,它由互联网安全研究小组ISRG(Internet Security Research Group)提供服务,ISRG是来自美国加利福尼亚州的一个公益组织。Let's Encrypt 得到了 Mozilla、Cisco和 Chrome 等众多公司和机构的支持。
Let's Encrypt证书对中小网站来说免费且配置简单,唯一的问题就是每次申请只有90天的有效期,但可以通过脚本定期更新,配置好之后一劳永逸。通过Github发现又一个acme-tiny项目,它是一个Python脚本的工具可以协助完成证书的申请,简化申请流程。

1、创建账号

Let's Encrypt使用一个私钥来进行账号的创建与登陆,因此我们需要使用openssl创建一个account.key

openssl genrsa 4096 > account.key

生成的key格式需要转换,于是我又发现一个好的脚本

# 下载脚本
wget -O - "https://gist.githubusercontent.com/JonLundy/f25c99ee0770e19dc595/raw/6035c1c8938fae85810de6aad1ecf6e2db663e26/conv.py" > conv.py

# 把private key 拷贝到你的工作目录
cp /etc/letsencrypt/accounts/acme-v01.api.letsencrypt.org/directory/<id>/private_key.json private_key.json

# 创建一个DER编码的private key
openssl asn1parse -noout -out private_key.der -genconf <(python conv.py private_key.json)

# 转换成PEM格式
openssl rsa -in private_key.der -inform der > account.key

2、创建域名的CSR

Let's Encrypt使用的ACME协议需要一个CSR(CERTIFICATE SIGNING REQUEST)文件,可以使用它来重新申请HTTPS证书,接下来我们就可以创建域名CSR,在创建CSR之前,我们需要给我们的域名创建一个私钥(这个和上面的账户私钥无关)。

#创建普通域名私钥
openssl genrsa 4096 > domain.key

接下来,使用你的域名私钥创建CSR文件,这一步里面是可以增加最多100个需要加密的域名的,替换下面的chy.mobi即可(注意,稍后会说到,每个域名都会涉及到验证)

#单个域名
openssl req -new -sha256 -key domain.key -subj "/CN=foofish.net" > domain.csr

#多个域名(如果你有多个域名,比如:www.chy.mobi和chy.mobi,使用这种方式)
openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:chy.mobi,DNS:chy.mobi")) > domain.csr

3、配置域名验证

CA 在签发 DV(Domain Validation)证书时,需要验证域名所有权。
Let's Encrypt 的方式是在你的服务器上生成一个随机验证文件,再通过创建 CSR 时指定的域名访问,如果可以访问则表明你对这个域名有控制权。 首先创建用于存放验证文件的目录,例如:

mkdir -p var/www/challenges

然后编辑 /etc/nginx/sites-enabled/default 配置HTTP服务,注意此处应使用80端口

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name chy.mobi www.chy.mobi;

        location /.well-known/acme-challenge/ {
                alias /home/pi/Websites/Chy/challenges/;
                try_files $uri =404;
        }

        location / {
                return 302 http://chengyong.im$request_uri;
                try_files $uri =404;
        }
}

这个验证服务以后更新证书还要用到,需要一直保留,不要在Nginx的配置中删除。

4、获取网站证书

先把 acme-tiny 脚本保存到之前的 ssl 目录:

wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py

指定账户私钥、CSR 以及验证目录,执行脚本:

python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/challenges/ > ./signed.crt

如果一切正常,当前目录下就会生成一个 signed.crt,这就是申请好的证书文件。

5、安装证书

证书生成后,就可以把它配置在web 服务器上了,需要注意的是,Nginx需要追加一个Let's Encrypt的中间证书,在 Nginx 配置中,需要把中间证书和网站证书合在一起:

wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained.pem

最终,修改 Nginx 中有关证书的配置,下面是我的网站的完整的配置:

server {
        # SSL configuration
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;

        server_name chy.mobi;
        root /home/pi/Websites/Chy;

        ssl on;
        ssl_certificate /home/pi/SSL/chained.pem;
        ssl_certificate_key /home/pi/SSL/domain.key;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE$
        ssl_session_cache shared:SSL:50m;
        ssl_prefer_server_ciphers on;

        # Add index.php to the list if you are using PHP
        index index.php index.html index.htm index.nginx-debian.html;

        location / {
                if (-f $request_filename/index.html){
                        rewrite (.*) $1/index.html break;
                }
                if (-f $request_filename/index.php){
                        rewrite (.*) $1/index.php;
                }
                if (!-f $request_filename){
                        rewrite (.*) /index.php;
                }
        }

        location ~ .*\.php(\/.*)*$ {
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_index index.php;
                include fastcgi.conf;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}
}


server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name chy.mobi www.chy.mobi;

        location /.well-known/acme-challenge/ {
                alias /home/pi/Websites/Chy/challenges/;
                try_files $uri =404;
        }

        location / {
                return 302 http://chengyong.im$request_uri;
                try_files $uri =404;
        }
}

至此,所有证书已经配置成功,reload服务即可生效。

6、定期手动更新

为了方便更新,把上面的步骤写成一个脚本 renew_cert.sh 保存到本地,每隔2个多月执行一次即可:

#!/usr/bin/sh
python /path/to/acme_tiny.py --account-key /path/to/account.key --csr /path/to/domain.csr --acme-dir /var/www/challenges/ > /tmp/signed.crt || exit
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat /tmp/signed.crt intermediate.pem > /path/to/chained.pem
service nginx reload

下次直接执行以下命令即可:

sh renew_cert.sh

前言

上周,收到阿里云域名和主机到期的邮件,想着套路云虽然价格还算公道,但把数据放在一个始终被监控的环境,始终不舒服,于是本着不折腾不舒服斯基的原则,周末在家重新折腾了一遍,把阿里云上的博客迁移到家里面一台吃灰的树莓派上,以下是在折腾过程中遇到的问题和一些记录,以备查询和供其他看到这篇文章的人作参考,先放一张我家弱电箱里面的布局图。

安装Raspbian系统

手头的这台树莓派是很早之前购买的,已经吃灰有一年多,今天翻出来,加了一个5V 1A的电源,还能正常点亮,于是乎系统装起。
为了方便,直接用老婆那台Windows把下载好的镜像烧录进TF卡,直接把卡插入树莓派的卡槽,基本上安装工作就基本结束了。

用 Win32DiskImager 烧写镜像,选择要烧写的镜像,点击"Write"进行烧写

Raspbian系统配置

系统烧录好以后,默认SSH不可用,需在TF卡的boot分区根目录创建一个空白无后缀的 ssh 文件,然后就可以使用 ssh 工具连接,给系统配置一些常量,此外说明下,为了以后配置方便,最好在路由器上把树莓派的IP设置为固定地址,这样以后树莓派的IP地址就不会改变,不用每次都看下IP是多少。

Windows上使用putty连接登录,图来自网络

MacOS上直接使用终端,图来自网络

连接用到的命令:
ssh pi@192.168.100.5
连接上以后,为了方便查看时间,最好更改下系统时区,这时候我们需要安装NTP,主要就是自动对时的,不用每次手动设置。
安装NTP:
sudo apt-get install ntpdate
启用NTP:
sudo timedatectl set-ntp true
修改本地时区:
sudo dpkg-reconfigure tzdata
在这一步中,我选的是“Asia/Shanghai”
查看时间是否正确:
date

可以看到时间已经更改为北京时间了,设置完成时间以后,需要更新下软件源,建议先更新源地址为阿里云源。
编辑源:
sudo nano /etc/apt/sources.list
打开以后,替换原来源中的链接为阿里云源,替换后大概会如下:

deb http://mirrors.aliyun.com/raspbian/raspbian/ wheezy main non-free contrib
deb-src http://mirrors.aliyun.com/raspbian/raspbian/ wheezy main non-free contrib

替换后,更新源:
sudo apt-get update
更新后,更新已安装包:
sudo apt-get upgrade
更新完以后,树莓派基本上配置完成了!

安装和配置 Nginx/PHP/SQLite3

考虑到树莓派性能比较弱鸡,如果使用MySql或者其他数据库,那基本上每天都会宕机,综合考虑还是适合Nginx+SQLite3的配置较为合适,当然PHP是必不可少的。
安装nginx:
sudo apt-get install nginx
安装SQLite3:
sudo apt-get install sqlite3
安装PHP(PHP5):
sudo apt-get install php5-fpm
安装PHP5的SQLite支持:
sudo apt-get install php5-sqlite
安装PHP-APC优化:
sudo apt-get install php-apc

安装完毕,开始配置。

配置 Nginx:
nano /etc/nginx/nginx.conf
打开以后找到下面的位置,并修改:

user www-data; 
worker_processes 1; #修改这里 
pid /var/run/nginx.pid; 
events { 
   worker_connections 64; #修改这里 
   #multi_accept on; 
}

继续向后找到 gzip 去掉前面的注释 修改如下:

- gzip on; 
gzip_disable “msie6”; 
gzip_vary on; 
gzip_proxied any; 
gzip_comp_level 6; 
gzip_buffers 16 8k; 
gzip_http_version 1.1; 
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

保存并退出 nginx.conf。

配置 PHP:
nano /etc/php5/fpm/php.ini
打开以后找到下面的位置,并修改:

; Maximum amount of memory a script may consume (128MB) 
;http://php.net/memory-limit 
memory_limit = 32M #修改这里

继续向后面找或者手动搜索关键字,找到下面的位置,并修改:

; cgi.fix_pathinfo provides real PATH_INFO/PATH_TRANSLATED support for CGI. PHP’s 
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok 
; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting 
; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting 
; of zero causes PHP to behave as before. Default is 1. You should fix your scripts 
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. 
;http://php.net/cgi.fix-pathinfo 
cgi.fix_pathinfo=1 #修改这里

保存并退出 php.ini。

配置PHP-FPM:
nano /etc/php5/fpm/php-fpm.conf

找到下面的位置,并修改:

; The maximum number of processes FPM will fork. This has been design to control 
; the global number of processes when using dynamic PM within a lot of pools. 
; Use it with caution. 
; Note: A value of 0 indicates no limit 
; Default Value: 0 
process.max = 4 #修改这里

保存并退出 php-fpm.conf。

配置网站的相关配置,先备份一份较为安全:
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
修改配置文件:
sudo nano /etc/nginx/sites-available/default
一般来说,80端口是默认启用的,如果前面有#,那就去掉启用:

listen 80;

下面这一行需要增加一句index.php

index index.html index.htm;

变成:

index index.php index.html index.htm;

接着往下翻页继续修改

#location ~ \.php$ {
#       fastcgi_split_path_info ^(.+\.php)(/.+)$;
#       # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
#
#       # With php5-cgi alone:
#       fastcgi_pass 127.0.0.1:9000;
#       # With php5-fpm:
#       fastcgi_pass unix:/var/run/php5-fpm.sock;
#       fastcgi_index index.php;
#       include fastcgi_params;
#}

改为:

if (!-e $request_filename) {
    rewrite ^(.*)$ /index.php$1 last;
}
location ~ \.php$ {
#       fastcgi_split_path_info ^(.+\.php)(/.+)$;
#       # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
#
#       # With php5-cgi alone:
#       fastcgi_pass 127.0.0.1:9000;
#       # With php5-fpm:
       fastcgi_pass unix:/var/run/php5-fpm.sock;
       fastcgi_index index.php;
       include fastcgi_params;
}

修改完成以后,测试下PHP是否已经能正常支持
sudo nano /etc/home/pi/www/index.php #路径为之前配置里面定义的root根目录
输入如下内容:

<?php
      phpinfo();
?>

重启nginx,和php5-fpm
sudo /etc/init.d/nginx restart
sudo /etc/init.d/php5-fpm restart

局域网的电脑中输入树莓派的IP地址查看是否成功:

http://192.169.100.5/index.php

安装Typecho

上面的配置结束以后,基本上是一个已经能正常运行的环境了,但为了能顺利安装,还需要给文件夹目录授权:
sudo chmod 755 /home/pi/www -R

授权后下载最新的安装包并解压,解压完移动目录:
cd /home/pi/www
wget http://typecho.org/downloads/1.1-17.10.30-release.tar.gz
tar zxvf 1.1-17.10.30-release.tar.gz
mv build/* /home/pi/www

然后就按照官方给出的教程自己设置就 OK 了。

有些时候我们需要在服务器里使用一个脚本来运行服务,但是如果服务器重启了,还需要手动再执行一次,这样就比较麻烦,为了简化工作,可以把这些脚本加入到开机选项中去。

方法一

1.先编写启动脚本,注意模板代码前面注释不可以丢弃,如下:

#add for chkconfig
#chkconfig: 2345 70 30
#description: the description of the shell   #关于脚本的简短描述
#processname: servicename                    #第一个进程名,后边设置自启动的时候会用到

说明:
2345是指脚本的运行级别,即在2345这4种模式下都可以运行,234都是文本界面,5就是图形界面X
70是指脚本将来的启动顺序号,如果别的程序的启动顺序号比70小(比如44、45),则脚本需要等这些程序都启动以后才启动。
30是指系统关闭时,脚本的停止顺序号。

加入注释以后,接着后面添加需要加入开机启动的脚本或者服务。

2.chkconfig

给脚本添加上可执行权限:
chmod +x youshell.sh
利用chkconfig命令将脚本设置为自启动:
chkconfig --add servicename

方法二

编辑rc.local文件,将需要开机执行的脚本加入到文件中,需要注意要放在 exit 0 的前面,否则无效!
sudo nano /etc/rc.d/rc.local

例如:

# Other codes ...
# Your command add here
sudo sh /home/pi/Lanproxy/bin/startup.sh &
/etc/init.d/nginx start &
/etc/init.d/php5-fpm start &

exit 0

P.S.

有时我们自己在/etc/rc.d/rc.local里面增加的随机器启动的脚本和指令总是不能自动加载和启动,机器启动后手动执行脚本又能成功,经常被搞得晕头转向的。最近我经过1天的辛苦测试和查找资料,终于解决了这问题,因为我的脚本需要调用jdk,但是在该脚本执行过程中,环境变量未被加载,所以需要在所执行的sh脚本前手动加一句:

source /etc/profile #使环境变量生效