[{"content":"Hugo 是一个用 Go 编写的开源静态网站生成器，一般只需几秒钟就能生成一个网站，被称为“世界上最快的网站构建框架”。用户可以使用 markdown 语法编写博客内容，结合 Github Page 可以无需服务器部署自己的博客，同时也支持采用 Nginx 、Apache 等 HTTP 服务器的私有化部署方式。本文结合本博客的部署过程，详细叙述以上两种部署方式，以及 CI/CD 自动化部署、国际化配置等过程。\n英文站点 - Github Page 访问地址:\nzoyao.github.io\n中文站点 - Nginx 私有化部署访问地址:\nzoyao.top\nHugo 安装 hugo 本地安装，建议首次使用时在本地安装好 hugo 客户端，方便调试。后续使用过程中，可脱离 hugo 客户端使用，在本地编辑好 markdown 文件上传至 github，即可触发自动化部署，详见 Github Pages 自动化部署与私有化自动化部署章节\nhugo 安装\n安装过程 - 以 windows winget 为例，安装 Extended 版本\n1 2 3 4 5 //安装 winget install Hugo.Hugo.Extended //卸载 winget uninstall --name \u0026#34;Hugo (Extended)\u0026#34; 其它系统及安装方式，可查看 官方文档\n新建站点\n执行以下命令，即可在当前文件夹下新建站点 mysite\n1 hugo new site mysite 预览\n执行成功，可以在本地 1313 端口下，预览网站\n1 hugo server 打包\n打包完成，在 public 目录下生成静态网站\n1 hugo 环境配置\nhugo 在 config 文件夹下对环境配置文件进行管理(默认不存在该目录，需要用户自己新建)，目录结构如下所示\n1 2 3 4 5 6 7 mysite ├── config.toml └── config ├── development │ └── config.toml └── production └── config.toml 如上，新建了 development 与 production 环境配置，可以通过 --environment development 指定配置文件，若无指定，则\nhugo server 预览命令，默认使用 development 环境\nhugo 打包命令，默认使用 production 环境\n指定配置文件的启动命令：\n1 2 3 4 5 //预览 hugo server --environment development //打包 hugo --environment development 主题配置 得益于 hugo 丰富的主题库，我们可以简单快捷地获取到许多个性化 hugo 主题，可以预览 官网主题库 挑选自己喜欢的主题\n以下，将采用 hugo-theme-stack 主题为例进行说明\ngit 初始化\n1 2 3 4 5 //进入所在目录 cd mysite //git初始化 git init 添加子模块，方便后续主题更新\n1 2 //在 mysite/themes 目录下，拉取 hugo-theme-stack 并创建名为 stack 的主题 git submodule add https://github.com/CaiJimmy/hugo-theme-stack.git themes/stack 配置主题\n打开刚刚下载的主题文件，将 themes/stack/exampleSite 目录下的配置文件复制到根目录，覆盖原先的配置文件，编辑配置文件，将 theme 字段配置为上述步骤创建的主题名称，即 stack\nhugo-theme-stack 部分配置说明\n1 2 3 4 5 6 7 8 9 10 11 //访问url，页面跳转时用到 baseurl: https://example.com/ //主题名称，在此处应为 stack theme: hugo-theme-stack //网站名称 title: Example Site //网站说明 copyright: Example Person 配置完成重启即可看到主题改动\nhugo-theme-stack 其他配置可至 官网查询\nGithub Pages 自动化部署 CI/CD GitHub Pages 是 GitHub 提供的一个网页寄存服务，可以用于存放静态网页，包括博客、项目文档等，hugo 可以快速构建静态网站，天然支持使用 GitHub Pages 部署\nGitHub Pages 配置\n使用 Github Pages 需要创建一个以 Github 用户名开头，.github.io 结尾的 repository，并且必须为公开仓库。具体流程为：\nNew repository\nRepository name: xxxx(用户名).github.io\nPublic\nCreate repository\n创建完成，打开仓库的 Settings 配置，修改 Default branch 可以修改默认展示的分支。\n上传静态页面 index.html 文件至仓库指定分支\n1 2 3 4 5 6 7 8 9 10 \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Hello World\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;Hello World\u0026lt;/h1\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 打开 https://用户名.github.io/ 即可看到刚刚上传的静态页面。\n关联 Hugo 仓库自动化部署\n在这里，我们采用两个不同的 Github 仓库\nblog 仓库 \u0026ndash; 用来存放原始的博客文件，主要格式为 Mrakdown\nGitHub Pages 仓库 \u0026ndash; 即上一个步骤创建的仓库，用来存放打包后的静态网站\n具体流程如下：\n打通两个仓库的权限\n打开 Github 全局配置（非仓库配置）Settings / Settings / Personal access tokens / Fine-grained tokens / Generate new token\nToken name 可随意填写\nExpiration 过期时间建议选择 No expiration，避免过期后无法使用\nRepository access 安全考虑建议选择 Only select repositories，只选择刚刚创建的 GitHub Pages 仓库仓库\nPermissions 权限配置将 Contents 修改为 Read and write\n保存并复制好自动生成的 token\n在 blog 仓库增加 token 配置，路径为：blog 仓库 / Settings / Security / Secrets and variables / Actions / Repository secrets / New repository secret，Name 命名为 PERSONAL_TOKEN，并将上述步骤复制的 token 粘贴到 Secret 中保存\nhugo 自动打包、发布\n在 blog 仓库的 .github/workflows 目录下，创建deploy.yml，配置内容如下\n1 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 name: deploy on: # git push时执行 action push: workflow_dispatch: schedule: # Runs everyday at 8:00 AM - cron: \u0026#34;0 0 * * *\u0026#34; jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 with: submodules: true fetch-depth: 0 - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: hugo-version: \u0026#34;latest\u0026#34; # hugo 打包 - name: Build Web run: hugo # 打包完成推送至指定仓库 - name: Deploy Web uses: peaceiris/actions-gh-pages@v3 with: PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }} EXTERNAL_REPOSITORY: zoyao/zoyao.github.io PUBLISH_BRANCH: master PUBLISH_DIR: ./public commit_message: ${{ github.event.head_commit.message }} 配置完成之后，当执行 git push 之后，即触发自动化部署，可在 blog 仓库的 action 中，看到相关流程\n私有化自动化部署 CI/CD 采用 GitHub Pages 可以很方便的完成自动化部署，但是 GitHub 域名在部分网络环境下访问较慢，如果有这部分需求的童鞋，可以采用私有化部署，部署到自己的服务器上。\n私有化部署\n这里采用 Nginx 进行私有化部署\n将打包后的博客静态文件复制到私有服务器，/app/blog/目录下\n配置 Nginx，在 Nginx 的 ./nginx/conf.d目录下，新建配置文件，这里命名为blog-8888.conf\n1 2 3 4 5 6 7 8 9 10 11 12 13 server { # 监听8888端口 listen 8888; # 这里先采用IP访问，后续 HTTPS 配置再修改为域名 server_name 服务器公网IP; # server_name www.zoyao.top; # 指定静态资源位置 location / { root /app/blog; index index.html index.htm; } } 更新 Nginx 配置之后，访问 http://服务器公网IP:8888/ 即可看到博客首页\n自动化部署\n使用自动化部署，需要先配置 ssh key 登录，建议先新建用户，做好权限隔离\n使用 adduser 命令创建新用户，这里命名为 git，可自定义\n1 sudo adduser git 目录授权，需要将 /app/blog 授权给上一步骤新建的用户，切换到git用户执行\n1 sudo chmod -R 777 /app/blog 切换到 git 用户，创建 ssh key，并保存在 Github secret 中\n切换到 git 用户\n1 su git 在 /home/git 目录下创建新目录 .ssh 并授权\n1 mkdir -p ~/.ssh \u0026amp;\u0026amp; chmod 700 ~/.ssh 执行 ssh-keygen 生成密钥对，建议使用 ed25519 比 rsa 更安全\n1 ssh-keygen -t ed25519 -C \u0026#34;github-actions-deploy-key\u0026#34; -f ~/.ssh/github_actions 复制公钥至 authorized_keys\n1 sh -c \u0026#39;cat ~/.ssh/github_actions.pub \u0026gt;\u0026gt; ~/.ssh/authorized_keys 授权 authorized_keys\n1 chmod 600 ~/.ssh/authorized_keys 查看并复制私钥内容备用\n1 cat ~/.ssh/github_actions 本地使用 ssh 登录验证是否成功\n在 blog 仓库增加密钥配置，路径为：blog 仓库 / Settings / Security / Secrets and variables / Actions / Repository secrets / New repository secret，Name 命名为 SERVER_SSH_KEY，并将上述步骤复制的私钥粘贴到 Secret 中保存\nGithub 配置自动化部署\n在 blog 仓库的 .github/workflows 目录下，创建deploy.yml，配置内容如下，服务器IP修改为自己的私有化服务器\n1 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 name: deploy on: push: workflow_dispatch: schedule: # Runs everyday at 8:00 AM - cron: \u0026#34;0 0 * * *\u0026#34; jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 with: submodules: true fetch-depth: 0 - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: hugo-version: \u0026#34;latest\u0026#34; - name: Build Web run: hugo - name: Deploy Web Self uses: easingthemes/ssh-deploy@main with: SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }} REMOTE_HOST: 服务器IP REMOTE_USER: git SOURCE: ./public/ TARGET: /app/blog/hugo/ ARGS: -avz --delete --chown=git:git HTTPS 配置 这里我们使用阿里云的免费 ssl 证书进行 HTTPS 配置，但是由于免费证书有效期较短，需要安装 acme 进行自动续期，自动更新\n申请阿里云的 api\n创建 acme 访问用户\n登录阿里云后台后，进入 权限与安全 / 权限与安全， 选择 身份管理 / 用户，创建新用户，勾选 使用永久 AccessKey 访问，确认后保存对应的 key 以及 secret 备用\n配置权限\n点击添加权限，授予新用户以下权限：\nAliyunRAMFullAccess\n配置 acme 自动更新\n安装 acme\n1 curl https://get.acme.sh | sh -s email=xxxx@xxxx.com 使用步骤1保存的 key 以及 secret ，配置好阿里云的系统参数\n1 2 export Ali_Key=\u0026#34;key\u0026#34; export Ali_Secret=\u0026#34;Secret\u0026#34; 拉取证书\n1 acme.sh --issue --dns dns_ali -d zoyao.top -d \u0026#39;*.zoyao.top\u0026#39; --dnssleep 300 --debug 保存证书, 因本人使用 docker 部署的 nginx，拉取证书后，需要重启 nginx，所以增加了--reloadcmd \u0026quot;docker restart nginx\u0026quot;可根据实际需要删除或修改为自己的命令\n1 acme.sh --install-cert -d zoyao.top --key-file /app/nginx/ssl/zoyao.top/key.pem --fullchain-file /app/nginx/ssl/zoyao.top/cert.pem --reloadcmd \u0026#34;docker restart nginx\u0026#34; 执行成功后，可在 /app/nginx/ssl/zoyao.top/ 目录下查看到证书\nnginx ssl 配置\n在 Nginx 的 ./nginx/conf.d目录下，新建配置文件，这里命名为common.conf\n在前边的私有化部署中，我们使用了8888端口作为博客的访问端口，在这里只需要将 ssl 443 端口转发至 8888 端口，并配置上 ssl 证书地址即可，配置文件如下：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 server { listen 443 ssl http2; listen [::]:443 ssl http2; # 配置博客域名 server_name www.zoyao.top zoyao.top; # 上一个步骤保存的 ssl 证书地址，这里因为是 docker 部署，配置了映射后的地址 ssl_certificate \u0026#34;/app/ssl/zoyao.top/cert.pem\u0026#34;; ssl_certificate_key \u0026#34;/app/ssl/zoyao.top/key.pem\u0026#34;; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { # 请求转发至实际博客部署的端口 proxy_pass http://127.0.0.1:8888; # 转发规则 proxy_set_header Host $proxy_host; # 修改转发请求头，让8080端口的应用可以受到真实的请求 proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } 至此，HTTPS 部署完成，打开 https://www.zoyao.top 即可访问\ni18n国际化 Hugo 本身提供的完整的国际化方案，可以在 hugo.yaml 中，定义不同的语言方案\n在这里，我定义了中英文两种语言\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 languages: en: languageName: English title: zoyao’s Travel Diary weight: 1 params: sidebar: subtitle: Let\u0026#39;s bust our asses and meet again at the pinnacle of success. zh-cn: languageName: 中文 title: zoyao的旅行日记 weight: 2 params: sidebar: subtitle: 顶峰相见 相对应的，在文章中，也需要不同的 markdown 来区分不同的语言\n例如，本篇文章，采用index.zh-cn.md为中文\n在相同目录下，可创建index.en.md为英文\n可以通过DefaultContentLanguage配置网站默认语言\n1 2 DefaultContentLanguage: zh-cn languageCode: zh-cn 本网站针对不同的部署方式，采用了不同的默认语言，在 zoyao.top 中默认中文，在 zoyao.github.io 中默认英文，只需要在根目录下的 config 文件夹中定义好相应的配置\n1 2 3 4 5 6 7 mysite ├── config.toml └── config ├── development │ └── config.toml └── production └── config.toml 不同的配置文件采用不同的DefaultContentLanguage\n同样的，在自动化部署时，可以指定不同的配置文件，即可完成对应语言环境的部署\n1 2 - name: Build Web run: hugo --environment production ","date":"2025-06-03T00:00:00Z","image":"https://zoyao.top/p/hugo-%E5%8D%9A%E5%AE%A2-github-page-/%E7%A7%81%E6%9C%89%E5%8C%96-%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97/hugo-logo-wide.svg","permalink":"https://zoyao.top/p/hugo-%E5%8D%9A%E5%AE%A2-github-page-/%E7%A7%81%E6%9C%89%E5%8C%96-%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97/","title":"Hugo 博客 Github Page /私有化 部署指南"},{"content":"This article offers a sample of basic Markdown syntax that can be used in Hugo content files, also it shows whether basic HTML elements are decorated with CSS in a Hugo theme.\nHeadings The following HTML \u0026lt;h1\u0026gt;—\u0026lt;h6\u0026gt; elements represent six levels of section headings. \u0026lt;h1\u0026gt; is the highest section level while \u0026lt;h6\u0026gt; is the lowest.\nH1 H2 H3 H4 H5 H6 Paragraph Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.\nItatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.\nBlockquotes The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a footer or cite element, and optionally with in-line changes such as annotations and abbreviations.\nBlockquote without attribution Tiam, ad mint andaepu dandae nostion secatur sequo quae. Note that you can use Markdown syntax within a blockquote.\nBlockquote with attribution Don\u0026rsquo;t communicate by sharing memory, share memory by communicating.\n— Rob Pike1\nTables Tables aren\u0026rsquo;t part of the core Markdown spec, but Hugo supports supports them out-of-the-box.\nName Age Bob 27 Alice 23 Inline Markdown within tables Italics Bold Code italics bold code A B C D E F Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus ultricies, sapien non euismod aliquam, dui ligula tincidunt odio, at accumsan nulla sapien eget ex. Proin eleifend dictum ipsum, non euismod ipsum pulvinar et. Vivamus sollicitudin, quam in pulvinar aliquam, metus elit pretium purus Proin sit amet velit nec enim imperdiet vehicula. Ut bibendum vestibulum quam, eu egestas turpis gravida nec Sed scelerisque nec turpis vel viverra. Vivamus vitae pretium sapien Code Blocks Code block with backticks 1 2 3 4 5 6 7 8 9 10 \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block indented with four spaces \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026quot;en\u0026quot;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026quot;utf-8\u0026quot;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Code block with Hugo\u0026rsquo;s internal highlight shortcode 1 2 3 4 5 6 7 8 9 10 \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Example HTML5 Document\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;p\u0026gt;Test\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Diff code block 1 2 3 4 5 [dependencies.bevy] git = \u0026#34;https://github.com/bevyengine/bevy\u0026#34; rev = \u0026#34;11f52b8c72fc3a568e8bb4a4cd1f3eb025ac2e13\u0026#34; - features = [\u0026#34;dynamic\u0026#34;] + features = [\u0026#34;jpeg\u0026#34;, \u0026#34;dynamic\u0026#34;] List Types Ordered List First item Second item Third item Unordered List List item Another item And another item Nested list Fruit Apple Orange Banana Dairy Milk Cheese Other Elements — abbr, sub, sup, kbd, mark GIF is a bitmap image format.\nH2O\nXn + Yn = Zn\nPress CTRL + ALT + Delete to end the session.\nMost salamanders are nocturnal, and hunt for insects, worms, and other small creatures.\nHyperlinked image The above quote is excerpted from Rob Pike\u0026rsquo;s talk during Gopherfest, November 18, 2015.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"2019-03-11T00:00:00Z","image":"https://zoyao.top/p/markdown-syntax-guide/pawel-czerwinski-8uZPynIu-rQ-unsplash_hu_9e6bcf9cfe9a9448.jpg","permalink":"https://zoyao.top/p/markdown-syntax-guide/","title":"Markdown Syntax Guide"}]