<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://sourlemonjuice.github.io/feed.xml" rel="self" type="application/atom+xml"/><link href="https://sourlemonjuice.github.io/" rel="alternate" type="text/html" hreflang="en"/><updated>2026-04-05T15:16:35+08:00</updated><id>https://sourlemonjuice.github.io/feed.xml</id><title type="html">SourLemonJuice-blog</title><subtitle>A blog of 酸柠檬猹/SourLemonJuice. A random stranger, and love the OS ( • ᴖ • ｡)</subtitle><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><entry xml:lang="zh-Hans"><title type="html">macOS 键盘修饰符的设计理念和 Windows 差别好大</title><link href="https://sourlemonjuice.github.io/posts2/2026/04/macos-modifier-keys" rel="alternate" type="text/html" title="macOS 键盘修饰符的设计理念和 Windows 差别好大"/><published>2026-04-04T03:55:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2026/04/macos-modifier-keys</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2026/04/macos-modifier-keys"><![CDATA[<p>今年已经进入四月初了，2026年终究还是已经过完了1/4。鉴于前两个月这里一篇新文章都没有加上最近碰了碰 macOS 所以想到来写一写我对 macOS 中快捷键修饰符的感受和理解。</p> <h2 id="command-键--ctrl-键">Command 键 &amp; Ctrl 键</h2> <p>一上手 Mac 给人最大的不同就是就连复制粘贴这类耳熟能详的 Control C/V 都变成了 Command C/V，小拇指的肌肉记忆也在反反复复的按地球仪键并打开 emoji 选择器（什）。<br/> 不仅如此包括全选（Ctrl+A）、前后跳转一个单词（Ctrl+Left/Right）、跳到行首行尾（Home/End，它们在笔记本上位置一般很奇怪或者没有所以超级影响打字体验）全都变成了另一种以 Command 为中心的快捷键。</p> <p>在几乎一天的不习惯但好奇的尝试之后这套方案逐渐让我感受到了它和 IBM 和微软最初的设计师在理念上最大的差异：到底是小拇指还是大拇指灵活。</p> <p>如果作为读者的你正在用着常见布局的键盘，不妨重新尝试一下让左手从手指平摊在 asdf 到小拇指放在 ctrl 上的过程，即使食指保留了键盘突起所在的位置其它两根本不该移动的手指依然改变了位置，这就造成了输入完快捷键后重新定位时的轻微不自信和延迟，并且在按下 ctrl 后输入字母键时由于每根手指活动的中点从 asdf 变成了小拇指所在的键盘左下角，导致用哪根手指按下按键也和平坦状态不一样，比如 C 在平摊时属于中指而 Ctrl+C 属于食指。</p> <p>而 Command 键处于常见布局中 alt 键所在的位置属于大拇指的管理范围。大拇指不参与字母键的敲击，移动起来也不受小拇指上韧带的生理所限可以在不改变手掌的情况下随意移动（只要够长x）。</p> <p>明白了底层设计后我的大脑就开始用上字母键打字的肌肉记忆来完成快捷键了，相对于小拇指的设计这无疑无形中减小了很多初期的学习成本。</p> <blockquote> <p>Tips: Command+Left/Right 是跳到行首行尾，Command+Up/Down 是跳转文件头尾（等于 Shift+Home/End）</p> </blockquote> <h2 id="option-键--alt-键">Option 键 &amp; Alt 键</h2> <p>如果说 Command 可以概括为 ctrl 的超集，那其它两个快捷键可以对应么？</p> <p>虽然 Option 所在的地方看上去应该是 win 键的位置，但更像是个 alt 键。它干的所有活都很杂，属于是用 Command 屈才（idk）或者对应快捷键字母部分和 Command 一致但实现的是同一功能的变体（Option+Left/Right 前后跳转一个单词，终于找到家的感觉了）。</p> <p>虽然它的位置也能用大拇指够到，但确实处于边缘位置，不过作为一个没什么字母键需要配合的家伙它的体验已经相当优秀了。</p> <h2 id="control-一点也不-ctrl">Control 一点也不 Ctrl</h2> <p>一整个 win/meta 键，和方向键一起都能控制虚拟桌面和窗口的 overview 了。</p> <p>从这里开始就和左边的 fn 一起重新沦为小拇指的管理了。</p> <p>不过我完全不清楚 Control 在现代快捷键方面除了多一重修饰以外还有什么用。有一种说法是作为标准 Unix 修饰符终端里处处都需要它（这是真的，比如 Ctrl+C 强行停止或者 Ctrl+D 发送 EOF），也可能是 macOS 最初采用了一堆 Emacs 快捷键所以 Control 在文本输入的时候还是有用的。<br/> 无论如何嘛…… 有点无聊。</p> <h2 id="ending">Ending</h2> <p>是什么原因会让一个人在凌晨不睡觉写这些没什么用的东西呢？</p> <p>可能是不记下来就会彻底忘记吧。该睡觉咯~</p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2026"/><summary type="html"><![CDATA[今年已经进入四月初了，2026年终究还是已经过完了1/4。鉴于前两个月这里一篇新文章都没有加上最近碰了碰 macOS 所以想到来写一写我对 macOS 中快捷键修饰符的感受和理解。]]></summary></entry><entry xml:lang="zh-Hans"><title type="html">明日方舟：终末地，启动！（卸载）</title><link href="https://sourlemonjuice.github.io/posts2/2026/02/arknights-endfield" rel="alternate" type="text/html" title="明日方舟：终末地，启动！（卸载）"/><published>2026-02-22T08:30:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2026/02/arknights-endfield</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2026/02/arknights-endfield"><![CDATA[<p>我从一月22号终末地公测开始有在断断续续的玩，今天打通主线剧情了也看了不少武陵的风景，所以来记录一下感受</p> <h2 id="一句话总结">一句话总结🤓</h2> <p>纯纯的通马桶剧情，千万不要玩，千万不要为了工厂玩法入坑，但如果你和我一样是个只要游戏画面好看有心意就愿意花时间的话… 那还不错（？</p> <p>场景和角色的美术超级好看，也怪不得鹰角自己宣传的时候也在说这些。<br/> 武陵好好看呃啊wwww 能不能把四号谷地删掉，求求了。<del>最好再把所有通马桶一样的主线剧情删掉</del></p> <p>其实我个人觉得终末地的每个玩法本身还是不错的，但是串联它们的剧情实在是惨不忍睹。唉，可惜咯（怎么说得好像只要鹰角做得好我就会长期玩一样，玩抽卡二游没有好下场）</p> <p><img src="/static/asset/2026-02-22-arknights-endfield/Screenshot_20260222.webp" alt="游戏任务提示：行动已结束，请自由探索塔卫二" width="800"/></p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2026"/><summary type="html"><![CDATA[我从一月22号终末地公测开始有在断断续续的玩，今天打通主线剧情了也看了不少武陵的风景，所以来记录一下感受]]></summary></entry><entry xml:lang="en"><title type="html">Some History About the Computer and Me</title><link href="https://sourlemonjuice.github.io/posts2/2025/12/computer" rel="alternate" type="text/html" title="Some History About the Computer and Me"/><published>2025-12-27T02:25:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2025/12/computer</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2025/12/computer"><![CDATA[<p>At the beginning, one of my relatives gave me an old OEM PC. That’s my first real full-functional computer. My parents are holding onto the negative opinions at that time, but I at least owned something when I was 13(or 12?) years old.</p> <p>My first teacher would be Minecraft, I think. Configure the java dev kit, and figure out how to use Windows 10 is a pretty challenging task for me. My friends and I want to play together, so I’m also studying how to use NAT traveling out of school.</p> <p>I was born in 2009, the last gen z. Everyone was talking more about phones in my childhood. People talking, using, playing, and controlling the dumb or smart phones. Even though I still have some memories about optical disks and other things before the internet grew up.</p> <p>Back then, we even tried variants of apps to run the Minecraft java version on Android for some reason(we didn’t have a PC). Tech barrier could never block tech studying.</p> <p>Some others will say I have a little old-school, but that might be my practices: walk through the history once and understand where we are today. For example, I have used Nginx as reverse proxy for a long time before replacing it with Caddy.</p> <p>Funny retro but not old atmosphere.</p> <p>The afterword of the story was: Playing some video game and being blamed; Have been asked why I need VSCode on that computer; Following a series of stupid java tutorial videos, but have done nothing. So I never watch any long video tutorials after that.</p> <p>I also had to build some physical electronic “stuff”, but that part was boring.</p> <h2 id="after-started-trying-linux">After started trying Linux</h2> <p>Why not to learn about other OS, or some other more serious programming languages? I don’t want to stop at being a tech lover. That’s why I decided to learn about Linux and C between 2022 and 2024.</p> <p>My first Linux distro is Ubuntu, which is the end of 2022(probably?). Like every regular person, it’s hard. There was a desktop edition, but I use it as a server on a pretty useless PC. This is fun, but did nothing related to “server”. And I started using Debian as my day-to-day system more than six months ago.</p> <p>After another six months, I had learned a lot about how to do daily tasks with Debian. Really stable distro, until you accidentally uninstall VirtualBox the wrong way. After that, I wanted to challenge myself a little and also for learning more fundamental things. In August 2023, I spent a whole night migrating my PC to Arch Linux.</p> <p>In that year, I tried to jailbreak a stock Nintendo Switch. Soldered an existing hacking board and cooking some software from the community. But be honest, pricey games are not enjoyable. I’m not a genius, so I didn’t code something for that.<br/> There is an article for that: <a href="/posts/简体中文/2024/04/23/从头破解NintendoSwitch的总结与心得">从头破解 Nintendo Switch 的总结与心得</a></p> <p>At that time, I was very familiar with shell, but still knew nothing about real programming, <em>even Python</em>. So in 2024, I bought a book called C Primer Plus, and started learning and practicing C.</p> <p>I would say attempting to do some jailbreaks every year is great. Even if they look small.<br/> Article: <a href="/posts2/2024/06/Linux-for-Chromebook">在 Chromebook 上安装完整 Linux 发行版的方法总结</a></p> <p>In 2025, I’m focused on networking and cloud. I’m more and more seriously managing my website and domain on Cloudflare. Trying to use AWS at surface(who can master that mess <code class="language-plaintext highlighter-rouge">:|</code>). And… I also learned the Go language as my primary choice to build something.</p> <p>In this context, I swapped my PC and server OS with Red Hat Linux family in October 2025 :&gt;</p> <h2 id="why-do-i-write-this-post">Why do I write this post?</h2> <p>There is a previous page of this blog, called “The Computer Science” under the “about” page. I hid it so deep and have a lot of useless stuff randomly. So I decided to organize them and add some more content to fill this empty December for me…</p> <p>Networking, javascript, and the frontend are boring this year…</p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2025"/><category term="Featured"/><summary type="html"><![CDATA[At the beginning, one of my relatives gave me an old OEM PC. That’s my first real full-functional computer. My parents are holding onto the negative opinions at that time, but I at least owned something when I was 13(or 12?) years old.]]></summary></entry><entry xml:lang="zh-Hans"><title type="html">或许对我来说，web 是个更加值得慎重的地方…</title><link href="https://sourlemonjuice.github.io/posts2/2025/11/web-is-uncontrollable" rel="alternate" type="text/html" title="或许对我来说，web 是个更加值得慎重的地方…"/><published>2025-11-30T03:32:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2025/11/web-is-uncontrollable</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2025/11/web-is-uncontrollable"><![CDATA[<p>这两个月里我做了一些之前的我觉得很诧异的事情：注册一个新域名 <code class="language-plaintext highlighter-rouge">charchar.dev</code> 并把 blog 迁移到那里。<br/> 讲真，这对我的好处真的那么大么，为什么我要用一个新域名呢。从做出决定的一刻到现在我都在一直想着这些，或者说担心这这些</p> <p>这绝不正常，也绝不会是一个正确的决定</p> <h2 id="域名">域名</h2> <p>其实域名是我从小以来第一个觉得最酷而自己又却最触碰不到的概念。但截至 2025 年，<code class="language-plaintext highlighter-rouge">sourlemonjuice.net</code> 已经持续存在了一年多了，这一切都变得如此熟悉但我也一直保持着警惕。</p> <p>为什么？<br/> 因为相比 github pages 这种 Platform as a Service，自己的域名和服务器基础设施需要一个维护者和金钱。这引入了一系列的不确定性，虽然对于功能网站来说这再合适不过了，但对于内容网站一旦发生变化造成的后果也是灾难性的。在过去所建立的所有链接都将无法使用，所写过的内容除了 web archive 也将无人得知。<br/> 即使我是个会把源代码公开到 github 上的人（有些人会在本地构建完后推到一个单独的公开分支上），但我相信没有多少人会真的去看的。除了自己以外再也用没人在乎的东西，可以被叫做遗物吧</p> <p>对于我的时间线而言，<code class="language-plaintext highlighter-rouge">sourlemonjuice.net</code> 是我用来公开所有我自己需要的公开服务的地方。不考虑 URL 长度，和优雅，只有单纯的功能性和来自网络的粗旷。<br/> 至少我是这么想的，比如 <code class="language-plaintext highlighter-rouge">connectivity.sourlemonjuice.net/generate_204</code> 这种东西的存在都是经过考量的</p> <p>而另一个新域名的背景则更为复杂：<code class="language-plaintext highlighter-rouge">charchar.dev</code><br/> 我不知道如果作为读者的你看到会怎么想，但 char 是我用在拉丁字母的 nickname。我总是说着不想，但 SourLemonJuice 实在是太长太长，而且即使作为一个命名空间也不完全独特。但总的来说够用，名字嘛向来如此</p> <p>但由此引发的问题是作为访问者的割裂，和维护上的多余复杂度。我想在不同的地方上写清我的名字也可以是 char，但这并不够，非最主要用途的名字注定只会被自己亲近的人知道，这对我的 blog 有什么意义呢。<br/> 我又有什么把以 SourLemonJuice 为名义认识我的人放到 <code class="language-plaintext highlighter-rouge">charchar.dev</code> 上呢?<br/> 但它又足够的短，足以支撑起类似 <code class="language-plaintext highlighter-rouge">ip.charchar.dev</code> 这样的需要经常手动输入的 URL。仔细来看我简直是在逐渐把自己绑死在这两个域名上，互相牵制，互相依赖</p> <p>这永远都不应该发生</p> <p>但有哪些地方做错了，又有哪些是值得保留的呢？</p> <h2 id="方便输入和名字贴脸什">方便输入和名字贴脸（什</h2> <p>就保留 <code class="language-plaintext highlighter-rouge">ip.charchar.dev</code> 的角度来看 <code class="language-plaintext highlighter-rouge">charchar.dev</code> 其实是一个有用的域名，但唯独不适合长时间保存内容和当作 API 接口。<br/> 所以我也想借着这篇帖子重新捋清自己的想法：</p> <ul> <li>永远不要根据他人的抱怨偏离自己的内心！这点真的对我自己很重要</li> <li>单个内容依赖的基础设施越少越好</li> <li>PaaS 永远比自托管好，除非必要</li> <li>如果觉得做了什么比不做会造成可预见但可以挽回的长期危害，不要做。<code class="language-plaintext highlighter-rouge">blog.charchar.dev</code> 就是例子</li> </ul> <p>或许很快就会把 blog 从 <code class="language-plaintext highlighter-rouge">blog.charchar.dev</code> 改到 <code class="language-plaintext highlighter-rouge">blog.sourlemonjuice.net</code> 吧…</p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2025"/><summary type="html"><![CDATA[这两个月里我做了一些之前的我觉得很诧异的事情：注册一个新域名 charchar.dev 并把 blog 迁移到那里。 讲真，这对我的好处真的那么大么，为什么我要用一个新域名呢。从做出决定的一刻到现在我都在一直想着这些，或者说担心这这些]]></summary></entry><entry xml:lang="en"><title type="html">Quick note about AV1 and SVT-AV1</title><link href="https://sourlemonjuice.github.io/posts2/2025/11/svt-av1" rel="alternate" type="text/html" title="Quick note about AV1 and SVT-AV1"/><published>2025-11-03T19:03:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2025/11/svt-av1</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2025/11/svt-av1"><![CDATA[<p>Lately, I’m looking for video codecs. Just because I’m on Linux and ffmpeg VAAPI HEVC somehow generated wrong output.<br/> It can’t handle scaling correctly, then rest these green bar on my output: <a href="https://github.com/LizardByte/Sunshine/issues/4314">LizardByte/Sunshine#4314</a>. That’s the beginning.</p> <h2 id="background-of-av1">Background of AV1</h2> <p>The <strong><a href="https://en.wikipedia.org/wiki/AV1">AV1</a></strong> video coding format was released in 2019 and is becoming more and more common on internet video streaming platforms. Small size and high quality are best for the internet.<br/> That’s how my hardware video accelerator zero load when watching youtube, AMD RX 5700 is strong enough, but kind of old :)</p> <h2 id="available-software-codecs">Available Software Codecs</h2> <p>Like OpenH264 and x264, AV1 now have two major software codec: <strong>AOM-AV1</strong> and <strong>SVT-AV1</strong>.</p> <p>AOM-AV1 is developed by AOMedia(‘A’ in AV1) themselves, but… a little slow. Not the best first impression.</p> <p>SVT-AV1 is second, developed by Intel and Netflix in 2020. It faster and design for serious applications.</p> <h2 id="bitrate-control">Bitrate Control</h2> <p>In the past, I only know the <strong>CBR(constant)</strong> and <strong>VBR(variable)</strong> methods to adjust output size.<br/> But instead, you can use <strong>CRF(Constant Rate Factor)</strong> to keep image quality across the video, and reduce/increase bitrate on the fly.</p> <p>Unlike bitrate, CRF is completely defined by codec. If codec say it can be INT_MAX that still correct.</p> <p>In SVT-AV1, 35 is the default on ffmpeg. The number is more smaller, quality and size are larger.<br/> You may want to try it at around 30 to start. There is a incredible article of this topic:</p> <blockquote> <p><a href="https://ottverse.com/analysis-of-svt-av1-presets-and-crf-values/">Comparing SVT-AV1 Presets: Size, Quality, and Speed with CRF Variations</a></p> </blockquote> <h2 id="preset">Preset</h2> <p>The second thing after bitrate is preset, which controls how hard to encode/decode the video could be.<br/> You can also see the graphic table about performance in the previous link.</p> <h2 id="perceptual-video-evaluation">Perceptual Video Evaluation</h2> <p>To evaluate how good a transcoded video and original video are, a method is calculate signal to noise ratio: PSNR. But it can’t perfectly reflect human feel.<br/> Another option is VMAF, developed by Netflix. I would say it more considers how humans perceive video and uses machine-learning for some parts of the algorithm. It’s cool, and accurate.</p> <p>You can find them implementation at GitHub: <a href="https://github.com/Netflix/vmaf">Netflix/vmaf</a><br/> Or download it from your distro repo.</p> <p>This article knows more and more than me: <a href="https://visionular.ai/vmaf-ssim-psnr-quality-metrics/">Making Sense of PSNR, SSIM, VMAF</a></p> <h2 id="can-that-stuff-fix-my-hardware-encoding-issue">Can that stuff fix my hardware encoding issue?</h2> <p>Can not.<br/> But set the output resolution as same as my screen resolution can prevent scaling. I think which is the most useful part of these days, haha.</p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2025"/><summary type="html"><![CDATA[Lately, I’m looking for video codecs. Just because I’m on Linux and ffmpeg VAAPI HEVC somehow generated wrong output. It can’t handle scaling correctly, then rest these green bar on my output: LizardByte/Sunshine#4314. That’s the beginning.]]></summary></entry><entry xml:lang="zh-Hans"><title type="html">要照顾好自己的数据哦 feat. dm-crypt Syncthing</title><link href="https://sourlemonjuice.github.io/posts2/2025/10/take-care-of-your-data" rel="alternate" type="text/html" title="要照顾好自己的数据哦 feat. dm-crypt Syncthing"/><published>2025-10-26T15:45:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2025/10/take-care-of-your-data</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2025/10/take-care-of-your-data"><![CDATA[<p>很多时候数据的丢失不光是由一个事情出了错引起的，而是由一连串的诱因共同导致。<br/> 不过最近我把自己的一个加密 root 系统分区搞坏了，所以无论如何至少我又多了一个理由来 blog 上写东西233</p> <blockquote> <p>PS: 丢掉的数据里好像有两篇帖子的草稿（划掉划掉</p> </blockquote> <p>这台系统是我的主力机，Arch Linux 加上稍微调整过超频的 AMD CPU 和 GPU。在一块 NVMe 固态上用着 LUKS2 模式的 dm-crypt 加密的根文件系统，绑定了我之前写过的 systemd <a href="/posts2/2025/08/linux-x86-bootloader-and-tpm2">TPM2 Policy</a> 解密方式。里面的文件系统是 zstd:3 压缩模式的 btrfs<br/> 或许你已经在想很多种出问题的方式了，但实际情况其实还是复杂了不少的</p> <p>嘛，要从哪里开始说起呢</p> <h2 id="btrfs-中损坏的数据">Btrfs 中损坏的数据</h2> <p>事情的起源并不来自于 dm-crypt 而是上层的文件系统。<br/> 虽然很匪夷所思，但这一两个月以来这台电脑在大范围更新系统的时候经常抛出错误（”Truncated tar archive”），由于出现后 pacman 并不会认为这个包安装失败了，所以在这段时间里它已经损坏了几个软件包，导致后来我见到这个报错都是直接打开新的终端单独重新安装一下出错的包</p> <p>同样还出现过一次的是 kernel panic… 报错说 btrfs 的 b-tree 爆炸了，但重启后什么问题都没有，<code class="language-plaintext highlighter-rouge">btrfs check</code> 之类的都能通过。虽然疑点重重但后来也没有重建文件系统，毕竟太麻烦了。</p> <p>但这样的问题似乎就一直存在着存在着，没有任何重要文件被损坏了，除了 pacman 外也没有其他异常。我记得好像有一个 arch forum 上的帖子说可能是硬件问题，但分区上也没有坏块。<br/> 直到有一天更新完系统后整个 KDE 桌面崩溃了，很多设置组件和整个显示设置都少了很多。或许是时候丢掉现有的文件系统了吧</p> <p>之后就是提取所有 root 文件系统下的文件到一块独立的储存上打包成了 <code class="language-plaintext highlighter-rouge">.tar</code> 准备重建文件系统。这块储存倒是很可靠，这么长时间了一点问题也都没有，倒是让我相信了现在的处境是文件系统的问题。<br/> 创建文件系统重新解压数据，最后确认一下 fstab 和 bootloader 整个过程除了等还是等。不过这次我选了 xfs 当做文件系统，毕竟相信一个凶手在没有任何变化的情况下不杀掉数据是不现实的（而且当时我也在尝试用 Red Hat 生态的服务器系统，xfs 是它们的默认值）</p> <p>但问题还是存在，而且没有了内置的文件透明压缩，磁盘占用量高了两倍左右</p> <p>从 KDE 崩溃到问题的开始其实已经很近了，被这么折腾了一大圈真的好累好累。这是第一个诱因</p> <h2 id="我是怎么用-syncthing-的">我是怎么用 Syncthing 的</h2> <p>年初的时候我就有琢磨过怎么备份才是最好的解决方案：<br/> <a href="/posts2/2025/03/own-something-on-cloud">用端到端加密在自托管的云服务器上安全的储存和同步文件的思路</a></p> <p>但到后来由于 webdav 在同步方面的各种不方便，就用起了 syncthing 来同步 keepass 的数据库，而帖子的主角也就是那块 root 分区的 LUKS2 恢复密钥就存在其中。<br/> Syncthing 是一个去中心化的本地（好像也可以 relay）文件同步软件。每个客户端只要连接着彼此他们之间的更改就都可以被几乎及时的同步到其他客户端</p> <p>在我的网络里有一个笔记本、一部手机、还有这台主力电脑。考虑到笔记本的开机时间大概率会和主力机错开，所以我一直都依赖手机在两者之间做缓冲，而且这样手机本身也可以查看密钥嘛</p> <p>问题是…<br/> Syncthing 如果在手机上一直启动会特别耗电…… 电池续航–<br/> 这也就导致了在整个网络中，数据能被同步的窗口从近乎90%下降到了&lt;50%。到这里事情就已经开始不妙了</p> <p>但还有更不妙的…<br/> 给手机初始化了系统，所以里面少了很多软件或者有些没有被配置。比如 syncthing…</p> <p>至此，网络中的同步就开始完全依赖与主力机和笔记本同时开机了，没有任何其它冗余。而这也意味着在没有主动同时打开笔记本的情况下数据是很难离开主力机的</p> <h2 id="鼓捣-tpm2">鼓捣 TPM2</h2> <p>紧接着的一两天内我又在看 systemd 的 systemd-cryptenroll 要怎么在已经用上 TPM2 Policy 的同时绑定一个固定的 PCR 值，这并不是重点。<br/> 但在鼓捣的同时，出于某些原因我重新生成了一个新的恢复密钥并添加了一个临时密码用来快速输入去测试其他解密方式。而新的恢复密钥则和旧的一样放到了 keepass 数据库里</p> <p>然后就是…</p> <ul> <li>我觉得这可以</li> <li>试一下，不可以</li> <li>这样肯定可以了，唉。顺便删掉临时密码，毕竟还要重启一次好麻烦</li> <li>诶，怎么还是不行</li> <li>…恢复密钥</li> </ul> <p>所以恢复密钥会在哪里呢？</p> <p>当当当当，只有加密分区里有最新的版本。<br/> 同步系统的冗余失效了，其它冷备份在需要最新数据的场景下也显得相当无力。面对64个随机字符的恢复密钥，唯一的选择只有删除分区</p> <h2 id="cpu-pbo-配置的问题">CPU PBO 配置的问题？</h2> <p>之后在准备装新系统的时候打算把电脑里的 windows 和 linux 都重装一下，前者已经因为 bug 更新不了了，后者已经消失了嘛</p> <p>但这时突然发现 windows 的安装过程一切顺利，但另一边新选的 Fedora 在用 btrfs 时安装会报错，而且是和 Arch 下一模一样的问题：”Truncated tar archive”<br/> Fedora 作为 Red Hat 系列发行版的最上游，虽然发布节奏超快但发行版自身的组件相当稳定，就像 Ubuntu 非 LTS 那样。第二次重试安装后，安装时报错的包名甚至不一样了。到这里我才意识到，原来问题的根源来自硬件</p> <p>想要 debug 最好的入手点就是找找我改过什么。AMD CPU 的 PBO 机制和 Intel 的睿频类似，只是可以更加细致的控制怎么提升频率，电压和频率的关系是怎么样的。<br/> 其中有个功能叫做 Curve Optimizer，一般用来欠压超频用，可以稍微省点电。这个值应该只是计算公式中的一部分，根据之前的测试，我的个这台电脑的设置是全核心 -20。但经过这件事后我就去找了正经工具测试了一下稳定性：<a href="https://github.com/sp00n/CoreCycler">sp00n/CoreCycler</a></p> <p>结果反复测试发现，整个 CPU 只有一个核心的体制甚至不能支撑到 -10 的欠压，但其它核心都能跑在 -20 以下。<br/> 由于我之前给这颗体制很烂的核心也设置了 -20。在实际场景中就导致了只要有极重负载的计算落到这颗核心上持续的时间只要长过5秒就一定会返回错误结果。有一个场景很符合这种“极重负载”，加密和压缩，dm-crypt 和 btrfs 的 zstd 压缩全都占了。<br/> 可能这也是为什么之前小批量更新软件就不会出问题吧，负载分摊到这颗烂核心上的概率稍微小一些，而且即使有持续时间也不长</p> <h2 id="那现在怎么样了呢">那现在怎么样了呢</h2> <p>咕咕了很多天后，所有的事情都在被逐一解决。先是在本地常开的小服务器上跑了 syncthing 的节点，这样只要设备在家里就99%可以同步数据。加上之前给其它服务们用的 tailscale 网络，即使不在家里同步机会也相当的多</p> <p>另外也在其它方面上改变了对待各种长期不变的“密钥”类数据的备份方式，不在依赖于单一备份手段了。更何况这个“备份”手段主打的功能是“同步”呢，意义上就不一样</p> <p>最后就是把主力机从 Arch Linux 换成了 Fedora，我真的不知道这是不是个正确的决定，但… 我喜欢系统，不代表要天天被系统玩弄做那些学不到新东西的事情。Arch 教会了我超多的知识，但当明白了之后剩下的恼人成分反而侵蚀了日常。<br/> 不过 Arch 以后还是会在某些地方用的啦，我对系统的看法真的相当因地制宜233</p> <p>终于…<br/> 可以清静一阵子了么</p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2025"/><summary type="html"><![CDATA[很多时候数据的丢失不光是由一个事情出了错引起的，而是由一连串的诱因共同导致。 不过最近我把自己的一个加密 root 系统分区搞坏了，所以无论如何至少我又多了一个理由来 blog 上写东西233]]></summary></entry><entry xml:lang="zh-Hans"><title type="html">Linux 上不同类型的只读访问</title><link href="https://sourlemonjuice.github.io/posts2/2025/09/linux-readonlys" rel="alternate" type="text/html" title="Linux 上不同类型的只读访问"/><published>2025-09-17T05:51:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2025/09/linux-readonlys</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2025/09/linux-readonlys"><![CDATA[<p>“只读”这一特性在所有系统上都作为一种控制软件和用户访问文件系统的功能。这篇文章大概会简短的说一说我认识的 Linux 下的“只读/read-only”意味着些什么</p> <h2 id="posix-文件系统权限">POSIX 文件系统权限</h2> <p>一般来说只读的英文全称 read-only 会在很多地方简化为 <code class="language-plaintext highlighter-rouge">ro</code>，对应的反义词是 read-write 简写是 <code class="language-plaintext highlighter-rouge">rw</code></p> <p>POSIX 文件系统作为最常见的权限系统存在于几乎所有 Unix 系统上，你可以用 <code class="language-plaintext highlighter-rouge">ls -l &lt;filename&gt;</code> 查看到相应文件的权限：</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ll
total 4.0K
drwx------  2 root root  60 Sep 17 04:32 ./
drwx------ 34 root root   0 Sep 17 04:32 ../
-rw-r--r--  1 root root  10 Sep 17 04:32 filename
</code></pre></div></div> <p>最下面的文件 <code class="language-plaintext highlighter-rouge">filename</code> 就是例子，在那一行最左边的元素 <code class="language-plaintext highlighter-rouge">-rw-r--r--</code> 就是它的权限：</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-     |rw-    |r--    |r--  |
type  |owner  |group  |other|
</code></pre></div></div> <p>Type 意味着这个文件是一个普通的文件而不是文件夹或者硬件设备。Owner 权限表示它的所有者对这个文件可读可写，Group 权限表示文件对它所属的组仅可读，Other 权限表示除此之外的所有人对它都仅可读</p> <p>这里的场景也可能变成这样子：</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-     |rwx    |rwx    |rwx  |
type  |owner  |group  |other|
</code></pre></div></div> <p>这样，无论是所有者还是文件所属的组还是其他人都可以读写这个文件，并且如果这个文件是可执行文件，无论是二进制文件还是脚本，所有人都有权限执行它。比如：<code class="language-plaintext highlighter-rouge">$ ./filename</code></p> <p>开头的 type，也可能是 <code class="language-plaintext highlighter-rouge">d</code> 表示目录（directory），或者 <code class="language-plaintext highlighter-rouge">b</code> 表示块设备（block）比如 <code class="language-plaintext highlighter-rouge">/dev/sda</code> 这块硬盘就是一个块设备。<br/> 另外目录“文件”必须要有可执行权限，也就是 <code class="language-plaintext highlighter-rouge">rwx</code> 中的 <code class="language-plaintext highlighter-rouge">x</code> 才能被进入，比如命令 cd。所以在 <code class="language-plaintext highlighter-rouge">drw-rw-rw-</code> 的情况下，所有人都可以修改这个文件夹本身的名字，但谁都不能进去看到里面的内容</p> <p>更改文件权限可以用命令 chmod 实现，不过方式有很多种可能类似与下面这些形式：</p> <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">chmod </span>700 <span class="nb">dirname
chmod </span>o-rwx <span class="nb">dirname
chmod </span>644 filename
<span class="nb">chmod </span>a-w filename
</code></pre></div></div> <p>如果有需要的话一个权限为 <code class="language-plaintext highlighter-rouge">----------</code> 的文件也是可以存在的（<code class="language-plaintext highlighter-rouge">chmod 000 filename</code>），不过除了 root 以外没人能直接读写就是了。而且所有者也可以随时把权限改成别的状态再进行读写</p> <p>另外，如果你知道的话 suid 和 guid 这种东西也归这里管。好了，就说这么多</p> <h2 id="文件属性attributes">文件属性/Attributes</h2> <p>这是个我很陌生的领域，因为日常场景中基本完全不需要它。我上次见他还是在 btrfs，有一个属性可以去关闭某个文件的 CoW（写时复制）功能</p> <p>想要查看当前文件拥有的属性可以用命令 lsattr，它和 ls 很像，但每一行最前面的条条变长了好多…<br/> 设置或者更改属性可以用命令 chattr，它类似于 chmod，一般来说整个命令可能看起来像这样子：<code class="language-plaintext highlighter-rouge">chattr +i filename</code></p> <p>和 read-only 相关的属性就是 <code class="language-plaintext highlighter-rouge">i</code>，他的介绍是这样的：</p> <blockquote> <p>A file with the ‘i’ attribute cannot be modified: it cannot be deleted or renamed, no link can be created to this file, most of the file’s metadata can not be modified, and the file can not be opened in write mode. Only the superuser or a process possessing the CAP_LINUX_IMMUTABLE capability can set or clear this attribute.<br/> 具有’i’属性的文件不可修改：无法删除或重命名该文件，无法创建指向该文件的链接，文件的大部分元数据不可修改，且无法以写入模式打开该文件。仅超级用户或拥有CAP_LINUX_IMMUTABLE能力的进程可设置或清除此属性。—— Deepl.com free</p> </blockquote> <p>大概是 immutable/不可变 的意思。<br/> 设置了这个属性的文件或者文件夹即使是所有者在也不能修改一点内容，而且即使是 root 也需要先动用特权删除这一属性才能修改内容：<code class="language-plaintext highlighter-rouge">chattr -i filename</code></p> <p>添加了属性后在看 lsattr 会看起来像这样：</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ lsattr
----i----------------- ./filename
</code></pre></div></div> <h2 id="文件系统挂载选项">文件系统挂载选项</h2> <p>在 /etc/fstab 里写文件系统的配置时，还有 <code class="language-plaintext highlighter-rouge">mount -o &lt;options&gt;</code> 时都可以指定一系列的挂载选项。用的最多的选项合集 <code class="language-plaintext highlighter-rouge">defaults</code> 中就包含了一个 <code class="language-plaintext highlighter-rouge">rw</code> 选项。与之对应的，你也可以在挂载时补上一个 <code class="language-plaintext highlighter-rouge">ro</code> 来在文件系统层面上禁止所有账户和软件的写入操作，甚至完全包括 root</p> <p>另一个好玩的选项是 <code class="language-plaintext highlighter-rouge">umask=XXXX</code>，它和命令 umask 类似都是用来指定文件权限的掩码，但命令 umask 是应用于当前的终端登陆中创建的文件的，而 <code class="language-plaintext highlighter-rouge">umask=XXXX</code> 挂载选项则是应用在了整个文件系统上。<br/> 比如为 /boot 分区的挂载指定 <code class="language-plaintext highlighter-rouge">umask=0077</code> 就可以完全屏蔽掉所有原先存在的所有者以外的任何权限。权限列表也会变成 <code class="language-plaintext highlighter-rouge">-rwx------</code></p> <p>有一个可能的限制方式是挂载一个类型为 bind 的“文件系统”，它会将一个路径绑定到挂载点上，在这个过程中就可以加上一些挂载选项来做些什么。<br/> 比如：</p> <div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount <span class="nt">--bind</span> <span class="nt">-o</span> <span class="s2">"ro"</span> /path/dir /path/dir
</code></pre></div></div> <p>虽然两次路径一样，但由于新加入的挂载选项也让 /path/dir 这个目录变为了文件系统级别的只读</p> <p>关于挂载选项什么的，还有些比较有用的选项比如 <code class="language-plaintext highlighter-rouge">noexec</code>，<code class="language-plaintext highlighter-rouge">nodev</code>，<code class="language-plaintext highlighter-rouge">nosuid</code>。分别能在文件执行时阻止它，禁止出现特殊的设备文件，和禁止出现 suid 可执行文件</p> <h2 id="文件系统错误">文件系统错误</h2> <p>这是个听上去很危险的话题（事实上也是）。<br/> 一些文件系统的实现在发现磁盘上出现了自己无法处理的错误时，会触发一定的保护机制将挂载选项里的 <code class="language-plaintext highlighter-rouge">rw</code> 改成 <code class="language-plaintext highlighter-rouge">ro</code>，并拒绝执行任何更多的写入操作。btrfs 就是一个例子，因为我没遇到过 ext4 出问题过（什（怎么感觉是讽刺</p> <p>一般来说重启后内核模块都会重置，文件系统会重新可写，但一定一定要在出问题后运行一次对应文件系统的检查功能。不然数据可能在过一段时间真的会消失（大概吧，也可能什么都不会发生233</p> <h2 id="eof">EOF</h2> <p>虽然不知道为什么，但是突发奇想花了一个小时面无表情的写了这篇东西。校对很少，所以，谢谢你能看到这里awa</p> <h2 id="thanks-for">Thanks for</h2> <ul> <li><a href="https://man.archlinux.org/man/chmod.1.en">chmod(1) — Arch manual pages</a></li> <li><a href="https://man.archlinux.org/man/chattr.1.en">chattr(1) — Arch manual pages</a></li> <li><a href="https://wiki.archlinux.org/title/File_permissions_and_attributes#File_attributes">File permissions and attributes - ArchWiki</a></li> <li><a href="https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/global_file_system_2/s1-manage-pathnames">4.12. Bind Mounts and Context-Dependent Path Names - Global File System 2 - Red Hat Enterprise Linux - 6 - Red Hat Documentation</a></li> <li><a href="https://serverfault.com/a/547240/1244499">linux - Explanation of nodev and nosuid in fstab - Server Fault</a></li> </ul> <p>Jekyll 的 markdown 解析器把 Red Hat 链接里的 <code class="language-plaintext highlighter-rouge">|</code> 解析成表格了…<br/> 所以手动换成 <code class="language-plaintext highlighter-rouge">-</code> 咯，抱怨一下</p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2025"/><summary type="html"><![CDATA[“只读”这一特性在所有系统上都作为一种控制软件和用户访问文件系统的功能。这篇文章大概会简短的说一说我认识的 Linux 下的“只读/read-only”意味着些什么]]></summary></entry><entry xml:lang="en"><title type="html">Linux x86 bootloader and TPM2 policy disk encryption explanation</title><link href="https://sourlemonjuice.github.io/posts2/2025/08/linux-x86-bootloader-and-tpm2" rel="alternate" type="text/html" title="Linux x86 bootloader and TPM2 policy disk encryption explanation"/><published>2025-08-04T16:15:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2025/08/linux-x86-bootloader-and-tpm2</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2025/08/linux-x86-bootloader-and-tpm2"><![CDATA[<p>In regular Linux x86 distro, GRUB by GNU is still being the default bootloader. Personally, I don’t like GNU’s overall style, but no matter what as time changes, the latest boot method UKI(Unified Kernel Image) is the future.</p> <p>It’s not a full tutorial, but an overall concept explanation with many examples you need.</p> <h2 id="basic-history-about-bootloader">Basic history about bootloader</h2> <p>Installing the bootloader in Arch Linux is always the first difficult and complex step that user encounter. But still under control, the beginners just need to run a few commands to get a GRUB install:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># root</span>
grub-install <span class="nt">--target</span><span class="o">=</span>x86_64-efi <span class="nt">--efi-directory</span><span class="o">=</span>/boot <span class="nt">--bootloader-id</span><span class="o">=</span>GRUB
grub-mkconfig <span class="nt">-o</span> /boot/grub/grub.cfg
</code></pre></div></div> <p>After installation, each time GRUB’s EFI entry is running, it will combine the microcode, initramfs and the kernel image at runtime.<br/> Those file archive images are stored in EFI system partition(ESP), that’s <code class="language-plaintext highlighter-rouge">/boot</code> in the filesystem.</p> <p>So where do those archives come from?<br/> The <em>kernel</em> file is a binary executable that’s downloaded from package manager, which is usually named <code class="language-plaintext highlighter-rouge">vmlinuz-linux</code>. The <em>microcode</em> is the same, but named <code class="language-plaintext highlighter-rouge">*-ucode.img</code>(e.g. <code class="language-plaintext highlighter-rouge">amd-ucode.img</code>).<br/> But the <em><a href="https://wiki.archlinux.org/title/Arch_boot_process#initramfs">initramfs</a></em> wouldn’t appear out of the air. It actually is a <a href="https://en.wikipedia.org/wiki/Cpio">cpio</a> archive that contains the basic kernel modules and the essential support files to help the kernel prepare the entire filesystem tree, then switch root into the real filesystem that’s placed on real drives.</p> <h3 id="about-initramfs">About initramfs</h3> <p>In Arch Linux, the <em>initramfs</em> is generated by <a href="https://wiki.archlinux.org/title/Mkinitcpio">Mkinitcpio</a>(whisper: because they made this). The other alternatives are <a href="https://wiki.archlinux.org/title/Dracut">Dracut</a> and <a href="https://wiki.archlinux.org/title/Booster">Booster</a>(Though I never used booster at all).<br/> Anyway, the dracut is a popular solution for other distributions like Fedora, I also use it personally.</p> <p>In addition, microcode is usually packaged in initramfs. The difference between can be found here: <a href="https://wiki.archlinux.org/title/Microcode#Microcode_initramfs_packed_together_with_the_main_initramfs_in_one_file">ArchWiki Microcode</a><br/> Some initramfs generator will package them automatically, so you probably don’t need worry about microcode in the later part.</p> <h3 id="about-boot-manager">About boot manager</h3> <p>Remember, the initramfs is just a <strong>filesystem archive</strong>, they are <strong>not executable</strong>. The real software that start from UEFI(or BIOS?) can be called <em>“bootloader”</em>, but many of them have a select menu and a kernel parameters editor, so they also can be called <em>“boot manager”</em>.<br/> GRUB is an extremely popular and common software for this purpose, almost all the distributions use it, except Arch Linux is uses <a href="https://wiki.archlinux.org/title/Systemd-boot">systemd-boot</a>. Considering its some auto-discover features, we will also use it later in some non-traditional way.</p> <p>As an example, my dracut configuration is this:</p> <div class="language-conf highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># /etc/dracut.conf.d/&lt;any_filename&gt;.conf
# the world best compression algorithms.
</span><span class="n">compress</span>=<span class="s2">"zstd"</span>
<span class="c"># some essential modules for following steps, I'm not sure.
</span><span class="n">add_dracutmodules</span>+=<span class="s2">" systemd resume crypt tpm2-tss "</span>
<span class="c"># cause bugs on my machine, but may not on yours.
</span><span class="n">omit_dracutmodules</span>+=<span class="s2">" brltty "</span>
</code></pre></div></div> <p>You can call it manually, but I will use kernel-install to call it automatically which I’ll explain later.</p> <h3 id="about-stub">About stub</h3> <p>There is a last thing may cause some confusing: <em>stub</em><br/> It’s kind a filler between UEFI and kernel. So if you want, boot the kernel image just from firmware setup menu directly isn’t impossible. Don’t try it yourself, unhealthy for mind…</p> <h2 id="ukiunified-kernel-image">UKI(Unified Kernel Image)</h2> <p>After finishing the classic method, let’s talk about <em>Unified Kernel Image(UKI)</em>.<br/> Systemd’s UKI is basically around the <em><a href="https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html">systemd-stub</a></em>, it’s a stub that we previously talked about. But the special point is it will lookup the resources that kernel needs from its executable binary section self, like kernel command line parameters, kernel binary and initramfs.</p> <p>The systemd-stub is just a bunch of support files and a format spec, the generator of this format by systemd is <em><a href="https://www.freedesktop.org/software/systemd/man/latest/ukify.html">systemd-ukify</a></em>.</p> <p>It’s a command line focused software, it feels like designed for command but added config file support later.<br/> I didn’t use it individually, but with another systemd tiny script util: <a href="https://wiki.archlinux.org/title/Kernel-install">kernel-install</a>. It can help me get some kernel ver staff automatically and call ukify.<br/> It sounds like a lot of stuff here, but the basic configuration and the usage are very simple:</p> <div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># /etc/kernel/install.conf
</span><span class="py">layout</span><span class="p">=</span><span class="s">uki</span>
<span class="py">initrd_generator</span><span class="p">=</span><span class="s">dracut</span>
<span class="py">uki_generator</span><span class="p">=</span><span class="s">ukify</span>
</code></pre></div></div> <div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># /etc/kernel/uki.conf
# basic configuration doesn't need any content in this file
# but if you want... add a splash image are also great (O-O)
</span><span class="nn">[UKI]</span><span class="w">
</span><span class="py">Splash</span><span class="p">=</span><span class="s">/usr/share/systemd/bootctl/splash-arch.bmp</span>
</code></pre></div></div> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code># /etc/kernel/cmdline
# put your command line parameters here. for example:
ro quiet splash
</code></pre></div></div> <p>Then run this to install all the kernel versions with UKI format:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># root</span>
kernel-install add-all
</code></pre></div></div> <p>It will auto-discover the ESP mount point(e.g. /boot) and output the <code class="language-plaintext highlighter-rouge">.efi</code> file in <code class="language-plaintext highlighter-rouge">/boot/EFI/Linux/</code> directory. It maybe named <code class="language-plaintext highlighter-rouge">&lt;random_id&gt;-6.15.8-arch1-2.efi</code>.</p> <p>Now you have two options to boot this efi file with UEFI firmware:</p> <ol> <li>Fix the filename, and add a UEFI boot entry manually(via <em>efibootmgr</em>?) then boot it directly from firmware.</li> <li>Install another boot manager, dynamically search all available efi files then chain-loading them. You will also get a selection menu as a bonus. (o-o)</li> </ol> <p>They are both ok, and I tried both of them for a long time.</p> <blockquote> <p>By the way, the <code class="language-plaintext highlighter-rouge">.efi</code> file is actually a PE format executable, just like Windows(because Microsoft is the leader of UEFI).</p> </blockquote> <p>However, not only ukify can generate UKI. Like dracut can also do it, I used it for a long time in the past too, but more complex then ukify.</p> <h2 id="systemd-boot">systemd-boot</h2> <p><em><a href="https://wiki.archlinux.org/title/Systemd-boot">systemd-boot</a></em> is a UEFI boot manager, it’s mainly used to chain-loading other efi files.<br/> It doesn’t require much configuration, it will find common efi files with itself and show them up in the selection menu(like Windows Boot Manager or /boot/EFI/Linux/*.efi).</p> <p>Run this command to install it, but notice it won’t be auto update by default:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># root</span>
bootctl <span class="nb">install</span>
</code></pre></div></div> <p>It will generate some stuff in /boot/loader/, don’t care.</p> <p>Ok, those are all the knowledge you and me should know, time to switch_topic<del>.service</del> to <strong>TPM2</strong>.</p> <blockquote> <p>The last <code class="language-plaintext highlighter-rouge">.service</code> runs in initramfs named <code class="language-plaintext highlighter-rouge">switch_root.service</code></p> </blockquote> <h2 id="pcrplatform-configuration-registers">PCR(Platform Configuration Registers)</h2> <p>I need to say it is a meaningless term, we can clearly call it “TPM2 Registers”.</p> <p>The <em>PCR</em> is the most important part of TPM2, which <strong>measures</strong> the platform state and reflects the states into those registers.<br/> Now, only <em>PCR 0-15</em> has been used, and the <em>PCR 0-7</em> are controlled by platform firmware. For example, the <em>PCR 0</em> means: “Core system firmware executable code”.<br/> A full reference: <a href="https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/">Linux TPM PCR Registry</a></p> <p>As for the <em>PCR 11</em>, this register is used by <em>systemd</em>. The <em>systemd-stub</em> and <em>systemd-pcrphase</em> will continually extend this register in the whole boot process.</p> <ul> <li>PCR 11 will be reset to 0 when platform power on.</li> <li><em><a href="https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html">systemd-stub</a></em> will measure the bootloader(including kernel) info before the kernel starts.</li> <li><em><a href="https://www.freedesktop.org/software/systemd/man/latest/systemd-pcrphase.service.html">systemd-pcrphase</a></em> just like its name, contains multiple services that build many barriers to separate the PCR 11’s value in each boot state.</li> </ul> <p>Due to the way TPM2 works, the value in PCR are inreversible, so theoretically we can restrict some action to <strong>only</strong> happen in a specific boot phase.<br/> (even though I didn’t understand this part now, more documents please qwq)</p> <h2 id="ukify-pcr-signatures">Ukify PCR signatures</h2> <p>An important tool made by systemd is <a href="https://www.freedesktop.org/software/systemd/man/latest/systemd-measure.html">systemd-measure</a>. When generating UKI, this tool is designed for reproduce what the things that systemd-stub and systemd-pcrphase will do with PCR 11 at next time they are started. Unlike PCR 0-7, this is possible because PCR 11 is only related to systemd components in UKI.</p> <p>It also can sign that PCR 11’s value with a pre-generated <strong>asymmetric encryption</strong> private key, other application can verify these signature later.<br/> You can run these commands to generate a key pair into the default path:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># root</span>
ukify genkey <span class="se">\</span>
    <span class="nt">--pcr-private-key</span> /etc/systemd/tpm2-pcr-private-key.pem <span class="se">\</span>
    <span class="nt">--pcr-public-key</span> /etc/systemd/tpm2-pcr-public-key.pem
</code></pre></div></div> <p>To use this key pair, there’s some configuration need to be added to the ukify config file:</p> <div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># /etc/kernel/uki.conf
</span><span class="w">
</span><span class="c"># &lt;previous content&gt;
</span><span class="nn">[PCRSignature:default]</span><span class="w">
</span><span class="py">PCRPrivateKey</span><span class="p">=</span><span class="s">/etc/systemd/tpm2-pcr-private-key.pem</span>
<span class="py">PCRPublicKey</span><span class="p">=</span><span class="s">/etc/systemd/tpm2-pcr-public-key.pem</span>
</code></pre></div></div> <p>After generated a key pair. When next time ukify generating UKI image it will call systemd-measure to pre-calculate the PCR 11, and sign the value by above cert pair then insert the signatures into <code class="language-plaintext highlighter-rouge">.pcrsig</code> UKI executable section.<br/> The public key is also placed in executable section <code class="language-plaintext highlighter-rouge">.pcrpkey</code>. With these two section, the application now can ensure the bootloader has not been tampered with.</p> <p>You can check all the sections content with <code class="language-plaintext highlighter-rouge">ukify inspect &lt;UKI path&gt;</code>.</p> <hr/> <p>I don’t know what the <code class="language-plaintext highlighter-rouge">[PCRSignature:NAME]</code> means, but if don’t add a NAME here, everything will be wrong.<br/> The phases of signs can also be defined with: <code class="language-plaintext highlighter-rouge">Phases=enter-initrd</code>, but I don’t really know how to use them, just use the <a href="https://man.archlinux.org/man/ukify.1.en#%5BPCRSignature:%3Ci%3ENAME%3C/i%3E%5D_section">defaults</a>.</p> <h2 id="enroll-tpm2-policy-into-luks2-disk">Enroll TPM2 policy into LUKS2 disk</h2> <p>The <em>systemd-cryptenroll</em> can help us to setup decrypt method in systemd ecosystem.<br/> If you don’t know, you can use this following command to bind a inflexible PCR value into LUKS2 metadata:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># root</span>
systemd-cryptenroll <span class="nt">--tpm2-device</span><span class="o">=</span>auto /dev/&lt;block_device&gt;
</code></pre></div></div> <blockquote> <p>Also add a <code class="language-plaintext highlighter-rouge">--tpm2-with-pin=true</code> flag will blend a password(PIN) in the authorization process. TPM2 can even protect this PIN out of brute force attacks.</p> </blockquote> <p>Back to the <strong><a href="https://www.freedesktop.org/software/systemd/man/latest/systemd-cryptenroll.html#TPM2%20PCRs%20and%20policies">TPM2 policy</a></strong>. It can use PCR signature(PCR 11 only at here) and <strong>asymmetric encryption</strong> key pair above to calculate a secret to encrypt/decrypt LUKS2 disks. With this method, the secrets are no longer bound to a <strong>specific set</strong> of PCR values, instead the trust chain transferred to a proof that the bootloader has not been modified.<br/> To be fair, we always bound the <em>PCR 7(SecureBoot state)</em> as the LUKS2 secret to verify bootloader previously, so we are still doing the same things.</p> <p>In Arch Linux, each bootloader file are generated in user’s environment self, but in many case the distribution can generate their own key pair and share the public key to the users. This is telling users their bootloader has not been modified and works properly until the decrypt moment.<br/> (I don’t know who really did this at now, it’s a cutting-edge feature of systemd :|)</p> <p>To use this TPM2 policy, you can use these following flags of systemd-cryptenroll:</p> <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># root</span>
systemd-cryptenroll <span class="nt">--tpm2-device</span><span class="o">=</span>auto <span class="nt">--tpm2-pcrs</span><span class="o">=</span><span class="s2">""</span> <span class="nt">--tpm2-public-key</span><span class="o">=</span>/etc/systemd/tpm2-pcr-public-key.pem /dev/&lt;block_device&gt;
</code></pre></div></div> <p>Emm… you can see the man page online: <a href="https://www.freedesktop.org/software/systemd/man/latest/systemd-cryptenroll.html#--tpm2-public-key=PATH">systemd-cryptenroll</a></p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>--tpm2-public-key=PATH, --tpm2-public-key-pcrs=PCR[+PCR...], --tpm2-signature=PATH
</code></pre></div></div> <p>If you don’t add <code class="language-plaintext highlighter-rouge">--tpm2-public-key</code>, it still will search file <code class="language-plaintext highlighter-rouge">tpm2-pcr-public-key.pem</code> in some directories by default.<br/> And you maybe seen the <code class="language-plaintext highlighter-rouge">--tpm2-public-key-pcrs</code> flag looks so attractive, can I also bind a PCR value together with the TPM2 policy? No, it’s just an option to declare which PCR are signed, but the systemd-measure will only calculate and sign PCR 11, so it’s maybe useless now.<br/> A TPM2 PIN is still recommended.</p> <p>After enroll, you can try to close and reopen your LUKS2 disk. Since the secret is independent of the PCR’s value, feel free to turn off and on secure boot as a revenge. awa</p> <h2 id="thanks-for">Thanks for</h2> <ul> <li>all the manual/wiki links</li> <li><a href="https://itm4n.github.io/tpm-based-bitlocker/">A Deep Dive into TPM-based BitLocker Drive Encryption - itm4n’s blog</a></li> <li><a href="https://neodyme.io/en/blog/bitlocker_why_no_fix/">On Secure Boot, TPMs, SBAT, and downgrades – Why Microsoft hasn’t fixed BitLocker yet — Neodyme</a></li> </ul> <h2 id="end">End</h2> <p>Now I have finally said everything I want to say. It’s not my native language, and also had to reference many manuals. Tired works, it took me about two days.<br/> But I got a new blog post for August now. Yeah, one month peace(or maybe two months).</p> <p>It’s doesn’t matter, but still thank you, systemd. <code class="language-plaintext highlighter-rouge">d(d＇∀＇)</code></p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2025"/><category term="Featured"/><summary type="html"><![CDATA[In regular Linux x86 distro, GRUB by GNU is still being the default bootloader. Personally, I don’t like GNU’s overall style, but no matter what as time changes, the latest boot method UKI(Unified Kernel Image) is the future.]]></summary></entry><entry xml:lang="en"><title type="html">June 2025: Getting more real</title><link href="https://sourlemonjuice.github.io/posts2/2025/07/june-getting-more-real" rel="alternate" type="text/html" title="June 2025: Getting more real"/><published>2025-07-01T02:37:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2025/07/june-getting-more-real</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2025/07/june-getting-more-real"><![CDATA[<p>In the whole 2025 I’m always trying to be more outside. Meet more strangers and feel more fleeting gazes.<br/> Maybe I’m already get ready for more long travels? I really want to meet more friends in the different cities. Can I really do it?</p> <p>Whisper: <em>someone said I’m cute ^=^</em></p> <h2 id="on-designs">On designs</h2> <p>After Google’s <a href="https://youtu.be/n17dnMChX14">Material Design 3 Expressive</a>, Apple released their new design system <a href="https://www.apple.com/newsroom/2025/06/apple-introduces-a-delightful-and-elegant-new-software-design/">Liquid Glass</a>. Now the whole world is shifting to using more and more glass effects. But people(customers) love glass, so I accept this fed.<br/> But overall, they are all way better than linux desktops. qwq</p> <p>Emm, another thing is that Nothing(a company name) will release a new flagship android phone: Phone (3)<br/> It will not released until July, so now there’s nothing fun to talk about.</p> <p>Speaking of Nothing, I switched my system and editor fonts recently.<br/> For monospace font the choice is still <a href="https://monaspace.githubnext.com">Monaspace(by GitHub Next)</a> but using different family: <code class="language-plaintext highlighter-rouge">Argon</code> -&gt; <code class="language-plaintext highlighter-rouge">Xenon</code>. Also means sans-serif to serif.<br/> I’m discovering serif font recently. Nothing is famous precisely because their graph and hardware designs, why not use their font directly? For that I find this repository: <a href="https://github.com/Yokilleurs/NothingFonts">Yokilleurs/NothingFonts</a>.</p> <p>But be honest, unlike my previous choice Google Sans, their fonts are not quite so generic. So compact, so artistic. The system UI font still required sans-serif fonts.<br/> But I used NType Mono for my window title. That doesn’t matter, dose it? Reasonable sacrifice for art:</p> <p><img src="https://sourlemonjuice.github.io/static/asset/2025-07-01-june-getting-more-real/images/20250701_033411.jpg" alt=""/></p> <p>I think that’s all.</p> <h2 id="development">Development</h2> <p>In June 2025, I only created 23 commits on github. I haven’t focused on programming since April.<br/> However, Now I have a long-standing repository of my solutions to algorithm problems: <a href="https://github.com/SourLemonJuice/algorithm-problems-archive">SourLemonJuice/algorithm-problems-archive</a>.</p> <h2 id="games">Games</h2> <p>I didn’t spend too much time on gaming, but I did want to finish OneShot in July.</p> <p>One big change is about Heroic Games Launcher, a great manager for linux gaming. I migrated all my “Non-Steam Game” to Heroic, easy to open winecfg, explicit wine prefix path. That’s way more useful.</p> <blockquote> <p>“Non-Steam Game” referred to pirated games, but it also covered regular windows apps(e.g. NetEase Cloud Music).</p> </blockquote> <p>And… I finally switched my Steam UI language to English. :)<br/> I’m really concerned about cultural issues… The publisher set up the different marketing materials for each language zone, even some game covers are also different.<br/> I… don’t know.</p> <h2 id="ending">Ending</h2> <p>I missed someone’s invitation and let their down. I’m sorry for that, if you can see this.<br/> Maybe I should plan for only next two weeks?</p> <p>Even though the pride month has ended, I think I’ll still keep that rainbow emoji on some of my messaging platforms.<br/> Why not, especially at today.</p> <p>EOF</p>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2025"/><summary type="html"><![CDATA[In the whole 2025 I’m always trying to be more outside. Meet more strangers and feel more fleeting gazes. Maybe I’m already get ready for more long travels? I really want to meet more friends in the different cities. Can I really do it?]]></summary></entry><entry xml:lang="en"><title type="html">Minecraft Playtime Command Block</title><link href="https://sourlemonjuice.github.io/posts2/2025/05/mc-playtime" rel="alternate" type="text/html" title="Minecraft Playtime Command Block"/><published>2025-05-08T03:55:00+08:00</published><updated>2026-04-05T15:16:06+08:00</updated><id>https://sourlemonjuice.github.io/posts2/2025/05/mc-playtime</id><content type="html" xml:base="https://sourlemonjuice.github.io/posts2/2025/05/mc-playtime"><![CDATA[<p>A set of commandblock to track player’s online time, storage as minutes, display using custom unit.</p> <h2 id="command-block-code-and-structure">Command Block Code and Structure</h2> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[repeating]
execute as @a if score @s playtime_ticks matches 1200.. run scoreboard players add @s playtime_minutes 1
[chain]
execute as @a if score @s playtime_ticks matches 1200.. run scoreboard players set @s playtime_ticks 0

[chain]
scoreboard players set @a kPlaytimeDisplayDivisor 60
[chain]
execute as @a run scoreboard players operation @s playtime_display = @s playtime_minutes
[chain]
execute as @a run scoreboard players operation @s playtime_display /= @s kPlaytimeDisplayDivisor
</code></pre></div></div> <blockquote> <p>NOTE:<br/> Please point the previous block to the next one properly.</p> </blockquote> <blockquote> <p>WARNING:<br/> The <code class="language-plaintext highlighter-rouge">score @s playtime_ticks matches 1200..</code> part must use <code class="language-plaintext highlighter-rouge">1200..</code>(score greater than 1200) as the condition because the chain block needs 1 tick to pass the signal to the next block.<br/> Not doing so will cause a lot of bugs.</p> </blockquote> <p>The scoreboard objective <code class="language-plaintext highlighter-rouge">playtime_ticks</code> is a temporary variable of the structure, the real playtime storage in <code class="language-plaintext highlighter-rouge">playtime_minutes</code>.</p> <p>The minute is the smallest unit that can be recorded here, but we usually don’t want to display them directly, that would be too long.<br/> So the second part of the code is used to calculate objective <code class="language-plaintext highlighter-rouge">playtime_display</code> by <code class="language-plaintext highlighter-rouge">playtime_minutes / kPlaytimeDisplayDivisor</code>. As an example in the code, the <code class="language-plaintext highlighter-rouge">kPlaytimeDisplayDivisor</code> is 60, which means the display unit is one hour.<br/> Same thing, 120 is two hours.</p> <h2 id="show-to-users">Show to users</h2> <p>Type this command to display this objective in sidebar:</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/scoreboard objectives setdisplay sidebar playtime_display
</code></pre></div></div> <h2 id="see-also">See also</h2> <ul> <li><a href="https://minecraft.wiki/w/Command_Block">Command Block – Minecraft Wiki</a></li> <li><a href="https://minecraft.wiki/w/Scoreboard">Scoreboard – Minecraft Wiki</a></li> <li>And some random YouTube videos :D</li> </ul>]]></content><author><name>酸柠檬猹/SourLemonJuice</name><email>SourLemonJuice233@outlook.com</email></author><category term="posts2"/><category term="2025"/><summary type="html"><![CDATA[A set of commandblock to track player’s online time, storage as minutes, display using custom unit.]]></summary></entry></feed>