本站的建立过程

0x00 序言

本站的服务器为Ubuntu 20.04LTS,Wordpress及Mysql均运行在Docker上。

注意,下面的步骤的前提都是当前用户为root用户!

0x01 准备工作

执行以下命令更新apt的镜像信息并完成系统所有组件的更新:

apt -y update
apt -y upgrade

0x02 配置SSH

首先打开/etc/ssh/sshd_config文件,修改如下配置项:

Port xxxx #修改SSH端口号,以确保安全
PermitRootLogin yes #允许Root用户登录,以方便上传文件(这里使用的是WinSCP)
MaxAuthTries 20 #设置最大重试次数,方便一些终端自动尝试证书登录
PasswordAuthentication yes #允许密码认证
PermitEmptyPasswords no #不允许空密码登录
ClientAliveInterval 30 #设置心跳包的时间间隔
ClientAliveCountMax 60 #设置Socket无相应的超时时间

保存后执行service sshd restart生效。

然后给SSH配置Radius,首先执行如下命令:

apt install libpam-radius-auth

然后在/etc/pam-radius-auth.conf文件中根据示例加入Radius服务器信息,超时时间设置为10s。

加入完成后执行以下命令限制pam-radius-auth.conf文件的访问权以保证安全:

chmod 0600 /etc/pam-radius-auth.conf

然后分别修改/etc/pam.d/sshd与/etc/pam.d/sudo文件,在文件头部加入如下内容:

auth sufficient pam_radius_auth.so

然后修改/etc/pam.d/common-auth文件,在如下代码行后面加上try_first_pass:

auth  pam_unix.so nullok_secure

0x03 配置Vim

这里参考了vim c/c++配置Ubuntu 16.04.04-desktop 中VIM安装YouCompleteMe插件以及The legacy SnipMate parser is deprecated. Please see :h SnipMate-deprecate.

首先添加Vundle管理工具,执行以下命令:

git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim

下载配色方案:

cd ~/.vim
mkdir colors
cd colors
wget https://raw.githubusercontent.com/sickill/vim-monokai/master/colors/monokai.vim

修改.vimrc为如下内容:

set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'VundleVim/Vundle.vim'
Plugin 'mileszs/ack.vim'
Plugin 'scrooloose/nerdtree'
Plugin 'tyok/nerdtree-ack'
Plugin 'Xuyuanp/nerdtree-git-plugin'
Plugin 'tpope/vim-rails'
Plugin 'drmingdrmer/xptemplate'
" Begin Snippet
Plugin 'MarcWeber/vim-addon-mw-utils'
Plugin 'tomtom/tlib_vim'
Plugin 'garbas/vim-snipmate'
Plugin 'honza/vim-snippets'
Plugin 'altercation/vim-colors-solarized'
" End Snippet
"Plugin 'Valloric/YouCompleteMe'
Bundle 'Valloric/YouCompleteMe'
" Plugin 'majutsushi/tagbar'
call vundle#end()            " required

set nocompatible              " be iMproved, required
set backspace=2 
set encoding=utf-8
set fileencoding=utf-8
set number
set autoindent
set smartindent
set tabstop=4
set autochdir
set shiftwidth=4
syntax enable
colorscheme monokai

let g:tagbar_width = 30
let g:snipMate = { 'snippet_version' : 1 }
nmap <F2> :NERDTreeToggle<CR>
nmap <F3> :TagbarToggle<CR>
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 3 && !exists("s:std_in") | NERDTree | endif

输入:PluginInstall进行插件更新,更新完后会有Snipmate以及YouCompleteMe相关的报错,暂时不用理会,直接退出Vim。

紧接着完成YouCompleteMe依赖组件的编译:

首先安装cmake:

apt-get install build-essential cmake

安装Python相关的库:

apt-get install python-dev python3-dev

编译YCM:

cd ~/.vim/bundle/YouCopmleteMe
./install.py --clang-completer

即可完成Vim的全部配置。

0x04 安装Docker

这里参考了Install Docker Engine on Ubuntu

首先需要清除可能存在的Docker旧版本:

apt-get remove docker docker-engine docker.io containerd runc

配置Docker镜像:

apt-get update
apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

安装Docker引擎:

apt-get update
apt-get install docker-ce docker-ce-cli containerd.io

运行测试:

docker run hello-world

显示Hello World等信息即说明已配置完成。

0x05 安装Wordpress

这里参考了使用Docker搭建一个WordPress博客以及如何调整Linux系统为正确时区Ubuntu上Apache2服务器添加SSL证书

首先拉取WordPress及Mysql的镜像:

docker pull wordpress:latest
docker pull mysql:5.6

执行以下命令创建并进入Docker脚本目录:

mkdir ~/docker
cd ~/docker

在~/docker新建mysql.sh脚本,用于创建Mysql容器,内容如下:

#/bin/sh
docker run -d --privileged=true --name mysql -v /data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=数据库密码 -p 3306:3306 mysql:5.6

在~/docker新建wp.sh脚本,用于创建WordPress容器,内容如下:

#/bin/sh
docker run -d --name wp -e WORDPRESS_DB_HOST=mysql -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=数据库密码 -e WORDPRESS_DB_NAME=wordpress -p 80:80 -p 443:443 --link mysql:mysql wordpress

执行以下两条命令为脚本设置可执行权限:

chmod u+x mysql.sh
chmod u+x wp.sh

然后分别执行以下两条命令即可创建容器:

./mysql.sh
./wp.sh

此时我们调整两个镜像的时区为上海时区:

docker exec -it mysql /bin/bash
rm -f /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
exit
docker exec -it wp /bin/bash
rm -f /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
exit

在Mysql数据库中创建wordpress数据库:

apt install mysql-client
mysql -h 127.0.0.1 -u root -p
输入数据库密码
create database wordpress;
exit;

准备好SSL证书,执行以下命令在WordPress Docker中创建/etc/apache2/ssl目录:

docker exec -it wp /bin/bash
mkdir /etc/apache2/ssl
exit

并利用以下命令将SSL证书复制到Docker内:

docker cp 公钥文件 wp:/etc/apache2/ssl/
docker cp 私钥文件 wp:/etc/apache2/ssl/
docker cp 证书链文件 wp:/etc/apache2/ssl/

然后进入WordPress Docker内配置SSL。

首先执行以下命令进入Docker:

docker exec -it wp /bin/bash

安装一些基础组件:

apt install vim wget zip unzip

然后切换目录到/etc/apache2:

cd /etc/apache2

为SSL配置文件创建软链接:

ln -s /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-enabled/000-000-default.conf
ln -s /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-enabled/000-default-ssl.conf

在/etc/apache2/sites-available/default-ssl.conf中添加修改如下内容:

#设置服务器域名
ServerName 服务器域名
#开启SSL
SSLEngine on
#添加证书文件
SSLCertificateFile /etc/apache2/ssl/公钥文件名
SSLCertificateKeyFile /etc/apache2/ssl/私钥文件名
SSLCertificateChainFile /etc/apache2/ssl/证书链文件名

然后在/etc/apache2/sites-available/000-default.conf中添加如下内容以实现访问http时自动跳转到https:

RewriteEngine on
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*) https://%{SERVER_NAME}$1 [L,R]

然后启用Apache2的SSL与Rewrite模块:

a2enmod ssl
a2enmod rewrite

重启Docker镜像:

exit
docker restart wp

完成后打开浏览器,访问服务器,此时会自动跳转到WordPress安装界面,根据向导指示进行安装即可。

0x06 配置WordPress

这里参考了wordpress链接google字体慢的完美解决教程

首先为WordPress加入Radius认证支持:

在插件市场中搜索miniOrange的Radius client插件并安装,然后在配置中完成相关配置。

注意,该插件一旦开启Radius Login登录后,将不支持WordPress原生身份认证,为了解决这个问题,我们利用插件编辑器修改该插件的mo_rad_settings.php文件,找到331行的mo_rad_login函数,并改成如下代码实现(这里的更改体现在wp_authenticate_username_password那一个else分支):

function mo_rad_login($user, $username, $password){
    if(empty($username) || empty ($password)){

        $error = new WP_Error();

        if(empty($username)){ //No email
            $error->add('empty_username', __('<strong>ERROR</strong>: Email field is empty.'));
        }

        if(empty($password)){
            $error->add('empty_password', __('<strong>ERROR</strong>: Password field is empty.'));
        }
        return $error;
    }

    $response = $this->mo_radius_validate_login_data($username, $password);
    $user = false;
    if ($response === true) {
        $find_user_by = get_option('mo_radius_find_user_by');
        $exists = $find_user_by.'_exists';
        $attr = get_option('mo_radius_find_user_by') == 'username' ? 'login' : get_option('mo_radius_find_user_by');
        if($exists($username))
            $user = get_user_by($attr, $username);
        if(get_option('mo_radius_auto_create_user')=="allowed" && !$user) {
            $random_password = wp_generate_password( 10, false );
            if(is_email($username))
                $user_id = wp_create_user( $username, $random_password, $username );
            else
                $user_id = wp_create_user( $username, $random_password);
            $user = get_user_by( 'login', $username);             
        }
    }
    else {
        $user = wp_authenticate_username_password($user, $username, $password);
    }
    return $user;
}

为了反垃圾评论,启用并配置插件"Akismet反垃圾评论和表单提交"。

为了加速博客的国内访问速度,首先安装"Disable Google Fonts"插件,然后从https://pan.baidu.com/s/1jG7qvm2下载"googlefonts to 360"插件并安装。

为了方便修改头像,安装"Simple Local Avatars"插件。

为了Markdown支持,安装"WP Githuber MD"插件并根据喜好进行配置,同时通过以下方式禁用了Shortcode以防止一些标记无法在Markdown中正常使用:

首先进入Docker:

docker exec -it wp /bin/bash

然后打开/var/www/html/wp-includes/shortcodes.php文件,找到add_shortcode函数,并在其第一行代码之下加入return语句,即:

function add_shortcode( $tag, $callback ) {
    global $shortcode_tags;

    return;

    if ( '' === trim( $tag ) ) {
        _doing_it_wrong(
            __FUNCTION__,
            __( 'Invalid shortcode name: Empty name given.' ),
            '4.4.0'
        );
        return;
    }

    if ( 0 !== preg_match( '@[<>&/\[\]\x00-\x20=]@', $tag ) ) {
        _doing_it_wrong(
            __FUNCTION__,
            sprintf(
                /* translators: 1: Shortcode name, 2: Space-separated list of reserved characters. */
                __( 'Invalid shortcode name: %1$s. Do not use spaces or reserved characters: %2$s' ),
                $tag,
                '& / < > [ ] ='
            ),
            '4.4.0'
        );
        return;
    }

    $shortcode_tags[ $tag ] = $callback;
}

然后从https://lanzoui.com/iEd8Seqa34h下载xiaoyou66.com改版过的kratos2.2主题并安装以美化论坛,并注意在后台中“设置”中的“主题”项中,将各种资源包、头像和表情包全部下载,否则会导致论坛访问缓慢,同时,为博客配置live2d组件以保证该主题正常使用:

cd /var/www/html/
wget https://github.com/xiaoyou66/Kratos-/raw/3.0/live2d.zip
unzip live2d.zip
``

同时,会发现自己的头像变成了该主题的预置头像并且无法修改,为了解决这个问题,利用主题编辑器对该主题中inc/myfunction.php文件进行编辑,定位到第107行,注释如下代码行即可:

```php
//add_filter( 'get_avatar' , 'local_random_avatar' , 1 , 5 );

做完以上这些安装配置后,再对本站的其他设置选项进行精心调整后,就变成了现在的样子。

0x07 让主机支持多网站共存

这里参考了[Host Multiple Websites On One VPS With Docker And Nginx](https://blog.ssdnodes.com/blog/host-multiple-websites-docker-nginx/ "Host Multiple Websites On One VPS With Docker And Nginx")及[jwilder/nginx-proxy](https://hub.docker.com/r/jwilder/nginx-proxy "jwilder/nginx-proxy")。

一台服务器的资源毕竟不少,只运行一个网站太浪费了,因此,这里开始改造工作,让服务器根据用户输入的域名自动将请求转发到对应的镜像,同时统一管理SSL,以方便之后其它的建站操作。

首先删除WordPress中的SSL设定:

docker exec -it wp /bin/bash
cd sites-enabled
rm 000-000-default.conf
rm default-ssl.conf

然后执行如下命令打开000-default.conf并删除HTTPS Rewrite相关的选项:

vim 000-default.conf

退出docker:

exit

停止WordPress与Mysql的Docker:

docker stop wp
docker stop mysql

然后将WordPress与Mysql的容器进行commit:

docker commit wp wp-lzr-202108131357
docker commit mysql mysql-202108131343

记录下WordPress容器的Hash:

docker ps -a

删除WordPress与Mysql容器:

docker rm wp
docker rm mysql

在Docker中创建网桥:

docker network create nginx-proxy

执行如下命令进入Docker脚本目录:

cd ~/docker

新建一个脚本nginx-proxy.sh,内容如下:

#!/bin/sh
docker run --name nginx-proxy -d -p 80:80 -p 443:443 --net nginx-proxy -v /root/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

为上述脚本分配可执行权限:

chmod u+x nginx-proxy.sh

修改wp.sh为如下内容:

#/bin/sh
docker run -d --name wp -v /data/wp:/var/www/html -e WORDPRESS_DB_HOST=mysql -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=wordpressmysql. -e WORDPRESS_DB_NAME=wordpress --expose 80 --net nginx-proxy -e VIRTUAL_HOST=CDN域名 --link mysql:mysql wp-lzr-202108131357

修改mysql.sh为如下内容:

#/bin/sh
docker run -d --privileged=true --name mysql -v /data/mysql:/var/lib/mysql --net nginx-proxy -e MYSQL_ROOT_PASSWORD=wordpressmysql. -p 3306:3306 mysql-202108131343

将WordPress原先镜像中的数据拷贝到数据目录中:

mkdir /data/wp
cp -rf /var/lib/docker/volumes/106bd6810d7f2b0e82a95d234d94531743b5cf1a6bdd35568c98406462e02ff0/_data/. /data/wp/

注意,上面源路径最后结尾必须是一个点,否则隐藏文件无法复制,上述的106bd6810d7f2b0e82a95d234d94531743b5cf1a6bdd35568c98406462e02ff0为之前删除的WordPress仓库的Hash。

接下来准备SSL证书,执行如下命令创建ssl目录:

mkdir ~/certs

准备好服务器的公钥和私钥,分别命名为CDN域名.crt与CDN域名.key,放置在~/certs目录下。

按顺序安装并启动三个容器:

cd ~/docker
./nginx-proxy.sh
./mysql.sh
./wp.sh

这样博客就恢复运行了。

0x08 加速网站的访问

首先我安装了Automattic的超级缓存插件,并开启了缓存功能,然后我为网站配置了Azure CDN,大致步骤如下:

1、在Azure CDN上注册并创建终结点,终结点指向源站,同时开启https支持。
2、将WordPress的Docker Coomit并删除,然后修改wp.sh中的主机域名,将cdn域名改成源站域名并重新启动。
3、在~/certs下为源站域名分配证书。
4、为源站域名创建A记录域名映射项,并为CDN域名创建指向CDN的CNAME记录。
5、网站后台地址改为CDN域名。

但是,上述步骤做完后,打开网站会发现,一些链接并没有指向CDN域名,pjax也无法正常运行,为了解决这些问题,大概需要做以下几件事:

首先,大部分原因来自于WordPress的自身,为了让CDN访问时站点提供源站域名,而访问者访问CDN时,提供的则是CDN域名,修改了data/wp/wp-includes/option.php中的get_option函数的头部(该修改只适用于Apache):

global $wpdb;
$activehome = 'https://'.$_SERVER['HTTP_HOST'];

$option = trim( $option );
if ( empty( $option ) ) {
    return false;
}

foreach(getallheaders() as $name => $value)
{   
    if($name == 'xxxx')
    {   
        $activehome = 'https://'.$value;
    }
}

if('home' == $option || 'siteurl' == $option)
{
    return $activehome;
}

然后需要在Azure CDN中对所有请求加入一条规则,该规则始终增加一个请求头,名称为xxxx,值为源站域名,来指导WordPress判断访问是否来自CDN服务器。

然后将主题中的图片路径全部换成相对路径。

最后,为了解决头像路径的问题,需要修改simple-local-avatars插件的代码,源代码文件路径是/data/wp/wp-content/plugins/simple-local-avatars/class-simple-local-avatars.php,需要将get_simple_local_avatar_url函数的最后返回部分修改成这样:

$ret = esc_url( $local_avatars[ $size ] );
$targethost = 'https://'.$_SERVER['HTTP_HOST'];

foreach(getallheaders() as $name => $value)
{
    if($name == 'xxxx')
    {
        $targethost = 'https://'.$value;
    }
}

$ret = str_replace('https://CDN域名', $targethost, $ret);
$ret = str_replace('https://源站域名', $targethost, $ret);
return $ret;
点赞
  1. zhangsonglin_cjr说道:

    期待中

  2. Lethon说道:

    前排留念
    不是,为啥我这评论发不出去...

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据