在 vultr 买了新的主机,准备把网站迁过去。机房选在洛杉矶,果然西海岸的稳定性还是最好啊,丢包也少,东京在晚上高峰丢包太高了,受不了。说来在 V 家之前还试了试 IOZoom 的机子,然而到手时分到个被墙的 ip,ssh 都连不上,然后提工单换了;买了个亚洲优化,也就是 CN2 路线的 ip,又是被墙的我去……来来回回折腾几下相当失望,换完 ip 后高峰期丢包还是高得不行,基本在 10%(CN2) 和 16%(主 ip) 左右,后面果断退钱了。之后就入了 vultr 的。

现在记录一下从头搭建的过程吧。专为 centos 7 x64 量身打造。

SSH

  1. 首先设置 ssh 公钥访问、更换默认端口和取消密码访问
  2. 使用
    ssh-keygen -t rsa

    生成一对 rsa 密钥对存放在 /root/.ssh/ 目录下,带 .pub 后缀的是公钥

  3. 使用
    cat id_rsa.pub > authorized_keys

    导入。

  4. sftp 下载公私钥到本地,先保存好,怎么用下面会说,现在接着配服务器。
  5. 修改配置文件(/etc/ssh/sshd_config)
    • 去掉
      PubkeyAuthentication yes
      AuthorizedKeysFile      .ssh/authorized_keys

      前的 # 注释。

    • #Port 22 的注释去掉,并改为一个任意的空闲高位端口。
    • PasswordAuthentication yes 改为 PasswordAuthentication no

    保存退出后使用

    systemctl restart sshd

    重启 ssh。

  6. 配置 centos7 防火墙
    1. 添加新的端口 A,就是刚刚在 ssh 配置里填的那个,比如下面的命令添加了 tcp 的 7777 端口(顺便一提把命令中的 “add” 换成 “remove” 即可删除;把 “7777” 换成 “7777-8888” 即可添加范围端口)。
      firewall-cmd --permanent --zone=public --add-port=7777/tcp
    2. 重新加载规则
      firewall-cmd --reload
    3. 添加自启动
      systemctl enable firewalld
    4. ※ 这里添加一条就结束了,其他端口的添加如法炮制即可。
    5. ※ 添加 http(s) 等类似常用端口可以直接添加现有服务来完成
      firewall-cmd --permanent --zone=public --add-service=http
      firewall-cmd --permanent --zone=public --add-service=https
    6. ※未尽的说明可参考 vultr 的文档 Using FirewallD to Manage Your Firewall on CentOS 7
    • 防火墙有各种 “zone”,其实就是不同的规则集,默认是 “public” zone,可用
      firewall-cmd --get-default-zone
      firewall-cmd --set-default-zone=home

      查看和修改。

    • 查看某个 zone 下的现有规则
      firewall-cmd --zone=public --list-ports
      firewall-cmd --zone=public --list-services
  7. ※ 如果在 vultr 的 web 面板中配置了防火墙规则,则在那里也要进行相应的端口添加。
  8. 以上配置完成后在 port.ping.pe 中检测相应端口的结果应该是可以成功连接的。没成功前千万别退出现有的 ssh 连接哦,因为没有后路了(o???)
    (配置 sshd_config 时不删除 Port 22,直接补充一行如 Port 7777 即可同时监听两个端口,全部配完再删掉 22 端口。)
  9. (本地电脑上)用 puttygen.exe 打开下载的私钥(软件界面上的 “Load” 按钮),完成后再点 “Save private key” 另存为 ppk 文件,这样在 putty 中就能使用该私钥登录了(在 Connection-SSH-Auth 中填入 ppk 文件路径,在 Connection-Data 中的 “Auto login username” 中填入你的用户名)。

BBR

  1. 添加 ELRepo 源
    rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
    rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
  2. 安装最新内核
    yum --enablerepo=elrepo-kernel install kernel-ml -y
  3. 成功后用
    rpm -qa | grep kernel

    列出已安装的内核,其中应含有形如 “kernel-ml-5.0.6-1.el7.elrepo.x86_64” 的输出。

  4. 列出 grub2 启动菜单
    egrep ^menuentry /etc/grub2.cfg | cut -f 2 -d \'
  5. 按顺序从上往下找到 5.0.6 内核的行数,第一行序号是 0,记住序号,输入
    grub2-set-default <你的序号>
  6. 重启
    shutdown -r now
  7. 重启后查看
    uname -r

    应显示 5.0.6 内核。

  8. 启用 BBR。逐行执行
    echo 'net.core.default_qdisc=fq' | sudo tee -a /etc/sysctl.conf
    echo 'net.ipv4.tcp_congestion_control=bbr' | sudo tee -a /etc/sysctl.conf
    sysctl -p
    // 确认:sysctl net.ipv4.tcp_available_congestion_control 输出应类似 "reno cubic bbr"
    // 确认:sysctl -n net.ipv4.tcp_congestion_control 输出应为 "bbr"
    // 确认:lsmod | grep bbr 输出含有 "tcp_bbr"

    完成

  9. ※ Ex: OpenVZ 用的 BBR 一键脚本

LNMP

  1. 安装 nginx
    yum install nginx -y
    systemctl enable nginx
    systemctl start nginx

    现在通过 ip 直接访问应该可以看过欢迎页(防火墙已开,参照 ssh 处设置防火墙)。

  2. 可在配置文件的 http 块中添加一行 server_tokens off; 来隐藏 nginx 的版本。
  3. 安装 php7
    // yum list installed | grep php    // 新机肯定没装 php,装过的要先卸掉。看一眼
    rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm    // 更新 rpm 源
    yum install php70w php70w-fpm php70w-mysql -y
    systemctl enable php-fpm
    systemctl start php-fpm
    
  4. 配置 nginx。php-fpm 的默认端口为 9000,现在将它加入 nginx 的配置中(此处不用开防火墙,内部使用)。打开 nginx 配置文件
    vi /etc/nginx/nginx.conf

    在 “server” 块的末尾加上

    location ~ \.php$ {
          fastcgi_pass   127.0.0.1:9000;
          fastcgi_index   index.php;
          fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
          include        fastcgi_params;
      }

    保存退出并

    systemctl restart nginx

    重启 nginx。

  5. 安装 MariaDB。有疑问可直接看 How to Install MariaDB 10.1 on CentOS 7
    1. 创建 yum repo :粘贴以下全部后一次执行
      cat &lt;&lt; EOF | sudo tee -a /etc/yum.repos.d/MariaDB.repo
      # MariaDB 10.1 CentOS repository list
      # http://downloads.mariadb.org/mariadb/repositories/
      [mariadb]
      name = MariaDB
      baseurl = http://yum.mariadb.org/10.1/centos7-amd64
      gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
      gpgcheck=1
      EOF
    2. yum 安装
      yum install MariaDB-server MariaDB-client -y
    3. 启动并加入自启动
      systemctl start mariadb.service
      systemctl enable mariadb.service
    4. 安全化配置
      /usr/bin/mysql_secure_installation

      当前数据库 root 密码为空直接回车,然后设置新的 root 密码,脚本中所有 yes/no 的选项都选 yes 即可,不放心的也可每个看一遍,都很直白的选项。

  6. ※ php-fpm进程过多,内存耗尽
    1. 打开 /etc/php-fpm.conf,翻到最后的 Pool Definitions 节,里面包含了 /etc/php-fpm.d/ 目录下的 .conf 文件
    2. 打开 /etc/php-fpm.d/www.conf(只有这一个),修改
      # 另一种模式 ondemand 工作方式是直接杀死空闲了 pm.process_idle_timeout 秒的闲置进程
      pm = dynamic
      # 最大数根据内存情况设置,也不能太小
      pm.max_children = 10
      pm.start_servers = 3
      # 最小和最大的闲置进程数,dynamic 模式只会杀死超过最大闲置进程数的进程
      pm.min_spare_servers = 1
      pm.max_spare_servers = 3
      pm.max_requests = 2048
      request_terminate_timeout = 1200
    3. 重启 php-fpm
      systemctl restart php-fpm

ss

秋水逸冰一键脚本四合一版:Shadowsocks 一键安装脚本(四合一)

kcptun

焕发第二春

  1. 下载一键脚本进行安装
    wget --no-check-certificate https://github.com/kuoruan/shell-scripts/raw/master/kcptun/kcptun.sh
    chmod +x ./kcptun.sh
    ./kcptun.sh
  2. 设置 kcptun 服务器端口,默认为 29900,有防火墙的话注意打开。
  3. 设置加速地址,一般 ss 监听的端口都是形如 0.0.0.0:7777,所以 kcptun 的地址和加速端口分别填 127.0.0.1 和 <你的ss端口> 即可。
  4. 设置 kcptun 用的密钥用于客户端和服务器认证,注意和 ss 的密码是两回事。
  5. 剩下的可直接用脚本的默认设置。
  6. kcptun Release 下载合适的客户端。
  7. 以 windows 为例,可以
    client_windows_amd64.exe -c config.json

    启动客户端, json 来自安装服务器时的输出,或是直接在命令行中一个个指定参数

    client_windows_amd64.exe -r <ip>:<port> --key <kcptun 的密码> --sndwnd 512

    因为我的服务器 sndwnd 设为 512,和默认的 128 不同,所以重新指定,其他参数因为和默认值一样所以不用特地在命令行中指出了。

  8. 这样就能顺利连接了。
  9. 手机端
    1. 下载用于 ss 客户端的 kcptun-Android 插件:
    2. 在 ss 的配置界面里选择插件为 kcptun。
    3. 在插件下面的配置编辑框中填入服务器的配置内容(来自安装服务器时的输出,当然自己指定也是一样的)。
    4. 在插件配置中补充
      remoteaddr=<你的服务器ip>:<你的 kcptun 端口>

    5. 保持其他 ss 配置不变就能顺利连接了。
    6. 如有不能连接的情况首先确保禁用 kcptun 插件时能正常使用 ss;然后再校对 kcptun 的各个参数。要是还没用的话把插件中的 UDP Fallback 打开,选另一个 ss 节点就能连上了。
  10. ※ 有疑难可以看作者的博客

docker

这个其实是个可选项,一起塞在这里吧。

docker 前置条件是 kernel 大于等于 3.10,centos 7 没问题。

  1. yum 安装
    yum upgrade -y
    yum install docker -y
    systemctl start docker
  2. 设置镜像。打开 /etc/docker/daemon.json,添加成
    {
      "registry-mirrors": ["https://aj2rgad5.mirror.aliyuncs.com"]
    }

    保存退出。

  3. 重启docker
    systemctl daemon-reload
    systemctl restart docker.service
  4. 测试docker
    docker run hello-world

    应该有 “Hello from Docker!” 的输出。

到这里基本的部署就结束了,下面就把 wordpress 整个搬过来就好了。

迁移 wordpress

一开始想尝试直接修改 wp 的站点链接后复制整个目录和数据库,结果失败了,页面样式一直没法正常显示,浪费了不少时间搞来搞去。于是走常规路线,将插件 UpdraftPlus Backup 备份的数据进行还原。

  1. wget http://wordpress.org/latest.tar.gz
    tar -xzf latest.tar.gz

    下载最新版 wp 并解压到安装目录。

  2. 创建和原来相同的数据库和数据库用户。
    // 以数据库名=wordpress,用户名=wp@localhost 为例,原密码 pwd 也保持一致
    CREATE DATABASE wordpress;
    CREATE USER wp@localhost;
    SET PASSWORD FOR wp@localhost=PASSWORD("pwd");
    GRANT ALL PRIVILEGES ON wordpress.* TO wp@localhost IDENTIFIED BY 'pwd';
    FLUSH PRIVILEGES;
  3. 设置 wp 目录下的 wp-config.php 文件。
    /** 数据库名 */
    define('DB_NAME','wordpress');
    /** 数据库用户 */
    define('DB_USER','wordpress');
    /** 数据库密码 */
    define('DB_PASSWORD','pwd');
  4. 将 wp 所在整个目录的所有权转移给 apache 用户。以便 wp 能正常运行。
  5. 访问 <yoursite>/wp-admin/install.php 进行安装。
  6. 安装 UpdraftPlus Backup 插件并连接原来进行备份的云端账号(如果是用其他方式备份的保持相同即可),导入账号中的备份数据。
  7. 还原后一切正常。

做 wp 的修改的时候要注意 wp-content/cache 目录下的缓存,会导致改动的效果不会立刻展现。

最后强烈推荐安装 Classic Editor 插件回复经典编辑器界面,md 辣鸡 Gutenberg 浪费我时间。

Ex: frp with nginx

让 nginx 把 443 的 https 连接转发到 frps 做内网穿透。

下载最新版 frp。注意服务器和客户端的软件版本要保持一致。现在的版本加入了 systemd 的服务脚本,使用更方便了。以服务器为例,将解压后的 systemd/frps.service 复制到 /etc/systemd/system 下,frps 复制到 /usr/bin/ 下,frps.ini 复制到 /etc/frp/ 下,最后 systemctl enable frpssystemctl start frps 即可。
基本的配置就跳过了,就说下 nginx 转发的事。首先在 frps 配置中修改设置

vhost_https_port = 9100

随后在 nginx 配置中添加这么一个 server 块。

server {
    listen       443 ssl http2;
    listen       [::]:443 ssl http2;
    server_name <你要映射的外网域名>;
    ssl_certificate "<tls 证书>.crt";
    ssl_certificate_key "<tls 证书>.key";
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    location / {
        resolver 8.8.8.8;
        proxy_ssl_server_name on;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_pass https://$host:9100;    # 与 frps 中的端口保持一致即可
    }
}

最后在 frpc(客户端)配置中加入

[https1]
type = https
local_port = 443    ; 客户端本地服务使用的端口
custom_domains = <你要映射的外网域名>

就可以顺利连接了。

这里省略了基本的配置过程,所以在配置 nginx 转发前应确保正常的比如 tcp 转发能够进行,最后加入上面的配置就没问题了。

更新:一开始连接都是正常的,第二天才出现了 502 bad gateway 的错误,原因在于 frp 客户端和 nginx 上使用的证书不是同一份,导致 ssl 握手失败,换掉证书就正常了。还有一个方法就是将

proxy_set_header Host $host

的 $host 改为 frp 客户端上证书对应的域名。