博客搬家

前言

3 月份腾讯云搞了一波活动,我也跟了一波车,花了 360 换了五年的服务器,美滋滋!虽然后来四月份阿里云也出了活动,我是更喜欢阿里云的,但是这波也不算亏。有了服务器之后做的第一件事就是把博客搬到服务器上,其实两个月前就弄好了,后来又折腾服务器去了,本来想等各种东西都折腾一遍后再写这篇博客,但是一拖拖到现在,罪过罪过!

系统环境为 CentOS 7.4,默认用户为 root

系统初始化

新系统需要安装更新和一些常用工具

$ yum -y update
// 安装 node 和 npm
$ yum install epel-release
$ yum install nodejs
$ node --version
$ npm --version

// 也可以通过 node 版本管理工具 nvm 安装 node
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
$ export NVM_DIR="${XDG_CONFIG_HOME/:-$HOME/.}nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
$ nvm install 8.9.1

// 设置 npm 源
$ npm config get registry
$ npm config set registry https://registry.npm.taobao.org

// 安装 git
$ yum install git
$ git --version

修改域名解析

原本域名是解析到 wangriyu.github.io 上,现在改为 A 类 ip 地址,填服务器的公有 ip

设置 webserver

安装最新版 nginx

$ vi /etc/yum.repos.d/nginx.repo

写入以下内容,baseurl 根据系统修改如果是 centos 6 的话把当中的 7 改成 6,输入 cat /etc/centos-release 或者 hostnamectl 可以查看系统版本信息

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=0

清空缓存

$ yum clean all
$ yum makecache

输入 list 可以查看是否包含最新版本

$ yum list | grep nginx

然后安装

$ yum install -y nginx
$ nginx -V # 查看版本
$ rpm -ql nginx # 列出nginx的安装文件

启动服务并设置开机自启动

$ systemctl start nginx
$ systemctl enable nginx

此时访问服务器 ip 应该可以看到 nginx 的默认欢迎页了

添加 Let’ Encrypt 通配符证书

国内的域名需要先备案,不然最后生成证书的时候可能会失败

使用 CertBot 来生成证书,不同系统的方法可以到官网看: https://certbot.eff.org/lets-encrypt/centosrhel7-nginx

安装 Certbot

$ yum -y install yum-utils
$ yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
$ yum install certbot-nginx

生成证书:

$ certbot certonly --manual -d *.wangriyu.wang --agree-tos --manual-public-ip-logging-ok --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory

zsh 可能需要在 * 前加上反斜杠 \

这里 *.wangriyu.wang 并不包括 wangriyu.wang,你可以添加多个域名,比如再加上 -d wangriyu.wang,但是这样打包的话后面续期会有问题

输入上面的命令后会提示添加一条 DNS TXT 的记录,需要手动到你服务器的 DNS 解析那里添加,添加完等一会儿在回车确认

image

证书创建好后会输出证书位置,可以到 nginx 里设置 server 的 ssl_certificate 和 ssl_certificate_key 为生成的证书位置

$ certbot certificates // 查看本地证书信息

$ certbot delete // 删除证书

续期问题

Let’s Encrypt 证书只有 90 天有效期,普通证书快到期时可以用 certbot renew 直接更新证书,但是通配符证书续期需要重新验证 DNS,一般只能手动更新,不过已经有大神写好脚本调用 api 实现自动更新 DNS 记录了,仓库地址: https://github.com/ywdblog/certbot-letencrypt-wildcardcertificates-alydns-au

我们需要的是 PHP 环境和一份 api 密钥,以 CentOS7 和腾讯云 DNS 为例

## 安装 php7
$ rpm -ivh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
$ rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
$ yum install php70w
$ php -v

## 拉取脚本
$ git clone https://github.com/ywdblog/certbot-letencrypt-wildcardcertificates-alydns-au
$ cd certbot-letencrypt-wildcardcertificates-alydns-au
$ chmod 0777 au.sh autxy.sh python-version/au.sh

https://console.cloud.tencent.com/cam/capi 页面获取 SecretId 和 SecretKey,编辑 txydns.php 文件,将 SecretId 填入 txyaccessKeyId,将 SecretKey 填入 txyaccessSecrec,这里注意别弄反了

## 可以先用 --dry-run 试下是否能成功
$ certbot renew --manual --preferred-challenges dns --manual-auth-hook /脚本目录/autxy.sh --dry-run
## 如果不报错就可以直接 renew 了
$ certbot renew --manual --preferred-challenges dns --manual-auth-hook /脚本目录/autxy.sh

## 再添加进 cron 任务每周 renew 一次
$ crontab -e
写入 30 0 * * 0 certbot renew --manual --preferred-challenges dns --manual-auth-hook /脚本目录/autxy.sh --renew-hook "/usr/sbin/nginx -s reload"

$ crontab -l # 查看所有任务
$ service crond restart

pyOpenSSL 版本报错

如果之后使用 certbot 出现 ImportError: ‘pyOpenSSL’ module missing required functionality. Try upgrading to v0.14 or newer. 错误
依次输入以下命令可以修复

$ pip uninstall requests
$ pip uninstall urllib3
$ yum remove python-urllib3
$ yum remove python-requests
$ yum remove certbot
$ yum install python-urllib3
$ yum install python-requests
$ yum install certbot

配置服务器和虚拟机

$ cd /etc/nginx
$ tree .
├── conf.d # 虚拟机文件,最好一个域名一个文件
│   ├── default.conf
│   ├── blog.wangriyu.wang.conf
│   └── wangriyu.wang.conf
├── default.d
├── nginx.conf # 服务器配置文件
├── ssl
│   └── dhparam.pem
└── ...

详细的设置我这不多说,上网搜一下 nginx 配置大把教程,我这里贴一下我的配置,仅作参考

  • nginx.conf
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;
    tcp_nodelay    on;

    keepalive_timeout  60;

    server_tokens off;

    # 设置 gzip 压缩
    gzip  on;
    gzip_min_length 1k;
    gzip_comp_level 3;
    gzip_buffers    16 8k;
    gzip_types text/plain application/javascript application/x-javascript application/octet-stream application/json text/css application/xml text/javascript application/x-httpd-php image/jpeg image/jpg image/gif image/png font/ttf font/otf image/svg+xml;
    gzip_vary on;
    gzip_proxied       any;
    gzip_disable "MSIE [1-6]\.";

    fastcgi_intercept_errors on;

    include /etc/nginx/conf.d/*.conf;
}
  • blog.wangriyu.wang.conf
server {
     server_name  blog.wangriyu.wang;

     # Load configuration files for the default server block.
     include /etc/nginx/default.d/*.conf;

     # 开启 tls 和 http2
     listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
     listen 443 ssl http2; # managed by Certbot
     ssl_certificate /path/to/fullchain.pem; # managed by Certbot
     ssl_certificate_key /path/to/privkey.pem; # managed by Certbot
     include /path/to/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
     ssl_dhparam /path/to/letsencrypt/ssl-dhparams.pem; # managed by Certbot

     # 优化 OCSP 查询
     ssl_stapling on;
     ssl_stapling_verify on;
     ssl_trusted_certificate /path/to/letsencrypt/live/wangriyu.wang/chain.pem;

     resolver                 8.8.4.4 8.8.8.8  valid=300s;
     resolver_timeout         10s;

     # HSTS 策略
     add_header Strict-Transport-Security "max-age=63072000; includeSubdomains" always;

     # 静态文件目录
     root /www/website;
     index index.html index.htm;

     # 设置 http2 的 ServerPush 文件,需要 nginx/1.13.9 以上才支持此功能
     location = /index.html {
       http2_push /css/style.css;
       http2_push /js/main.js;
       http2_push /img/yule.jpg;
       http2_push /img/avatar.jpg;
     }

     # 设置静态文件缓存时间
     location ~* ^.+\.(ico|gif|jpg|jpeg|png|moc|mtn|mp3|mp4|mov)$ {
       access_log   off;
       etag         on;
       expires      30d;
     }

     location ~* ^.+\.(css|js|txt|xml|swf|wav|json)$ {
       access_log   off;
       etag         on;
       expires      5d;
     }

     location ~* ^.+\.(html|htm)$ {
       etag         on;
       expires      24h;
     }

     location ~* ^.+\.(eot|ttf|otf|woff|svg)$ {
       access_log   off;
       etag         on;
       expires      30d;
     }

     # 设置 404 错误页
     error_page 404 403 /404.html;
     location = /404.html {
       root /www/website;
     }

     error_page 500 502 503 504 /50x.html;
       location = /50x.html {
     }
}

# 重定向非加密连接的访问
server {
    if ($host = blog.wangriyu.wang) {
      return 301 https://$host$request_uri;
    } # managed by Certbot

    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  blog.wangriyu.wang;
    return 404; # managed by Certbot
}
  • wangriyu.wang.conf
server {
    server_name wangriyu.wang;

    listen 80;
    listen 443 ssl;

    return 301 https://blog.wangriyu.wang$request_uri;
}

关于 nginx 的配置推荐看下屈大大的博客: Nginx 配置之性能篇Nginx 配置之安全篇

通过优化 SEO 分数比 githubpage 要高得多

image

image

nginx 访问的目录要存放博客生成的静态文件,接下来会介绍如何使用 git 部署

搭建 Git 服务

之前博客是托管在 github 上的,我是在本地编辑完后再 push 到远端。现在放到服务器上,若用 git 部署,需要在服务器上搭建 Git 服务。

创建用户

创建一个 git 专用的用户

$ useradd -m git
$ passwd git # 设置密码,之后部署时登录用

禁用 git 用户的 shell 登录权限

出于安全考虑,我们要让 git 用户不能通过 shell 登录。可以编辑 /etc/passwd 来实现,在 /etc/passwd 中找到类似下面的一行:

git:x:1001:1001::/home/git:/bin/bash

将 bash 改为 git-shell,可以通过 which git-shell 获取

git:x:1001:1001::/home/git:/usr/bin/git-shell

这样 git 用户可以通过 ssh 正常使用 git,但是无法登录 sehll

创建仓库

新建一个 git 仓库地址比如 /data/git-repo。然后在这个文件夹里创建 blog.git 这个仓库。

$ mkdir /data/git-repo
$ cd /data/git-repo
$ git init --bare blog.git

然后进入 blog.git 可以看到 hooks 文件夹,可以再这里面写 Git Hook 脚本,不了解钩子的可以看下 Git 钩子

$ cd blog.git/hooks
$ vi post-update

写入:

#!/bin/sh
git --work-tree=/www/website --git-dir=/data/git-repo/blog.git checkout -f

worktree 就是我们要放置静态文件的目录,每次这个裸库收到 git 更新时会把文件更新到 worktree,这样 nginx 就可以访问新部署的文件了

如果 post-update 不是可执行权限,输入 chmod +x post-update 设置为可执行

设置权限

这里要注意的一点是除了要设置仓库的所有者和可读写权限外,还要设置工作目录,即静态文件存放的地方,要不然钩子函数可能更新不了工作目录

$ chown -R git:git /data/git-repo/blog.git
$ chmod 755 /data/git-repo/blog.git

$ chown -R git:git /www/website
$ chmod 755 /www/website

到本地使用 git 克隆服务器上的仓库测试一下是否可用:

$ git clone git@<CVM IP>:/data/git-repo/blog.git

到此服务器的配置应该已经结束

测试本地编辑部署

到 hexo 博客目录,编辑站点配置文件 _config.yml 的 deploy 选项

deploy:
  - type: git
    repo:
      github: git@github.com:wangriyu/wangriyu.github.io.git
      server: git@<CVM IP>:/data/git-repo/blog.git
    branch: master

之后同样使用 hexo clean && hexo g && hexo d 命令,然后输入 git 用户的密码就可部署到服务器上了

如果不想每次都输密码可以去创建一个密钥放到本地,这里就不叙述了

升级 vim

$ cd /etc/yum.repos.d/
$ wget https://copr.fedorainfracloud.org/coprs/mcepl/vim8/repo/epel-7/mcepl-vim8-epel-7.repo
$ rpm --import https://copr-be.cloud.fedoraproject.org/results/mcepl/vim8/pubkey.gpg
$ yum update vim

如果 update vim 报错:

Transaction check error:
  file /usr/share/man/man1/vim.1.gz from install of vim-common-2:8.0.1735-1.0.96.el7.centos.x86_64 conflicts with file from package vim-minimal-2:7.4.160-2.el7.x86_64

Error Summary

先执行一下 yum erase vim-minimalyum update vim

如果升级后发现只能用 vim 命令不能用 vi,设置如下

$ ls -l /usr/bin | grep vi
$ cp /usr/bin/vim /usr/bin/vi

推荐安装 oh-my-zsh,配合 zsh-syntax-highlighting 插件和合适的主题,可以大大改善 shell 使用体验

接下来会写几篇折腾服务器的博客,比如搭建 FTP、nextcloud、docker 等等

文章目录
  1. 前言
  2. 系统初始化
  3. 修改域名解析
  4. 设置 webserver
    1. 安装最新版 nginx
    2. 添加 Let’ Encrypt 通配符证书
      1. 续期问题
      2. pyOpenSSL 版本报错
    3. 配置服务器和虚拟机
  5. 搭建 Git 服务
    1. 创建用户
    2. 创建仓库
    3. 设置权限
  6. 测试本地编辑部署
  7. 升级 vim