<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ruis Blog</title><link>https://ruis.ai/</link><description>Recent content on Ruis Blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 25 Mar 2026 08:00:00 +0000</lastBuildDate><atom:link href="https://ruis.ai/index.xml" rel="self" type="application/rss+xml"/><item><title>从零搭建个人技术博客：Hugo + Gitea + Docker 全栈部署记录</title><link>https://ruis.ai/post/homelab-blog-deployment/</link><pubDate>Wed, 25 Mar 2026 08:00:00 +0000</pubDate><guid>https://ruis.ai/post/homelab-blog-deployment/</guid><description>&lt;h2 id="背景"&gt;背景
&lt;/h2&gt;&lt;p&gt;一直想有一个自己的技术博客，用来记录日常折腾的东西。趁着这次有时间，在家里的 Proxmox 集群上从零搭了一套，全程 Self-hosted，没有依赖任何云服务。&lt;/p&gt;
&lt;h2 id="最终架构"&gt;最终架构
&lt;/h2&gt;&lt;p&gt;两台机器，分工明确：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;机器&lt;/th&gt;
 &lt;th&gt;角色&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;lxc (10.10.10.61)&lt;/td&gt;
 &lt;td&gt;Caddy v2 网关，负责 HTTPS 和反向代理&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;debian (10.10.10.62)&lt;/td&gt;
 &lt;td&gt;应用服务器，跑所有 Docker 服务&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;完整的部署流程：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;本地写 Markdown
 → git push
 → Gitea (git.ruisv.com)
 → Gitea Actions 触发
 → act_runner 拉起 hugomods/hugo:exts 容器构建
 → 输出到 /apps/blog/public
 → nginx 容器对外提供服务
 → Caddy 反代 ruis.hk → nginx:8080
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;评论系统独立部署：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ruis.hk 页面加载 Waline JS
 → 请求 comments.ruis.hk
 → Caddy 反代 → Waline 容器:8360
 → SQLite 存储
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="服务一览"&gt;服务一览
&lt;/h2&gt;&lt;p&gt;所有服务全部跑在 Docker 里，主机只挂载数据目录：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;~/apps/
├── gitea/ Gitea 代码托管
├── gitea-runner/ Gitea Actions Runner
├── blog/ nginx 静态文件服务
│ └── public/ Hugo 构建输出
└── waline/ 评论系统
 └── data/ SQLite 持久化
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="踩过的坑"&gt;踩过的坑
&lt;/h2&gt;&lt;h3 id="1-gitea-内置-ssh-server-没有启动"&gt;1. Gitea 内置 SSH Server 没有启动
&lt;/h3&gt;&lt;p&gt;现象：端口 2222 在监听，但连接直接被 reset。&lt;/p&gt;
&lt;p&gt;原因：&lt;code&gt;app.ini&lt;/code&gt; 缺少 &lt;code&gt;SSH_SERVER_HOST_KEYS&lt;/code&gt; 配置，Gitea 找不到存放主机密钥的路径，SSH Server 静默跳过启动。&lt;/p&gt;
&lt;p&gt;修复：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;[server]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;SSH_SERVER_HOST_KEYS&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;ssh/gitea.rsa,ssh/gitea.rsa.pub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="2-lxc-容器内-nftables-nat-不生效"&gt;2. LXC 容器内 nftables NAT 不生效
&lt;/h3&gt;&lt;p&gt;现象：在 lxc 里配好了 nftables DNAT 规则，规则看起来正常，但实际流量没有被转发。&lt;/p&gt;
&lt;p&gt;原因：Proxmox LXC 容器共享宿主机内核，容器内的 nftables NAT hook 无法正常工作。&lt;/p&gt;
&lt;p&gt;修复：换用 &lt;code&gt;socat&lt;/code&gt; 在应用层做 TCP 转发，绕开内核 NAT 限制：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;socat TCP-LISTEN:2222,fork,reuseaddr TCP:10.10.10.62:2222
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;用 systemd 管理，开机自启，稳定可靠。&lt;/p&gt;
&lt;h3 id="3-gitea-actions-构建失败duplicate-mount-point"&gt;3. Gitea Actions 构建失败：Duplicate mount point
&lt;/h3&gt;&lt;p&gt;现象：第一次 push 触发构建，报错 &lt;code&gt;Error response from daemon: Duplicate mount point: /blog-public&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;原因：runner 的 &lt;code&gt;config.yml&lt;/code&gt; 里通过 &lt;code&gt;container.options&lt;/code&gt; 挂载了 &lt;code&gt;/blog-public&lt;/code&gt;，workflow 文件里的 &lt;code&gt;container.volumes&lt;/code&gt; 又挂载了一次，Docker 不允许同一路径挂载两次。&lt;/p&gt;
&lt;p&gt;修复：去掉 workflow 里的 &lt;code&gt;container.volumes&lt;/code&gt;，只保留 runner config 里的挂载。&lt;/p&gt;
&lt;h3 id="4-docker-创建的文件-root-权限"&gt;4. Docker 创建的文件 root 权限
&lt;/h3&gt;&lt;p&gt;现象：用 &lt;code&gt;docker run hugomods/hugo:exts new site .&lt;/code&gt; 初始化站点后，生成的文件全是 root 所有，无法直接编辑。&lt;/p&gt;
&lt;p&gt;修复：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;sudo chown -R ruis:ruis ~/apps/blog/src
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="5-caddy-泛域名证书优化"&gt;5. Caddy 泛域名证书优化
&lt;/h3&gt;&lt;p&gt;原本每个子域名单独一张证书，Caddyfile 里 AliDNS 凭据重复了六次。&lt;/p&gt;
&lt;p&gt;优化后：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;*.ruisv.com&lt;/code&gt; 统一一张泛域名证书，所有子域名自动复用&lt;/li&gt;
&lt;li&gt;提取 &lt;code&gt;(tls_ruis_hk)&lt;/code&gt; 和 &lt;code&gt;(proxy_headers)&lt;/code&gt; snippet，消除重复配置&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="写文章流程"&gt;写文章流程
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 新建文章&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hugo new content post/文章标题/index.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 编辑内容（Markdown）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;vim content/post/文章标题/index.md
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 推送，自动部署&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;git add . &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit -m &lt;span style="color:#e6db74"&gt;&amp;#34;post: 文章标题&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git push
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;push 之后大概 30 秒，文章就出现在 ruis.hk 上。&lt;/p&gt;
&lt;h2 id="小结"&gt;小结
&lt;/h2&gt;&lt;p&gt;整套方案完全 Self-hosted，没有月租费用，数据在自己手里。Gitea Actions 的体验和 GitHub Actions 基本一致，Hugo 构建速度很快，Stack 主题开箱即用。&lt;/p&gt;
&lt;p&gt;后续计划把 Waline 的管理员账号配好，再折腾一下博客的样式定制。&lt;/p&gt;</description></item><item><title>Hello World</title><link>https://ruis.ai/post/hello-world/</link><pubDate>Wed, 25 Mar 2026 07:42:07 +0000</pubDate><guid>https://ruis.ai/post/hello-world/</guid><description>&lt;p&gt;第一篇文章，部署测试。&lt;/p&gt;</description></item></channel></rss>