<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>烧饼博客</title><description>烧饼博客是一个专注于服务器运维、专业域名投资分析的网站。</description><link>https://u.sb/</link><language>zh-CN</language><copyright>© 2026 烧饼博客</copyright><item><title>博客大联盟：一个给独立博客的收录与聚合站</title><link>https://u.sb/boke/</link><guid isPermaLink="true">https://u.sb/boke/</guid><description>介绍博客大联盟，一个独立博客目录和 RSS 聚合站，帮助大家找到更多有趣的独立博客。</description><pubDate>Sat, 11 Jul 2026 12:39:00 GMT</pubDate><content:encoded>&lt;p&gt;近几年我越来越不爱用搜索引擎找博客了，搜一个技术问题，前几页经常是采集站、营销软文和批量生成的内容。&lt;/p&gt;
&lt;p&gt;社交平台也差不多。算法觉得您喜欢什么，就追着喂什么。刷起来很省事，想顺着一个人的文章慢慢读下去却不容易。&lt;/p&gt;
&lt;p&gt;我认识的那些博客作者其实还在写，只是不太容易在搜索和信息流里碰到他们。于是，我做了一个叫「&lt;a href=&quot;https://bo.ke/&quot;&gt;博客大联盟&lt;/a&gt;」的网站。&lt;/p&gt;
&lt;h2&gt;1、博客大联盟是什么&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://bo.ke/&quot;&gt;博客大联盟&lt;/a&gt; 是一个独立博客目录，顺便聚合每个博客的 RSS。&lt;/p&gt;
&lt;p&gt;它的前身是我手工维护的朋友博客友链聚合 &lt;a href=&quot;https://peng.you/&quot;&gt;peng.you&lt;/a&gt;。后来实在嫌手工维护太麻烦，干脆写了个小系统，把博客名片和 RSS 聚合都自动化了。&lt;/p&gt;
&lt;p&gt;每个博客都有一张名片，上面是名称、作者、简介、标签和最新文章。系统定时读取 RSS，新文章按照发布时间排列。没有猜你喜欢，也没有什么神奇的推荐算法，您可以翻目录、看标签，或者直接搜博客名称和作者。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/2026/07/11/6m3xp/image.webp&quot; alt=&quot;博客大联盟中的烧饼博客详情页，展示已验证标记、博客简介与标签、首页预览和最新文章&quot;&gt;&lt;/p&gt;
&lt;p&gt;目前暂时没打算把这货做成另一个信息流平台。先把各处的独立博客放到一个目录里，让大家能互相找到，这就够了。&lt;/p&gt;
&lt;h2&gt;2、怎么加入博客大联盟&lt;/h2&gt;
&lt;p&gt;整个流程是登录、填写资料、自动检查、验证域名，最后等管理员审核。&lt;/p&gt;
&lt;h3&gt;2.1 登录&lt;/h3&gt;
&lt;p&gt;打开 &lt;a href=&quot;https://bo.ke/&quot;&gt;bo.ke&lt;/a&gt;，使用 GitHub 或 Google 一键登录即可，不需要另外注册账号和记一套新密码。第一次登录时，系统会自动创建账号，只读取昵称、头像和邮箱这些基本资料。您也可以通过&lt;a href=&quot;https://bo.ke/invite/a60a56483c30efb7d61f2f4a457bb03e/&quot;&gt;我的邀请链接&lt;/a&gt;注册哦。&lt;/p&gt;
&lt;h3&gt;2.2 提交博客&lt;/h3&gt;
&lt;p&gt;登录后点击「提交博客」，填写下面这些信息：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;博客名称和链接；&lt;/li&gt;
&lt;li&gt;RSS / Atom 订阅地址，没有也可以不填，不过建议独立博客还是配一个；&lt;/li&gt;
&lt;li&gt;作者和博客简介；&lt;/li&gt;
&lt;li&gt;从现有分类中选择 1 – 5 个标签；&lt;/li&gt;
&lt;li&gt;上传博客头像，或者使用 Gravatar、GitHub、Google 头像；&lt;/li&gt;
&lt;li&gt;如果已经放了博客大联盟的链接，也可以填写链接所在页面。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个账号最多可以收录 5 个博客。&lt;/p&gt;
&lt;p&gt;目前加入的条件如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;博客必须是独立的原创博客，有自己的独立域名，比如 &lt;code&gt;example.com&lt;/code&gt; 或 &lt;code&gt;blog.example.com&lt;/code&gt;，或者使用 PSL 列表的二三级域名，比如 &lt;code&gt;example.github.io&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;博客内容必须是中文为主，不能是纯其他语言的博客；&lt;/li&gt;
&lt;li&gt;博客内容必须是公开的，不能是私密或需要登录才能访问的博客；&lt;/li&gt;
&lt;li&gt;博客必须有一定的更新频率，至少每一年能更新一次，特殊情况可以豁免；&lt;/li&gt;
&lt;li&gt;博客内容必须积极向上，不能包含违法、低俗、恶意攻击、政治敏感等内容；&lt;/li&gt;
&lt;li&gt;不能是采集站、资源下载站、营销软文或批量生成的内容。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.3 自动检查&lt;/h3&gt;
&lt;p&gt;提交后，系统会检查博客链接能不能打开、RSS 能不能解析、头像能不能加载。页面会列出每一项的结果，有问题就改完再提交。全部通过以后，才会进入域名所有权验证。&lt;/p&gt;
&lt;h3&gt;2.4 验证域名并等待审核&lt;/h3&gt;
&lt;p&gt;自动检查通过后，需要证明这个域名确实属于您。完成验证，提交才会进入管理员审核。这一步稍微麻烦一点，下面仔细说。&lt;/p&gt;
&lt;h2&gt;3、域名所有权验证&lt;/h2&gt;
&lt;p&gt;DNS TXT、DNS CNAME 和文件验证三选一。页面会生成一个 token，下面的写法只是示例，实际操作时直接复制页面给出的内容。&lt;/p&gt;
&lt;p&gt;假设您的域名是 &lt;code&gt;example.com&lt;/code&gt;，那么有三种验证方式：&lt;/p&gt;
&lt;h3&gt;3.1 DNS TXT 验证&lt;/h3&gt;
&lt;p&gt;在域名的 DNS 解析中给您博客的域名添加一条 TXT 记录，内容如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;bo-ke-verify=&amp;lt;您的 token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不同 DNS 服务商的填写方式不太一样，有些要给 TXT 内容加引号，有些不需要，添加后记得看一眼服务商显示的完整记录哦。&lt;/p&gt;
&lt;p&gt;加完解析记录后可以用 &lt;code&gt;dig&lt;/code&gt; 或 &lt;code&gt;nslookup&lt;/code&gt; 检查解析结果，确认 TXT 记录已经生效。&lt;/p&gt;
&lt;p&gt;DNS 记录生效可能需要几分钟到几小时。等解析生效后，回到验证页面点击「开始验证」即可。&lt;/p&gt;
&lt;h3&gt;3.2 DNS CNAME 验证&lt;/h3&gt;
&lt;p&gt;为域名添加下面这条 CNAME 记录：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;bo-ke-verify.example.com.  CNAME  verify-&amp;lt;token&amp;gt;.bo.ke.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不同 DNS 服务商的填写方式不太一样。有些只需要填 &lt;code&gt;bo-ke-verify&lt;/code&gt;，有些要填完整域名，有些要给 CNAME 域名最后加点号，添加后记得看一眼服务商显示的完整记录哦。&lt;/p&gt;
&lt;p&gt;加完以后可以用 &lt;code&gt;dig&lt;/code&gt; 或 &lt;code&gt;nslookup&lt;/code&gt; 检查解析结果，确认 CNAME 指向了 &lt;code&gt;verify-&amp;lt;token&amp;gt;.bo.ke.&lt;/code&gt;。等解析生效后，回到验证页面点击「开始验证」即可。&lt;/p&gt;
&lt;h3&gt;3.3 文件验证&lt;/h3&gt;
&lt;p&gt;如果不方便修改 DNS，也可以使用文件验证。在网站根目录放置下面这个纯文本文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;bo-ke-verify-&amp;lt;token&amp;gt;.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;文件内容就是 token 本身。验证页面会直接生成文件供您下载，上传到网站根目录后，确认下面这样的地址可以公开访问：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;https://example.com/bo-ke-verify-&amp;lt;token&amp;gt;.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;如果您的博客开了 WAF、防火墙或反爬虫的话，记得放行带有 &lt;code&gt;bo.ke&lt;/code&gt; 关键字的 User-Agent，不然验证请求可能直接被挡在门外。&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;3.4 验证记录不要删除&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;无论选择哪一种方式，验证通过后都不要删除 DNS 记录或验证文件哦。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;系统每 7 天重新检查一次。连续 3 次找不到验证记录，博客就会和账号解除关联。这个设计主要是防止域名转手以后，旧站长还能修改新站的资料。&lt;/p&gt;
&lt;p&gt;所以不要在验证成功后顺手删掉记录，不然三个星期后还得重新认领。&lt;/p&gt;
&lt;h2&gt;4、认领已经存在的博客&lt;/h2&gt;
&lt;p&gt;以前 &lt;code&gt;peng.you&lt;/code&gt; 里的数据有一部分导入了新站，管理员偶尔也会手工添加博客。这些条目还没有绑定账号，页面上会显示「认领此博客」。&lt;/p&gt;
&lt;p&gt;如果发现自己的博客已经在里面，点击认领，再走一遍域名验证。通过后条目就会归到您的账号名下，以后可以自己修改资料。&lt;/p&gt;
&lt;h2&gt;5、互链不是门槛，但会加权&lt;/h2&gt;
&lt;p&gt;您可以在博客首页、友链页面或者任意内页，放一个指向 &lt;a href=&quot;https://bo.ke/&quot;&gt;https://bo.ke/&lt;/a&gt; 的链接。&lt;/p&gt;
&lt;p&gt;互链不是收录条件，不放也能正常提交。系统会定期检查，找到链接后会提高博客的展示权重。&lt;/p&gt;
&lt;p&gt;可以参考我们的&lt;a href=&quot;https://u.sb/links/&quot;&gt;友情链接&lt;/a&gt;页面，里面也放了博客大联盟。&lt;/p&gt;
&lt;h2&gt;6、收录以后能做什么&lt;/h2&gt;
&lt;p&gt;审核通过后，博客会出现在目录和标签页里，也可以按照名称、域名或作者搜索。博客名片下面会显示最新一篇文章。&lt;/p&gt;
&lt;p&gt;如果填写了 RSS / Atom 地址，系统会每 6 小时抓取一次，每个博客保留最近 20 篇。全站文章也有提供 &lt;a href=&quot;https://bo.ke/rss.xml&quot;&gt;RSS&lt;/a&gt; 和 &lt;a href=&quot;https://bo.ke/atom.xml&quot;&gt;Atom&lt;/a&gt; 订阅，丢进任何一个支持 RSS 的阅读器就能订阅。您也可以&lt;a href=&quot;https://bo.ke/subscribe/&quot;&gt;定制自己的专属订阅&lt;/a&gt;，屏蔽不想看到的博客。&lt;/p&gt;
&lt;p&gt;如果你博客的资料有变化可以直接在控制台编辑，不用重新审核。&lt;/p&gt;
&lt;p&gt;如果不想使用这个平台，在控制台删除博客即可，博客资料、聚合文章和认领记录会一起清除。&lt;/p&gt;
&lt;h2&gt;7、给喜欢折腾的人&lt;/h2&gt;
&lt;p&gt;博客大联盟有一套&lt;a href=&quot;https://bo.ke/api/&quot;&gt;公开 JSON API&lt;/a&gt;，可以读取博客列表、全站最新文章和单个博客的最近文章。接口不用认证，支持跨域，做展示页或小工具都够用。数据每 6 小时才更新一次，别按秒轮询哦。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bo.ke/brand/&quot;&gt;品牌资源页面&lt;/a&gt;放了深浅两色的 Logo 和徽标，提供 SVG、PNG、WebP 格式。颜色也可以在页面上改，做友链图标时比较省事。&lt;/p&gt;
&lt;p&gt;访问统计用的是自建 Plausible，没有统计 Cookie，也不做跨站跟踪。&lt;/p&gt;
&lt;h2&gt;8、加入博客大联盟&lt;/h2&gt;
&lt;p&gt;如果您也在写博客，欢迎来加入&lt;a href=&quot;https://bo.ke/&quot;&gt;博客大联盟&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;登录、填资料、验证域名，几分钟就能弄完，剩下的交给管理员审核。&lt;/p&gt;
&lt;p&gt;如有问题可以随时&lt;a href=&quot;https://bo.ke/contact/&quot;&gt;联系我们&lt;/a&gt;。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>回归初心，文字为王</title><link>https://u.sb/writing-first/</link><guid isPermaLink="true">https://u.sb/writing-first/</guid><description>这篇文章从一次博客重构说起，反思这些年从 WordPress、静态博客到 AI vibe coding 的不断折腾。技术和工具当然能让博客更快、更漂亮，但它们终究只是载体。真正能留下来的，不是框架、封面图或动画，而是一个人真实写下的文字和思考。与其追逐每一个新工具，不如回归初心，慢慢写博客，让文字重新成为博客的核心。</description><pubDate>Tue, 07 Jul 2026 02:00:00 GMT</pubDate><content:encoded>&lt;p&gt;这篇文章从一次博客重构说起，反思这些年从 WordPress、静态博客到 AI vibe coding 的不断折腾。技术和工具当然能让博客更快、更漂亮，但它们终究只是载体。真正能留下来的，不是框架、封面图或动画，而是一个人真实写下的文字和思考。与其追逐每一个新工具，不如回归初心，慢慢写博客，让文字重新成为博客的核心。&lt;/p&gt;
&lt;h2&gt;前言&lt;/h2&gt;
&lt;p&gt;从大学开始算起，本人写博客也快 20 年了。&lt;/p&gt;
&lt;p&gt;这 20 年里，我见过各种各样的博客站点，也见过不少小伙伴从入坑到弃坑，再入坑，再弃坑。有的人写博客，是为了记录技术和生活上的点滴；有的人写博客，是为了 SEO，提高排名，顺便推广自己的产品；有的人写博客，是为了赚钱；更多的人，可能和我一样，纯属折腾。&lt;/p&gt;
&lt;p&gt;从折腾 WordPress 主题和插件，到折腾静态化 HTML 博客程序，再到如今用 AI vibe coding 定制自己的博客系统，工具一代一代换，框架一轮一轮火。等夜深人静的时候，你大概也应该停下来问问自己：写博客的目的到底是什么？&lt;/p&gt;
&lt;p&gt;是为了把网站做得更炫吗？是为了用上最新的框架吗？是为了让 Lighthouse 跑满分吗？还是为了把脑子里那些乱七八糟的想法，尽量诚实地留下来？&lt;/p&gt;
&lt;h2&gt;折腾&lt;/h2&gt;
&lt;p&gt;前段时间，我又开始折腾自己的博客首页。&lt;/p&gt;
&lt;p&gt;再加上最近 AI 作图流行，我还给每篇文章都做了统一风格的封面图。刚开始看着还挺像那么回事，时间一久，越看越不顺眼。&lt;/p&gt;
&lt;p&gt;一个好端端的分享技术的博客网站，要那么多图片干嘛？&lt;/p&gt;
&lt;p&gt;更何况我又没什么艺术细胞，AI 的确能作图，但没艺术细胞的人用 AI 做出来的图，基本上一眼也能看出是 AI 做的。它可能很精致，也可能很「正确」，但就是少了点人味。甚至有些时候，那些图并不是在帮文章表达什么，而是在证明我也跟上了某种潮流。&lt;/p&gt;
&lt;p&gt;于是趁着这个周末，我又一次折腾了自己的博客。&lt;/p&gt;
&lt;p&gt;这次从 &lt;a href=&quot;https://nextjs.org/&quot;&gt;Next.js&lt;/a&gt; 换到了构建速度更快、也更适合纯静态内容的 &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;。同时，我撤掉了所有文章封面图，OG 图片也改成由程序自动生成。至于 SEO、文章内页 ToC 这些东西，交给 AI 来处理就行了，不再让它们喧宾夺主。&lt;/p&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;th&gt;版本&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;运行时 / 包管理&lt;/td&gt;
&lt;td&gt;Bun&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;框架&lt;/td&gt;
&lt;td&gt;Astro（纯静态输出，零运行时框架）&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;样式&lt;/td&gt;
&lt;td&gt;Tailwind CSS（&lt;code&gt;@tailwindcss/vite&lt;/code&gt; 插件，CSS-first 配置）&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;内容格式&lt;/td&gt;
&lt;td&gt;MDX（&lt;code&gt;@astrojs/mdx&lt;/code&gt;，&lt;code&gt;optimize: true&lt;/code&gt;）&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;交互&lt;/td&gt;
&lt;td&gt;原生 JS（&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 块，无 React/Vue 运行时）&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;放在以前，这种事情不折腾几个星期大概是做不完的。现在有了 AI，一晚上就能搞定。&lt;/p&gt;
&lt;p&gt;这当然很爽。&lt;/p&gt;
&lt;p&gt;但爽完以后，我又不得不问自己：这么折腾来折腾去，目的到底是什么？&lt;/p&gt;
&lt;p&gt;是为了体验最新科技？是为了追逐更快的 build 速度？是为了证明自己还没有被前端时代抛弃？还是只是因为我们这些老网民，总觉得网站不改点什么就浑身难受？&lt;/p&gt;
&lt;p&gt;技术当然重要。一个轻量、快速、结构清晰的博客系统，可以让写作这件事变得更舒服。但技术终究只是水管，不是水本身。框架再新，页面再快，动画再丝滑，如果文章本身没有内容，那也只是一个加载速度很快的空壳。&lt;/p&gt;
&lt;p&gt;博客最重要的东西，始终不是首页长什么样，不是封面图够不够统一，也不是用了哪个新框架，而是文字本身有没有留下你的思考。&lt;/p&gt;
&lt;h2&gt;文字&lt;/h2&gt;
&lt;p&gt;现在的互联网越来越像信息流水线。&lt;/p&gt;
&lt;p&gt;社交平台追求即时反馈，短视频追求几秒钟的刺激，AI 负责把内容变得更快、更满、更像样。每个人都可以很快生成一篇文章、一张图、一个视频，甚至一个看起来完整的个人网站。&lt;/p&gt;
&lt;p&gt;但也正因为如此，真正稀缺的东西反而变了。&lt;/p&gt;
&lt;p&gt;以前稀缺的是发布能力。你得会建站，会写 HTML，会折腾服务器，才能拥有自己的一个小角落。现在稀缺的不是发布，而是判断；不是表达能力，而是诚实表达；不是内容数量，而是你到底有没有真正想过。&lt;/p&gt;
&lt;p&gt;AI 可以帮你写得更顺，帮你修语法，帮你生成摘要，甚至帮你做图。但 AI 不能替你活过那些日子，也不能替你在某个深夜突然想明白一件小事。&lt;/p&gt;
&lt;p&gt;博客的价值，恰恰在这里。&lt;/p&gt;
&lt;p&gt;它不一定要服务算法，也不一定要讨好读者。它可以很慢，可以很个人，可以有点啰嗦，甚至可以有点笨。它像是你在互联网上留给自己的一个锚点：过了几年再回头看，你会知道当时的自己在想什么，关心什么，又为什么要这样折腾。&lt;/p&gt;
&lt;p&gt;这也是我越来越觉得，博客不应该被做成一个小型媒体站，也不一定非要变成作品集、流量入口或者商业落地页。&lt;/p&gt;
&lt;p&gt;博客首先应该是一个人说话的地方。&lt;/p&gt;
&lt;h2&gt;总结&lt;/h2&gt;
&lt;p&gt;我们这些互联网老人的折腾精力和速度，已经越来越跟不上科技的发展了。&lt;/p&gt;
&lt;p&gt;现在 AI 大爆发，几乎每周，甚至每天都有新的模型、新的工具、新的框架、新的工作流冒出来。你当然可以一直追，也可以一直改，一直重构，一直把自己的博客当成前端实验田。&lt;/p&gt;
&lt;p&gt;但到最后，真正能留下来的，大概率还是那些你亲手写下来的文字。&lt;/p&gt;
&lt;p&gt;所以，就让我们回归初心吧。&lt;/p&gt;
&lt;p&gt;少一点花里胡哨的 JS、CSS 动画和 AI 作图，少一点为了折腾而折腾的冲动，多一点安静写字的耐心。&lt;/p&gt;
&lt;p&gt;毕竟，博客不是展示工具链的地方，而是留下思考的地方。&lt;/p&gt;
&lt;p&gt;文字，才是自己真正的原创。&lt;/p&gt;
&lt;p&gt;不是嘛？&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Ubuntu 24.04 Noble 升级 Ubuntu 26.04 Resolute</title><link>https://u.sb/ubuntu-upgrade-2604/</link><guid isPermaLink="true">https://u.sb/ubuntu-upgrade-2604/</guid><description>本文将指导如何升级 Ubuntu 24.04 Noble Numbat 到 Ubuntu 26.04 Resolute Raccoon。</description><pubDate>Tue, 19 May 2026 19:12:04 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何升级 Ubuntu 24.04 Noble Numbat 到 Ubuntu 26.04 Resolute Raccoon。&lt;/p&gt;
&lt;p&gt;相关教程：&lt;a href=&quot;https://u.sb/ubuntu-upgrade-2404/&quot;&gt;Ubuntu 22.04 Jammy 升级 Ubuntu 24.04 Noble&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;准备工作&lt;/h2&gt;
&lt;p&gt;除非你是物理服务器，以及没有用过奇奇怪怪定制或修改的内核的 KVM 构架的 VPS 和云主机，否则升级大版本更新内核是有一定机率导致 Grub 加载失败的，切记备份重要数据！&lt;/p&gt;
&lt;p&gt;&lt;em&gt;OpenVZ 和 LXC 构架的 VPS 是无法升级的，因为他们没有自己独立的内核&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;再强调一遍，一定要备份重要数据！&lt;/p&gt;
&lt;p&gt;Ubuntu 26.04 LTS 已经正式发布，不过 Ubuntu LTS 版本的自动升级提示通常会等到第一个小版本发布后才会开放。如果你在 Ubuntu 26.04.1 LTS 发布前从 Ubuntu 24.04 LTS 升级，&lt;code&gt;do-release-upgrade&lt;/code&gt; 需要加上 &lt;code&gt;-d&lt;/code&gt; 参数。&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;更新系统&lt;/h2&gt;
&lt;p&gt;首先需要更新你当前的系统&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt autoclean
sudo apt autoremove -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果内核更新了，可以重启让最新的内核生效，也可以直接进行升级。&lt;/p&gt;
&lt;h2&gt;升级系统&lt;/h2&gt;
&lt;p&gt;这里有两种升级系统的方法，第一种是使用 &lt;code&gt;do-release-upgrade&lt;/code&gt; 命令，第二种是手动更新 &lt;code&gt;apt&lt;/code&gt; 源文件。&lt;/p&gt;
&lt;h3&gt;方法一：使用 &lt;code&gt;do-release-upgrade&lt;/code&gt; 命令&lt;/h3&gt;
&lt;p&gt;首先需要安装 &lt;code&gt;ubuntu-release-upgrader-core&lt;/code&gt; 包：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install ubuntu-release-upgrader-core
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后修改 &lt;code&gt;/etc/update-manager/release-upgrades&lt;/code&gt; 文件，确保 &lt;code&gt;Prompt&lt;/code&gt; 值为 &lt;code&gt;lts&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat /etc/update-manager/release-upgrades | grep lts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;显示如下内容即可：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@ubuntu ~ # cat /etc/update-manager/release-upgrades | grep lts
#  lts    - Check to see if a new LTS release is available.  The upgrader
Prompt=lts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后执行以下命令升级系统：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo do-release-upgrade -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;等 Ubuntu 26.04.1 LTS 发布并开放 LTS 自动升级后，可以直接使用：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo do-release-upgrade
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;方法二：手动更新 &lt;code&gt;apt&lt;/code&gt; 源文件&lt;/h3&gt;
&lt;p&gt;Ubuntu 24.04 的默认软件源配置文件已经变更为 &lt;code&gt;DEB822&lt;/code&gt; 格式，路径为 &lt;code&gt;/etc/apt/sources.list.d/ubuntu.sources&lt;/code&gt;。我们可以直接替换 &lt;code&gt;noble&lt;/code&gt; 为 &lt;code&gt;resolute&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sed -i &amp;#39;s/noble/resolute/g&amp;#39; /etc/apt/sources.list.d/ubuntu.sources
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你的系统里仍然有传统 One-Line-Style 的源文件，也可以一并替换：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sed -i &amp;#39;s/noble/resolute/g&amp;#39; /etc/apt/sources.list
sudo sed -i &amp;#39;s/noble/resolute/g&amp;#39; /etc/apt/sources.list.d/*.list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有对应文件会提示诸如 &lt;code&gt;sed: can&amp;#39;t read /etc/apt/sources.list: No such file or directory&lt;/code&gt; 的错误，忽略即可。&lt;/p&gt;
&lt;p&gt;或者直接一行命令：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sed -i &amp;#39;s/noble/resolute/g&amp;#39; /etc/apt/sources.list /etc/apt/sources.list.d/*.{list,sources} 2&amp;gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用 &lt;code&gt;DEB822&lt;/code&gt; 格式的源文件 &lt;code&gt;/etc/apt/sources.list.d/ubuntu.sources&lt;/code&gt; 应该是类似这样的：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Types: deb
URIs: https://archive.ubuntu.com/ubuntu
Suites: resolute resolute-updates resolute-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://security.ubuntu.com/ubuntu
Suites: resolute-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;国内服务器可以替换 &lt;code&gt;archive.ubuntu.com&lt;/code&gt; 和 &lt;code&gt;security.ubuntu.com&lt;/code&gt; 为 &lt;code&gt;mirrors.tuna.tsinghua.edu.cn&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;如果你有第三方源或 PPA，建议先备份并根据情况临时禁用，升级完成后再确认是否支持 Ubuntu 26.04：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mkdir -p /root/apt-sources-backup
sudo cp -a /etc/apt/sources.list.d /root/apt-sources-backup/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第三方源通常需要单独检查，不能简单把 &lt;code&gt;noble&lt;/code&gt; 替换成 &lt;code&gt;resolute&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;然后我们再次执行更新系统：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt full-upgrade -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;更新过程中会提示一些软件是否需要自动重启，选 Yes 即可，以及一些软件的配置文件是否需要更新，按照自己的情况选择即可，默认回车即视为使用旧的配置文件，一般会出现在 OpenSSH 等软件的更新上。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;更新后删除不必要的软件和依赖：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt autoclean
sudo apt autoremove -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们使用 &lt;code&gt;sudo reboot&lt;/code&gt; 命令重启系统，耐心等待后，查看最新的系统版本：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@ubuntu ~ # lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 26.04 LTS
Release:	26.04
Codename:	resolute
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@ubuntu ~ # uname -a
Linux Nana 7.0.0-15-generic #15-Ubuntu SMP PREEMPT_DYNAMIC Wed Apr 22 16:06:43 UTC 2026 x86_64 GNU/Linux
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这时我们就已经更新到了最新的 Ubuntu 26.04 Resolute 和内核了。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>WSL 2 使用 Docker 桥接模式网络访问 HTTPS 超时的解决方法</title><link>https://u.sb/fix-wsl-2-docker-network/</link><guid isPermaLink="true">https://u.sb/fix-wsl-2-docker-network/</guid><description>本文介绍在 WSL 2 中使用 Docker 的桥接模式（bridge network）访问 HTTPS 时出现超时问题的解决方法。</description><pubDate>Wed, 21 Jan 2026 04:53:46 GMT</pubDate><content:encoded>&lt;p&gt;本文介绍在 WSL 2 中使用 Docker 的桥接模式（bridge network）访问 HTTPS 时出现超时问题的解决方法。&lt;/p&gt;
&lt;p&gt;最近一直在 Windows 下使用基于 WSL 2 的 Debian 进行开发。许多场景下需要使用 Docker 构建镜像，但过程中遇到一个奇怪的问题，在 Docker 容器内部访问 HTTP 站点时一切正常：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ docker run --rm curlimages/curl time curl -s http://ip.gs
192.0.2.2
real    0m 0.02s
user    0m 0.00s
sys     0m 0.00s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一旦切换为 HTTPS，访问就会明显变慢，并且有一定概率出现超时：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ docker run --rm curlimages/curl time curl -s https://ip.gs
192.0.2.2
real    0m 6.52s
user    0m 0.00s
sys     0m 0.00s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然而，如果将 Docker 切换到 Host 模式（&lt;code&gt;--network=host&lt;/code&gt;），访问又恢复正常：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ docker run --rm --network=host curlimages/curl time curl -s https://ip.gs
192.2.0.2
real    0m 0.28s
user    0m 0.00s
sys     0m 0.00s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在排查了 WSL 2 的 Debian 系统配置后，最终请教 ChatGPT 得到结论：&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Path MTU 与防火墙流量检查（inspection）不兼容导致问题&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;解决方法很简单：将 WSL 2 虚拟网络的 MTU 下调为 &lt;code&gt;1400&lt;/code&gt; 即可。&lt;/p&gt;
&lt;h2&gt;1、添加 Docker 配置&lt;/h2&gt;
&lt;p&gt;在 WSL 2 的系统里，使用 root 权限（&lt;code&gt;sudo&lt;/code&gt;）修改 &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt; 文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
    &amp;quot;log-driver&amp;quot;: &amp;quot;json-file&amp;quot;,
    &amp;quot;log-opts&amp;quot;: {
        &amp;quot;max-size&amp;quot;: &amp;quot;20m&amp;quot;,
        &amp;quot;max-file&amp;quot;: &amp;quot;3&amp;quot;
    },
    &amp;quot;mtu&amp;quot;: 1400,
    &amp;quot;dns&amp;quot;: [
      &amp;quot;8.8.8.8&amp;quot;,
      &amp;quot;1.1.1.1&amp;quot;
    ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中 &lt;code&gt;&amp;quot;mtu&amp;quot;: 1400,&lt;/code&gt; 是关键配置。&lt;/p&gt;
&lt;p&gt;然后在 Windows 下把 WSL 2 关闭：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;wsl --shutdown
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2、修改 WSL 2 网卡配置&lt;/h2&gt;
&lt;p&gt;在 Windows 下使用管理员身份运行 Powershell，检查网卡名称：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;PS C:\Users\showfom&amp;gt; Get-NetAdapter | Where-Object { $_.Name -like &amp;quot;*WSL*&amp;quot; }

Name                      InterfaceDescription                    ifIndex Status       MacAddress             LinkSpeed
----                      --------------------                    ------- ------       ----------             ---------
vEthernet (WSL (Hyper-V … Hyper-V Virtual Ethernet Adapter #3          41 Up           12-34-56-78-AB-CD        10 Gbps

PS C:\Users\showfom&amp;gt; Get-NetAdapter | Format-Table -AutoSize

Name                               InterfaceDescription                      ifIndex Status       MacAddress        Lin
                                                                                                                    kSp
                                                                                                                    eed
----                               --------------------                      ------- ------       ----------        ---
vEthernet (Default Switch)         Hyper-V Virtual Ethernet Adapter               35 Up           12-34-56-78-AB-AB …ps
vEthernet (WSL (Hyper-V firewall)) Hyper-V Virtual Ethernet Adapter #3            41 Up           12-34-56-78-AB-CD …ps
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出可以看到完整名称为 &lt;code&gt;vEthernet (WSL (Hyper-V firewall))&lt;/code&gt;，然后为其设置 MTU：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;netsh interface ipv4 set subinterface &amp;quot;vEthernet (WSL (Hyper-V firewall))&amp;quot; mtu=1400 store=persistent
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;出现 &lt;code&gt;Ok.&lt;/code&gt; 字样即代表设置成功。&lt;/p&gt;
&lt;h2&gt;3、测试 WSL 2 中的 Docker 网络&lt;/h2&gt;
&lt;p&gt;然后重新运行 WSL 2 虚拟机：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;wsl -d debian
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再次测试：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ docker run --rm curlimages/curl time curl -s https://ip.gs
192.0.2.2
real    0m 0.28s
user    0m 0.00s
sys     0m 0.00s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题已完美解决，可以继续愉快地 Vibe Coding 了！ &lt;em&gt;★,°&lt;/em&gt;:.☆(￣▽￣)/$:&lt;em&gt;.°★&lt;/em&gt; 。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian / Ubuntu 下使用 nginx-acme 自动签发并配置 SSL 证书</title><link>https://u.sb/debian-nginx-acme/</link><guid isPermaLink="true">https://u.sb/debian-nginx-acme/</guid><description>本文将介绍在 Debian 或 Ubuntu 下使用 nginx-acme 自动签发并配置 SSL 证书的方法。</description><pubDate>Fri, 16 Jan 2026 03:05:21 GMT</pubDate><content:encoded>&lt;p&gt;本文将介绍在 Debian 或 Ubuntu 下使用 nginx-acme 自动签发并配置 SSL 证书的方法。&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;1、什么是 nginx-acme&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nginx/nginx-acme&quot;&gt;nginx-acme&lt;/a&gt; 是 Nginx 官方开发的基于 ACME 协议自动签发 SSL 证书的模块，隔壁 Caddy 都出了几百年的功能， Nginx 也终于赶上了。&lt;/p&gt;
&lt;p&gt;和 Nginx 使用 C 语言开发不同，这个模块是用 Rust 语言开发的，这里就不做评价。&lt;/p&gt;
&lt;p&gt;这个模块支持 &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc8555&quot;&gt;RFC8555&lt;/a&gt;、&lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc8737&quot;&gt;RFC8737&lt;/a&gt;、&lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc8738&quot;&gt;RFC8738&lt;/a&gt; 和 &lt;a href=&quot;https://datatracker.ietf.org/doc/draft-ietf-acme-profiles/&quot;&gt;draft-ietf-acme-profiles&lt;/a&gt; 等规范，目前我实际测试下来已经基本可以用于生产环境。&lt;/p&gt;
&lt;h2&gt;2、安装 N.WTF&lt;/h2&gt;
&lt;p&gt;这里我们使用&lt;a href=&quot;https://u.sb/&quot;&gt;烧饼博客&lt;/a&gt;打包的 &lt;a href=&quot;https://n.wtf/&quot;&gt;N.WTF&lt;/a&gt;，这个项目已经集成了 &lt;code&gt;nginx-acme&lt;/code&gt; 模块，可以做到开箱即用。&lt;/p&gt;
&lt;p&gt;首先，安装一些必要的软件包：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后加入 N.WTF 的 GPG 公钥和 apt 源：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -sSL https://n.wtf/public.key | sudo bash -c &amp;#39;gpg --dearmor &amp;gt; /usr/share/keyrings/n.wtf.gpg&amp;#39;
sudo bash -c &amp;#39;echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror-cdn.xtom.com/sb/nginx/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/n.wtf.list&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;国内机器可以用&lt;a href=&quot;https://mirrors.tuna.tsinghua.edu.cn/&quot;&gt;清华 TUNA&lt;/a&gt; 的国内源：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -sSL https://mirrors.tuna.tsinghua.edu.cn/n.wtf/public.key | sudo bash -c &amp;#39;gpg --dearmor &amp;gt; /usr/share/keyrings/n.wtf.gpg&amp;#39;
sudo bash -c &amp;#39;echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirrors.tuna.tsinghua.edu.cn/n.wtf/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/n.wtf.list&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Debian 下也可以直接使用 &lt;a href=&quot;https://u.sb/debian-extrepo/&quot;&gt;extrepo&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install extrepo -y
sudo extrepo enable n.wtf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接着更新系统并安装 Nginx：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install nginx-extras -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3、nginx-acme 准备工作&lt;/h2&gt;
&lt;p&gt;准备工作很简单，我们需要建立一个目录来存放 SSL 证书并给予正确的权限，这里我们以 &lt;code&gt;/var/cache/nginx/letsencrypt&lt;/code&gt; 为演示：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mkdir -p /var/cache/nginx
sudo mkdir -p /var/cache/nginx/letsencrypt
sudo chown 33:33 /var/cache/nginx -R
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后别忘了把域名解析到你的服务器哦！&lt;/p&gt;
&lt;h2&gt;4、配置 Nginx 站点&lt;/h2&gt;
&lt;p&gt;我们以 &lt;code&gt;example.com&lt;/code&gt; 为例，假设你的邮箱是 &lt;code&gt;user@example.com&lt;/code&gt;，需要配置的域名是 &lt;code&gt;example.com&lt;/code&gt; 和 &lt;code&gt;www.example.com&lt;/code&gt;，并且希望访问 &lt;code&gt;www.example.com&lt;/code&gt; 跳转到 &lt;code&gt;example.com&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;直接修改 &lt;code&gt;/etc/nginx/sites-enabled/default&lt;/code&gt; 文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;resolver 8.8.8.8:53 ipv6=off valid=5s;

acme_issuer letsencrypt {
    uri         https://acme-v02.api.letsencrypt.org/directory;
    contact     user@example.com;
    state_path  /var/cache/nginx/letsencrypt;
    accept_terms_of_service;
    ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
    ssl_verify on;
}

acme_shared_zone zone=ngx_acme_shared:1M;

server {
    # Listen on port 80 for all IPv4 and IPv6 addresses
    listen 80 default_server;
    listen [::]:80 default_server;
   
    # Match all domain names
    server_name _;

    location /.well-known/ {
        return 404;
    }

    location / {
        # Redirect all other HTTP requests to HTTPS using 301 permanent redirect
        return 301 https://$host$request_uri;
    }
}

server {
    # Standard TLS listening
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    # HTTP/2 protocol support
    http2 on;
   
    # HTTP/3 QUIC protocol support
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;
    add_header Alt-Svc &amp;#39;h3=&amp;quot;:443&amp;quot;; ma=86400&amp;#39; always;
    add_header X-Protocol $server_protocol always;

    server_name example.com;
    root /var/www/html;
    index index.html;

    # modern configuration
    ssl_protocols TLSv1.3;
    ssl_ecdh_curve X25519:prime256v1:secp384r1;
    ssl_prefer_server_ciphers off;

    acme_certificate letsencrypt;

    ssl_certificate       $acme_certificate;
    ssl_certificate_key   $acme_certificate_key;

    # do not parse the certificate on each request
    ssl_certificate_cache max=2;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    http2 on;

    listen 443 quic;
    listen [::]:443 quic;

    add_header Alt-Svc &amp;#39;h3=&amp;quot;:443&amp;quot;; ma=86400&amp;#39; always;
    add_header X-Protocol $server_protocol always;

    server_name www.example.com;
    return 301 https://example.com$request_uri;

    ssl_protocols TLSv1.3;
    ssl_ecdh_curve X25519:prime256v1:secp384r1;
    ssl_prefer_server_ciphers off;

    acme_certificate letsencrypt;

    ssl_certificate       $acme_certificate;
    ssl_certificate_key   $acme_certificate_key;

    # do not parse the certificate on each request
    ssl_certificate_cache max=2;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后验证 Nginx 配置并重新加载：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -t
sudo nginx -s reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时，在默认的 Nginx 日志文件 &lt;code&gt;/var/log/nginx/access.log&lt;/code&gt; 中可以看到 Let&amp;#39;s Encrypt 验证服务器的请求记录：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;23.178.112.210 - - [15/Jan/2026:16:08:18 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
34.212.137.78 - - [15/Jan/2026:16:08:18 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
18.222.179.58 - - [15/Jan/2026:16:08:18 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
16.171.19.61 - - [15/Jan/2026:16:08:18 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
13.228.72.222 - - [15/Jan/2026:16:08:18 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
2600:3000:2710:200::81 - - [15/Jan/2026:16:08:20 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
2600:1f14:804:fd02:f7fd:3c68:dec7:a062 - - [15/Jan/2026:16:08:20 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
2600:1f16:269:da00:c9ce:508c:ea69:9c2 - - [15/Jan/2026:16:08:20 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
2a05:d016:39f:3101:8b83:62b8:2603:d15d - - [15/Jan/2026:16:08:20 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
2406:da18:85:1401:1f69:967a:a988:cdc8 - - [15/Jan/2026:16:08:20 +0000] &amp;quot;GET /.well-known/acme-challenge/blablablablablablablablablablablablablablab HTTP/1.1&amp;quot; 200 87 &amp;quot;-&amp;quot; &amp;quot;Mozilla/5.0 (compatible; Let&amp;#39;s Encrypt validation server; +https://www.letsencrypt.org)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;等待数秒后即可访问 &lt;code&gt;https://example.com/&lt;/code&gt; 了。&lt;/p&gt;
&lt;p&gt;如果要给 IP 地址签发证书，则需要在 &lt;code&gt;acme_issuer letsencrypt {}&lt;/code&gt; 段里添加一行 &lt;code&gt;profile shortlived;&lt;/code&gt;，并且 &lt;code&gt;server_name&lt;/code&gt; 必须写入完整的 IP 地址，不能直接用 &lt;code&gt;server_name _&lt;/code&gt; 哦。&lt;/p&gt;
&lt;p&gt;&lt;del&gt;不过目前 nginx-acme 最新版本 0.3.1 签发 IP 证书还是会失败，开发版已经修复，应该需要等下一个版本才能使用。&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;目前最新版本已经支持 IP 地址证书的签发，可以在 &lt;code&gt;accept_terms_of_service;&lt;/code&gt; 下方加入一条 &lt;code&gt;profile shortlived;&lt;/code&gt; 并且自行修改 &lt;code&gt;server_name example.com;&lt;/code&gt; 为你的 IP 地址，比如 &lt;code&gt;server_name 192.0.2.2 2001:db8::2;&lt;/code&gt; 即可。&lt;/p&gt;
&lt;p&gt;读者们在使用过程中如果遇到问题，可以在 V2EX 交流讨论：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://be.st/Mv7j&quot;&gt;https://be.st/Mv7j&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>使用 acme.sh 配置 Let&apos;s Encrypt 签发的 IP 地址 SSL 证书</title><link>https://u.sb/acme-sh-ip-ssl/</link><guid isPermaLink="true">https://u.sb/acme-sh-ip-ssl/</guid><description>本文将介绍使用 acme.sh 配置 Let&apos;s Encrypt 为 IP 地址签发 SSL 证书。</description><pubDate>Wed, 17 Dec 2025 16:13:37 GMT</pubDate><content:encoded>&lt;p&gt;本文将介绍使用 acme.sh 配置 Let&amp;#39;s Encrypt 为 IP 地址签发 SSL 证书。&lt;/p&gt;
&lt;p&gt;acme.sh 本身不强制 root 运行（&lt;a href=&quot;https://github.com/acmesh-official/acme.sh/wiki/How-to-install#4-advanced-installation&quot;&gt;官方&lt;/a&gt;也写了 &amp;quot;You don&amp;#39;t have to be root then, although it is recommended&amp;quot;），但本文的证书需要写入 &lt;code&gt;/etc&lt;/code&gt; 且 &lt;code&gt;--reloadcmd&lt;/code&gt; 需要重载服务，均需要 root 权限，所以建议先使用 &lt;code&gt;sudo -i&lt;/code&gt; 切换到 root 用户再执行本文命令。&lt;/p&gt;
&lt;p&gt;之前写过一篇使用 &lt;a href=&quot;https://github.com/acmesh-official/acme.sh&quot;&gt;acme.sh&lt;/a&gt; 签发证书的&lt;a href=&quot;https://u.sb/acme-sh-ssl/&quot;&gt;教程&lt;/a&gt;，但在很长一段时间里，Let&amp;#39;s Encrypt 只能给&lt;strong&gt;域名&lt;/strong&gt;签发证书。  &lt;/p&gt;
&lt;p&gt;经过几个月的&lt;a href=&quot;https://letsencrypt.org/2025/07/01/issuing-our-first-ip-address-certificate&quot;&gt;测试&lt;/a&gt;之后，现在终于可以对 &lt;strong&gt;IP 地址&lt;/strong&gt; 下手了。&lt;/p&gt;
&lt;h2&gt;为什么要给 IP 签发证书&lt;/h2&gt;
&lt;p&gt;在很多场景下，我们并不一定需要域名，但&lt;strong&gt;确实需要 HTTPS&lt;/strong&gt;。比如：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DNS over HTTPS（DoH）服务无需依赖域名解析&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;直接通过 IP 提供 DoH 服务，避免「为了安全先做一次不安全的域名解析」这种哲学问题。&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Web 服务默认站点隐藏真实域名&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;默认站点只暴露 IP，不暴露真实域名，顺便还能挡掉一部分不太礼貌的爬虫。&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;临时服务或测试环境&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;临时起个服务，只想加个锁，不想再去 DNS 那边折腾。&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;避免证书透明日志（Certificate Transparency Log）暴露域名，保护隐私&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;有些域名不太想出现在公开日志里，低调一点总是好的。&lt;/p&gt;
&lt;h2&gt;准备工作&lt;/h2&gt;
&lt;p&gt;首先更新 acme.sh 到最新版本：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;acme.sh --upgrade
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因为 IP 证书目前只能通过 &lt;a href=&quot;https://letsencrypt.org/docs/challenge-types/#http-01-challenge&quot;&gt;http-01&lt;/a&gt; 和 &lt;a href=&quot;https://letsencrypt.org/docs/challenge-types/#tls-alpn-01&quot;&gt;tls-alpn-01&lt;/a&gt; 方式进行验证，所以你需要检查服务器的防火墙，设置允许 TCP 80 和 TCP / UDP 443 端口在公网可以访问。&lt;/p&gt;
&lt;h2&gt;配置 Nginx 80 端口的默认站点&lt;/h2&gt;
&lt;p&gt;这里我只介绍在 Nginx 下的配置吧，我们可以直接写入 80 端口的默认配置：&lt;/p&gt;
&lt;p&gt;如果你在 Debian 或 Ubuntu 下安装 Nginx，可以直接覆盖 &lt;code&gt;/etc/nginx/sites-available/default&lt;/code&gt; 文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;server {
    # Listen on port 80 for all IPv4 and IPv6 addresses
    listen 80 default_server;
    listen [::]:80 default_server;
   
    # Match all domain names
    server_name _;

    # Merge Let&amp;#39;s Encrypt and SSL verification path configuration
    location ~ ^/.well-known/(acme-challenge|pki-validation)/ {
        add_header Content-Type text/plain;
        root /var/www/letsencrypt;
    }

    # Redirect all other HTTP requests to HTTPS using 301 permanent redirect
    location / {
        return 301 https://$host$request_uri;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后创建两个目录并重新加载 Nginx：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir -p /var/www/letsencrypt
mkdir -p /etc/nginx/ssl
nginx -t
nginx -s reload
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;使用 acme.sh 签发 IP 证书&lt;/h2&gt;
&lt;p&gt;假设你服务器的 IP 地址是 &lt;code&gt;192.0.2.2&lt;/code&gt; 和 &lt;code&gt;2001:db8::2&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;acme.sh --issue --server letsencrypt -d 192.0.2.2 -d 2001:db8::2 \
  -w /var/www/letsencrypt \
  --certificate-profile shortlived \
  --days 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意这里我们必须使用 &lt;a href=&quot;https://letsencrypt.org/docs/profiles/#shortlived&quot;&gt;shortlived&lt;/a&gt; 这个 Profile，因为 Let&amp;#39;s Encrypt 的 IP 证书有效期只有 6.66666 天（160 小时），同时 acme.sh 需要更短的时间来进行检查更新证书，所以可以设置 &lt;code&gt;--days 3&lt;/code&gt; 参数，让它 3 天检查并更新一次，你也可以设置 4 或 5，但是不要设置 6，否则可能证书过期了都没更新哦。&lt;/p&gt;
&lt;p&gt;执行命令以后会看到类似的申请成功返回：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Wed Dec 17 05:46:28 AM UTC 2025] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Wed Dec 17 05:46:28 AM UTC 2025] Multi domain=&amp;#39;IP:192.0.2.2,IP:2001:db8::2&amp;#39;
[Wed Dec 17 05:46:30 AM UTC 2025] Getting webroot for domain=&amp;#39;192.0.2.2&amp;#39;
[Wed Dec 17 05:46:30 AM UTC 2025] Getting webroot for domain=&amp;#39;2001:db8::2&amp;#39;
[Wed Dec 17 05:46:30 AM UTC 2025] Verifying: 192.0.2.2
[Wed Dec 17 05:46:31 AM UTC 2025] Pending. The CA is processing your order, please wait. (1/30)
[Wed Dec 17 05:46:34 AM UTC 2025] Success
[Wed Dec 17 05:46:34 AM UTC 2025] Verifying: 2001:db8::2
[Wed Dec 17 05:46:35 AM UTC 2025] Pending. The CA is processing your order, please wait. (1/30)
[Wed Dec 17 05:46:38 AM UTC 2025] Success
[Wed Dec 17 05:46:38 AM UTC 2025] Verification finished, beginning signing.
[Wed Dec 17 05:46:38 AM UTC 2025] Let&amp;#39;s finalize the order.
[Wed Dec 17 05:46:38 AM UTC 2025] Le_OrderFinalize=&amp;#39;https://acme-v02.api.letsencrypt.org/acme/finalize/blablablablablablablabla/blablablablablablablabla&amp;#39;
[Wed Dec 17 05:46:41 AM UTC 2025] Downloading cert.
[Wed Dec 17 05:46:41 AM UTC 2025] Le_LinkCert=&amp;#39;https://acme-v02.api.letsencrypt.org/acme/cert/blablablablablablablabla&amp;#39;
[Wed Dec 17 05:46:42 AM UTC 2025] Cert success.
-----BEGIN CERTIFICATE-----
blablablablablablablablablablablablablablablablablablabla
-----END CERTIFICATE-----
[Wed Dec 17 05:46:42 AM UTC 2025] Your cert is in: /root/.acme.sh/192.0.2.2_ecc/192.0.2.2.cer
[Wed Dec 17 05:46:42 AM UTC 2025] Your cert key is in: /root/.acme.sh/192.0.2.2_ecc/192.0.2.2.key
[Wed Dec 17 05:46:42 AM UTC 2025] The intermediate CA cert is in: /root/.acme.sh/192.0.2.2_ecc/ca.cer
[Wed Dec 17 05:46:42 AM UTC 2025] And the full-chain cert is in: /root/.acme.sh/192.0.2.2_ecc/fullchain.cer
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们可以把申请好的证书放在 &lt;code&gt;/etc/nginx/ssl&lt;/code&gt; 目录：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir -p /etc/nginx/ssl

acme.sh --install-cert -d 192.0.2.2 \
  --key-file       /etc/nginx/ssl/ip.key  \
  --fullchain-file /etc/nginx/ssl/ip.crt \
  --ca-file        /etc/nginx/ssl/ip.ca.crt \
  --reloadcmd     &amp;quot;systemctl restart nginx&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;配置 Nginx 443 端口的默认站点&lt;/h2&gt;
&lt;p&gt;安装完证书后我们即可配置 Nginx 默认的 443 端口了，你可以把这段配置一起放入 &lt;code&gt;/etc/nginx/sites-available/default&lt;/code&gt; 文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;# HTTPS Server block - Handle all HTTPS requests
server {
    # Standard TLS listening
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    # HTTP/2 protocol support
    http2 on;
   
    # HTTP/3 QUIC protocol support
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;
    add_header Alt-Svc &amp;#39;h3=&amp;quot;:443&amp;quot;; ma=86400&amp;#39; always;
    add_header X-Protocol $server_protocol always;
   
    # Match all domain names
    server_name _;
    return 403;

    # modern configuration
    ssl_protocols TLSv1.3;
    ssl_ecdh_curve X25519:prime256v1:secp384r1;
    ssl_prefer_server_ciphers off;

    ssl_certificate /etc/nginx/ssl/ip.crt;
    ssl_certificate_key /etc/nginx/ssl/ip.key;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后检查并重新加载 Nginx：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nginx -t
nginx -s reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一切就绪以后就可以直接访问 &lt;code&gt;https://192.0.2.2/&lt;/code&gt; 并返回 403 错误页面，我们可以看到证书里 &lt;code&gt;Subject Alt Names&lt;/code&gt; 字段也显示 &lt;code&gt;IP Address&lt;/code&gt; 了：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/2025/12/17/image_sK4sr.png&quot; alt=&quot;证书详情中 Subject Alt Names 字段显示 IP Address&quot;&gt;&lt;/p&gt;
&lt;p&gt;读者们在使用过程中如果遇到问题，可以在 V2EX 交流讨论或在下方评论：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://be.st/pGx9&quot;&gt;https://be.st/pGx9&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>RDAP.SS - 基于 RDAP 协议的 Whois 查询网站</title><link>https://u.sb/rdap-ss/</link><guid isPermaLink="true">https://u.sb/rdap-ss/</guid><description>RDAP.SS 是一个基于 RDAP 协议的 Whois 查询网站，本文介绍 RDAP 协议以及如何使用。</description><pubDate>Mon, 03 Nov 2025 17:01:40 GMT</pubDate><content:encoded>&lt;p&gt;RDAP.SS 是一个基于 RDAP 协议的 Whois 查询网站，本文介绍 RDAP 协议以及如何使用。&lt;/p&gt;
&lt;h2&gt;1、什么是 RDAP 协议？&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.icann.org/en/contracted-parties/registry-operators/resources/registration-data-access-protocol&quot;&gt;RDAP&lt;/a&gt;，全称 Registration Data Access Protocol，由 IETF（互联网工程任务组）制定，主要用于查询以下注册信息：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;域名（Domain）&lt;/li&gt;
&lt;li&gt;IP 地址（IPv4 / IPv6）&lt;/li&gt;
&lt;li&gt;ASN（自治系统号）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它定义在 RFC &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7480.txt&quot;&gt;7480&lt;/a&gt;、&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7481.txt&quot;&gt;7481&lt;/a&gt;、&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7482.txt&quot;&gt;7482&lt;/a&gt;、&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7483.txt&quot;&gt;7483&lt;/a&gt;、&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7484.txt&quot;&gt;7484&lt;/a&gt; 等系列标准中。&lt;/p&gt;
&lt;h2&gt;2、RDAP 和 Whois 协议的区别&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;WHOIS&lt;/th&gt;
&lt;th&gt;RDAP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;传输协议&lt;/td&gt;
&lt;td&gt;基于 TCP 文本协议&lt;/td&gt;
&lt;td&gt;基于 HTTPS RESTful API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据格式&lt;/td&gt;
&lt;td&gt;纯文本、非结构化&lt;/td&gt;
&lt;td&gt;JSON 格式、结构化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;国际化支持&lt;/td&gt;
&lt;td&gt;差，编码不统一&lt;/td&gt;
&lt;td&gt;完全支持 UTF-8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;安全性&lt;/td&gt;
&lt;td&gt;无加密、无认证&lt;/td&gt;
&lt;td&gt;支持 HTTPS、OAuth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;分布式查询&lt;/td&gt;
&lt;td&gt;依靠人工跳转&lt;/td&gt;
&lt;td&gt;内置 &lt;code&gt;bootstrap&lt;/code&gt; 机制，可自动重定向至正确注册局&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;标准化程度&lt;/td&gt;
&lt;td&gt;各注册局格式不同&lt;/td&gt;
&lt;td&gt;格式统一，易于机器读取与解析&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;在传统的 Whois 协议中，用户需要给 Whois 服务器的 43 端口发送查询，然后 Whois 服务器返回纯文本的结果。&lt;/p&gt;
&lt;p&gt;这导致了传统的 Whois 协议有几个无法修补的劣势：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;非结构化的文本输出，没有标准化的接口&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;传统的 Whois 没有统一的查询和返回 API，只有简单的文本命令，这导致每家注册局返回的信息格式不一致，例如有的字段写作 &lt;code&gt;Registrant Email&lt;/code&gt;，有的写作 &lt;code&gt;Contact Email&lt;/code&gt;。这给开发者带来了巨大的解析工作量，需要为不同注册局甚至注册商编写对应的匹配规则。&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;非加密传输&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;TCP 43 端口使用明文传输，任何中间节点（包括运营商）都能看到查询内容。🤷‍♂️ 这在 2025 年已经难以被接受。&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;缺乏访问控制权限&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Whois 服务器只能识别查询的 IP 地址，无法针对单个用户分配权限或进行身份区分，安全设置也只能基于 IP 层面。&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;管理混乱&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Whois 客户端需要为每个 TLD 手动配置对应的 Whois 服务器，缺乏类似 RDAP 的自动 &lt;code&gt;bootstrap&lt;/code&gt; 机制。&lt;/p&gt;
&lt;h2&gt;3、RDAP 协议的优势&lt;/h2&gt;
&lt;p&gt;而 RDAP 协议完美的弥补了这些劣势：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;标准化的 JSON 输出&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RDAP 返回的数据是结构化的 JSON，字段统一定义，例如：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;objectClassName&amp;quot;: &amp;quot;domain&amp;quot;,
  &amp;quot;ldhName&amp;quot;: &amp;quot;example.com&amp;quot;,
  &amp;quot;status&amp;quot;: [&amp;quot;active&amp;quot;],
  &amp;quot;entities&amp;quot;: [...]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这让程序能直接解析字段，无需依赖正则或人工格式识别。&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;统一的 API&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RDAP 基于 HTTP/HTTPS 的 RESTful API，支持 GET 请求、分页、过滤等现代查询方式。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;GET https://rdap.verisign.com/com/v1/domain/example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;即可从注册局调用 &lt;code&gt;example.com&lt;/code&gt; 的信息&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Bootstrap 自动重定向&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RDAP 客户端无需知道具体注册商，它会根据 IANA 的 bootstrap 数据自动跳转到正确的注册局或 RIR&lt;/p&gt;
&lt;p&gt;IANA 的 Bootstrap 数据是公开的，可在以下地址访问：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://data.iana.org/rdap/&quot;&gt;https://data.iana.org/rdap/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;按照 RDAP.org 的&lt;a href=&quot;https://deployment.rdap.org/&quot;&gt;统计&lt;/a&gt;，目前大约有 77% 的注册局已经接入了 RDAP 协议，除了少部分 TLD 需要手工添加 RDAP 服务器，大部分已经都接入了 IANA 的 bootstrap 数据。&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;安全和隐私&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RDAP 强制使用 HTTPS，保障查询与返回内容的完整性与保密性。防止中间人攻击与数据监听。&lt;/p&gt;
&lt;p&gt;如有需要，注册局还可以通过 OAuth 2.0 或 Token 认证实现访问控制，根据用户身份（如公众、注册商或执法机构）返回不同级别的信息。这非常契合 GDPR 等隐私法规的要求。&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;可扩展性&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RDAP 支持使用 extensions（扩展字段），注册局可以在标准字段外添加自定义信息，而不会破坏兼容性。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;&amp;quot;rdapConformance&amp;quot;: [&amp;quot;rdap_level_0&amp;quot;, &amp;quot;icann_rdap_technical_implementation_guide_0&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4、RDAP.SS 网站&lt;/h2&gt;
&lt;p&gt;基于 RDAP 的优势，我使用 Claude Code 开发了一个基于 RDAP 协议的 Whois 查询网站： &lt;a href=&quot;https://rdap.ss/&quot;&gt;RDAP.SS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;技术栈：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;Redis 缓存&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;目前支持如下格式的 Whois 查询：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;域名 - &lt;a href=&quot;https://rdap.ss/whois/google.com&quot;&gt;https://rdap.ss/whois/google.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IPv4 - &lt;a href=&quot;https://rdap.ss/whois/8.8.8.8&quot;&gt;https://rdap.ss/whois/8.8.8.8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IPv4 CIDR - &lt;a href=&quot;https://rdap.ss/whois/8.8.8.0/24&quot;&gt;https://rdap.ss/whois/8.8.8.0/24&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IPv6 - &lt;a href=&quot;https://rdap.ss/whois/2001:4860:4860::8888&quot;&gt;https://rdap.ss/whois/2001:4860:4860::8888&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IPv6 CIDR - &lt;a href=&quot;https://rdap.ss/whois/2001:4860::/32&quot;&gt;https://rdap.ss/whois/2001:4860::/32&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ASN - &lt;a href=&quot;https://rdap.ss/whois/AS15169&quot;&gt;https://rdap.ss/whois/AS15169&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;仅当对应的 TLD 注册局支持 RDAP 协议时，域名查询才可用；未支持的注册局会降级为传统 Whois 协议返回结果。&lt;/p&gt;
&lt;p&gt;如果在使用过程中遇到问题，请随时在 GitHub 提交 &lt;a href=&quot;https://github.com/rdapss/rdap.ss/issues&quot;&gt;issue&lt;/a&gt;。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian 使用 extrepo 配置第三方软件源</title><link>https://u.sb/debian-extrepo/</link><guid isPermaLink="true">https://u.sb/debian-extrepo/</guid><description>本文将指导如何在 Debian 下使用 extrepo 配置第三方软件源。</description><pubDate>Tue, 21 Oct 2025 05:45:49 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何在 Debian 下使用 extrepo 配置第三方软件源。&lt;/p&gt;
&lt;h2&gt;什么是 extrepo？&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://packages.debian.org/stable/extrepo&quot;&gt;extrepo&lt;/a&gt; 用于管理 Debian 中的外部软件源。&lt;/p&gt;
&lt;p&gt;在没有 extrepo 之前，想要使用未被 Debian 官方打包的软件，用户通常需要手动编写 APT 配置文件、以 root 身份运行未经签名的脚本，或安装一个包含所有系统配置的未签名 &lt;code&gt;.deb&lt;/code&gt; 包。&lt;/p&gt;
&lt;p&gt;遗憾的是，这些方法都不是很安全。&lt;/p&gt;
&lt;p&gt;打个比方，我们要添加 Docker 的软件源，有三种方式。&lt;/p&gt;
&lt;p&gt;第一种是传统的 &lt;code&gt;One-Line Style&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -sSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor &amp;gt; /usr/share/keyrings/docker-ce.gpg

echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-ce.gpg] https://download.docker.com/linux/debian $(lsb_release -sc) stable&amp;quot; | sudo bash -c &amp;#39;cat &amp;gt; /etc/apt/sources.list.d/docker-ce.list&amp;#39;

sudo apt update
sudo install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第二种是新的 &lt;code&gt;DEB822&lt;/code&gt; 格式：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -sSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor &amp;gt; /usr/share/keyrings/docker-ce.gpg

sudo bash -c &amp;#39;cat &amp;gt; /etc/apt/sources.list.d/docker-ce.sources &amp;lt;&amp;lt; EOF
Components: stable
Architectures: $(dpkg --print-architecture)
Suites: $(lsb_release -cs)
Types: deb
Uris: https://download.docker.com/linux/debian
Signed-By: /usr/share/keyrings/docker-ce.gpg
EOF&amp;#39;

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第三种方法则更为简单粗暴，直接运行脚本：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在以上这些方法中（包括第三种脚本方式），我们都需要手动下载并导入 GPG 密钥，创建必要的 APT 配置文件，更新软件列表，然后再安装软件。而我们推荐使用 extrepo 的话，只需要简单的三个命令即可完成整个过程。&lt;/p&gt;
&lt;h2&gt;安装并使用 extrepo&lt;/h2&gt;
&lt;p&gt;Debian Stable 下直接用如下命令安装 extrepo 即可：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install extrepo -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接着我们就可以启用比如 Docker CE 的仓库源：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo extrepo enable docker-ce
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后更新系统并安装 Docker：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时我们会发现在 &lt;code&gt;/etc/apt/sources.list.d&lt;/code&gt; 目录中多了一个 &lt;code&gt;extrepo_docker-ce.sources&lt;/code&gt; 文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# cat /etc/apt/sources.list.d/extrepo_docker-ce.sources 
Suites: trixie
Types: deb
Uris: https://download.docker.com/linux/debian
Components: stable
Architectures: amd64 arm64 armhf s390x ppc64el
Signed-By: /var/lib/extrepo/keys/docker-ce.asc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;换句话说，extrepo 帮我们完成了以下工作：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;抓取经过验证的 GPG Key&lt;/li&gt;
&lt;li&gt;使用 DEB822 格式写入 APT 配置&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;对比之前的几种方法，你可能还需要满大街找配置命令，找脚本命令，现在只要敲几行命令就可以搞定，何乐而不为呢？&lt;/p&gt;
&lt;h2&gt;External Repository Metadata&lt;/h2&gt;
&lt;p&gt;看到这里读者可能有疑问，extrepo 的数据又是谁维护的呢？它是由 &lt;a href=&quot;https://salsa.debian.org/extrepo-team&quot;&gt;Debian External Repositories Team&lt;/a&gt; 维护，成员主要为志愿者（包括本文作者），数据本身也有个仓库叫做 &lt;a href=&quot;https://salsa.debian.org/extrepo-team/extrepo-data&quot;&gt;extrepo-data&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;我个人维护了一些仓库，包括 &lt;a href=&quot;https://salsa.debian.org/extrepo-team/extrepo-data/-/commits/master/repos/debian/redis.yaml?ref_type=heads&quot;&gt;Redis&lt;/a&gt;，&lt;a href=&quot;https://salsa.debian.org/extrepo-team/extrepo-data/-/commits/master/repos/debian/mariadb.yaml?ref_type=heads&quot;&gt;MariaDB&lt;/a&gt;，&lt;a href=&quot;https://salsa.debian.org/extrepo-team/extrepo-data/-/commits/master/repos/debian/n.wtf.yaml?ref_type=heads&quot;&gt;N.WTF&lt;/a&gt; 等，你可以从这里看到我的 &lt;a href=&quot;https://salsa.debian.org/showfom/extrepo-data/-/commits/master?author=Xiufeng+Guo&quot;&gt;commits&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;任何人都可以对这个 Git 仓库做出贡献，而且 YAML 语法也十分容易上手，你可以参考默认的&lt;a href=&quot;https://salsa.debian.org/extrepo-team/extrepo-data/-/blob/master/template.yaml?ref_type=heads&quot;&gt;模板文件&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;需要查看完整的第三方软件源列表的话，你可以在&lt;a href=&quot;https://salsa.debian.org/extrepo-team/extrepo-data/-/tree/master/repos/debian?ref_type=heads&quot;&gt;这里&lt;/a&gt;浏览所有的第三方仓库的 &lt;code&gt;.yaml&lt;/code&gt; 文件。&lt;/p&gt;
&lt;p&gt;了解了 extrepo 的机制和优势后，我们再来总结一下。&lt;/p&gt;
&lt;h2&gt;结论&lt;/h2&gt;
&lt;p&gt;总之，使用 extrepo 是一种既安全又方便的添加第三方软件源的方法。&lt;/p&gt;
&lt;p&gt;它的主要优点在于：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;可以让你快速启用经过测试和验证的软件源，而无需手动搜索和复制第三方软件源的配置信息。&lt;/li&gt;
&lt;li&gt;当第三方仓库的 GPG 密钥过期或 URI 发生变化（这种情况相当常见）时，也不再需要手动更新。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;比如，使用 extrepo 时，只需运行 &lt;code&gt;extrepo enable docker-ce&lt;/code&gt; 和 &lt;code&gt;extrepo update docker-ce&lt;/code&gt;，它就会自动刷新 Docker CE 仓库的 GPG 密钥和 URI。&lt;/p&gt;
&lt;p&gt;不过，extrepo 也有一定的缺点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;目前只兼容 Debian 系统，Ubuntu 因为没有人维护 extrepo-data 所以基本没有可以用的第三方软件源。&lt;/li&gt;
&lt;li&gt;默认的 &lt;a href=&quot;https://extrepo-team.pages.debian.net/extrepo-data/&quot;&gt;extrepo-data&lt;/a&gt; 托管在 Debian 官方的 GitLab Pages，这对一些网络不通畅的服务器来说获取仓库信息就有点困难，而自建 extrepo-data 的过程相对繁琐，并不算方便。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/2025/10/20/that-will-save-lots-of-time-alicia-rodriguez_BhSQa.gif&quot; alt=&quot;That will save a lot of time&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://be.st/MIQr&quot;&gt;English Version&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>升级 Debian 后 GitLab PostgreSQL 无法启动的解决方法</title><link>https://u.sb/fix-gitlab-postgresql-not-starting-debian-upgrade/</link><guid isPermaLink="true">https://u.sb/fix-gitlab-postgresql-not-starting-debian-upgrade/</guid><description>本文将介绍在升级 Debian 系统后，GitLab 的 PostgreSQL 数据库无法正常启动的问题。</description><pubDate>Tue, 16 Sep 2025 06:09:09 GMT</pubDate><content:encoded>&lt;p&gt;本文将介绍在升级 Debian 系统后，GitLab 的 PostgreSQL 数据库无法正常启动的问题。&lt;/p&gt;
&lt;h2&gt;背景前提&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;本文的 GitLab 是基于官方源安装的，具体安装和升级方法限于篇幅，不再阐述。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我们从 Debian 11 升级到 Debian 12 后，再更新 GitLab 会发现如下报错：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gitlab [execute] WARNING: database &amp;quot;postgres&amp;quot; has a collation version mismatch DETAIL: The database was created using collation version 2.31, but the operating system provides version 2.36.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者从 Debian 12 升级到 Debian 13 后更新 GitLab 也会有如下报错：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;WARNING:  database “gitlabhq_production” has a collation version mismatch
DETAIL:  The database was created using collation version 2.36, but the operating system provides version 2.41.
HINT:  Rebuild all objects in this database that use the default collation and run ALTER DATABASE gitlabhq_production REFRESH COLLATION VERSION, or build PostgreSQL with the right library version.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们以 Debian 13 为例，可以看到系统自带的 glibc 版本为 2.41：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# ldd --version
ldd (Debian GLIBC 2.41-12) 2.41
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而 Debian 12 自带的 glibc 版本为 2.36：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# ldd --version
ldd (Debian GLIBC 2.36-9+deb12u13) 2.36
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Debian 11 的 glibc 版本为 2.31：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# ldd --version
ldd (Debian GLIBC 2.31-13+deb11u13) 2.31
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所以我们直接升级系统以后 GitLab 的 PostgreSQL 数据库仍使用旧版本的排序规则，导致版本不匹配，所以 GitLab 升级会失败。&lt;/p&gt;
&lt;h2&gt;解决方法&lt;/h2&gt;
&lt;p&gt;我们以 Debian 11 升级到 Debian 12 后的情况举例，首先备份一下 GitLab：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo gitlab-backup create
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们进入 GitLab 的 PostgreSQL 控制台：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo gitlab-psql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接着重新建立索引并修复 &lt;code&gt;gitlabhq_production&lt;/code&gt; 数据库：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SET statement_timeout = 0;
REINDEX DATABASE gitlabhq_production;
ALTER DATABASE gitlabhq_production REFRESH COLLATION VERSION;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重建完成后输入 &lt;code&gt;\q&lt;/code&gt; 并按回车退出，然后我们修复 &lt;code&gt;template1&lt;/code&gt; 和 &lt;code&gt;postgres&lt;/code&gt; 数据库：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo gitlab-psql -d template1 -c &amp;quot;ALTER DATABASE template1 REFRESH COLLATION VERSION;&amp;quot;
sudo gitlab-psql -d postgres -c &amp;quot;ALTER DATABASE postgres REFRESH COLLATION VERSION;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修复完成后验证结果：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo gitlab-psql -c &amp;quot;
SELECT 
    datname,
    datcollversion,
    pg_collation_actual_version((SELECT oid FROM pg_collation WHERE collname = &amp;#39;default&amp;#39;)) as system_version,
    CASE 
        WHEN datcollversion = pg_collation_actual_version((SELECT oid FROM pg_collation WHERE collname = &amp;#39;default&amp;#39;)) 
        THEN &amp;#39;✅ Good&amp;#39; 
        ELSE &amp;#39;❌ Bad&amp;#39; 
    END as status
FROM pg_database 
WHERE datname IN (&amp;#39;template1&amp;#39;, &amp;#39;postgres&amp;#39;, &amp;#39;gitlabhq_production&amp;#39;)
ORDER BY datname;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果出现如下结果，则修复完成：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;       datname       | datcollversion | system_version | status  
---------------------+----------------+----------------+---------
 gitlabhq_production | 2.36           | 2.36           | ✅ Good
 postgres            | 2.36           | 2.36           | ✅ Good
 template1           | 2.36           | 2.36           | ✅ Good
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们就可以重新配置 GitLab 并更新升级了：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo gitlab-ctl reconfigure
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;完成以后重启 GitLab 即可恢复服务：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo gitlab-ctl restart
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian 12 Bookworm 升级 Debian 13 Trixie</title><link>https://u.sb/debian-upgrade-13/</link><guid isPermaLink="true">https://u.sb/debian-upgrade-13/</guid><description>本文将指导如何升级 Debian 12 Bookworm 到 Debian 13 Trixie。</description><pubDate>Tue, 05 Aug 2025 17:46:44 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何升级 Debian 12 Bookworm 到 Debian 13 Trixie。&lt;/p&gt;
&lt;p&gt;相关教程：&lt;a href=&quot;https://u.sb/debian-upgrade-12/&quot;&gt;Debian 11 Bullseye 升级 Debian 12 Bookworm&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;准备工作&lt;/h2&gt;
&lt;p&gt;除非你是物理服务器，以及没有用过奇奇怪怪定制或修改的内核的 KVM 构架的 VPS 和云主机，否则升级大版本更新内核是有一定机率导致 Grub 加载失败的，切记备份重要数据！&lt;/p&gt;
&lt;p&gt;&lt;em&gt;OpenVZ 6 和 LXC 构架的 VPS 是无法升级的，因为他们没有自己独立的内核&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;再强调一遍，一定要备份重要数据！&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;更新系统&lt;/h2&gt;
&lt;p&gt;首先需要更新你当前的系统&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt full-upgrade -y
sudo apt autoclean
sudo apt autoremove -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果内核更新了，可以重启让最新的内核生效，也可以直接进行升级。&lt;/p&gt;
&lt;h2&gt;升级系统&lt;/h2&gt;
&lt;p&gt;首先更新 &lt;code&gt;apt&lt;/code&gt; 源，替换 &lt;code&gt;bookworm&lt;/code&gt; 为 &lt;code&gt;trixie&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sed -i &amp;#39;s/bookworm/trixie/g&amp;#39; /etc/apt/sources.list
sudo sed -i &amp;#39;s/bookworm/trixie/g&amp;#39; /etc/apt/sources.list.d/*.list
sudo sed -i &amp;#39;s/bookworm/trixie/g&amp;#39; /etc/apt/sources.list.d/*.sources
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有对应文件会提示诸如 &lt;code&gt;sed: can&amp;#39;t read /etc/apt/sources.list.d/*.sources: No such file or directory&lt;/code&gt; 的错误，忽略即可。&lt;/p&gt;
&lt;p&gt;或者直接一行命令：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sed -i &amp;#39;s/bookworm/trixie/g&amp;#39; /etc/apt/sources.list /etc/apt/sources.list.d/*.{list,sources} 2&amp;gt;/dev/null
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改完成后你的 &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; 文件内容应该类似如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;deb https://deb.debian.org/debian trixie main contrib non-free non-free-firmware

deb https://security.debian.org/debian-security trixie-security main contrib non-free non-free-firmware

deb https://deb.debian.org/debian trixie-updates main contrib non-free non-free-firmware
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;大部分旧的安装的 Debian 的软件源配置文件使用传统的 One-Line-Style，路径为 &lt;code&gt;/etc/apt/sources.list&lt;/code&gt;；但是从 Debian 12 的容器版本开始，以及 Debian 13 正式版后，其软件源配置文件变更为 &lt;code&gt;DEB822&lt;/code&gt; 格式，路径为 &lt;code&gt;/etc/apt/sources.list.d/debian.sources&lt;/code&gt;:（&lt;a href=&quot;https://mirrors.help/debian/&quot;&gt;参考&lt;/a&gt;）&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Types: deb
URIs: https://deb.debian.org/debian
Suites: trixie trixie-updates trixie-backports
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

Types: deb
URIs: https://security.debian.org/debian-security
Suites: trixie-security
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果使用 &lt;code&gt;DEB822&lt;/code&gt; 格式，则你可以安全地删除 &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; 文件，只保留 &lt;code&gt;/etc/apt/sources.list.d/debian.sources&lt;/code&gt; 即可。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;国内服务器可以替换 &lt;code&gt;deb.debian.org&lt;/code&gt; 和 &lt;code&gt;security.debian.org&lt;/code&gt; 为 &lt;code&gt;mirrors.tuna.tsinghua.edu.cn&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;然后我们再次执行更新系统：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt full-upgrade -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;更新过程中，Debian 13 早期版本可能会提示你是否自动更换为软件源配置文件为 &lt;code&gt;DEB822&lt;/code&gt; 格式，如果需要的话可以使用 &lt;code&gt;sudo apt modernize-sources&lt;/code&gt; 命令来自动转换，或者自行重写 sources 文件。如果使用命令转换，请自行重写 backports 仓库，目前的转换会有 bug 漏掉这个仓库的 GPG Key。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;推荐更换成更科学的 &lt;code&gt;DEB822&lt;/code&gt; 格式哦~&lt;/p&gt;
&lt;p&gt;&lt;em&gt;如果 apt 命令最后没有带 &lt;code&gt;-y&lt;/code&gt; 自动同意参数的话，更新过程中还会提示一些软件的更新列表，是否需要自动重启等，选 &lt;code&gt;Yes&lt;/code&gt; 即可，以及一些软件的配置文件是否需要更新，按照自己的情况选择即可，默认回车即视为使用旧的配置文件，一般会出现在 &lt;code&gt;OpenSSH&lt;/code&gt; 等软件的更新上。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;apt-listchanges: News&lt;/code&gt; 界面可以按 &lt;code&gt;q&lt;/code&gt; 退出：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/2025/08/05/image_S2xQK.png&quot; alt=&quot;apt-listchanges News 界面&quot;&gt;&lt;/p&gt;
&lt;p&gt;提示是否自动重启服务：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/2025/08/05/image_CeXju.png&quot; alt=&quot;询问是否自动重启服务的提示界面&quot;&gt;&lt;/p&gt;
&lt;p&gt;提示是否更新配置文件：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/2025/08/05/image_v7Yk2.png&quot; alt=&quot;询问是否更新配置文件的提示界面&quot;&gt;&lt;/p&gt;
&lt;p&gt;注意某些软件更新后可能会更新 &lt;code&gt;systemd&lt;/code&gt; 服务配置，此时我们可以执行 &lt;code&gt;sudo systemctl daemon-reload&lt;/code&gt; 重新加载配置。&lt;/p&gt;
&lt;p&gt;更新后删除不必要的软件和依赖：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt autoclean
sudo apt autoremove -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们使用 &lt;code&gt;sudo reboot&lt;/code&gt; 命令重启系统，耐心等待后，查看最新的系统版本：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # cat /etc/debian_version 
13.0
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # lsb_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 13 (trixie)
Release:	13
Codename:	trixie
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # uname -a
Linux upload 6.12.38+deb13-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.38-1 (2025-07-16) x86_64 GNU/Linux
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这时我们就已经更新到了最新的 Debian 13 Trixie 和内核了。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Ubuntu 22.04 Jammy 升级 Ubuntu 24.04 Noble</title><link>https://u.sb/ubuntu-upgrade-2404/</link><guid isPermaLink="true">https://u.sb/ubuntu-upgrade-2404/</guid><description>本文将指导如何升级 Ubuntu 22.04 Jammy Jellyfish 到 Ubuntu 24.04 Noble Numbat。</description><pubDate>Fri, 21 Jun 2024 15:28:05 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何升级 Ubuntu 22.04 Jammy Jellyfish 到 Ubuntu 24.04 Noble Numbat。&lt;/p&gt;
&lt;p&gt;相关教程：&lt;a href=&quot;https://u.sb/ubuntu-upgrade/&quot;&gt;Ubuntu 20.04 Focal Fossa 升级 Ubuntu 22.04 Jammy Jellyfish&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;准备工作&lt;/h2&gt;
&lt;p&gt;除非你是物理服务器，以及没有用过奇奇怪怪定制或修改的内核的 KVM 构架的 VPS 和云主机，否则升级大版本更新内核是有一定机率导致 Grub 加载失败的，切记备份重要数据！&lt;/p&gt;
&lt;p&gt;&lt;em&gt;OpenVZ 和 LXC 构架的 VPS 是无法升级的，因为他们没有自己独立的内核&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;再强调一遍，一定要备份重要数据！&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;更新系统&lt;/h2&gt;
&lt;p&gt;首先需要更新你当前的系统&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt autoclean
sudo apt autoremove -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果内核更新了，可以重启让最新的内核生效，也可以直接进行升级。&lt;/p&gt;
&lt;h2&gt;升级系统&lt;/h2&gt;
&lt;p&gt;这里有两种升级系统的方法，第一种是使用 &lt;code&gt;do-release-upgrade&lt;/code&gt; 命令，第二种是手动更新 &lt;code&gt;apt&lt;/code&gt; 源文件。&lt;/p&gt;
&lt;h3&gt;方法一：使用 &lt;code&gt;do-release-upgrade&lt;/code&gt; 命令&lt;/h3&gt;
&lt;p&gt;首先需要安装 &lt;code&gt;ubuntu-release-upgrader-core&lt;/code&gt; 包：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install ubuntu-release-upgrader-core
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后修改 &lt;code&gt;/etc/update-manager/release-upgrades&lt;/code&gt; 文件，确保 &lt;code&gt;Prompt&lt;/code&gt; 值为 &lt;code&gt;lts&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat /etc/update-manager/release-upgrades | grep lts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;显示如下内容即可：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@ubuntu ~ # cat /etc/update-manager/release-upgrades | grep lts
#  lts    - Check to see if a new LTS release is available.  The upgrader
Prompt=lts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后执行以下命令升级系统：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo do-release-upgrade -d
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;方法二：手动更新 &lt;code&gt;apt&lt;/code&gt; 源文件&lt;/h3&gt;
&lt;p&gt;首先更新 &lt;code&gt;apt&lt;/code&gt; 源，替换 &lt;code&gt;jammy&lt;/code&gt; 为 &lt;code&gt;noble&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sed -i &amp;#39;s/jammy/noble/g&amp;#39; /etc/apt/sources.list
sudo sed -i &amp;#39;s/jammy/noble/g&amp;#39; /etc/apt/sources.list.d/*.list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;系统 &lt;code&gt;apt&lt;/code&gt; 源文件 &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; 应该是类似这样的：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;deb https://archive.ubuntu.com/ubuntu/ noble main restricted universe multiverse

deb https://archive.ubuntu.com/ubuntu/ noble-updates main restricted universe multiverse

deb https://archive.ubuntu.com/ubuntu/ noble-backports main restricted universe multiverse

deb http://security.ubuntu.com/ubuntu/ noble-security main restricted universe multiverse
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;由于在 Ubuntu 24.04 之前，Ubuntu 的软件源配置文件使用传统的 One-Line-Style，路径为 &lt;code&gt;/etc/apt/sources.list&lt;/code&gt;；从 Ubuntu 24.04 开始，Ubuntu 的软件源配置文件变更为 &lt;code&gt;DEB822&lt;/code&gt; 格式，路径为 &lt;code&gt;/etc/apt/sources.list.d/ubuntu.sources&lt;/code&gt;（&lt;a href=&quot;https://mirrors.help/ubuntu/&quot;&gt;参考&lt;/a&gt;），所以使用 &lt;code&gt;DEB822&lt;/code&gt; 格式的源文件 &lt;code&gt;/etc/apt/sources.list.d/ubuntu.sources&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Types: deb
URIs: https://archive.ubuntu.com/ubuntu
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

Types: deb
URIs: http://security.ubuntu.com/ubuntu
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;国内服务器可以替换 &lt;code&gt;archive.ubuntu.com&lt;/code&gt; 和 &lt;code&gt;security.ubuntu.com&lt;/code&gt; 为 &lt;code&gt;mirrors.tuna.tsinghua.edu.cn&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;然后我们再次执行更新系统：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt full-upgrade -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;更新过程中会提示一些软件是否需要自动重启，选 Yes 即可，以及一些软件的配置文件是否需要更新，按照自己的情况选择即可，默认回车即视为使用旧的配置文件，一般会出现在 OpenSSH 等软件的更新上。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;更新后删除不必要的软件和依赖：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt autoclean
sudo apt autoremove -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们使用 &lt;code&gt;sudo reboot&lt;/code&gt; 命令重启系统，耐心等待后，查看最新的系统版本：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@ubuntu ~ # lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 24.04 LTS
Release:	24.04
Codename:	noble
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@ubuntu ~ # uname -a
Linux ubuntu 6.8.0-35-generic #35-Ubuntu SMP PREEMPT_DYNAMIC Mon May 20 15:51:52 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这时我们就已经更新到了最新的 Ubuntu 24.04 Noble 和内核了。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Docker 安装 FreshRSS 教程</title><link>https://u.sb/docker-freshrss/</link><guid isPermaLink="true">https://u.sb/docker-freshrss/</guid><description>本文将指导如何在 Linux 下使用 Docker 和 Docker Compose 安装 FreshRSS 开源 RSS 聚合器服务。</description><pubDate>Fri, 21 Jun 2024 14:34:43 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何在 Linux 下使用 Docker 和 Docker Compose 安装 FreshRSS 开源 RSS 聚合器服务。&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。其中 &lt;code&gt;docker&lt;/code&gt; 命令未加 &lt;code&gt;sudo&lt;/code&gt;：建议把当前用户加入 &lt;code&gt;docker&lt;/code&gt; 用户组（&lt;code&gt;sudo usermod -aG docker $USER&lt;/code&gt;，重新登录生效），或自行为 &lt;code&gt;docker&lt;/code&gt; 命令加上 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;PS：本文同时适用于任何可安装 Docker 的 Linux 发行版。&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;什么是 FreshRSS？&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://freshrss.org/&quot;&gt;FreshRSS&lt;/a&gt; 是一款免费且开源的 RSS 聚合器，设计用于帮助用户集中管理和阅读来自不同网站的新闻源。它具有高效、轻量的特点，并且支持多用户使用。&lt;/p&gt;
&lt;h2&gt;安装 Docker 和 Docker Compose&lt;/h2&gt;
&lt;p&gt;Debian 和 Ubuntu 系统请参考&lt;a href=&quot;https://u.sb/debian-install-docker/&quot;&gt;本站教程&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;其他 Linux 系统可以使用 Docker 官方的脚本安装 Docker 和 Docker Compose：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;安装 FreshRSS&lt;/h2&gt;
&lt;p&gt;这里我们使用 PostgreSQL 数据库，首先创建一个目录用于存放 FreshRSS 的配置文件和数据库文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mkdir -p /opt/freshrss
cd /opt/freshrss
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后创建一个 &lt;code&gt;docker-compose.yml&lt;/code&gt; 文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;services:

  freshrss:
    image: freshrss/freshrss:latest
    container_name: freshrss
    hostname: freshrss
    restart: unless-stopped
    logging:
      options:
        max-size: 10m
    volumes:
      - ./data:/var/www/FreshRSS/data
      - ./extensions:/var/www/FreshRSS/extensions
    environment:
      TZ: Etc/UTC
      CRON_MIN: &amp;#39;3,33&amp;#39;
      TRUSTED_PROXY: 172.16.0.1/12 192.168.0.1/16
      ADMIN_EMAIL: 你的邮箱
      BASE_URL: 你的 FreshRSS 访问地址
    ports:
      - 127.0.0.1:8080:80

  freshrss-db:
    image: postgres:16
    container_name: freshrss-db
    hostname: freshrss-db
    restart: unless-stopped
    logging:
      options:
        max-size: 10m
    volumes:
      - ./db:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: freshrss
      POSTGRES_USER: freshrss
      POSTGRES_PASSWORD: freshrss
    command:
      - -c
      - shared_buffers=1GB
      - -c
      - work_mem=32MB
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;请自行替换 &lt;code&gt;ADMIN_EMAIL&lt;/code&gt; 和 &lt;code&gt;BASE_URL&lt;/code&gt; 的值，&lt;code&gt;BASE_URL&lt;/code&gt; 需要写全，比如 &lt;code&gt;https://freshrss.example.com&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;然后拉取 Docker 镜像并运行：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd /opt/freshrss
docker compose pull
docker compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;安装配置 Nginx 反向代理&lt;/h2&gt;
&lt;p&gt;我们的 Docker Compose 配置文件中，FreshRSS 服务监听在 &lt;code&gt;127.0.0.1:8080&lt;/code&gt; 端口，所以我们需要配置 Nginx 反代来访问，假设你 FreshRSS 的地址是 &lt;code&gt;https://freshrss.example.com&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;freshrss.example.com&lt;/code&gt; 段配置：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;	location / {
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $http_host;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_redirect off;
		proxy_set_header        X-Forwarded-Proto $scheme;
		proxy_connect_timeout       300;
		proxy_send_timeout          300;
		proxy_read_timeout          300;
		send_timeout                300;
		proxy_pass http://127.0.0.1:8080;
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后记得参考本站 &lt;a href=&quot;https://u.sb/nginx-ssl/&quot;&gt;Nginx SSL 配置教程&lt;/a&gt;加上 SSL 证书后，即可访问 &lt;code&gt;https://freshrss.example.com/&lt;/code&gt;：&lt;/p&gt;
&lt;h2&gt;配置 FreshRSS&lt;/h2&gt;
&lt;p&gt;访问 &lt;code&gt;https://freshrss.example.com/&lt;/code&gt;，在安装向导中填写数据库信息：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据库类型：&lt;code&gt;PostgreSQL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;数据库主机（Host）：&lt;code&gt;freshrss-db&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;数据库名称（Database）：&lt;code&gt;freshrss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;数据库用户（User）：&lt;code&gt;freshrss&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;数据库密码（Password）：&lt;code&gt;freshrss&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;然后点击 &lt;code&gt;Install FreshRSS&lt;/code&gt; 即可完成安装。&lt;/p&gt;
&lt;p&gt;如果需要安装插件，可以把插件上传到 &lt;code&gt;/opt/freshrss/extensions&lt;/code&gt; 目录，然后在 FreshRSS 后台安装。&lt;/p&gt;
&lt;p&gt;推荐在官方插件仓库里下载插件：&lt;a href=&quot;https://github.com/FreshRSS/Extensions&quot;&gt;FreshRSS Extensions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;推荐安装 &lt;a href=&quot;https://github.com/FreshRSS/Extensions/tree/master/xExtension-CustomCSS&quot;&gt;CustomCSS&lt;/a&gt; 插件，就可以使用自定义 CSS 样式了，个人比较喜欢&lt;a href=&quot;https://github.com/catppuccin/freshrss&quot;&gt;这个主题系列&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;如果需要第三方客户端，可以在这里查看支持的应用：&lt;a href=&quot;https://github.com/FreshRSS/FreshRSS/blob/edge/README.md#apis--native-apps&quot;&gt;APIs &amp;amp; native apps&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;迁移 FreshRSS&lt;/h2&gt;
&lt;p&gt;可以参考《&lt;a href=&quot;https://u.sb/docker-mailcow/#mailcow-%E7%9A%84%E8%BF%81%E7%A7%BB-t2&quot;&gt;使用 Docker 安装 Mailcow 自建域名邮箱&lt;/a&gt;》。&lt;/p&gt;
&lt;h2&gt;备份 FreshRSS&lt;/h2&gt;
&lt;p&gt;我们可以定期备份 FreshRSS 网站文件和数据库，压缩网站目录和导出数据库命令如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;backup_folder_name=$(date +&amp;quot;%Y_%m_%d_%I_%M_%p&amp;quot;)
# 备份 FreshRSS 网站文件
tar --exclude /opt/freshrss/data/cache -zcvf data-$backup_folder_name.tar.gz /opt/freshrss/data
tar -zcvf extensions-$backup_folder_name.tar.gz /opt/freshrss/extensions
# 备份 FreshRSS 数据库
docker exec -t freshrss-db pg_dumpall -c -U freshrss | gzip &amp;gt; database-$backup_folder_name.gz
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian / Ubuntu 开启 SSH 的 RSA Key 登录</title><link>https://u.sb/debian-enable-ssh-rsa-key/</link><guid isPermaLink="true">https://u.sb/debian-enable-ssh-rsa-key/</guid><description>本文将指导如何在 Debian 和 Ubuntu 开启 SSH 的 RSA Key 登录。</description><pubDate>Sat, 10 Jun 2023 03:16:24 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何在 Debian 和 Ubuntu 开启 SSH 的 RSA Key 登录。&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;自从 OpenSSH 8.3 开始，RSA Key 登录默认&lt;a href=&quot;https://lwn.net/Articles/821544/&quot;&gt;被禁用&lt;/a&gt;，并被认为&lt;a href=&quot;https://confluence.atlassian.com/bitbucketserverkb/ssh-rsa-key-rejected-with-message-no-mutual-signature-algorithm-1026057701.html&quot;&gt;不安全&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;所以自从 Ubuntu 22.04 和 Debian 12 开始，如果某些古老的业务需要使用 RSA Key 登录，你需要手动开启 RSA Key 登录。&lt;/p&gt;
&lt;h2&gt;开启 RSA Key 登录&lt;/h2&gt;
&lt;p&gt;我们不需要修改 &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; 这个系统默认的 SSH 配置文件，只需要添加一个 &lt;code&gt;/etc/ssh/sshd_config.d/enable_rsa_keys.conf&lt;/code&gt; 配置文件即可：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo bash -c &amp;#39;cat &amp;gt; /etc/ssh/sshd_config.d/enable_rsa_keys.conf &amp;lt;&amp;lt; EOF
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
EOF&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;重启 SSH 服务&lt;/h2&gt;
&lt;p&gt;然后重启 SSH 服务即可：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl restart ssh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl restart sshd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这两个服务在 Debian 12 下都是一样的：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Fri 2023-06-09 16:54:43 UTC; 15min ago
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对比&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # systemctl status sshd
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Fri 2023-06-09 16:54:43 UTC; 15min ago
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们可以看到 sshd 其实是 ssh 服务的别称：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # cat /lib/systemd/system/ssh.service | grep Alias
Alias=sshd.service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时您就可以使用 RSA Key 登录 SSH 了。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian 11 Bullseye 升级 Debian 12 Bookworm</title><link>https://u.sb/debian-upgrade-12/</link><guid isPermaLink="true">https://u.sb/debian-upgrade-12/</guid><description>本文将指导如何升级 Debian 11 Bullseye 到 Debian 12 Bookworm。</description><pubDate>Sat, 10 Jun 2023 03:16:24 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何升级 Debian 11 Bullseye 到 Debian 12 Bookworm。&lt;/p&gt;
&lt;p&gt;相关教程：&lt;a href=&quot;https://u.sb/debian-upgrade/&quot;&gt;Debian 10 Buster 升级 Debian 11 Bullseye&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;准备工作&lt;/h2&gt;
&lt;p&gt;除非你是物理服务器，以及没有用过奇奇怪怪定制或修改的内核的 KVM 构架的 VPS 和云主机，否则升级大版本更新内核是有一定机率导致 Grub 加载失败的，切记备份重要数据！&lt;/p&gt;
&lt;p&gt;&lt;em&gt;OpenVZ 6 和 LXC 构架的 VPS 是无法升级的，因为他们没有自己独立的内核&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;再强调一遍，一定要备份重要数据！&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;更新系统&lt;/h2&gt;
&lt;p&gt;首先需要更新你当前的系统&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt autoclean
sudo apt autoremove -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果内核更新了，可以重启让最新的内核生效，也可以直接进行升级。&lt;/p&gt;
&lt;h2&gt;升级系统&lt;/h2&gt;
&lt;p&gt;首先更新 &lt;code&gt;apt&lt;/code&gt; 源，替换 &lt;code&gt;bullseye&lt;/code&gt; 为 &lt;code&gt;bookworm&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sed -i &amp;#39;s/bullseye/bookworm/g&amp;#39; /etc/apt/sources.list
sudo sed -i &amp;#39;s/bullseye/bookworm/g&amp;#39; /etc/apt/sources.list.d/*.list
sudo sed -i &amp;#39;s/bullseye/bookworm/g&amp;#39; /etc/apt/sources.list.d/*.sources
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对于 Debian 12 以后的版本，所有 Debian 可以分发的打包的非自由固件二进制文件 (non-free)，比如某些驱动，都被转移到 Debian Archive 中的一个新组件，称为非自由固件 (non-free-firmware)。如果您从旧版的 Debian 升级，并且需要这些固件二进制文件，您应该更新您系统上的 &lt;code&gt;/etc/apt/sources.list&lt;/code&gt;，以使用这个新组件 (&lt;a href=&quot;https://wiki.debian.org/Firmware#Debian_12_.28bookworm.29_and_later&quot;&gt;来源&lt;/a&gt;)：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo sed -i &amp;#39;s/non-free/non-free non-free-firmware/g&amp;#39; /etc/apt/sources.list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;默认的系统 &lt;code&gt;apt&lt;/code&gt; 源文件 &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; 应该是类似这样的：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware

deb http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware

deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;大部分 Debian 的软件源配置文件使用传统的 One-Line-Style，路径为 &lt;code&gt;/etc/apt/sources.list&lt;/code&gt;；但是对于容器镜像，从 Debian 12 开始，其软件源配置文件变更为 &lt;code&gt;DEB822&lt;/code&gt; 格式，路径为 &lt;code&gt;/etc/apt/sources.list.d/debian.sources&lt;/code&gt;:（&lt;a href=&quot;https://mirrors.help/debian/&quot;&gt;参考&lt;/a&gt;）&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Types: deb
URIs: https://deb.debian.org/debian
Suites: bookworm bookworm-updates bookworm-backports
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

Types: deb
URIs: http://security.debian.org/debian-security
Suites: bookworm-security
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;国内服务器可以替换 &lt;code&gt;deb.debian.org&lt;/code&gt; 和 &lt;code&gt;security.debian.org&lt;/code&gt; 为 &lt;code&gt;mirrors.tuna.tsinghua.edu.cn&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;然后我们再次执行更新系统：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;更新过程中会提示一些软件是否需要自动重启，选 Yes 即可，以及一些软件的配置文件是否需要更新，按照自己的情况选择即可，默认回车即视为使用旧的配置文件，一般会出现在 OpenSSH 等软件的更新上。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;apt-listchanges: News&lt;/code&gt; 界面可以按 &lt;code&gt;q&lt;/code&gt; 退出：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/uploads/2023/06/10/6zkX4boedhWO9nR.png&quot; alt=&quot;apt-listchanges News 界面&quot;&gt;&lt;/p&gt;
&lt;p&gt;提示是否自动重启服务：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/uploads/2023/06/10/gtoa1WO57ST24ui.png&quot; alt=&quot;询问是否自动重启服务的提示界面&quot;&gt;&lt;/p&gt;
&lt;p&gt;提示是否更新 OpenSSH 配置文件：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/uploads/2023/06/10/l4fe7Y9VckH8iBz.png&quot; alt=&quot;询问是否更新 OpenSSH 配置文件的提示界面&quot;&gt;&lt;/p&gt;
&lt;p&gt;注意某些软件更新后可能会更新 &lt;code&gt;systemd&lt;/code&gt; 服务配置，此时我们可以执行 &lt;code&gt;sudo systemctl daemon-reload&lt;/code&gt; 重新加载配置。&lt;/p&gt;
&lt;p&gt;如果升级的时候遇到了如下错误：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Setting up dbus-daemon (1.14.6-1) ...
UUID file &amp;#39;/var/lib/dbus/machine-id&amp;#39; should contain a hex string of length 32, not length 0, with no other text
dpkg: error processing package dbus-daemon (--configure):
 installed dbus-daemon package post-installation script subprocess returned error exit status 1
dpkg: dependency problems prevent configuration of dbus:
 dbus depends on dbus-daemon (= 1.14.6-1); however:
  Package dbus-daemon is not configured yet.

dpkg: error processing package dbus (--configure):
 dependency problems - leaving unconfigured
Processing triggers for libc-bin (2.36-9) ...
Errors were encountered while processing:
 dbus-daemon
 dbus
E: Sub-process /usr/bin/dpkg returned an error code (1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;删除 &lt;code&gt;/var/lib/dbus/machine-id&lt;/code&gt; 这个空文件后重新执行命令即可，升级 &lt;code&gt;dbus&lt;/code&gt; 时会自动生成这个文件。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo rm -rf /var/lib/dbus/machine-id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更新后删除不必要的软件和依赖：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt autoclean
sudo apt autoremove -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们使用 &lt;code&gt;sudo reboot&lt;/code&gt; 命令重启系统，耐心等待后，查看最新的系统版本：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # cat /etc/debian_version 
12.5
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # lsb_release -a
No LSB modules are available.
Distributor ID:	Debian
Description:	Debian GNU/Linux 12 (bookworm)
Release:	12
Codename:	bookworm
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # uname -a
Linux debian 6.1.0-21-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.90-1 (2024-05-03) x86_64 GNU/Linux
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这时我们就已经更新到了最新的 Debian 12 Bookworm 和内核了。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian / Ubuntu 下使用 HTTP/3 协议的 Nginx QUIC</title><link>https://u.sb/debian-nginx-quic/</link><guid isPermaLink="true">https://u.sb/debian-nginx-quic/</guid><description>本文适合 Debian Stable 和 Ubuntu LTS.。</description><pubDate>Mon, 20 Feb 2023 05:44:13 GMT</pubDate><content:encoded>&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。其中 &lt;code&gt;docker&lt;/code&gt; 命令未加 &lt;code&gt;sudo&lt;/code&gt;：建议把当前用户加入 &lt;code&gt;docker&lt;/code&gt; 用户组（&lt;code&gt;sudo usermod -aG docker $USER&lt;/code&gt;，重新登录生效），或自行为 &lt;code&gt;docker&lt;/code&gt; 命令加上 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;1、什么是 HTTP/3 和 QUIC？&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/HTTP/3&quot;&gt;HTTP/3&lt;/a&gt; 是一种基于 &lt;a href=&quot;https://en.wikipedia.org/wiki/QUIC&quot;&gt;QUIC&lt;/a&gt; (Quick UDP Internet Connections) 协议的 HTTP 协议版本，它是 HTTP/2 的后继者，旨在改进 Web 性能和安全性。&lt;/p&gt;
&lt;p&gt;HTTP/3 与之前的 HTTP 协议有很大的不同，最明显的区别是它使用 QUIC 协议而不是 TCP 协议来传输数据。&lt;/p&gt;
&lt;p&gt;QUIC 是一种由 Google 开发的协议，基于 &lt;a href=&quot;https://en.wikipedia.org/wiki/User_Datagram_Protocol&quot;&gt;UDP&lt;/a&gt;，它在保持安全性的同时提供更快的连接和更少的延迟。与 TCP 不同，QUIC 允许多个请求同时在同一连接上进行，从而减少了网络拥塞和握手延迟的影响。&lt;/p&gt;
&lt;p&gt;总的来说，HTTP/3 的设计目标是通过减少延迟和提高性能，为 Web 应用程序提供更快、更安全和更高效的用户体验。&lt;/p&gt;
&lt;h2&gt;2、安装 Nginx Quic&lt;/h2&gt;
&lt;p&gt;这里我们推荐&lt;a href=&quot;https://n.wtf/&quot;&gt;烧饼博客&lt;/a&gt;团队打包的 Nginx Quic 版本，它是基于最新的官方 1.25.0 源码打包的，支持 HTTP/3 和 QUIC 协议。&lt;/p&gt;
&lt;h3&gt;2.1 更新系统并安装部分必要软件&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.2 增加 GPG Key&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -sSL https://n.wtf/public.key | sudo gpg --dearmor -o /usr/share/keyrings/n.wtf.gpg
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.3 添加 Nginx QUIC 源&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror-cdn.xtom.com/sb/nginx/ $(lsb_release -sc) main&amp;quot; | sudo tee /etc/apt/sources.list.d/n.wtf.list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你的服务器在国内，可以使用下面的源：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror.iscas.ac.cn/sb/nginx/ $(lsb_release -sc) main&amp;quot; | sudo tee /etc/apt/sources.list.d/n.wtf.list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/n.wtf.gpg] https://mirror.nju.edu.cn/sb/nginx/ $(lsb_release -sc) main&amp;quot; | sudo tee /etc/apt/sources.list.d/n.wtf.list
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.4 更新并安装 Nginx&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install nginx-extras -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装完毕后，我们可以使用 &lt;code&gt;nginx -V&lt;/code&gt; 命令看到 Nginx 已经是最新的 1.31.2 主线版 + QUIC 了：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # nginx -V
nginx version: nginx-n.wtf/1.31.2
built by gcc 14.2.0 (Debian 14.2.0-19) 
built with OpenSSL 4.0.1 9 Jun 2026
TLS SNI support enabled
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.5 使用 Docker 安装&lt;/h3&gt;
&lt;p&gt;你也可以使用 &lt;a href=&quot;https://github.com/u-sb/nginx-docker&quot;&gt;Docker&lt;/a&gt; 进行体验：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker run --name nginx --net host --restart always -v $HOME/nginx-config:/usr/src/docker-nginx/conf:ro -d ghcr.io/u-sb/nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时配置文件的目录在当前目录的 &lt;code&gt;nginx-config&lt;/code&gt; 文件夹下。&lt;/p&gt;
&lt;h2&gt;3、配置 Nginx&lt;/h2&gt;
&lt;p&gt;首先，HTTP/3 仅支持 HTTPS 协议，因此我们需要准备好 SSL 证书，可以参考&lt;a href=&quot;https://u.sb/nginx-ssl/&quot;&gt;《Nginx 配置 SSL 证书》&lt;/a&gt;获取 SSL 证书。&lt;/p&gt;
&lt;p&gt;其次，需要开启 TLS 1.3 支持，因为 HTTP/3 是基于 TLS 1.3 的，如果没有开启 TLS 1.3，那么 HTTP/3 将无法正常工作。&lt;/p&gt;
&lt;p&gt;&lt;del&gt;最后，需要添加 &lt;code&gt;listen 443 http3&lt;/code&gt; 监听端口并开启 HTTP/3 支持，以及需要添加一个 &lt;code&gt;Alt-Svc&lt;/code&gt; 的头部信息 &lt;code&gt;add_header Alt-Svc &amp;#39;h3=&amp;quot;:443&amp;quot;; ma=86400&amp;#39;;&lt;/code&gt;，用于告诉浏览器使用 HTTP/3 协议访问网站。&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;最后，需要添加 &lt;code&gt;listen 443 quic&lt;/code&gt; 监听端口并开启 HTTP/3 支持，以及需要添加一个 &lt;code&gt;Alt-Svc&lt;/code&gt; 的头部信息 &lt;code&gt;add_header Alt-Svc &amp;#39;h3=&amp;quot;:$server_port&amp;quot;; ma=86400&amp;#39;;&lt;/code&gt;，用于告诉浏览器使用 HTTP/3 协议访问网站。&lt;/p&gt;
&lt;p&gt;因为&lt;a href=&quot;https://hg.nginx.org/nginx-quic/rev/69bae2437d74&quot;&gt;这个修改&lt;/a&gt;，从 Nginx 1.25.0 开始，已经不支持 &lt;code&gt;http3&lt;/code&gt; 的 &lt;code&gt;listen&lt;/code&gt; 段，需要改为 &lt;code&gt;quic&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;另外，从 Nginx 1.25.1 开始，&lt;code&gt;listen ... http2&lt;/code&gt; 已废弃，需要改为 &lt;code&gt;http2 on&lt;/code&gt;，否则会报警告 &lt;code&gt;nginx: [warn] the &amp;quot;listen ... http2&amp;quot; directive is deprecated, use the &amp;quot;http2&amp;quot; directive instead&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;我们附上一个基本的配置示例：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;server {
	listen 443 ssl default_server;
	listen [::]:443 ssl default_server;
    # 开启 HTTP/3
	listen 443 quic reuseport;
	listen [::]:443 quic reuseport;
    # 开启 HTTP/2
    http2 on;

	server_name example.com;

	root /var/www/example.com;
	index index.html;

	ssl_certificate /etc/nginx/ssl/example.com.crt;
	ssl_certificate_key /etc/nginx/ssl/example.com.key;

    ssl_protocols TLSv1.3;
    ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1:secp384r1;
    ssl_prefer_server_ciphers off;

	add_header Alt-Svc &amp;#39;h3=&amp;quot;:$server_port&amp;quot;; ma=86400&amp;#39; always;
    add_header X-protocol $server_protocol always;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;请注意 &lt;code&gt;listen 443 quic reuseport&lt;/code&gt; 里的 &lt;code&gt;reuseport&lt;/code&gt; 参数，以及 &lt;code&gt;listen 443 ssl default_server&lt;/code&gt; 里的 &lt;code&gt;default_server&lt;/code&gt; 参数，所有 server 段里，只允许一个段出现 &lt;code&gt;reuseport&lt;/code&gt; 和 &lt;code&gt;default_server&lt;/code&gt; 参数，否则会报错。&lt;/p&gt;
&lt;p&gt;另外 &lt;code&gt;listen&lt;/code&gt; 段里的 &lt;code&gt;ssl&lt;/code&gt; 无法和 &lt;code&gt;quic&lt;/code&gt; 放一起，必须分开写两段。&lt;/p&gt;
&lt;h2&gt;4、测试 HTTP/3&lt;/h2&gt;
&lt;p&gt;我们使用 Firefox 浏览器，因为目前 DNS SVCB/HTTPS 记录&lt;a href=&quot;https://taoshu.in/dns/dns-svcb-https.html&quot;&gt;尚未普及&lt;/a&gt;，所以第一次访问的时候，浏览器还是走 TCP 协议使用 HTTP/2 或者 HTTP/1.1 请求你的网站，获取 &lt;code&gt;Alt-Svc&lt;/code&gt; 的头部信息后，才会走 HTTP/3 协议，所以第一次访问以后，可以关掉浏览器重新打开再测试。&lt;/p&gt;
&lt;p&gt;我们可以打开 F12 开发者工具，查看 Network 选项卡，可以看到 HTTP/3 协议的请求：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/uploads/2023/02/20/bzZGxtN9lRjMD3f.png&quot; alt=&quot;Firefox HTTP/3&quot;&gt;&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian / Ubuntu 使用 xcaddy 自定义编译 Caddy</title><link>https://u.sb/xcaddy/</link><guid isPermaLink="true">https://u.sb/xcaddy/</guid><description>本文将指导使用 xcaddy 自定义编译 Caddy。</description><pubDate>Sun, 22 Jan 2023 23:54:54 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导使用 xcaddy 自定义编译 Caddy。&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;上一篇文章介绍了如何&lt;a href=&quot;https://u.sb/debian-install-caddy/&quot;&gt;安装使用 Caddy&lt;/a&gt;，但是 Caddy 的功能有时候并不能满足业务需求，如果想要使用更多的功能，就需要自定义编译 Caddy。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/caddyserver/xcaddy&quot;&gt;xcaddy&lt;/a&gt; 是 Caddy 官方制作的用于自定义编译 Caddy 的工具，它可以帮助我们快速的编译出符合自己需求的 Caddy。&lt;/p&gt;
&lt;h2&gt;安装 xcaddy&lt;/h2&gt;
&lt;p&gt;我们按照官方的&lt;a href=&quot;https://caddyserver.com/docs/install#debian-ubuntu-raspbian&quot;&gt;安装方法&lt;/a&gt;，首先，安装一些必要的软件包：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后按照&lt;a href=&quot;https://go.dev/doc/install&quot;&gt;官方教程&lt;/a&gt;安装 Go：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;wget https://go.dev/dl/go1.24.5.linux-amd64.tar.gz
sudo rm -rf /usr/local/go &amp;amp;&amp;amp; sudo tar -C /usr/local -xzf go1.24.5.linux-amd64.tar.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后把 go 加入系统环境变量：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &amp;quot;export PATH=\$PATH:/usr/local/go/bin&amp;quot; | sudo tee -a /etc/profile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后加入 Caddy 的 GPG 公钥和 apt 源：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -sSL https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/xcaddy.gpg
echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/xcaddy.gpg] https://dl.cloudsmith.io/public/caddy/xcaddy/deb/debian any-version main&amp;quot; | sudo tee /etc/apt/sources.list.d/xcaddy.list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Debian 下也可以使用 extrepo：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install extrepo
sudo extrepo enable caddyserver
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后更新系统后即可安装 xcaddy：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install xcaddy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重启打开 SSH 后检查一下 go 和 xcaddy 的版本：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # go version
go version go1.24.5 linux/amd64

root@debian ~ # xcaddy version
v0.4.5 h1:7E4b+3Gm2do/WpuDXh5MWIj+qgCCvQqR487Sm8C6hwc=
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;自定义编译 Caddy&lt;/h2&gt;
&lt;p&gt;我们可以选择一些自己喜欢的模块，比如&lt;a href=&quot;https://github.com/caddyserver/cache-handler&quot;&gt;缓存模块&lt;/a&gt;和 &lt;a href=&quot;https://github.com/ueffel/caddy-brotli&quot;&gt;Brotli 压缩模块&lt;/a&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;xcaddy build \
    --with github.com/caddyserver/cache-handler \
	  --with github.com/ueffel/caddy-brotli
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;经过一段时间的编译以后，我们就可以在当前目录下看到一个名为 &lt;code&gt;caddy&lt;/code&gt; 的二进制文件，这就是我们自定义编译的 Caddy 了。&lt;/p&gt;
&lt;h2&gt;自定义 Caddy 和系统 Caddy 共存&lt;/h2&gt;
&lt;p&gt;如果我们想要自定义 Caddy 和系统 Caddy 共存，可以使用官方的&lt;a href=&quot;https://caddyserver.com/docs/build&quot;&gt;教程&lt;/a&gt;：&lt;/p&gt;
&lt;p&gt;首先，按照我们的教程&lt;a href=&quot;https://u.sb/debian-install-caddy/&quot;&gt;安装&lt;/a&gt; Caddy，安装完毕后，先停止 Caddy 服务：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl stop caddy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后使用 &lt;code&gt;dpkg-divert&lt;/code&gt; 命令将系统 Caddy 的二进制文件移动到 &lt;code&gt;/usr/bin/caddy.default&lt;/code&gt; 并做软链接：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo dpkg-divert --divert /usr/bin/caddy.default --rename /usr/bin/caddy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后把我们自己编译好的 Caddy 二进制文件移动到 &lt;code&gt;/usr/bin/caddy.custom&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mv ./caddy /usr/bin/caddy.custom
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后设置优先级，让我们的自定义 Caddy 优先启动：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.default 10
sudo update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.custom 50
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时我们可以看到默认的 &lt;code&gt;/usr/bin/caddy&lt;/code&gt; 已经是我们自定义的 Caddy 了：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # ls -l /usr/bin/caddy
lrwxrwxrwx 1 root root 23 Jan 22 10:52 /usr/bin/caddy -&amp;gt; /etc/alternatives/caddy*

root@debian ~ # ls -l /etc/alternatives/caddy
lrwxrwxrwx 1 root root 21 Jan 22 10:52 /etc/alternatives/caddy -&amp;gt; /usr/bin/caddy.custom
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们也可以使用 &lt;code&gt;sudo update-alternatives --config caddy&lt;/code&gt; 命令来切换系统安装的 Caddy 和自定义的 Caddy：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@caddy ~ # update-alternatives --config caddy
There are 2 choices for the alternative caddy (providing /usr/bin/caddy).

  Selection    Path                    Priority   Status
------------------------------------------------------------
* 0            /usr/bin/caddy.custom    50        auto mode
  1            /usr/bin/caddy.custom    50        manual mode
  2            /usr/bin/caddy.default   10        manual mode

Press &amp;lt;enter&amp;gt; to keep the current choice[*], or type selection number:
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们可以看到默认的 Caddy 二进制文件是我们自定义的，你可以输入 0 (按照优先级自动) 1 (手工切换自定义 Caddy) 或 2 (使用系统默认 Caddy) 来修改并切换默认的 Caddy 版本。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian / Ubuntu 安装 Caddy</title><link>https://u.sb/debian-install-caddy/</link><guid isPermaLink="true">https://u.sb/debian-install-caddy/</guid><description>本文将指导如何在 Debian 和 Ubuntu 下安装 Caddy。</description><pubDate>Tue, 27 Dec 2022 04:47:25 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何在 Debian 和 Ubuntu 下安装 Caddy。&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;什么是 Caddy？&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://caddyserver.com/&quot;&gt;Caddy&lt;/a&gt; 是一款开源的 Web 服务器，它设计简单，易于使用，并且有很多强大的功能。它可以自动处理 TLS (SSL)，并且可以使用中间件扩展功能。&lt;/p&gt;
&lt;p&gt;Caddy 采用简单的配置语法，可以轻松配置路由，反向代理，重定向，缓存和其他功能。它还支持 HTTP/2，QUIC (HTTP/3) 和 WebSockets 协议，可以提供快速的网络性能。&lt;/p&gt;
&lt;h2&gt;为什么尝试 Caddy？&lt;/h2&gt;
&lt;p&gt;对我来说比较简单的原因是 &lt;a href=&quot;https://quic.nginx.org/&quot;&gt;nginx-quic&lt;/a&gt; 这个项目一直未发布正式版，想要一款简单的能支持 &lt;a href=&quot;https://en.wikipedia.org/wiki/HTTP/3&quot;&gt;HTTP/3&lt;/a&gt; 的 Web 服务器软件，目前来说 Caddy 的选择是最合适的。&lt;/p&gt;
&lt;p&gt;Caddy 还支持自动化证书，对于懒人来说特别合适。&lt;/p&gt;
&lt;h2&gt;安装 Caddy&lt;/h2&gt;
&lt;p&gt;我们按照官方的&lt;a href=&quot;https://caddyserver.com/docs/install#debian-ubuntu-raspbian&quot;&gt;安装方法&lt;/a&gt;，首先，安装一些必要的软件包：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt upgrade -y
sudo apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后加入 Caddy 的 GPG 公钥和 apt 源：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -sSL https://dl.cloudsmith.io/public/caddy/stable/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/caddy.gpg
echo &amp;quot;deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/caddy.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main&amp;quot; | sudo tee /etc/apt/sources.list.d/caddy.list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Debian 下也可以使用 extrepo：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install extrepo
sudo extrepo enable caddyserver
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后更新系统后即可安装 Caddy：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install caddy
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;配置 Caddy&lt;/h2&gt;
&lt;p&gt;默认的 &lt;code&gt;Caddyfile&lt;/code&gt; 文件位于 &lt;code&gt;/etc/caddy/Caddyfile&lt;/code&gt;，官方的教程在&lt;a href=&quot;https://caddyserver.com/docs/caddyfile-tutorial&quot;&gt;这儿&lt;/a&gt;，如果你习惯了 Nginx 和 Apache 的配置，那么此时应该会非常不习惯，我们就来一个最简单的例子把：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;我们需要绑定域名 &lt;code&gt;example.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;这个域名的文件位于 &lt;code&gt;/var/www/example.com&lt;/code&gt;，默认首页文件名为 &lt;code&gt;index.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;我们需要开启 SSL 访问，并且访问 http 跳转到 https&lt;/li&gt;
&lt;li&gt;我们需要设置开启 TLS 1.2 和 TLS 1.3，并开启 HSTS Preload&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;首先，设置 &lt;code&gt;http://example.com/&lt;/code&gt; 跳转到 &lt;code&gt;https://example.com/&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：默认情况如果下面的 &lt;code&gt;example.com:80&lt;/code&gt; 和 &lt;code&gt;example.com:443&lt;/code&gt; 没有配置其他的端口，Caddy 会自动使用 443 端口，并自动开启 &lt;code&gt;http://example.com/&lt;/code&gt; 跳转到 &lt;code&gt;https://example.com/&lt;/code&gt;，这里的示范是为了给有些奇怪的需求比如一些特定的端口访问 HTTP 和 HTTPS，则需要手动配置。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;example.com:80 {
	redir https://{host}{uri} permanent
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后我们按照 Mozilla 的&lt;a href=&quot;https://ssl-config.mozilla.org/#server=caddy&amp;version=2.6.2&amp;config=intermediate&amp;guideline=5.6&quot;&gt;推荐配置&lt;/a&gt;写入 &lt;code&gt;Caddyfile&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;example.com:443 {
	tls {
		protocols tls1.2 tls1.3
		ciphers TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
	}

	header {
		Strict-Transport-Security &amp;quot;max-age=63072000; includeSubDomains; preload&amp;quot;
		Referrer-Policy strict-origin-when-cross-origin
		X-Frame-Options SAMEORIGIN
		X-Content-Type-Options nosniff
		X-XSS-Protection &amp;quot;1; mode=block&amp;quot;
	}

	root * /var/www/example.com

	file_server {
		index index.html
	}

	encode gzip zstd
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当然也可以设置 &lt;code&gt;www.example.com&lt;/code&gt; 跳转 &lt;code&gt;example.com&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;www.example.com:80 {
	redir https://example.com{uri} permanent
}

www.example.com:443 {
	redir https://example.com{uri} permanent
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后把以上所有内容合并成一个 &lt;code&gt;Caddyfile&lt;/code&gt; 文件，放到 &lt;code&gt;/etc/caddy/Caddyfile&lt;/code&gt;，然后检查 Caddy 配置：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo caddy validate --config /etc/caddy/Caddyfile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出如下内容则表示配置正确：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # caddy validate --config /etc/caddy/Caddyfile
2022/12/26 17:31:22.347	INFO	using provided configuration	{&amp;quot;config_file&amp;quot;: &amp;quot;/etc/caddy/Caddyfile&amp;quot;, &amp;quot;config_adapter&amp;quot;: &amp;quot;&amp;quot;}
2022/12/26 17:31:22.349	WARN	http	server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server	{&amp;quot;server_name&amp;quot;: &amp;quot;srv1&amp;quot;, &amp;quot;http_port&amp;quot;: 80}
2022/12/26 17:31:22.349	INFO	http	enabling automatic HTTP-&amp;gt;HTTPS redirects	{&amp;quot;server_name&amp;quot;: &amp;quot;srv0&amp;quot;}
2022/12/26 17:31:22.349	INFO	tls.cache.maintenance	started background certificate maintenance	{&amp;quot;cache&amp;quot;: &amp;quot;0xc00018ad90&amp;quot;}
2022/12/26 17:31:22.350	INFO	tls.cache.maintenance	stopped background certificate maintenance	{&amp;quot;cache&amp;quot;: &amp;quot;0xc00018ad90&amp;quot;}
Valid configuration
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有强迫症的也可以把你的 Caddyfile 文件美化一下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo caddy fmt /etc/caddy/Caddyfile --overwrite
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后重启 Caddy&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl restart caddy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;耐心等待自动签发 SSL 证书，然后我们就可以打开浏览器控制台查看 &lt;code&gt;https://example.com/&lt;/code&gt; 即可看到 SSL 证书已经自动部署，同时 HTTP/3 已经开启了：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/img/2022/12/e3e00d.png&quot; alt=&quot;HTTP/3&quot;&gt;&lt;/p&gt;
&lt;p&gt;更多的配置可以参考&lt;a href=&quot;https://caddyserver.com/docs/caddyfile&quot;&gt;官方文档&lt;/a&gt;或&lt;a href=&quot;https://mritd.com/2021/06/30/understand-caddyfile-syntax/&quot;&gt;《Caddyfile 语法浅析》&lt;/a&gt;&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Debian / Ubuntu 手工添加 Swap 分区</title><link>https://u.sb/debian-swap/</link><guid isPermaLink="true">https://u.sb/debian-swap/</guid><description>本文将指导如何在 Debian 11 和 Ubuntu 22.04 下手工添加 Swap 分区。</description><pubDate>Wed, 21 Dec 2022 02:38:29 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导如何在 Debian 11 和 Ubuntu 22.04 下手工添加 Swap 分区。&lt;/p&gt;
&lt;p&gt;以下操作需要 root 权限，本文命令均已带上 &lt;code&gt;sudo&lt;/code&gt; 前缀，请确保当前用户拥有 &lt;code&gt;sudo&lt;/code&gt; 权限；或者直接使用 root 用户操作并省略命令中的 &lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;准备工作&lt;/h2&gt;
&lt;p&gt;首先，检查你的系统是否已经有 Swap 分区：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo swapon -s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;free -m
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果没有返回结果或者 &lt;code&gt;free -m&lt;/code&gt; 中 &lt;code&gt;Swap&lt;/code&gt; 一列数值是 &lt;code&gt;0&lt;/code&gt;，则表示你的系统没有 Swap 分区。&lt;/p&gt;
&lt;h2&gt;创建 SWAP 分区&lt;/h2&gt;
&lt;p&gt;我们可以使用 &lt;code&gt;fallocate&lt;/code&gt; 命令创建一个 1GB 大小的 Swap 分区：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo fallocate -l 1G /swapfile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果这个命令无法使用，请安装 &lt;code&gt;util-linux&lt;/code&gt; 包：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install util-linux
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后设置这个文件的权限：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo chmod 600 /swapfile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后激活 SWAP 分区&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo mkswap /swapfile
sudo swapon /swapfile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时，你可以使用 &lt;code&gt;sudo swapon -s&lt;/code&gt; 或 &lt;code&gt;free -m&lt;/code&gt; 命令查看 Swap 分区是否已经激活。&lt;/p&gt;
&lt;h2&gt;设置开机自启&lt;/h2&gt;
&lt;p&gt;我们需要编辑 &lt;code&gt;/etc/fstab&lt;/code&gt; 这个文件，加入下面的内容即可：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &amp;quot;/swapfile swap swap defaults 0 0&amp;quot; | sudo tee -a /etc/fstab
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;大功告成，使用 &lt;code&gt;free -m&lt;/code&gt; 命令查看 Swap 分区是否正确：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/img/2022/12/1097a4.png&quot; alt=&quot;Debian / Ubuntu 手工添加 Swap 分区&quot;&gt;&lt;/p&gt;
&lt;h2&gt;调整系统内核 Swappiness 值&lt;/h2&gt;
&lt;p&gt;Swapiness 是 Linux 内核的一个属性，定义了系统使用交换空间的频率，Swapiness 的值在 0 到 100 之间 (默认是 60)，一个低的值会使内核尽可能地避免交换，而一个高的值会使内核更积极地使用交换空间。&lt;/p&gt;
&lt;p&gt;这个值默认是 &lt;code&gt;60&lt;/code&gt;，我们可以使用 &lt;code&gt;cat /proc/sys/vm/swappiness&lt;/code&gt; 命令查看当前值。&lt;/p&gt;
&lt;p&gt;一般我们可以给他改成 &lt;code&gt;10&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &amp;quot;vm.swappiness=10&amp;quot; | sudo tee -a /etc/sysctl.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后使用 &lt;code&gt;sudo sysctl -p&lt;/code&gt; 命令使其生效。&lt;/p&gt;
&lt;h2&gt;关闭 Swap&lt;/h2&gt;
&lt;p&gt;有时候我们需要关闭 Swap 分区，可以使用下面的命令：&lt;/p&gt;
&lt;p&gt;首先，停用 Swap 分区：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo swapoff -v /swapfile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后检查 &lt;code&gt;/etc/fstab&lt;/code&gt;，删除 &lt;code&gt;/swapfile swap swap defaults 0 0&lt;/code&gt; 这一行。&lt;/p&gt;
&lt;p&gt;最后删除 &lt;code&gt;/swapfile&lt;/code&gt; 这个文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo rm /swapfile
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>Nginx 使用 split_clients 进行简易 A/B 测试</title><link>https://u.sb/nginx-ab-testing/</link><guid isPermaLink="true">https://u.sb/nginx-ab-testing/</guid><description>本文将介绍在 Nginx 配置简易 A/B 测试的姿势。</description><pubDate>Sat, 02 Jul 2022 21:04:50 GMT</pubDate><content:encoded>&lt;p&gt;本文将介绍在 Nginx 配置简易 A/B 测试的姿势。&lt;/p&gt;
&lt;h2&gt;背景前提&lt;/h2&gt;
&lt;p&gt;有时候我们需要简单的做一些 A/B 测试，并不需要复杂的判断条件，这时候我们可以用到 Nginx 的 &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_split_clients_module.html&quot;&gt;ngx_http_split_clients_module&lt;/a&gt; 模块。&lt;/p&gt;
&lt;h2&gt;安装 ngx_http_split_clients_module 模块&lt;/h2&gt;
&lt;p&gt;一般来说这个模块已经自带，如果没有的话推荐安装我们打包的 &lt;a href=&quot;https://n.wtf/&quot;&gt;N.WTF&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;配置 Nginx&lt;/h2&gt;
&lt;p&gt;这里举例，我们想要 &lt;code&gt;20%&lt;/code&gt; 的用户跳转到网址 &lt;code&gt;https://example.com/&lt;/code&gt;，&lt;code&gt;30%&lt;/code&gt; 的用户跳转到网址 &lt;code&gt;https://example.org/&lt;/code&gt;，剩下的跳转到网址 &lt;code&gt;https://examle.edu/&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;split_clients &amp;quot;${remote_addr}AAA&amp;quot; $variant {
    20%               https://example.com/;
    30%               https://example.org/;
    *                 https://example.edu/;
}

server {
    listen 80;
    listen [::]:80;
    server_name _;

    return 302 ${variant};
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上述例子中，按照访客请求的 &lt;code&gt;IP 地址&lt;/code&gt; 加上 &lt;code&gt;AAA 字符串&lt;/code&gt; 会使用 &lt;a href=&quot;https://en.wikipedia.org/wiki/MurmurHash#MurmurHash2&quot;&gt;MurmurHash2&lt;/a&gt; 转换成数字，如果得出的数字在前 &lt;code&gt;20%&lt;/code&gt;，那么 &lt;code&gt;$variant&lt;/code&gt; 值为 &lt;code&gt;https://example.com/&lt;/code&gt;，相应的在中间 &lt;code&gt;30%&lt;/code&gt; 区间的值为 &lt;code&gt;https://example.org/&lt;/code&gt;，其他的为 &lt;code&gt;https://example.edu/&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;然后我们找两台不同 IP 的机器进行测试：&lt;/p&gt;
&lt;p&gt;机器 A：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ # curl -I 192.0.2.2
HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Sat, 02 Jul 2022 20:51:43 GMT
Content-Type: text/html
Content-Length: 138
Connection: keep-alive
Location: https://example.com/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;机器 B：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;root@debian ~ #  curl -I 192.0.2.2                         
HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Sat, 02 Jul 2022 20:52:12 GMT
Content-Type: text/html
Content-Length: 138
Connection: keep-alive
Location: https://example.org/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后就可以有更灵活的用法，比如指定不同的目录：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;root /var/www/${variant};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定不同的首页：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;index index-${variant}.html;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;读者可以举一反三，这个比较简易的 A/B 测试就完成啦～&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item><item><title>KDE Plasma 关闭单击打开文件或文件夹</title><link>https://u.sb/archlinux-kde-disable-single-click/</link><guid isPermaLink="true">https://u.sb/archlinux-kde-disable-single-click/</guid><description>本文将指导在 KDE Plasma 下关闭单击打开文件或文件夹。</description><pubDate>Fri, 01 Jul 2022 16:36:53 GMT</pubDate><content:encoded>&lt;p&gt;本文将指导在 KDE Plasma 下关闭单击打开文件或文件夹。&lt;/p&gt;
&lt;h2&gt;前言&lt;/h2&gt;
&lt;p&gt;对于从 Windows 或 macOS 迁移到 Linux 的用户，需要花费很多时间来适应各种不习惯的操作，在 &lt;a href=&quot;https://kde.org/plasma-desktop/&quot;&gt;KDE Plasma&lt;/a&gt; 下，有一个默认设置，单击即可打开某个文件或者文件夹，这让很多用户感到非常不适应。&lt;/p&gt;
&lt;h2&gt;解决方法&lt;/h2&gt;
&lt;p&gt;参考&lt;a href=&quot;https://forum.kde.org/viewtopic.php?t=128669&quot;&gt;这个帖子&lt;/a&gt;，打开 &lt;code&gt;System Settings&lt;/code&gt; -&amp;gt; &lt;code&gt;Workspace Behavior&lt;/code&gt; -&amp;gt; &lt;code&gt;General Behavior&lt;/code&gt;，然后找到 &lt;code&gt;Clicking files or folders&lt;/code&gt;，把默认的 &lt;code&gt;Opens them&lt;/code&gt; 改成 &lt;code&gt;Selects them&lt;/code&gt;：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://s.bh.sb/uploads/2022/07/02/nRCidrQz7qZNEPT.png&quot; alt=&quot;KDE Plasma 关闭单击打开文件&quot;&gt;&lt;/p&gt;
&lt;p&gt;好了，解决了这个非常不习惯的操作。&lt;/p&gt;
</content:encoded><author>i@m.ac (Showfom)</author></item></channel></rss>