<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
 xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:wfw="http://wellformedweb.org/CommentAPI/"
 xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:atom="http://www.w3.org/2005/Atom"
 xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
 xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
 xmlns:georss="http://www.georss.org/georss"
 xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
 xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<atom:link href="/blog/rss.xml" rel="self" type="application/rss+xml" />
<title>Lindsay</title>
<link>/</link>
<description><![CDATA[]]></description>
<language>en</language>
<lastBuildDate>Fri, 03 Jul 2026 11:43:29 +0800</lastBuildDate>
<generator>Emacs 30.2 org-publish-rss.el 0.8</generator>
<item>
<title>soft-serve git serve 和静态 git 页面</title>
<link>/blog/2026/my-git-server.html</link>
<pubDate>Wed, 24 Jun 2026 00:00:00 +0800</pubDate>
<guid>/blog/2026/my-git-server.html</guid>
<description>
<![CDATA[<p>
我喜欢 <a href="https://github.com/charmbracelet/soft-serve">soft-serve</a> 。
</p>

<p>
它比  <a href="https://about.gitea.com/">gitea</a>/<a href="https://forgejo.org/">forgejo</a>/<a href="https://about.gitlab.com/">gitlab</a> 更轻量：没有 wiki、软件包之类一些可有可无的周边功能，没有复杂的用户和组织权限，甚至没有 Issue/PR。
</p>

<p>
它比  <a href="https://git.zx2c4.com/cgit/about/">cgit</a>/<a href="https://git-scm.com/docs/git-daemon">git-daemon</a> 更完整：支持 http, git, ssh 三种协议克隆仓库。通过 ssh cli (<code>ssh git.charm.sh help</code>) 即可进行仓库管理。（cgit 不会处理 go-get 的请求，需要自己在中间件里注入，就很别扭）
</p>
<div id="outline-container-orgf878857" class="outline-2">
<h2 id="orgf878857">Static web service</h2>
<div class="outline-text-2" id="text-orgf878857">
<p>
soft-serve 没有 web 前端展示仓库。
</p>

<p>
动态的 git 仓库前端渲染，是一个比较耗费性能的功能，加上我的 git 仓库的前端界面不是特别重要，只需要能看一下软件介绍，能简单翻阅一下代码。静态的网页显然已经足够了。
</p>

<p>
可选的 git 静态网页生成器有：
</p>
<ul class="org-ul">
<li><a href="https://codemadness.org/stagit.html">https://codemadness.org/stagit.html</a></li>
<li><a href="https://github.com/mrmekon/itsy-gitsy">https://github.com/mrmekon/itsy-gitsy</a></li>
<li><a href="https://github.com/nmeum/depp">https://github.com/nmeum/depp</a></li>
</ul>
<p>
我选了 depp ，仅仅因为是我认识的人写的，加上 golang 改起来比较方便。
</p>

<p>
在服务端用 git post-receive hook 生成：
</p>
<div class="org-src-container">
<pre class="src src-shell"><span class="org-comment-delimiter"># </span><span class="org-comment">file: $SOFT_SERV_DATA_PATH/hooks/post-receive
</span><span class="org-comment-delimiter"># </span><span class="org-comment">$SOFT_SERV_DATA_PATH/hooks &#20026;soft-serve &#20844;&#29992; git hooks &#30446;&#24405;
</span>
<span class="org-keyword">if</span> [ -f <span class="org-string">"$SOFT_SERVE_REPO_PATH/git-daemon-export-ok"</span> ]; <span class="org-keyword">then</span>
        depp -c 10 <span class="org-sh-escaped-newline">\</span>
             -u <span class="org-string">"$SOFT_SERVE_GIT_PUBLIC_URL/$SOFT_SERVE_REPO_NAME.git"</span> <span class="org-sh-escaped-newline">\</span>
             -d <span class="org-string">"/srv/http/git/$SOFT_SERVE_REPO_NAME"</span> <span class="org-sh-escaped-newline">\</span>
             <span class="org-string">"$SOFT_SERVE_REPO_PATH"</span>
<span class="org-keyword">else</span> 
        [ -z <span class="org-string">"$SOFT_SERVE_REPO_NAME"</span> ] || rm -rf <span class="org-string">"/srv/http/git/$SOFT_SERVE_REPO_NAME"</span>
<span class="org-keyword">fi</span>

<span class="org-comment-delimiter"># </span><span class="org-comment">using my fork: https://git.lin.moe/fork/depp
</span>depp-index -r -x -d /srv/http/git -t git.lin.moe $<span class="org-variable-name">SOFT_SERVE_DATA_PATH</span>/repos
</pre>
</div>

<p>
全部的 server-side hooks 在 <a href="https://git.lin.moe/githooks/">https://git.lin.moe/githooks/</a>
</p>

<p>
nginx 需要能展示静态页面的同时，还要能将 git 请求传递到 soft-serve ，需要写一两条规则：
</p>

<div class="org-src-container">
<pre class="src src-nginx"><span class="org-keyword">upstream</span> <span class="org-function-name">soft-serve</span> {
        <span class="org-keyword">server</span> localhost:23232;
}

<span class="org-keyword">server</span>{
        <span class="org-keyword">listen</span> 443 ssl;
        <span class="org-keyword">listen</span> [::]:443 ssl;

        <span class="org-keyword">server_name</span> git.lin.moe;
        <span class="org-keyword">http</span>2 <span class="org-constant">on</span>;

        <span class="org-keyword">ssl_certificate</span> /path/to/certificate.pem;
        <span class="org-keyword">ssl_certificate_key</span> /path/to/prikey.pem;
        <span class="org-keyword">root</span> /srv/http/git/;

        <span class="org-keyword">location</span> <span class="org-function-name">/</span> {
                <span class="org-keyword">if</span> (<span class="org-variable-name">$arg_go-get</span> != <span class="org-string">""</span>) {
                        <span class="org-keyword">proxy_pass</span> http://soft-serve;
                }
                <span class="org-keyword">try_files</span> <span class="org-variable-name">$uri</span> <span class="org-variable-name">$uri</span>/ @softserve;
        }

        <span class="org-keyword">location</span> <span class="org-function-name">@softserve</span> {
                <span class="org-keyword">proxy_pass</span> http://soft-serve;
                <span class="org-keyword">proxy_set_header</span> Host <span class="org-variable-name">$host</span>;
                <span class="org-keyword">proxy_set_header</span> X-Forwarded-For <span class="org-variable-name">$remote_addr</span>;
                <span class="org-keyword">proxy_set_header</span> X-Forwarded-Proto <span class="org-variable-name">$scheme</span>;
        }
}
</pre>
</div>
</div>
</div>
<div id="outline-container-orgcf2f4dd" class="outline-2">
<h2 id="orgcf2f4dd">SSH CLI wrapper</h2>
<div class="outline-text-2" id="text-orgcf2f4dd">
<p>
使用 <code>ssh myserver.ltd</code> 的方式有几个小缺点：
</p>
<ul class="org-ul">
<li>命令太长了</li>
<li>相比本地 cli 稍微会有一点慢，每次都要建立新的 ssh 连接</li>
<li>ssh 协议是将所有命令参数作为一个字符串传递到服务端，遇到带引号的参数就无法保持原意了，比如 <code>ssh myserver.ltd repo demo desc "This is my repo"</code> ，服务端实际看到的是 <code>repo demo desc This is my repo</code></li>
</ul>

<p>
也为了以后方便支持 shell completion ，我写了一个小脚本：
</p>
<div class="org-src-container">
<pre class="src src-shell">: ${<span class="org-variable-name">RGIT_CONTROL_PATH</span>:=<span class="org-string">"$HOME/.ssh/controlmaster/rgit"</span>}
: ${<span class="org-variable-name">RGIT_INSTANCE</span>:=<span class="org-string">"ssh://git.lin.moe"</span>}

[ -d $(dirname $<span class="org-variable-name">RGIT_CONTROL_PATH</span>) ] || mkdir $(dirname $<span class="org-variable-name">RGIT_CONTROL_PATH</span>)
<span class="org-keyword">if</span> [ <span class="org-negation-char">!</span> -S $<span class="org-variable-name">RGIT_CONTROL_PATH</span> ]; <span class="org-keyword">then</span>
        ssh -f -N <span class="org-sh-escaped-newline">\</span>
            -o <span class="org-variable-name">ExitOnForwardFailure</span>=yes <span class="org-sh-escaped-newline">\</span>
            -o <span class="org-variable-name">ControlMaster</span>=auto <span class="org-sh-escaped-newline">\</span>
            -o <span class="org-variable-name">ControlPath</span>=<span class="org-string">"$RGIT_CONTROL_PATH"</span> <span class="org-sh-escaped-newline">\</span>
            -o <span class="org-variable-name">ControlPersist</span>=1h <span class="org-sh-escaped-newline">\</span>
            $<span class="org-variable-name">RGIT_INSTANCE</span>
<span class="org-keyword">fi</span>

<span class="org-function-name">_quoted_args</span>(){
        <span class="org-builtin">echo</span> -n <span class="org-string">"'$1'"</span>
        <span class="org-builtin">shift</span>
        <span class="org-keyword">for</span> arg<span class="org-keyword"> in</span> <span class="org-string">"$@"</span>; <span class="org-keyword">do</span>
                <span class="org-variable-name">arg</span>=$(<span class="org-builtin">echo</span> $<span class="org-variable-name">arg</span> | sed <span class="org-string">"s/'/'\"'\"'/g"</span>)
                <span class="org-builtin">echo</span> -n <span class="org-string">" '$arg'"</span>
        <span class="org-keyword">done</span>
}

ssh -o <span class="org-variable-name">ControlMaster</span>=auto <span class="org-sh-escaped-newline">\</span>
    -o <span class="org-variable-name">ControlPath</span>=<span class="org-string">"$RGIT_CONTROL_PATH"</span> <span class="org-sh-escaped-newline">\</span>
    -T $<span class="org-variable-name">RGIT_INSTANCE</span> <span class="org-string">"$(_quoted_args "$@")"</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-org2d5e27e" class="outline-2">
<h2 id="org2d5e27e">Issue/PR</h2>
<div class="outline-text-2" id="text-org2d5e27e">
<p>
用邮件列表
</p>
</div>
</div>
]]>
</description></item>
<item>
<title>六月总结</title>
<link>/blog/2026/jun-work.html</link>
<pubDate>Thu, 02 Jul 2026 00:00:00 +0800</pubDate>
<guid>/blog/2026/jun-work.html</guid>
<description>
<![CDATA[<p>
第一周在北京出差，回来之后轻松了一周。后半个月就全都是工作了，有点累，有点焦躁。
虽然说下班之后还是有时间能挤出来，但是上班时间如果不能摸鱼的话，下班之后也没什么精力了。
希望听起来不要像是在找借口。
</p>
<div id="outline-container-org598daa1" class="outline-2">
<h2 id="org598daa1">开源贡献</h2>
<div class="outline-text-2" id="text-org598daa1">
<p>
有点少，一部分原因是工作忙。我已经看到几个人提到 AI 打击做 side project 的热情了，另一部分也是如此。
</p>
</div>
<div id="outline-container-org66076d1" class="outline-3">
<h3 id="org66076d1">Alpine Linux</h3>
<div class="outline-text-3" id="text-org66076d1">
<ul class="org-ul">
<li>帮忙联系了一下 SpacemiT ，他们找经销商优先给欧洲寄 K3 的板子</li>
<li>提交只有一系列 upgrades</li>
</ul>
</div>
</div>
<div id="outline-container-org86e8565" class="outline-3">
<h3 id="org86e8565"><a href="https://github.com/charmbracelet/soft-serve">charmbracelet/soft-serve</a></h3>
<div class="outline-text-3" id="text-org86e8565">
<p>
感觉这个组织都搞 AI 去了，不关心这个项目了，提了两个 PR 都没人管
</p>

<ul class="org-ul">
<li><a href="https://github.com/charmbracelet/soft-serve/pull/799">feat: implements git gc cron job &amp; add cronjob ssh command</a></li>
<li><a href="https://github.com/charmbracelet/soft-serve/pull/897">fix(web): wrap lfs basic upload i/o operations in transactions</a></li>
</ul>
</div>
</div>
<div id="outline-container-org0566884" class="outline-3">
<h3 id="org0566884"><a href="https://github.com/nmeum/depp">nmeum/depp</a></h3>
<div class="outline-text-3" id="text-org0566884">
<ul class="org-ul">
<li><a href="https://github.com/nmeum/depp/issues/2">depp-index: scan git repositories in subdirectories</a></li>
</ul>
</div>
</div>
<div id="outline-container-org9ec0cb2" class="outline-3">
<h3 id="org9ec0cb2"><a href="https://github.com/gogs/git-module">gogs/git-module</a></h3>
<div class="outline-text-3" id="text-org9ec0cb2">
<ul class="org-ul">
<li><a href="https://github.com/gogs/git-module/issues/138">[feature request] Add sha256 object format support</a></li>
</ul>
</div>
</div>
</div>
<div id="outline-container-org81fab2b" class="outline-2">
<h2 id="org81fab2b">生活</h2>
<div class="outline-text-2" id="text-org81fab2b">
<p>
买了新公路车，银贝斯 Agile 。虽然多多少少有点脑袋一热，不过也不算后悔，碳车骑起来和旧的铝架车还是很不一样的，轻快很多。
换了新的码表，带了心率计。第三个周末去爬了武汉的环山绿道，天气有点太热了，码表上的记录到了 39 度。骑了 70 公里受不了回家了。平路巡航心率 170 左右 ，爬陡坡能到 185 。 
</p>

<p>
手机屏幕摔坏了，不如就借此减少一下手机的使用频率。之前经常在晚上躺在床上看漫画到一点左右，早上起来还刷一下二游才起床。下个月就关灯直接睡了吧。
</p>

<p>
不知道是因为 steam deck 还是分体键盘的原因，六月最后一周大拇指左手有点腱鞘炎了。前两天晚上回家关节都是僵硬的，今天稍微好一点了。
</p>
</div>
</div>
]]>
</description></item>
</channel>
</rss>
