部署hugo到服务器,网上一般方法是利用git hook。这里记录一种新的方法:利用FTP Deploy GitHub Actions自动部署hugo到Centos8服务器。今后只要提交源码到github仓库,剩下的事就交给GitHub Actions了。
本地操作
参考:hugo部署到coding&gitee&备份源码-本地操作
服务器操作
安装 Nginx
准备工作:如果服务器端口不是22,先要更改SSH端口:
1 2
   | vi /etc/ssh/sshd_config port 22
   | 
 
然后重启生效。
首先,在服务器上安装nginx。
1 2
   | yum update -y yum install nginx -y
   | 
 
如果是centos 7,先要安装安装epel:yum install epel-release,才能安装nginx。
启动 Nginx
Nginx 安装完成后需要手动启动,启动Nginx并设置开机自启:
1 2
   | systemctl start nginx systemctl enable nginx
   | 
 
关闭防火墙:
1 2
   | systemctl stop firewalld.service systemctl disable firewalld.service 
   | 
 
配置完成后,访问使用浏览器服务器 ip ,如果能看到以下界面,表示运行成功。
创建新的网站目录
为了图方便,可以直接将网站目录改为FTP家目录。
为了方便期间,我们在 /var/www/ 目录下为每个站点创建一个文件夹。
1 2 3
   | sudo mkdir -p /var/www/blog sudo chown -R $USER:$USER /var/www/blog sudo chmod -R 755 /var/www
   | 
 
如果后面利用FTP上传网页后,出现403 Forbidden,解决方法:
假设网站根目录在/var/www/blog/,则执行:
配置 nginx
1
   | vi /etc/nginx/conf.d/blog.conf
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
   | server {   listen  80 ;   listen [::]:80;   root /var/www/blog;   server_name bore.vip www.bore.vip;   access_log  /var/log/nginx/hexo_access.log;   error_log   /var/log/nginx/hexo_error.log;   error_page 404 =  /404.html;   location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {     root /var/www/blog;     access_log   off;     expires      1d;   }   location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {     root /var/www/blog;     access_log   off;     expires      10m;   }   location / {     root /var/www/blog;     if (-f $request_filename) {     rewrite ^/(.*)$  /$1 break;     }   }   location /nginx_status {     stub_status on;     access_log off;  } }
  | 
 
重启 Nginx 服务器,使服务器设定生效:
1
   | sudo systemctl restart nginx
   | 
 
配置ssl证书
更多查看:Nginx 配置 ssl 证书
这里记下怎样添加 Let’s Encrypt 免费证书。(貌似只有上传了文件到网站目录,才能申请证书成功。)如果想启用阿里证书,可查看:启用阿里免费证书
安装Certbot
1 2
   | yum install epel-release -y yum install certbot -y
   | 
 
然后执行:
1
   | certbot certonly --webroot -w /var/www/blog -d bore.vip -m 455343442@qq.com --agree-tos
   | 
 
配置Nginx
1
   | vi /etc/nginx/conf.d/blog.conf
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   | server {     listen 80;     server_name bore.vip www.bore.vip;     rewrite ^(.*)$ https://$server_name$1 permanent; } server {   listen 443;   root /var/www/blog;   server_name bore.vip www.bore.vip;   ssl on;   ssl_certificate /etc/letsencrypt/live/bore.vip/fullchain.pem;   ssl_certificate_key /etc/letsencrypt/live/bore.vip/privkey.pem;   ssl_session_timeout 5m;   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;   ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;   ssl_prefer_server_ciphers on;   access_log  /var/log/nginx/hexo_access.log;   error_log   /var/log/nginx/hexo_error.log;   error_page 404 =  /404.html;   location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {     root /var/www/blog;     access_log   off;     expires      1d;   }   location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {     root /var/www/blog;     access_log   off;     expires      10m;   }   location / {     root /var/www/blog;     if (-f $request_filename) {     rewrite ^/(.*)$  /$1 break;     }   }   location /nginx_status {     stub_status on;     access_log off;  } }
  | 
 
重启Nginx生效:
证书自动更新
由于这个证书的时效只有 90 天,我们需要设置自动更新的功能,帮我们自动更新证书的时效。首先先在命令行模拟证书更新:
模拟更新成功的效果如下(略)
在无法确认你的 nginx 配置是否正确时,一定要运行模拟更新命令,确保certbot和服务器通讯正常。使用 crontab -e 的命令来启用自动任务,命令行:
添加配置:(每隔两个月凌晨2:30自动执行证书更新操作)后保存退出。
1
   | 30 2 * */2 * /usr/bin/certbot renew --quiet && /bin/systemctl restart nginx
   | 
 
查看证书有效期的命令:
1
   | openssl x509 -noout -dates -in /etc/letsencrypt/live/bore.vip/cert.pem
   | 
 
安装vsftpd
Debian查看:Debian安装vsftpd,Centos参考下面的。
1
   | sudo yum install vsftpd -y
   | 
 
安装软件包后,启动vsftpd,并使其能够在引导时自动启动:
1 2
   | sudo systemctl start vsftpd sudo systemctl enable vsftpd
   | 
 
配置vsftpd
1
   | vi /etc/vsftpd/vsftpd.conf
   | 
 
在userlist_enable=YES下面,加上:
1 2
   | userlist_file=/etc/vsftpd/user_list userlist_deny=NO
   | 
 
创建FTP用户
创建一个新用户,名为admin:
1 2
   | sudo adduser admin sudo passwd admin
   | 
 
将用户添加到允许的FTP用户列表中:
1
   | echo "admin" | sudo tee -a /etc/vsftpd/user_list
   | 
 
设置正确的权限(使ftp用户可以上传网站文件到相应目录):
1 2
   | sudo chmod 755 /var/www/blog sudo chown -R admin: /var/www/blog
   | 
 
关闭防火墙
1 2
   | systemctl stop firewalld.service systemctl disable firewalld.service 
   | 
 
重启vsftpd服务
保存文件并重新启动vsftpd服务,以使更改生效:
1
   | sudo systemctl restart vsftpd
   | 
 
更多有关ftp部分可查看:centos8搭建ftp服务器
允许root登录FTP
- 将
root添加到允许的FTP用户列表中: 
1
   | echo "root" | sudo tee -a /etc/vsftpd/user_list
   | 
 
- 修改/etc/vsftpd/user_list和/etc/vsftpd/ftpusers两个设置文件脚本,将root账户前加上#号变为注释(使
 
root账户从禁止登录的用户列表中排除)。
1
   | vi /etc/vsftpd/user_list
   | 
 
- 重启vsftpd服务
1
   | sudo systemctl restart vsftpd
   | 
 
Github操作
配置FTP_MIRROR_PASSWORD
点击博客仓库的Settings->Secrets->Add a new secret,Name填写FTP_MIRROR_PASSWORD,Value填写用户密码。
配置 Github actions
在博客根目录新建.github/workflows/gh_pages.yml文件。代码(不添加缓存)如下:最好使用下面添加了缓存的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   | name: GitHub Page Deploy
  on:   push:     branches:       - develop jobs:   build-deploy:     runs-on: ubuntu-latest     steps:       - name: Checkout master         uses: actions/checkout@v2.3.4         with:           submodules: true             fetch-depth: 0           - name: Setup Hugo         uses: peaceiris/actions-hugo@v2.5.0         with:           hugo-version: 'latest'           extended: true
        - name: Build Hugo         run: hugo --minify
        - name: Deploy Hugo to gh-pages         uses: peaceiris/actions-gh-pages@v3.8.0         with:           github_token: ${{ secrets.GITHUB_TOKEN }}           PUBLISH_BRANCH: master           PUBLISH_DIR: ./public                         - name: Deploy Hugo to Server         uses: SamKirkland/FTP-Deploy-Action@4.2.0         with:           server: 104.224.191.88           username: admin           password: ${{ secrets.FTP_MIRROR_PASSWORD }}           local-dir: ./public/           server-dir: /var/www/blog/
   | 
 
添加缓存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
   | name: GitHub Page Deploy
  on:   push:     branches:       - develop jobs:   build-deploy:     runs-on: ubuntu-latest     steps:       - name: Checkout master         uses: actions/checkout@v2.3.4         with:           submodules: true             fetch-depth: 0           - name: Setup Hugo         uses: peaceiris/actions-hugo@v2.5.0         with:           hugo-version: 'latest'           extended: true                  - name: Cache resources          uses: actions/cache@v2         with:           path: resources                     key: ${{ runner.os }}-hugocache-${{ hashFiles('content/**/*') }}           restore-keys: ${{ runner.os }}-hugocache-          
        - name: Build Hugo         run: hugo --minify --gc
        - name: Deploy Hugo to gh-pages         uses: peaceiris/actions-gh-pages@v3.8.0         with:           github_token: ${{ secrets.GITHUB_TOKEN }}           PUBLISH_BRANCH: master           PUBLISH_DIR: ./public                         - name: Deploy Hugo to Server         uses: SamKirkland/FTP-Deploy-Action@4.3.0         with:           server: 104.224.191.88           username: root           password: ${{ secrets.FTP_MIRROR_PASSWORD }}           local-dir: ./public/           server-dir: /usr/share/nginx/html/
   | 
 
第三方:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
   | name: GitHub Page
  on:     push:         branches:             - master 
  jobs:     deploy:         runs-on: ubuntu-18.04         steps:             - uses: actions/checkout@v2               with:                   submodules: true                    fetch-depth: 0 
              - name: Setup Hugo               uses: peaceiris/actions-hugo@v2               with:                   hugo-version: "0.87.0"                    extended: true 
              - name: Cache resources                uses: actions/cache@v2               with:                   path: resources                                      key: ${{ runner.os }}-hugocache-${{ hashFiles('content/**/*') }}                   restore-keys: ${{ runner.os }}-hugocache-
              - name: Build                run: hugo --minify --gc
              - name: Deploy                uses: peaceiris/actions-gh-pages@v3               with:                                                         deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
                                       external_repository: 
                    publish_dir: ./public                   user_name: "github-actions[bot]"                   user_email: "github-actions[bot]@users.noreply.github.com"                   full_commit_message: Deploy from ${{ github.repository }}@${{ github.sha }} 🚀
   | 
 
提交源码
初始化git,新建并切换到develop分支,将源码提交到develop分支。稍等片刻,github action会自动部署blog到master分支和服务器。
1 2 3 4 5 6
   | git init git checkout -b develop git remote add origin git@github.com:iwyang/iwyang.github.io.git git add . git commit -m "备份源码" git push --force origin develop
   | 
 
最终部署脚本:
1 2 3 4 5 6 7 8 9
   | #!/bin/bash
  echo -e "\033[0;32mDeploying updates to gitee...\033[0m"
 
  git config --global core.autocrlf false git add . git commit -m "site backup" git push origin develop --force
   | 
 
克隆源码到本地
1
   | git clone -b develop git@github.com:iwyang/iwyang.github.io.git blog --recursive
   | 
 
因为使用Submodule管理主题,所以最后要加上 --recursive,因为使用 git clone 命令默认不会拉取项目中的子模块,你会发现主题文件是空的。(另外一种方法:git submodule init && git submodule update)
同步更新源文件
同步主题文件
1
   | git submodule update --remote
   | 
 
运行此命令后, Git 将会自动进入子模块然后抓取并更新,更新后重新提交一遍,子模块新的跟踪信息便也会记录到仓库中。这样就保证仓库主题是最新的。
github、gitee、服务器三线部署hexo
将hexo三线部署(由于部署hexo较慢,如果单独为gitee建立一个workflows,gitee会先部署完成,这样无法同步;hugo可以单独为gitee建立一个workflows,因为hugo部署到服务器会先于部署到gitee):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
   | name: Hexo Deploy
 
  on:   push:     branches:       - develop
 
  env:   POST_ASSET_IMAGE_CDN: true
  jobs:   build-and-deploy:     runs-on: ubuntu-latest
      steps:              - name: Checkout         uses: actions/checkout@v2.3.4
        - name: Checkout theme repo         uses: actions/checkout@v2.3.4         with:           repository: jerryc127/hexo-theme-butterfly           ref: master           path: themes/butterfly
               - name: Set up Node.js         uses: actions/setup-node@v2         with:           node-version: '14'
               - name: Get yarn cache directory path         id: yarn-cache-dir-path         run: echo "::set-output name=dir::$(yarn cache dir)"
        - name: Use yarn cache         uses: actions/cache@v2.1.6         id: yarn-cache         with:           path: ${{ steps.yarn-cache-dir-path.outputs.dir }}           key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}           restore-keys: |             ${{ runner.os }}-yarn-
               - name: Install dependencies         run: |           yarn install --prefer-offline --frozen-lockfile
               - name: Set up environment         env:           DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}         run: |           sudo timedatectl set-timezone "Asia/Shanghai"           mkdir -p ~/.ssh           echo "$DEPLOY_KEY" > ~/.ssh/id_rsa           chmod 600 ~/.ssh/id_rsa           ssh-keyscan github.com >> ~/.ssh/known_hosts
               - name: Deploy         run: |           npx hexo deploy --generate                  - name: Deploy Hexo to Server         uses: SamKirkland/FTP-Deploy-Action@4.1.0         with:           server: 104.224.191.88           username: admin           password: ${{ secrets.FTP_MIRROR_PASSWORD }}           local-dir: ./public/           server-dir: /var/www/blog/                  - name: Sync to Gitee         uses: wearerequired/git-mirror-action@master         env:                      SSH_PRIVATE_KEY: ${{ secrets.GITEE_RSA_PRIVATE_KEY }}         with:                      source-repo: git@github.com:iwyang/iwyang.github.io.git                      destination-repo: git@gitee.com:iwyang/iwyang.git
        - name: Build Gitee Pages         uses: yanglbme/gitee-pages-action@main         with:                      gitee-username: iwyang                      gitee-password: ${{ secrets.GITEE_PASSWORD }}                      gitee-repo: iwyang/iwyang                      branch: master
   | 
 
github、gitee、服务器三线部署hugo
由于部署到github和服务器先于gitee,所有可以建立两个workflows。
- 根目录新建
.github/workflows/deploy.yml(用于部署到github和服务器) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   | name: GitHub Page Deploy
  on:   push:     branches:       - develop jobs:   build-deploy:     runs-on: ubuntu-latest     steps:       - name: Checkout master         uses: actions/checkout@v2.3.4         with:           submodules: true             fetch-depth: 0           - name: Setup Hugo         uses: peaceiris/actions-hugo@v2.5.0         with:           hugo-version: 'latest'           extended: true
        - name: Build Hugo         run: hugo --minify
        - name: Deploy Hugo to gh-pages         uses: peaceiris/actions-gh-pages@v3.8.0         with:           github_token: ${{ secrets.GITHUB_TOKEN }}           PUBLISH_BRANCH: master           PUBLISH_DIR: ./public                         - name: Deploy Hugo to Server         uses: SamKirkland/FTP-Deploy-Action@4.1.0         with:           server: 104.224.191.88           username: admin           password: ${{ secrets.FTP_MIRROR_PASSWORD }}           local-dir: ./public/           server-dir: /var/www/blog/
   | 
 
- 根目录新建
.github/workflows/Sync to Gitee.yml(用于部署到gitee) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   | name: Sync to Gitee
  on:   push:     branches: develop
  jobs:   build:     runs-on: ubuntu-latest     steps:       - name: Sync to Gitee         uses: wearerequired/git-mirror-action@master         env:                      SSH_PRIVATE_KEY: ${{ secrets.GITEE_RSA_PRIVATE_KEY }}         with:                      source-repo: git@github.com:iwyang/iwyang.github.io.git                      destination-repo: git@gitee.com:iwyang/iwyang.git
        - name: Build Gitee Pages         uses: yanglbme/gitee-pages-action@main         with:                      gitee-username: iwyang                      gitee-password: ${{ secrets.GITEE_PASSWORD }}                      gitee-repo: iwyang/iwyang                      branch: master
   | 
 
解决问题
1.Error: FTPError: 550 Remove directory operation failed
1 2 3 4 5 6 7 8 9 10
   | rm -rf /var/www/blog
  sudo mkdir -p /var/www/blog sudo chown -R $USER:$USER /var/www/blog sudo chmod -R 755 /var/www
  sudo chmod 755 /var/www/blog sudo chown -R admin: /var/www/blog
  sudo systemctl restart vsftpd
   | 
 
参考链接
1.从 0 开始搭建 hexo 博客
2.为博客添加 Let’s Encrypt 免费证书
3.SamKirkland/FTP-Deploy-Action
4.vsftpd参数设置,并允许root账户登录ftp
5.Stack主题 + GitHub Action