CentOS 7 上配置 Let’s Encrypt 的 SSL 免费证书

参考官方文档:https://certbot.eff.org/lets-encrypt/centosrhel7-apache

启用EPEL储存库

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

安装 certbot 工具

$ sudo yum install python2-certbot-apache

安装 SSL 证书

$ sudo certbot --apache

续订证书 (证书有效期3个月)

$ sudo certbot renew

自定续订证书 (systemd timer)

创建 certbot 的 systemd service

$ sudo vi /etc/systemd/system/certbot.service
# certbot.service

[Unit]
Description=Certbot renew

[Service]
ExecStart=/usr/bin/certbot renew
ExecStartPost=/bin/systemctl reload httpd.service 

[Install]
WantedBy=multi-user.target

创建 certbot 的 systemd timer

$ sudo vi /etc/systemd/system/certbot.timer
[Unit]
Description=Auro certbot renew
 
[Timer]
OnCalendar=daily  
Persistent=true
 
[Install]
WantedBy=timers.target

启用 certbot 的服务以及它的定时器

$ sudo systemctl enable certbot.service
$ sudo systemctl start certbot.timer

查看定时器列表

$ systemctl list-timers --all

在 Centos7 上搭建 shadowsocks

安装epel源

$ sudo yum -y install epel-release

安装pip包管理

$ sudo yum -y install python-pip

使用pip安装shadowsocks

$ sudo pip install shadowsocks
如果出现 Command "python setup.py egg_info" failed 错误信息,则输入 pip install --upgrade pip 命令后,再执行上面的操作。
如果出现 Could not import setuptools which is required to install from a source distribution 错误信息,则输入 pip install setuptools 命令后,再执行上面的操作。

建立shadowsocks配置文件

$ sudo vi /etc/shadowsocks/shadowsocks.json

单端口配置

{
 "server":"0.0.0.0",
 "server_port":8838,
 "local_address": "127.0.0.1",
 "local_port":1080,
 "password":"123456",
 "timeout":300,
 "method":"aes-256-cfb",
 "fast_open": false
}

多端口配置

{
 "server":"0.0.0.0",
 "local_address": "127.0.0.1",
 "local_port":1080,
 "port_password": {
 "8838": "123456"
 },
 "timeout":300,
 "method":"aes-256-cfb",
 "fast_open": false
}

开启防火墙的端口访问

$ sudo firewall-cmd --zone=public --add-port=8388/tcp --permanent;
$ sudo firewall-cmd --reload;

启动shadowsocks

$ sudo ssserver -c /etc/shadowsocks/shadowsocks.json -d start

配置shadowsocks服务自启动

编辑 shadowsocks 服务配置文件

$ sudo vi /etc/systemd/system/shadowsocks.service
# shadowsocks.service

[Unit]
Description=Shadowsocks
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/ssserver -c /etc/shadowsocks/shadowsocks.json -d start
ExecReload=/usr/bin/ssserver -c /etc/shadowsocks/shadowsocks.json -d restart
ExecStop=/usr/bin/ssserver -d stop
PrivateTmp=true

[Install]
WantedBy=multi-user.target

服务的启动与关闭

$ systemctl start shadowsocks  // 启动
$ systemctl stop shadowsocks // 停止
$ systemctl restart shadowsocks // 重启
$ systemctl enable shadowsocks // 启用开机启动
$ systemctl disable shadowsocks // 禁用开机启动

CentOS7 LAMP环境安装

httpd

$ yum install -y httpd

开启防火墙http与https的端口

$ firewall-cmd --permanent --zone=public --add-service=http
$ firewall-cmd --permanent --zone=public --add-service=https

mariadb

$ yum install -y mariadb mariadb-server

初始化 mariadb 的账户配置

$ mysql_secure_installation

使用合适的配置文件

$ ls /usr/share/mysql/my-*
my-huge.cnf  my-innodb-heavy-4G.cnf  my-large.cnf  my-medium.cnf  my-small.cnf
$ mv /etc/my.cnf /usr/share/mysql/my.default.cnf # 备份默认配置
$ cp /usr/share/mysql/my-small.cnf /etc/my.cnf  # 复制新的配置文件

php56

# 安装 yum 支持库
$ rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
# 查看可安装的 php 列表
$ yum list php*
# 安装 php
$ yum install -y php56w php56w-mysql php56w-gd libjpeg* php56w-ldap php56w-odbc php56w-pear php56w-xml php56w-xmlrpc php56w-mbstring php56w-bcmath

配置默认时区

$ vi /etc/php.ini
# 修改行内容如下
date.timezone = PRC

服务的启动与关闭

$ systemctl start [server name]  // 启动
$ systemctl stop [server name] // 停止
$ systemctl restart [server name] // 重启
$ systemctl enable [server name] // 启用开机启动
$ systemctl disable [server name]// 禁用开机启动

Ubuntu 搭建 Zerotier One MOON 根目录服务器

博主倒腾了一天,总算搞定了,主要是受到各种搭建教程的错误引导,导致关键过程错误。
官网的MOON搭建教程:https://www.zerotier.com/manual.shtml
官网的安装教程:https://www.zerotier.com/download.shtml

前提概要
Zerotier One 版本:v1.2.10
10.0.0.2是一个公网IP, 根据实际情况设定
deadbeef00是根服务器的ID, sudo zerotier-cli info获取

根服务器节点

通过 identity.public 生成一个 moon.json 文件

sudo zerotier-idtool initmoon /var/lib/zerotier-one/identity.public >> moon.json

编辑 moon.json 文件,写入根服务器IP "stableEndpoints": [ "10.0.0.2/9993"]

{
  "id": "deadbeef00",
  "objtype": "world",
  "roots": [
    {
      "identity": "deadbeef00:0:34031483094...",
      "stableEndpoints": [ "10.0.0.2/9993"]
    }
  ],
  "signingKey": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
  "signingKey_SECRET": "ffc5dd0b2baf1c9b220d1c9cb39633f9e2151cf350a6d0e67c913f8952bafaf3671d2226388e1406e7670dc645851bf7d3643da701fd4599fedb9914c3918db3",
  "updatesMustBeSignedBy": "b324d84cec708d1b51d5ac03e75afba501a12e2124705ec34a614bf8f9b2c800f44d9824ad3ab2e3da1ac52ecb39ac052ce3f54e58d8944b52632eb6d671d0e0",
  "worldType": "moon"
}

生成 .moon 文件

sudo zerotier-idtool genmoon moon.json

移动 .moon 文件到 moons.d 文件夹中(需要手动创建该文件夹)

sudo mv 000000deadbeef00.moon /var/lib/zerotier-one/moons.d/

重启 zerotier-one

sudo killall -9 zerotier-one

常规节点

将根服务器添加到常规节点

sudo zerotier-cli orbit deadbeef00 deadbeef00

如果自动加载moon文件失败,请手动拷贝000000deadbeef00.moon文件到常规节点的机器上

Windows: C:\ProgramData\ZeroTier\One
Macintosh: /Library/Application Support/ZeroTier/One (在 Terminal 中应为 /Library/Application\ Support/ZeroTier/One)
Linux: /var/lib/zerotier-one
FreeBSD/OpenBSD: /var/db/zerotier-one

重启 zerotier-one

sudo killall -9 zerotier-one

查看节点列表,出现根服务器的MOON节点表示成功

$ sudo zerotier-cli listpeers
200 listpeers
200 listpeers 8841408a2e 159.203.2.154/9993;7723;2322 244 1.1.5 PLANET
200 listpeers 9d219039f3 154.66.197.33/9993;1527750499073;2055 479 1.1.5 PLANET
200 listpeers deadbeef 00 10.0.0.2/33389;2552;7773 189 1.2.10 MOON
200 listpeers e4da7455b2 - -1 1.2.5 LEAF

基于 vue-cli 的 webpack 打包之第三方库优化

由于加入了数个较为庞大的库,导致vendor.js 达到了恐怖的8M, 为此参考了网上的不少优化资料,并查阅官方文档进行一定的修正,得出一个较为满意的方案。
首先优化方案有两种 CDN和 DLL。

CDN 方案

该非常直接,粘贴到index.html模板中, 在build/webpack.base.conf.js 加上externals: { 'jquery': 'Jquery' }, 使用时和正常安装的没有区别, webpack打包时并不会引入该包。
CDN方案具体就不多介绍,因为这个方案在深思熟虑后被放弃了,因为别人的 CND无法放心,可能会极小可能访问出现问题,而且包过多时请求数暴涨会引起页面加载的缓慢。

DLL 方案

此方案属于对vendor.js文件打包的再次优化,有目标的合并较小的包,较大的包单独存在。
执行此方案前需要知道哪些包占了vendor.js文件较大的位置,可以独立出来,此时可以在package.json加上新的运行命令(使用了vue-cli内置的webpack-bundle-analyzer)

"build:sit-preview": "NODE_ENV=production env_config=sit npm_config_preview=true npm_config_report=true node build/build.js"

通过webpack-bundle-analyzer我们可以观察到包的组成情况dll的配置
 
接下来开始优化,在config/index.js文件中新增一个dll配置对象

   dll: {
    entry: {
      vue: [
        'vue/dist/vue.esm.js',
        'vue-router',
        'vuex'
      ],
      ui: [
        'element-ui'
      ],
      echarts: [
        'echarts'
      ],
      utils: [
        'axios',
        'lodash',
        'jquery',
        'moment'
      ],
      other: [
        'perfect-scrollbar'
      ]
    },
    outputPath: path.resolve(__dirname, '../dist/dll'),
    publicPath: '/dll/'
  }

 
新增一个build/webpack.dll.conf.js文件, 需要先安装webpack-manifest-plugin库支持,该库为dll文件生成了一个文件列表

const path = require('path')
const webpack = require('webpack')
const ManifestPlugin = require('webpack-manifest-plugin')
const config = require('../config').dll
const webpackConfig = {
  entry: config.entry,
  output: {
    path: config.outputPath,
    filename: '[name].dll.[chunkhash].js',
    library: '[name]_library',
    publicPath: config.publicPath
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh-cn|en-gb/),
    new webpack.DllPlugin({
      path: path.join(config.outputPath, '[name]-manifest.json'),
      libraryTarget: 'commonjs2',
      name: '[name]_library'
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),
    new ManifestPlugin({
      fileName: path.join(config.outputPath, 'manifest.dll.json')
    })
  ]
}
module.exports = webpackConfig

 
新增一个build/build-dll.js文件,其作用是运行前面配置好的打包dll文件

'use strict'
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config').dll
const webpackConfig = require('./webpack.dll.conf')
const spinner = ora('开始构建 dll...')
spinner.start()
rm(path.resolve(__dirname, config.outputPath), err => {
  if (err) throw err
  webpack(webpackConfig, function (err, stats) {
    spinner.stop()
    if (err) throw err
    process.stdout.write(stats.toString({
      colors: true,
      modules: false,
      children: false,
      chunks: false,
      chunkModules: false
    }) + '\n\n')
    if (stats.hasErrors()) {
      console.log(chalk.red('  构建发生了错误.\n'))
      process.exit(1)
    }
    console.log(chalk.cyan('  构建完成.\n'))
    console.log(chalk.yellow(
      '  提示:当第三方库升级或变动时,请重新构建dll .\n'
    ))
  })
})

 
此时只需要在package.json文件中增加一个script方法

 "build:dll": "node build/build-dll.js"

运行yarn run build:dll可以在dist/dll文件夹中看到打包的dll文件
接下来让build项目时引入dll文件,让其打包时不引入dll已经打包的库
build/utils.js中增加一个辅助方法, 用于快速获得dll文件的路径

exports.dllPath = function (_path) {
  const outputPath = config.dll.outputPath
  return path.posix.join(outputPath, _path)
}

 
接下来修改build/webpack.prod.conf.js文件

// 获得dll文件的列表
const manifestDll = require(utils.dllPath('manifest.dll.json'))

HtmlWebpackPlugin插件中加一行

dll: manifestDll,

DllReferencePlugin插件注入到webpack,由于有多个 dll 文件,采用了自执行的匿名循环新建插件实例,运用扩展运算符写入到webpackConfig

  ...(function () {
      let res = []
      let keys = Object.keys(config.dll.entry)
      keys.forEach(key => {
        res.push(new webpack.DllReferencePlugin({
          context: path.resolve(__dirname, '../'),
          manifest: require(utils.dllPath(`${key}-manifest.json`))
        }))
      });
      return res
    })()

 
最后只需要在index.html模板中添加dll打包文件

 <!-- dll files will be auto injected -->
 <% for (var name in htmlWebpackPlugin.options.dll) { %>
   <script type="text/javascript" src="<%= htmlWebpackPlugin.options.dll[name] %>"></script>
 <% } %>

 

在升级第三方库的情况下,dll文件可以以一直使用,不需要打包。
现在运行build速度飞快,webpack不用每次都去重复打包第三方库了