静态网站搭建流程

陈华 ⋅ 2021-10-18

此文记录本站的搭建流程,主要环境是 Windows 10 桌面系统和 Ubuntu 18.04 云服务器。逻辑是将本地桌面端每一次的更新推送到 GitHub 再同步到云服务器。大概思路如下

  1. 在 Windows 上通过 Hugo 架设网站,进行 Markdown 写作。
  2. 通过 Git 将更新推送到 GitHub 仓库。
  3. 配置工作流,一旦源站发生变动,Git Action 就会在虚拟环境中生成网站,并将其同步到绑定了域名的云服务器上。

备案的网站是需要存放在境内的服务器上,若不想备案,或是网站位于境外,则可以忽略最后一步,选择将网站托管到 Vercel。这样不仅省去了麻烦,而且国内的访问速度也不差1。本流程主要参考烂磁头的教程,其中详细介绍了工作流的具体作用。本文在此基础上增加了自动部署 Hugo 和 pandoc 的工作流,以简化本地操作2,同时也画蛇添足地增加了详尽的说明,既方便新手,也作为备忘录。整个过程虽然繁琐,配置好之后,就只需专注于写作。

Hugo

Hugo 是一个静态网站生成器,优点是网站生成速度非常快(以毫秒计),源站可移植性好,以及拥有多种主题,拿来即用;缺点是自定义主题需要熟悉 Hugo 语法,但自己动手岂不有趣。具体设置如下:

  1. 下载功能最全的 extended 压缩包,解压。这是可移植软件,无需安装,直接将文件夹移动到常用的软件安装文件夹中即可。

  2. 设置环境变量,以便在终端直接运行软件。在搜索栏中查找“编辑系统环境变量”,点击弹出窗口中的“环境变量”,选中“系统变量”下的 Path 变量,依次点击“编辑”、“新建”和“浏览”,最后选择 Hugo 路径。结果如下:

    将 hugo 文件夹加入环境变量
  3. 在搜索栏输入 cmd 打开 Windows 终端,键入 cd 路径 跳转到指定路径(直接拖动文件夹到终端,会显示相应的路径)。继续输入 hugo new site 网站文件夹名 在该路径下生成网站文件夹。该文件夹包含了所有的源文件,主要是模板(archetypes,预设文章扉页)、内容(content,博客文章)、布局(layouts,自定义网页布局、样式和脚本等)、静态资源(static,文档、图片和视频等文件)、主题(themes,引用别人的布局)和配置文件(config.toml,用以全局管理整个网站)。上述操作如下:

    本例在 Documents 中生成网站文件夹 blog,并得到了成功的提醒
  4. 设计网站布局。刚接触 Hugo 的朋友建议使用主题。挑选合适的主题,下载解压到 themes 文件夹中,拷贝覆盖 exampleSite 内的文件(如果有的话)到根目录。打开配置文件,确保 theme = "主题文件夹名"

  5. 在终端键入 cd 网站文件夹名 && hugo server,点击出现的链接,例如 http://localhost:1313/,在浏览器中预览网站。而键入 hugo 则会在 public 文件夹中生成一个完整的网站,但我们无需进行这个操作。关于其他命令可通过 hugo --help 查看。每个主题的构建逻辑和配置方式不同,一般会有详细介绍,依葫芦画瓢即可。

  6. 键入 hugo new 文件夹名/"标题.md" 在 content 目录下生成 Markdown 文档。打开后会看到扉页(front matter),用以填写标题、作者和链接等版权信息。以本文为例,输入 hugo new zh/"静态网站搭建流程.md",然后设置扉页(可通过模板自动生成相关信息)

    ---
    title: "静态网站搭建流程"
    date: "2021-10-18T19:41:59+08:00"
    draft: true
    slug: "static website"
    description: "Introduction to build static website by Hugo, git action, cloud server, apache2."
    ---

    若要公开文章,需要设置 draft: false,或将其删除。推荐使用 Typora Markdown 写作,以及使用 VS Code 编辑网站。

GitHub

在本地写好博客之后,我们将源站推送(push)到 GitHub 上。

  1. 注册 GitHub,点击右上角加号新建一个仓库,确定仓库名,以及是否公开。

  2. 安装分布式版本控制软件 Git,然后在终端键入

    git config --global user.name "GitHub 用户名"
    git config --global user.email "邮箱地址"
  3. 转到网站根目录 cd 网站根目录,输入以下内容

    git init
    git add .
    git commit -m "first commit"
    git branch -M main
    git remote add origin 仓库链接
    git push -u origin main

    以上操作分别表示初始化仓库,添加所有内容到缓存区,提交,设置 main 为主分支,添加远程仓库,以及推送缓存区内容到 mian 分支。

  4. 需要注意的是,如果我们不想公开某篇文章,可以在扉页设置 draft: true。但第三步依然会将该文档推送到仓库中。因此我们在网站根目录新建一个文件 .gitignore,令 Git 忽略特定的文件。例如,我将所有私密文章命名为 文章名_d.md,然后在 .gitignore 文件中添加 *_d.md,这样 git 在推送时会忽略所有以 _d.md 结尾的文件。

  5. 每次写好文章之后,只需要输入以下命令将其推送到远程仓库即可:

    git add .
    git commit -m "该次推送说明"
    git push

    关于 GitHub 的更多操作可参考官方文档

服务器

在进一步设置 GitHub 前,我们先配置好服务器。

  1. 将域名解析到服务器 IP 地址。以 domain.com 和阿里云为例,设置记录类型为 A,主机记录为指定的二级域名 @.domain.com 或三级域名(如 www.domain.com),解析线路默认,记录值为服务器 IP 地址,TTL 默认。

  2. 远程登陆到云服务器,为了方便起见,sudo su 进入管理员模式。安装和配置 apache2

    apt update
    apt -y upgrade
    apt install -y apache2

    将 SSL 证书上传到服务器的 /etc/apache2/cert/ 路径下,然后配置 apache2

    vim /etc/apache2/sites-available/blog.conf

    i 进入编辑模式,并输入(假设网站位于 /var/www/public/ 目录下)

    <VirtualHost *:80>
    ServerName www.domain.com
    ServerAlias domain.com
    DocumentRoot /var/www/public
    <Directory /var/www/public/>
    Options +FollowSymlinks
    AllowOverride All
    
    SetEnv HOME /var/www/public
    SetEnv HTTP_HOME /var/www/public
    </Directory>
    
    # 设置 http 跳转到 https
    RewriteEngine on
    RewriteCond %{SERVER_PORT} !^443$
    RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]
    </VirtualHost>
    
    <VirtualHost *:443>     
        ServerName domain.com                   
        DocumentRoot  /var/www/public       
        SSLEngine on   
        SSLProtocol all -SSLv2 -SSLv3
        SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
        SSLHonorCipherOrder on
        # 以下三行为证书路径,请自行修改
        SSLCertificateFile cert/domain.com_public.crt
        SSLCertificateKeyFile cert/domain.com.key
        SSLCertificateChainFile cert/domain.com_chain.crt
        # 设置 domain.com 域名跳转到 www.domain.com
        RewriteEngine on
        RewriteCond %{SERVER_NAME} =domain.com
        RewriteRule ^ https://www.%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
    </VirtualHost>
    
    #如果证书包含多个域名,复制以上参数,并将 ServerName 替换成第二个域名。
    <VirtualHost *:443>     
        ServerName www.domain.com                    
        DocumentRoot  /var/www/public        
        SSLEngine on   
        SSLProtocol all -SSLv2 -SSLv3
        SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
        SSLHonorCipherOrder on
        # 以下三行为证书路径,请自行修改
        SSLCertificateFile cert/domain.com_public.crt
        SSLCertificateKeyFile cert/domain.com.key
        SSLCertificateChainFile cert/domain.com_chain.crt
    </VirtualHost>

    完成后,按 Esc 输入 :eq 保存退出。在终端输入

    a2ensite blog.conf ##使配置文件生效
    systemctl reload apache2 ##重新加载 Apache 服务
    a2enmod rewrite headers env dir mime ssl ##启用 ssl 模块
    systemctl restart apache2 ##重启 Apache 服务

    以上假设的域名为 www.domain.comdomain.com,并设置了后者自动跳转到前者。若需要设置 www.domain.com 跳转到 domain.com,可参考这篇文章

  3. 安装同步软件: apt install rsync

  4. 生成 SSH 密钥,用以授权 GitHub 远程修改网站根目录 /var/www/public/ 下的内容。

    ssh-keygen -t ed25519 -f ~/.ssh/blog_deploy_key
    cd ~/.ssh/
    mv blog_deploy_key.pub authorized_keys
    cat blog_deploy_key

    复制屏幕中出现的一长串密钥。

工作流

  1. 在 GitHub 仓库中点击 Settings、Secrets 和 New repository secret。添加 Name 为 BLOG_DEPLOY_KEY,Value 为上一步生成的密钥。同理新增 Name: DIR 和 Value: /var/www/public 以及 Name: HOST 和 Value: 服务器 IP 地址

  2. 授权 Actions 自动运行工作流。依次点击 Settings 和 Actions,选择 Allow all actions,保存。

  3. 在 Windows 网站根目录下的 .github 文件夹中新建 workflows 文件夹。打开 workflows 新建 main.yml 文件,复制粘贴以下内容:

    name: Deploy on push events
    
    on:
      push:
        branches: [ main ] # 在推送到 mian 分支时触发工作流
    
    jobs:
      build:
        runs-on: ubuntu-18.04 # 服务器版本
        steps:
          - name: Checkout
            uses: actions/checkout@v2 # 检出最新代码到虚拟环境中
            with:
              submodules: 'recursive'
              fetch-depth: 0 # 拉取所有分支和标签的历史
          - name: hugo
            uses: klakegg/actions-hugo@1.0.0 # 在虚拟环境中运行 hugo 生成网站到 public 文件夹中
            with:
              command: --gc --minify
              image: ext-ubuntu
              pandoc_command: pandoc-default
          - uses: webfactory/ssh-agent@v0.4.1
            with:
              ssh-private-key: |
                ${{ secrets.BLOG_DEPLOY_KEY }} # 读取 secrets 中 BLOG_DEPLOY_KEY 的值
          - name: Scan public keys
            run: |
              ssh-keyscan ${{ secrets.HOST }} >> ~/.ssh/known_hosts # 匹配 secrets 中储存的密钥和服务器中的公钥
          - name: Deploy
            run: |
              rsync -av --delete public root@${{ secrets.HOST }}:${{ secrets.DIR }} # 同步虚拟环境中的 public 文件夹内容和服务器中的 DIR 文件夹内容。 

    其中,我使用 pandoc 将 Markdown 文档转换为网页。对于其他主题,直接删除上面的 pandoc_command: pandoc-default 即可。

  4. 推送本地内容到 GitHub,点击 GitHub 的博客仓库中的 Actions,查看是否设置成功。


  1. 针对境内访问,可将域名通过 CNAME 别名记录指向 cname-china.vercel-dns.com↩︎

  2. 原工作流需要先在本地通过 hugo 生成网站到 public 文件夹,再同步到 GitHub 和服务器,比较繁琐。↩︎