跳过正文

个人博客建站历程 Hugo & Blowfish

·3560 字

心血来潮想要搭建一个个人博客,给自己装修一个赛博小家。

本人网络小白,有误望佬友指出🥰🥰

我会把所有参考文献都放在一段的最前面共大家查阅

我想实现的效果是用一个仓库管理我的所有文章,然后本地写好文档只要一键git push,就能自动完成网页构建并完成部署🥰

网络拓扑是这样的,本地局域网:一台PVE装有Gitlab服务器与Gitlab Runner容器用于git管理和自动Hugo渲染构建,一台fnos装有ngnix docker用来部署静态网页;公网:一台vps小鸡用来frp打通内网和挂caddy反代,实现上述效果。

1. 选择渲染器
#

  • 参考视频📺

  • 在众多渲染器中走马观花,挑了挑,选了个 Hugo (他说什么百个md秒级构建啊啥的我就冲过来了)

2. 开始试用 Hugo&Blowfish
#

  • 我的环境如下:
  • Ubuntu 25.10

windows也有Hugo安装包的,可以直接在官网下载,但是我没有测试过

2.1. 本地安装 Hugo
#

这里就遇到了第一个大坑,版本不匹配!

这个神人中文文档似乎没有及时更新,他也不往ubuntu apt源里上传新的版本,导致我使用

sudo apt update
sudo apt install hugo

这两条命令安装完成,渲染不了blowfish的主题,导致我还卸了重装😅

apt源里放的应该是0.131.0版本,与更新速度十分在线的blowfish主题(latest:25.10.14)并不匹配,无法完成静态网页的渲染

所以我们使用 deb 包 的方式安装,你可以在官网中找到下载连接,我也贴在这里吧…

测试hugo安装

hugo version

安装git不必多说,至此,Hugo基础的测试环境就算完成了。

2.2. 准备一个博客仓库
#

我想实现的效果是用一个仓库管理我的所有文章,然后本地写好文档只要一键git push,就能自动完成网页构建并完成部署🥰

所以我在这里先创建了一个my_blog仓库,添加一个.gitignore文件

mkdir my_blog
cd my_blog
# 修改git默认分支为main
git config --global init.defaultBranch main
git init
touch .gitignore
nano .gitignore
# .gitignore
# others
node_modules
.hugo_build.lock

# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes

# Hugo
public
# 然后进行第一次提交
git add .
git commit -m "New: First commit" # 此处可能会报错,填写一下邮箱账号就好
git config user.email "your@mail.domain"
git config user.name "yourname"
# 再次执行这句话
git commit -m "New: First commit"
# 添加远程仓库
git remote add origin https://yourgitplatform.domain/username/projectname
# push
git push --set-upstream origin main

2.3. 创建第一个站点!
#

所有都准备好啦,我们来创建第一个站点

hugo new site --force .

在当前目录下(也就是刚才的仓库中)直接生成一个空的Hugo网站

执行完毕之后就可以尝试构建静态网页来访问网站了!

hugo server # 注意,此命令仅限用于调试,不得用在实际生产环境
# 如果你在没有图形化界面的机器上部署,可以使用:默认测试端口也是1313
# hugo server --bind=0.0.0.0

打开浏览器输入127.0.0.1:1313回车,就可以看到网站了

😅……他看起来是个404对吧?这很正常,因为现在只创建了一个空的网站,所以就404了

2.4. 添加 Blowfish 主题
#

官网有许多方法将主题包导入Hugo项目的方法,甚至还有 blowfish-tools 工具帮助你构建

这里我们我选择了git子模块安装的方法,为了方便后续更新主题,也是为了契合我的部署目标

使用这句命令导入 Blowfish 主题到 themes/blowfish 路径

git submodule add -b main https://github.com/nunocoracao/blowfish.git themes/blowfish

ok,等他克隆完成后,删除根目录下(指my_blog)Hugo自动生成的hugo.toml文件

Warning

这里是马后炮的我,这里的git子模块给后面pull埋了一颗雷

由于Runner容器网络环境问题,它拉不动github的仓库,所以这里建议使用稳定的镜像站转链🔗或者使用自建加速链接🔗,推荐后者

然后将 themes/blowfish/config/_default 下的所有 *.toml 都粘贴到根目录下的 config/_default 目录

rm hugo.toml
mkdir -p ./config/_default
cp ./themes/blowfish/config/_default/*.toml ./config/_default # 如果你通过模块安装,不要将文件module.toml直接覆盖

你的config文件夹 be like :

config/_default/
├─ hugo.toml
├─ languages.en.toml
├─ markup.toml
├─ menus.en.toml
├─ module.toml # 如果你通过模块安装,不要将此文件直接覆盖
└─ params.toml

修改 config/_default/ 下的 hugo.toml ,将 theme = "blowfish" 注释取消

nano ./config/_default/hugo.toml

好了再次回到根目录,重新执行

hugo server

这下应该可以看到一个带有主题的Blowfish界面了!🥰

Hugo

3. Gitlab CI/CD 集成 Hugo构建&产物传输
#

秉持着一套流程先跑通的理念,我先来进行gitlab工作流的配置🤪

3.1. 添加CI/CD必要的变量
#

进入自己的仓库后,点击左侧 Settings-> CI/CD -> Variables -> Add variable ,添加如下几个变量

  • DEPLOY_SERVER_IP 填入自己需要部署ngnix的主机地址 (变量 保护 遮罩)

  • DEPLOY_USER 填入目标主机的用户名 (变量 保护 遮罩)

  • DEPLOY_TARGET_PATH 填入目标主机ngnix docker映射出来的public文件夹路径 (变量 保护 遮罩)

  • SSH_PRIVATE_KEY 填入目标主机ssh登录私钥 (变量 保护 遮罩+隐藏)

此处有个坑,遮罩变量不能输入空格和换行,且必须大于8个字符(Gitlab 你要不要看看你在干什么😅

Tip

ssh密钥肯定有换行啊…

同学 @Realms 想了个绝妙的方法,先将私钥用base64加密,填入变量,然后再在CI的时候解密就好,甜菜!(遇到问题套一层)

所以我们自己生成随机的公钥私钥哈,然后把公钥放到fnos的~/.ssh上,再开启ssh密钥访问

# 目标主机上
nano /etc/ssh/sshd_config
# 修改如下项为 yes
PubkeyAuthentication yes
# 确认可用后重启sshd服务
sudo systemctl restart sshd
# 计算base64加密后的私钥     -w 0 参数可以生成没有换行和空格的私钥喵
echo -n "-----BEGIN OPENSSH PRIVATE KEY-----
privatekeyexampleAAAAAAAAAAAAAAAAAexample
exampleexampleexampleexampleexampleexample
exampleexampleexampleexampleexampleexample
-----END OPENSSH PRIVATE KEY-----
" | base64 -w 0

将加密后的密钥写入变量SSH_PRIVATE_KEY

3.2. 添加一个.gitlab-ci.yml
#

回到我们的工程仓库,点击左侧 Build -> Pipeline editor (偷懒喜欢用在线的) -> 新建一个文件

然后我给出我的文件参考:

stages:
  - build
  - deploy

# Hugo 渲染构建
build-job:
  tags:
    - your-runner-tag # gitlab的runner容器tags, 便于负载分离专机专用, 我这就一个runner, 直接选他就好
  stage: build
  image: hugomods/hugo:ci-0.151.1   # 这里是docker镜像, 请根据需要修改tags, 主包偷懒选了最新最大个的ci-0.151.1(((
  before_script:
    - git submodule update --init   # 这个必须带, 因为我是使用git submodule引入的主题模块
  script:
    - hugo --minify # 最小化部署
  artifacts:
    paths:
      - public # 产物保留给deploy
  after_script:
    - echo "Hugo build completed!"
  # 仅在 main 或 master 分支上触发
  only:
    - main
    - master

# 将静态文件推送到目标服务器
deploy_job:
  tags:
    - your-runner-tag
  stage: deploy
  image: hugomods/hugo:ci-0.151.1 # 镜像复用这一块/.
  before_script:
    # 安装 ssh 客户端和 rsync (rsync 比 scp 更高效)
    - apk update && apk add openssh-client rsync
    # 启动 ssh-agent 以管理密钥
    - eval $(ssh-agent -s)
    # 将我们存储在 CI/CD 变量中的私钥添加到 ssh-agent
    # 加入了base64解码 tr -d '\r'为了解决 Windows/Linux 换行符问题
    - echo "$SSH_PRIVATE_KEY" | base64 -d | tr -d '\r' | ssh-add -
    # 创建 .ssh 目录
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    # 自动接受目标服务器的 host key,避免流水线因交互而卡住
    - ssh-keyscan -H $DEPLOY_SERVER_IP >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts

  script:
    # 使用 rsync 将 public 目录的内容同步到目标服务器
    # -a: 归档模式, -v: 显示详细信息, -z: 压缩传输, --delete: 删除目标目录中多余的文件
    - rsync -avz --delete ./public/ ${DEPLOY_USER}@${DEPLOY_SERVER_IP}:${DEPLOY_TARGET_PATH}
    - echo "✅ Deployment successful!"
  only:
    - main
    - master

我有点蠢😅这里的Runner拉不动github这个主题模块😅😅😅,当时没有想到可以用加速链接,试了好多方法,什么export加代理啦啥的,都没用。我感觉是自建的Gitlab缓存也有点bug,在他拉不动的时候我取消了流水线,然后后面重试全都报一个错,我认为是他拉了一半的缓存没删掉……最后我重新删库换了一个仓库才好,感觉是被Gitlab做局了……

点击页面底部的 Commit changes 即可

到这里应该就会自动开始构建了,目前应该是 build 阶段能过,卡在 depoly 阶段,因为我还没搭好 ngnix 的 docker

4. 本地服务端接应部署
#

4.1. 安装 ngnix docker 镜像&部署
#

Fnos这点还是挺好用的,点点图形化界面就可以使用docker-compose来创建容器了

先新建一个文件夹用来映射publish的文件夹,哦还要一个文件映射ngnix的配置文件

点击 docker -> Compose -> 新建项目 -> 上传docker-compose.yml

给出我的compose文件参考:

services:
  web:
    image: nginx:1.29.2-alpine-slim
    container_name: hugo_blog_nginx
    restart: always
    ports:
      - "80:80" # 将服务器的 80 端口映射到容器的 80 端口
    volumes:
      - /yourpathtongnix/ngnix/public:/usr/share/nginx/html # 将存放 Hugo 产物的目录挂载到 Nginx
      - /yourpathtongnix/ngnix/conf.d:/etc/nginx/conf.d # 挂载 Nginx 配置文件

这里也给出我的conf.d文件参考

# conf.d/default.conf
server {
    listen 80;
    server_name _; # 替换成你的域名,如果没有就用 _ 这里我本地服务器仅实现静态部署,通过frp转发,所以就不加了

    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

OK,至此,跑去Gitlab点点重新尝试启动流水线,即可完成部署!

现在来尝试访问一下吧!打开浏览器输入 主机地址 即可显示🥰🥰

然后再在Fnos中添加一条frpc记录就好了!!点击提交

5. 公网接力部署
#

5.1. VPS端的caddy反代
#

来到vps小鸡,设置一下反向代理

添加一条主域名代理记录

nano /etc/caddy/Caddyfile
# 添加到行尾
your.domain {
    # tls
    tls /etc/caddy/certs/yourdomain.pem /etc/caddy/certs/yourdomain.key
    # 反代
    # hugo&blowfish 博客流量转发
    reverse_proxy localhost:portnum
}

这个人很蠢🤪改完忘记重启caddy服务了……(还搁那试着访问 试啥呢)

sudo systemctl restart caddy
sudo systemctl status caddy

5.2 来带善人处化缘
#

来到小黄云

  • 添加一条主域名DNS解析A记录

  • 添加一条www二级域名解析CNAME记录

搞定!✅大公告成!

浏览器访问自己域名即可!

6. 后记
#

然后就可以照着入门指南装修啦!

就这点东西还搞了我一天半…我还是太菜了…

upset
Haley
作者
Haley