<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on Ceba's Blog</title><link>https://blog.ceba.tech/post/</link><description>Recent content in Posts on Ceba's Blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 19 Sep 2025 02:00:00 +0800</lastBuildDate><atom:link href="https://blog.ceba.tech/post/index.xml" rel="self" type="application/rss+xml"/><item><title>新博客，新起点：Hugo + Stack</title><link>https://blog.ceba.tech/2025/09/new-blog-new-start-hugo-stack/</link><pubDate>Fri, 19 Sep 2025 02:00:00 +0800</pubDate><guid>https://blog.ceba.tech/2025/09/new-blog-new-start-hugo-stack/</guid><description>&lt;img src="https://blog.ceba.tech/2025/09/new-blog-new-start-hugo-stack/cover.png" alt="Featured image of post 新博客，新起点：Hugo + Stack" /&gt;&lt;p&gt;从 2018 年创建至今，这个博客已经陪伴了我 8 个年头，在这里我记录了不少折腾的过程和点滴感悟。随着时间的推移，当初选择的 Hexo 和 Material 主题已经渐渐显得过时了。于是，我想着能否换个新的模板和生成器，顺便调整一下网站部署，给这个博客寻找个新的起点。&lt;/p&gt;
&lt;h2 id="选择-stack-主题和-hugo"&gt;选择 Stack 主题和 Hugo
&lt;/h2&gt;&lt;p&gt;正如前面所提到的，hexo 和 hexo-theme-material 已经渐渐过时：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/iblh/hexo-theme-material" target="_blank" rel="noopener"
&gt;hexo-theme-material&lt;/a&gt; 的最后一个发行版 1.5.6 发布于在 2018 年，彼时 Google 的 Material 还能让人眼前一亮，到了今天就已经略显陈旧了&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hexo.io/" target="_blank" rel="noopener"
&gt;Hexo&lt;/a&gt; 本身版本演进速度十分缓慢，构建速度和扩展性也不尽人意，更何况 material 主题把 hexo 锁到了一个较早的版本上&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但是，找一个或者造一个美观好用的模板也不是那么容易的。打开各大生成器的主题列表，一眼望去全是些个人自用的、略显简陋的主题，大多缺乏活跃的用户群体和维护支持。我不是前端专家，对现代前端技术一窍不通，让我自己糊一个主题实在是强人所难。在经过一番筛选和对比后，我最终找到了 &lt;a class="link" href="https://cai.im/" target="_blank" rel="noopener"
&gt;Jimmy Cai&lt;/a&gt; 为 &lt;a class="link" href="https://gohugo.io/" target="_blank" rel="noopener"
&gt;Hugo&lt;/a&gt; 编写的 &lt;a class="link" href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener"
&gt;Stack 主题&lt;/a&gt;，这个主题的设计风格非常对我的胃口，简洁而又现代，功能上也能满足我的大多数要求，就它了。&lt;/p&gt;
&lt;p&gt;值得一提的是，Stack 主题对图片的支持非常强大，具备自动生成缩略图、响应式图片、懒加载等功能，还集成了 PhotoSwipe 插件，相比之前方便了不少。&lt;/p&gt;
&lt;p&gt;至于 Hugo，说实话我对网站生成器倒没有那么在意，是选择 Stack 导向了选择 Hugo。不过 Hugo 一直在积极开发中，速度快、功能强，也确实非常令人满意。&lt;/p&gt;
&lt;h2 id="适配和改造-stack"&gt;适配和改造 Stack
&lt;/h2&gt;&lt;p&gt;选定主题和生成器之后，就该把文章迁移过来了，还需要对 Stack 进行一些适配和改造。我是从 Stack 官方提供的 Starter 模板开始的，下面都是基于此的改造。&lt;/p&gt;
&lt;h3 id="文章目录迁移"&gt;文章目录迁移
&lt;/h3&gt;&lt;p&gt;Hugo 和 Hexo 的目录结构有一些差异，需要手动做一些处理。&lt;/p&gt;
&lt;p&gt;之前的 hexo 采用以下的格式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── source
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── _posts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── 2018
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ ├── The-Way-to-Go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ │── bg.jpg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ └── pic.png
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ ├── The-Way-to-Go.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;文章存放在 &lt;code&gt;source/_posts/&lt;/code&gt; 文件夹内，并且按年份分目录存放文章，如 &lt;code&gt;source/_posts/2018/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;每个文章 &lt;code&gt;article.md&lt;/code&gt; 都有一个同名的 &lt;code&gt;article/&lt;/code&gt; 文件夹，用来存放文章引用的图片等资源&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;讲道理，hexo 资源文件夹挺抽象的。在 Markdown 文件中引用图片时，要使用相对于资源文件夹的路径，而不是相对于 Markdown 文件的路径，这让人和 VSCode 都很难受。&lt;/p&gt;
&lt;p&gt;Hugo 和 Stack 采用以下的格式：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-plain" data-lang="plain"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── content
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── post
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── 2018
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ ├── The-Way-to-Go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ ├── bg.jpg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ ├── pic.png
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ │ │ └── index.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;文章存放在 &lt;code&gt;content/post/&lt;/code&gt; 文件夹内，可以按年份分目录存放文章，如 &lt;code&gt;content/post/2018/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;使用页面包（Page Bundles）格式，将文章内容 &lt;code&gt;index.md&lt;/code&gt; 和资源放在同一个文件夹内&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hugo 的目录结构似乎很自由，顶层节（Top-level Sections）和页面包之间的目录似乎可以随意田间，于是我直接沿用了之前按年份分组文章的结构。&lt;/p&gt;
&lt;h3 id="文章元数据迁移"&gt;文章元数据迁移
&lt;/h3&gt;&lt;p&gt;Hugo 和 Hexo 的 Markdown 元数据格式是非常相似的，无非都是些 &lt;code&gt;title&lt;/code&gt;、&lt;code&gt;tag&lt;/code&gt;、&lt;code&gt;categories&lt;/code&gt;、&lt;code&gt;date&lt;/code&gt;之类的，只有个别需要稍微调整一下格式即可。&lt;/p&gt;
&lt;p&gt;需要特别调整的主要是 Material 和 Stack 支持的文章头图功能，Material 用 &lt;code&gt;thumbnail&lt;/code&gt;，Stack 用 &lt;code&gt;image&lt;/code&gt;，而且相对路径格式略有不同，需要手动调整一下。另外，Stack 还支持一个 &lt;code&gt;description&lt;/code&gt; 字段，用来给文章加上副标题/描述。&lt;/p&gt;
&lt;h3 id="配置站点和主题"&gt;配置站点和主题
&lt;/h3&gt;&lt;p&gt;在 Stack Starter 模板的基础上调整一些 Hugo 的配置，以便适应使用习惯。Stack Starter 模板的配置用 TOML 格式编写，都放置在 &lt;code&gt;config/_default/&lt;/code&gt; 文件夹下。&lt;/p&gt;
&lt;p&gt;首先要调整的是文章永久链接的格式，需要想办法和原博客保持一致。在 &lt;code&gt;permalinks.toml&lt;/code&gt;文件（即 &lt;code&gt;[permalinks]&lt;/code&gt;）中设置如下的配置项。其中，&lt;code&gt;post&lt;/code&gt; 指顶层节，&lt;code&gt;:slugorcontentbasename&lt;/code&gt; 是元数据中的 slug 和 basename（文章所在文件夹的名字）二选一。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/:year/:month/:slugorcontentbasename/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;另外，Hugo 默认会把所有 URL 调整为小写，然而老博客中有不少文章是大小写混写的。在 &lt;code&gt;params.toml&lt;/code&gt; 文件（即 &lt;code&gt;[params]&lt;/code&gt;）中设置如下的配置项，关闭自动小写的功能。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;DisablePathToLower&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;之前博客的评论使用的是 &lt;a class="link" href="https://github.com/gitalk/gitalk" target="_blank" rel="noopener"
&gt;Gitalk&lt;/a&gt;，用 Github Issue 来充当评论区。这次切换到了 &lt;a class="link" href="https://giscus.app/" target="_blank" rel="noopener"
&gt;gitcus&lt;/a&gt;，改用 Github Disscussion 来充当评论区。通过 gitcus 的交互式工具获取参数，然后将参数填到对应的配置项即可。&lt;/p&gt;
&lt;p&gt;以及，调整一下语言、CJK 支持等配置，修改一下网站标题、头像、版权等信息，在页脚加入备案号等等。这些都相对比较简单，就不在赘述了。&lt;/p&gt;
&lt;p&gt;有一说一，TOML 格式真有点不是太习惯呢，各种嵌套关系让人眼花缭乱。Hugo 本身是支持 YAML、TOML、JSON 的，回头可能还是改回 YAML 吧。&lt;/p&gt;
&lt;h3 id="更换前端-cdn-资源"&gt;更换前端 CDN 资源
&lt;/h3&gt;&lt;p&gt;Stack 使用的外部 CDN 资源大多来自 JSDelivr，然而这玩意儿在国内的访问性实在是不怎么好，十分有必要换个靠谱的 CDN。&lt;/p&gt;
&lt;p&gt;我参考了 &lt;a class="link" href="https://blog.l3zc.com/2023/10/theme-stack-tweaks/" target="_blank" rel="noopener"
&gt;这篇文章&lt;/a&gt;，添加了 &lt;code&gt;data/external.yaml&lt;/code&gt;文件，通过 Hugo 的主题文件覆盖功能来修改调用的 CDN 资源。完整文件如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Vibrant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://cdnjs.cloudflare.com/ajax/libs/node-vibrant/3.1.6/vibrant.min.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;integrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sha256-awcR2jno4kI5X0zL8ex0vi2z+KMkF24hUW8WePSA9HM=&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;PhotoSwipe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;integrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sha256-ePwmChbbvXbsO02lbM3HoHbSHTHFAeChekF1xKJdleo=&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;integrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sha256-UKkzOn/w1mBxRmLLGrSeyB4e1xbrp4xylgAWb3M42pU=&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.min.css&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;style&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.css&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;style&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;KaTeX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;integrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;style&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;integrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/contrib/auto-render.min.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;integrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;defer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;Cactus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://latest.cactus.chat/cactus.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;integrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://latest.cactus.chat/style.css&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;integrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;style&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;现阶段，国内几乎没有靠谱的公共前端 CDN 库了，要么是因为被灰产滥用而被迫关闭，要么是之前出现过供应链投毒的事件。参考文章用的是 baomitu，然而它的主页已经被关闭很久了，看起来也不是很稳定。在多方考虑后，我最终选择了 cdnjs，由大慈善家 Cloudflare 托管，速度和可靠性都让人放心。&lt;/p&gt;
&lt;p&gt;此外，我并没有按照参考文章去掉用于校验文件完整性的 &lt;code&gt;integrity&lt;/code&gt; 字段。毕竟，供应链投毒是真发生过，而且 cdnjs 也支持这个特性。&lt;/p&gt;
&lt;h3 id="调整页面样式"&gt;调整页面样式
&lt;/h3&gt;&lt;p&gt;说是调整页面样式，实际上我只调整了一下背景颜色。Stack 原始的背景色是 &lt;code&gt;#f5f5fa&lt;/code&gt;，灰偏蓝，看起来有一些粉，我调整成了正灰色 &lt;code&gt;#f5f5f5&lt;/code&gt;。在文件 &lt;code&gt;assets/scss/custom.scss&lt;/code&gt; 中添加&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;--body-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;#f5f5f5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="部署到腾讯云-edgeone-pages"&gt;部署到腾讯云 EdgeOne Pages
&lt;/h2&gt;&lt;p&gt;因为我的网站已经做了备案，加上需要考虑国内访问的可用性，那就必须得考虑使用国内的云服务了。&lt;/p&gt;
&lt;p&gt;我的网站最初是用国内代码托管网站 Coding.net 提供的 Pages 服务，体验与 Github Pages 相差不大。但后来 Coding.net 被腾讯云收购，Pages 服务也经过几轮调整，最终被自动迁移到了腾讯云的 OSS 对象存储 + CDN 内容分发网络。&lt;/p&gt;
&lt;p&gt;一开始，腾讯云 OSS + CDN 的整体还是挺好的，代码推送到 coding.net 能自动部署到 OSS，一个月也就几毛钱的费用。后来某一天自动部署消失了，更新博客得手动上传 OSS。去年还出现了一个山西 PCDN 狂刷下载的事情，一个月给干掉了一百多块钱，CDN 本身没啥靠谱的拦截机制。这些麻烦事儿还是让人很是不爽。&lt;/p&gt;
&lt;p&gt;腾讯云推出了下一代内容分发网络 EdgeOne，功能上与 Cloudflare 十分相似。除了更好的 CDN 加速和更好的 DDoS 防护外，EdgeOne 还提供了一个 Pages 的功能。EdgeOne 有免费版，不限时间、不限流量，但需要通过兑换码才行。我当时是买 50 块钱的海外服务器就可以领 EdgeOne 免费版兑换券，现在似乎改成了每周抽选。总之，经过一番试用，我决定将博客部署到 EdgeOne Pages 上。&lt;/p&gt;
&lt;p&gt;现在博客的源码放在了 GitHub 的私有仓库里，用 GitHub Action 进行构建，构建结果推送到 gh-pages 分支。EdgeOne Pages 可以授权访问 GitHub 的仓库，并在 gh-pages 分支变化时自动部署。&lt;/p&gt;
&lt;p&gt;其实 EdgeOne Pages 是自带构建功能的，但我不是很想在腾讯云上折腾 Hugo 依赖的安装，于是就在 GitHub 上直接构建了。&lt;/p&gt;
&lt;h2 id="新的写作计划与展望"&gt;新的写作计划与展望
&lt;/h2&gt;&lt;p&gt;有了新的博客，自然也要多写点东西。写作这件事，往往是越写越顺，越不写就越难下笔。接下来还是争取每个月至少写一篇文章，锻炼一下自己的写作能力。目前我已经有两篇准备写的文章了，加油吧）&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://stack.jimmycai.com/" target="_blank" rel="noopener"
&gt;Hugo Theme Stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.l3zc.com/2023/10/theme-stack-tweaks/" target="_blank" rel="noopener"
&gt;Hugo Theme Stack 针对中国大陆部署优化不完全指南&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>使用 AMT + PXE + Alpine 抢救一台远程 Proxmox VE 服务器</title><link>https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/</link><pubDate>Fri, 21 Feb 2025 11:05:19 +0000</pubDate><guid>https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/</guid><description>&lt;p&gt;试图给一台远程的非空的 Proxmox VE &lt;a class="link" href="https://pve.proxmox.com/wiki/Renaming_a_PVE_node" target="_blank" rel="noopener"
&gt;主机改名&lt;/a&gt;，改完名重启。然而 Proxmox VE 的配置文件目录是跟主机名强绑定的，于是不出意料的炸了。现在是 web 页面访问不了，ssh 连不上去（提示密钥错误），非常崩溃。&lt;/p&gt;
&lt;p&gt;这个问题修起来也不是很容易。Proxmox VE 已经不能正常启动了，得想办法用其他启动盘启动，然后挂载主机硬盘把主机名改回去。可惜机器在 1000 公里外的家里，没法自己去操作，也很难让家里人帮忙操作……&lt;/p&gt;
&lt;p&gt;好消息是，家里另外一台机器我还能连上，挂掉的这台机器开启了 Intel AMT 主动管理功能。那么，如果我通过 AMT 连接到挂掉的这台机器上，让她以网络启动，那么是不是就能救活她了？&lt;/p&gt;
&lt;h2 id="远程救援的理论基础"&gt;远程救援的理论基础
&lt;/h2&gt;&lt;p&gt;在开始实操救援之前，先让我们理一理救援的理想过程，看看都需要配置哪些服务、解决哪些问题。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用 Intel AMT 将被救援主机重启到网络引导（PXE）模式&lt;/li&gt;
&lt;li&gt;PXE 程序发送 DHCP 请求，获得 IP 地址、下一步服务器地址&lt;code&gt;next-server&lt;/code&gt;、引导程序文件名&lt;code&gt;filename&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;PXE 程序使用 TFTP 协议从 &lt;code&gt;next-server&lt;/code&gt; 下载 &lt;code&gt;filename&lt;/code&gt; 指定的引导程序（iPXE），然后运行 iPXE&lt;/li&gt;
&lt;li&gt;iPXE 通过 TFTP 协议从 &lt;code&gt;next-server&lt;/code&gt; 下载 &lt;code&gt;autoexec.ipxe&lt;/code&gt; 脚本，根据脚本通过 HTTP 下载 Alpine 的 Linux 内核、initramfs，启动内核并传递指定的内核参数&lt;/li&gt;
&lt;li&gt;Alpine 根据内核参数配置 ssh 密钥、软件包仓库镜像地址，并下载并加载 modloop（打包好的额外的内核模块），最终完成初始化进入登录界面&lt;/li&gt;
&lt;li&gt;通过 Intel AMT Serial over LAN 或者 SSH 连入 Alpine&lt;/li&gt;
&lt;li&gt;安装 zfs 工具，导入 Proxmox VE 的启动池，挂载相关数据集，修改罪魁祸首 &lt;code&gt;/etc/hosts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;卸载数据集，导出池，关机，重启后 Proxmox VE 恢复正常。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="使用-intel-amt-连接到被救援服务器"&gt;使用 Intel AMT 连接到被救援服务器
&lt;/h2&gt;&lt;p&gt;之前部署这台服务器的时候，专门进 BIOS 里打开了 AMT 功能，现在想来真是有先见之明。这里简要介绍下 AMT 的启用流程：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在启动菜单中，选择进入 BIOS 设置（Computer Setup），找到 Advanced、Remote Management Options，确保 Active Management（AMT）被打开&lt;/li&gt;
&lt;li&gt;在启动菜单中，选择进入 Intel Management Engine 设置
&lt;ul&gt;
&lt;li&gt;默认密码是 admin，登录后修改密码，要求必须是带有数字、字母、符号的强密码&lt;/li&gt;
&lt;li&gt;启用需要的功能，应该不需要改太多&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;首先我们尝试用 AMT 连接到服务器。可以直接用浏览器访问服务器的 16992 端口外，还可以使用使用开源的 Intel AMT 客户端 &lt;a class="link" href="https://www.meshcommander.com/" target="_blank" rel="noopener"
&gt;MeshCommander&lt;/a&gt;。我们后续都使用后者。输入服务器 IP 和密码，顺利连上。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/AMT-1.png"
width="2232"
height="1651"
srcset="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/AMT-1_hu_a3ffa0c5d958ae73.png 480w, https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/AMT-1_hu_a05fbad12c333b8c.png 1024w"
loading="lazy"
alt="MeshCommander 连接上了服务器"
class="gallery-image"
data-flex-grow="135"
data-flex-basis="324px"
&gt;&lt;/p&gt;
&lt;p&gt;坏消息是，我的这台 HP 机器上没有 KVM（键盘、视频、鼠标）的选项，远程管理仅能用 Serial over LAN（SoL）远程串口功能。我在互联网上翻了一圈，大概是因为这台机器原装是 i3 处理器，不具备 Intel vPro 功能，于是 HP 直接在主板 BIOS 里干掉了 KVM 功能，后面再换 i5、i7 处理器也用不了 KVM 了。这个可以通过修改 BIOS 芯片数据来实现（&lt;a class="link" href="https://www.reddit.com/r/homelab/comments/167kg0f/til_intel_amtvpro_makes_a_decent_kvm_solution_for/" target="_blank" rel="noopener"
&gt;参考1&lt;/a&gt;，&lt;a class="link" href="https://winraid.level1techs.com/t/guide-clean-dumped-intel-engine-cs-me-cs-txe-regions-with-data-initialization/31277" target="_blank" rel="noopener"
&gt;参考2&lt;/a&gt;），只不过当时没时间搞了……&lt;/p&gt;
&lt;p&gt;对 SoL 进行了一系列探索，发现 Reset to BIOS 时能够让 SoL 有正常输出，可惜是乱码。盲操修改了语言，这下能看到正常的启动菜单了。&lt;/p&gt;
&lt;p&gt;启动菜单可以选择 Network (PXE) Boot，也可以在电源操作里选择 Reset to PXE 。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/AMT-2.png"
width="1970"
height="1651"
srcset="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/AMT-2_hu_aa9949b96ffe115e.png 480w, https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/AMT-2_hu_b86a302e5cd6aeda.png 1024w"
loading="lazy"
alt="SoL 显示了进入了启动菜单"
class="gallery-image"
data-flex-grow="119"
data-flex-basis="286px"
&gt;&lt;/p&gt;
&lt;h2 id="配置-dnsmasqdhcp-和-tftp"&gt;配置 dnsmasq（DHCP 和 TFTP）
&lt;/h2&gt;&lt;p&gt;我们已经能够用 AMT 让服务器从 PXE 引导，接下来配置 PXE 启动所需的 DHCP 和 TFTP 服务。在 PXE 启动中，DHCP 用于下发 &lt;code&gt;next-server&lt;/code&gt;、&lt;code&gt;filename&lt;/code&gt; 等启动参数，TFTP 用于传输引导文件。&lt;/p&gt;
&lt;p&gt;这里的 DHCP 就是那个自动分配 IP 地址的 DHCP，那么就有个问题：在家庭网络环境中，路由器往往仅提供了基础 DHCP 服务，无法扩展 PXE 所需的配置项；若禁用路由器的 DHCP 功能、部署独立的 DHCP 服务器，则可能有网络全面断联的风险。为解决这一问题，我们使用 Proxy DHCP 技术：当客户端发出 DHCP 请求时，原有 DHCP 服务器仍下发 IP 地址，Proxy DHCP 服务器补充下发 PXE 所需的附加参数，两者协同工作。现代 PXE 网卡应该都支持 Proxy DHCP。&lt;/p&gt;
&lt;p&gt;我准备了一台全新的 Ubuntu 24.04 虚拟机用来提供网络启动所需的一切服务，使用 &lt;a class="link" href="https://thekelleys.org.uk/dnsmasq/doc.html" target="_blank" rel="noopener"
&gt;dnsmasq&lt;/a&gt; 来同时提供 DHCP 和 TFTP 服务。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 安装 dnsmasq&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;apt-get install dnsmasq&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 查看 dnsmasq 服务状态&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;systemctl status dnsmasq&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;配置 dnsmasq，以启用 proxy DHCP 和 TFTP。将下面的配置文件保存到 &lt;code&gt;/etc/dnsmasq.d/pxe.conf&lt;/code&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Disable DNS Server&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;port=0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Enable TFTP server, setup root path&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;enable-tftp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;tftp-root=/var/ftpd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Enable DHCP logs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;log-dhcp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Enable Proxy DHCP Server&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# proxy enables Proxy DHCP mode&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 192.168.230.0 and 255.255.255.0 are my subnet and mask&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;dhcp-range=192.168.230.0,proxy,255.255.255.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# setup pxe for x86-64 EFI, load ipxe.efi from TFTP server&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;pxe-service=X86-64_EFI,&amp;#34;Network Boot UEFI x86_64&amp;#34;,ipxe.efi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里我只为 UEFI 做了配置（因为我的服务器就是 UEFI 启动的）。更多配置项可以仔细阅读 &lt;code&gt;/etc/dnsmasq.conf&lt;/code&gt; 或者 dnsmasq 的 &lt;a class="link" href="https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html" target="_blank" rel="noopener"
&gt;man 页面&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;接下来创建 TFTP 根目录、让 dnsmasq 检查配置文件、重启 dnsmasq 服务。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 创建 TFTP 根目录 /var/ftpd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;mkdir -p /var/ftpd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 检查 dnsmasq 配置文件&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;dnsmasq --test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 重启 dnsmasq 服务&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;systemctl restart dnsmasq&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 再次检查 dnsmasq 服务状态&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;systemctl restart dnsmasq&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后就可以在&lt;strong&gt;虚拟机&lt;/strong&gt;尝试进行 PXE 启动了！虚拟机的 BIOS/PXE 会抱怨找不到 ipxe.efi 文件（这个我们下一步去搞），但它已经知道了要去哪里找引导文件。也可以再去看看 dnsmasq 的日志，应该也能找到它类似的抱怨。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/PXE-success.png"
width="1665"
height="375"
srcset="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/PXE-success_hu_f6e886477655f43c.png 480w, https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/PXE-success_hu_b612eb52a200279b.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="444"
data-flex-basis="1065px"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;一定要先在虚拟机尝试 PXE 启动，确保所有组件部署完成、一切无误后再去救援实体机。&lt;/p&gt;
&lt;p&gt;把虚拟机的磁盘、光盘设备都删光，它自然会去尝试 PXE 启动。&lt;/p&gt;&lt;/blockquote&gt;
&lt;h2 id="配置-ipxe"&gt;配置 iPXE
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://ipxe.org/" target="_blank" rel="noopener"
&gt;iPXE&lt;/a&gt; 是一个更高级的网络启动固件，能够直接通过 HTTP 协议下载引导文件，比 TFTP 要快许多。我们用 PXE 引导 iPXE，然后再让 iPXE 启动 Linux 内核。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;除了 iPXE，还可以选择 pxelinux 来启动 Linux 内核，具体参考 &lt;a class="link" href="https://discourse.ubuntu.com/t/netbooting-the-live-server-installer/14510" target="_blank" rel="noopener"
&gt;Ubuntu 的网络启动指南&lt;/a&gt;。我选择 iPXE 单纯是我参考的博客选择了 iPXE，实际上 pxelinux 使用更广泛一点）&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;我们从源码构建 iPXE，并把编译好的 iPXE 放到 TFTP 根目录。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 安装必要的工具&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;apt-get install git make binutils mtools perl libc-dev gcc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 获取源码&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;git clone https://github.com/ipxe/ipxe.git&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;cd ipxe/src&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 为 x86-64 EFI 构建&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;make bin-x86_64-efi/ipxe.efi&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 把编译好的 ipxe.efi 复制到 TFTP 根目录&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;cp bin-x86_64-efi/ipxe.efi /var/ftpd/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;接下来就又可以在&lt;strong&gt;虚拟机&lt;/strong&gt;尝试启动了！你应该能看到 iPXE 的输出，并且它在抱怨找不到任何可以启动的东西。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;iPXE 会尝试从 TFTP 服务器获得 autoexec.ipxe，它抱怨的就是找不到这个文件。跟前面一样，这里也可以去看看 dnsmasq 的日志。稍后我们在配置 Alpine 时会去搞这个文件。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/iPXE-success.png"
width="1281"
height="486"
srcset="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/iPXE-success_hu_20f1c5ae4a984120.png 480w, https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/iPXE-success_hu_6bb69ea2e5c65aec.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="263"
data-flex-basis="632px"
&gt;&lt;/p&gt;
&lt;h2 id="配置-http-服务器"&gt;配置 HTTP 服务器
&lt;/h2&gt;&lt;p&gt;前面我们提到 iPXE 可以通过 HTTP 服务器来下载引导文件，实际上 Alpine Linux 启动过程中也需要从 HTTP 下载文件。我们需要部署一个 HTTP 服务器，这里选择最简单的 Apache2.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 安装 &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;apt-get install apache2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Ubuntu 的 Apache2 开箱即用，不需要什么配置。其默认根目录是 &lt;code&gt;/var/www/html&lt;/code&gt;，稍后我们就会把 Alpine Linux 的各种文件丢进去。现在，打开浏览器访问服务器地址，应该能看到它的默认页。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/Apache2-success.png"
width="1640"
height="689"
srcset="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/Apache2-success_hu_50165351f6ef3898.png 480w, https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/Apache2-success_hu_1ddfb2b037070a48.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="238"
data-flex-basis="571px"
&gt;&lt;/p&gt;
&lt;h2 id="配置-alpine-linux"&gt;配置 Alpine Linux
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://www.alpinelinux.org/" target="_blank" rel="noopener"
&gt;Alpine Linux&lt;/a&gt; 是一个新兴的 Linux 发行版，主打轻小、简单、安全，挺适合当救援系统的。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;选其他发行版来搞救援也行，比如 Ubuntu。这里选 Alpine 单纯是看到了相关的博客。&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id="获取-netboot-文件"&gt;获取 Netboot 文件
&lt;/h3&gt;&lt;p&gt;Alpine Linux 本身就提供了 Netboot 的版本，从&lt;a class="link" href="https://www.alpinelinux.org/downloads/" target="_blank" rel="noopener"
&gt;它的下载页&lt;/a&gt;下载，直接解压到 HTTP 服务器根目录里。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 下载 Alpine v3.21 netboot 版&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;wget https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/x86_64/alpine-netboot-3.21.3-x86_64.tar.gz&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 直接解压到 HTTP 服务器根目录 /var/www/html&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;tar -xzf alpine-netboot-3.21.3-x86_64.tar.gz -C /var/www/html&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;解压后应该能得到如下文件：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;└── boot&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── config-6.12.13-0-lts # 内核配置&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── config-6.12.13-0-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── dtbs-lts # 设备树（对于 x86 没用）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── dtbs-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── initramfs-lts # 初始内存文件系统&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── initramfs-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── modloop-lts # 额外的内核模块&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── modloop-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── System.map-6.12.13-0-lts # 内核符号表&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── System.map-6.12.13-0-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;├── vmlinuz-lts # 内核&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;└── vmlinuz-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;所有文件都有 &lt;code&gt;lts&lt;/code&gt; 和 &lt;code&gt;virt&lt;/code&gt; 结尾的两份，&lt;code&gt;lts&lt;/code&gt; 是标准版，&lt;code&gt;virt&lt;/code&gt; 是针对虚拟机裁剪的版本，我们后面总是使用前者。这些文件中，我们实际上只使用下面 3 个：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;vmlinuz-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;initramfs-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;modloop-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;记得检查所有文件的权限，确保它们都能通过浏览器下载。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;ls -l&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# total 275M&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw-r--r-- 1 ceba ceba 265K Feb 13 23:06 config-6.12.13-0-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw-r--r-- 1 ceba ceba 146K Feb 13 23:06 config-6.12.13-0-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# drwxr-xr-x 2 ceba ceba 4.0K Feb 13 23:06 dtbs-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# drwxr-xr-x 2 ceba ceba 4.0K Feb 13 23:06 dtbs-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw------- 1 ceba ceba 24M Feb 13 23:06 initramfs-lts &amp;lt;-- 权限不足&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw------- 1 ceba ceba 8.6M Feb 13 23:06 initramfs-virt &amp;lt;-- 权限不足&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw-r--r-- 1 ceba ceba 189M Feb 13 23:06 modloop-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw-r--r-- 1 ceba ceba 20M Feb 13 23:06 modloop-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw-r--r-- 1 ceba ceba 6.3M Feb 13 23:06 System.map-6.12.13-0-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw-r--r-- 1 ceba ceba 5.7M Feb 13 23:06 System.map-6.12.13-0-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw-r--r-- 1 ceba ceba 12M Feb 13 23:06 vmlinuz-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# -rw-r--r-- 1 ceba ceba 12M Feb 13 23:06 vmlinuz-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 补足权限&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;chmod 644 initramfs-lts initramfs-virt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;另外，往 HTTP 服务器根目录下丢一个公钥文件 &lt;code&gt;ssh_key&lt;/code&gt;，用于稍后 SSH 登录。&lt;/p&gt;
&lt;h3 id="配置-ipxe-启动脚本"&gt;配置 iPXE 启动脚本
&lt;/h3&gt;&lt;p&gt;创建 &lt;code&gt;autoexec.ipxe&lt;/code&gt; 文件，放在 TFTP 根目录 &lt;code&gt;/var/ftpd&lt;/code&gt; 下。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#!ipxe&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Init networking&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;dhcp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Server address&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set server http://192.168.230.12&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;echo server is ${server}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Set command line &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set cmdline modules=loop,squashfs quite&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;echo cmdline is ${cmdline}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Kernel file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set vmlinuz ${server}/boot/vmlinuz-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;echo vmlinuz is ${vmlinuz}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Initramfs file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set initramfs ${server}/boot/initramfs-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;echo initramfs is ${initramfs}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Modloop file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set modloop ${server}/boot/modloop-lts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;echo modloop is ${modloop}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Repository for apk&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set mirror http://mirrors.ustc.edu.cn/alpine&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set branch v3.21&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set repo ${mirror}/${branch}/main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;echo repo is ${repo}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Set SSH key&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;set ssh_key ${server}/ssh_key&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# Uncomment this if you want to see the information before continuing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# prompt Press any key to continue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;#Kernel, initrd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;kernel ${vmlinuz} ${cmdline} alpine_repo=${repo} modloop=${modloop} initrd=initramfs-lts ssh_key=${ssh_key}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;initrd ${initramfs}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;#Boot&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;boot&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;#Pause if errors&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;prompt Some error occurred, press any key to continue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="对于-zfs-的额外处理"&gt;对于 ZFS 的额外处理
&lt;/h3&gt;&lt;p&gt;我的 Proxmox VE 是装在两块 NVME 盘组的 zfs 阵列上的，我的救援系统就必须有 zfs 支持，包括 zfs 内核模块和 zfs 工具。然而，netboot 版的 Alpine Linux 并没有自带 zfs 内核模块，我在启动后尝试用 apk 安装会报莫名其妙的错误，救援一下子陷入了僵局。&lt;/p&gt;
&lt;p&gt;机缘巧合下，我发现 Alpine Linux 的 Extended 版带有 zfs 模块，那么把 Extended 和 Netboot 整合一下是不是就可以了？我注意到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;两者的 lts 内核完全一致（通过比较 config 和 md5sum）&lt;/li&gt;
&lt;li&gt;两者的 initramfs 各有千秋（通过 &lt;code&gt;lsinitramfs&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;Extended 比 Netboot 的 modloop 多了一些模块，其中包括 zfs （通过 &lt;code&gt;unsquashfs -l&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;那么可以试着用 Extended 的 modloop 替换掉 Netboot 的 modloop，具体如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下载 Extended 的 ISO，挂载到文件系统，找到 &lt;code&gt;boot/modloop-lts&lt;/code&gt;，替换掉原来的文件；&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;autoexec.ipxe&lt;/code&gt; 作以下可选修改
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;command&lt;/code&gt; 的 &lt;code&gt;modules&lt;/code&gt;选项修改为 &lt;code&gt;modules=loop,squashfs,zfs&lt;/code&gt;，以自动加载 zfs 内核模块&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kernel&lt;/code&gt; 命令中添加 &lt;code&gt;modloop_verify=no&lt;/code&gt;，关闭 modloop 校验&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这下 Alpine 就有 zfs 模块了。&lt;/p&gt;
&lt;h3 id="启动"&gt;启动！
&lt;/h3&gt;&lt;p&gt;现在，可以在&lt;strong&gt;虚拟机&lt;/strong&gt;上做最后的测试了。经过漫长的启动后，如果没有意外，应该能看到这样的登录画面。用户名是 root，没有密码。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/Alpine-success.png"
width="2051"
height="1535"
srcset="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/Alpine-success_hu_25203f9eede470b2.png 480w, https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/Alpine-success_hu_aada2caed828ad50.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;p&gt;Alpine 默认开启了 ssh 服务器，可以用 ssh 连接，前面添加的 ssh 公钥此时派上用场了。&lt;/p&gt;
&lt;p&gt;到此，一切就绪，可以尝试在物理服务器上进行 PXE 启动了。&lt;/p&gt;
&lt;h2 id="救援-zfs"&gt;救援 ZFS
&lt;/h2&gt;&lt;p&gt;通过 ssh 连接到被救援服务器，安装相关工具，挂载 zfs 文件系统，进行必要的修改。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# 安装 zfs 命令行工具&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;apk add zfs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 查看 zfs 状态&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;zfs status&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 搜寻磁盘上的 zpool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;zpool import&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 导入指定的 zpool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;zpool import rpool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 查看 zfs 文件系统信息&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;zfs list&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 挂载文件系统&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;mkdir -p /root/rpool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;mount -F zfs rpool/ROOT/pve-1 /root/rpool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 做修改&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;vi /root/rpoll/etc/hosts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 卸载文件系统&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;umount /root/rpool/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 导出 zpool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;zpool export rpool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="c"&gt;# 关机&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="l"&gt;poweroff&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;用 Intel AMT 再次启动服务器，web、ssh 全部恢复正常，救援成功！&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/ProxmoxVE-sucess.png"
width="1882"
height="1204"
srcset="https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/ProxmoxVE-sucess_hu_7b14a47ca8b12db7.png 480w, https://blog.ceba.tech/2025/02/rescue-a-proxmox-ve-server-with-amt-pxe-alpine/ProxmoxVE-sucess_hu_32400160c3329833.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="156"
data-flex-basis="375px"
&gt;&lt;/p&gt;
&lt;h2 id="结语"&gt;结语
&lt;/h2&gt;&lt;p&gt;这次远程救援花了好几天时间，最终省下了 1000 块钱的车票，总是值得的。&lt;/p&gt;
&lt;p&gt;Intel AMT 还是好用的，不过我下次回家一定得把 KVM 功能恢复了，SoL 的可用性实在堪忧啊。另外，从 &lt;a class="link" href="https://meshcentral2.blogspot.com/2023/02/starting-work-at-microsoft.html" target="_blank" rel="noopener"
&gt;MeshCommander 的网站&lt;/a&gt;上看到，它的开发者在 2022 年的时候被 Intel 裁掉了，真是令人唏嘘。&lt;/p&gt;
&lt;p&gt;希望这篇文章对你有所帮助~&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;这两篇文章是我 PXE 启动 Alpine Linux 的主要参考，感谢 apalrd。
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.apalrd.net/posts/2022/alpine_pxe/" target="_blank" rel="noopener"
&gt;Setting up a Netboot (PXE) Server for Alpine Linux :: apalrd&amp;rsquo;s adventures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.apalrd.net/posts/2022/alpine_vdiclient/" target="_blank" rel="noopener"
&gt;Net Booting the Proxmox VDI Client (feat. Alpine Linux) :: apalrd&amp;rsquo;s adventures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;如果你需要更复杂的无盘 Alpine Linux，可以参考第二篇。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;有关 Alpine Linux 网络启动的官方文档
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://wiki.alpinelinux.org/wiki/Netboot_Alpine_Linux_using_iPXE" target="_blank" rel="noopener"
&gt;Netboot Alpine Linux using iPXE - Alpine Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://wiki.alpinelinux.org/wiki/PXE_boot" target="_blank" rel="noopener"
&gt;PXE boot - Alpine Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;有关 dnsmasq 的配置
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://askubuntu.com/questions/1506431/dnsmasq-configuration-for-tftp-proxydhcp-in-ubuntu-server-22-04-3-lts" target="_blank" rel="noopener"
&gt;dhcp - dnsmasq configuration for TFTP + ProxyDHCP in Ubuntu Server 22.04.3 LTS - Ask Ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.fogproject.org/en/latest/installation/network-setup/proxy-dhcp/" target="_blank" rel="noopener"
&gt;Proxy DHCP with dnsmasq - Fog Project Documentation (FOG Docs)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;有关 Alpine Linux + ZFS 的文章
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://gist.github.com/alexalouit/37c6726d60f1ed19dcf95540331d90ff" target="_blank" rel="noopener"
&gt;run alpine linux as ramdisk/iso/usb with zfs modules (modloop)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://wiki.alpinelinux.org/wiki/Root_on_ZFS_with_native_encryption" target="_blank" rel="noopener"
&gt;Root on ZFS with native encryption - Alpine Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://openzfs.github.io/openzfs-docs/Getting%20Started/Alpine%20Linux/index.html" target="_blank" rel="noopener"
&gt;Alpine Linux — OpenZFS documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://openzfs.github.io/openzfs-docs/Getting%20Started/Alpine%20Linux/Root%20on%20ZFS.html" target="_blank" rel="noopener"
&gt;Alpine Linux Root on ZFS — OpenZFS documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;有关 ZFS 操作的材料
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forums.freebsd.org/threads/finding-old-zfs-pool-on-disks.61731/" target="_blank" rel="noopener"
&gt;Finding old zfs pool on disks | The FreeBSD Forums&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.oracle.com/cd/E26926_01/html/E25826/toc.html" target="_blank" rel="noopener"
&gt;Oracle Solaris 管理：ZFS 文件系统&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>搞台 NAS (4)：Openmediavault 通过 Docker 部署 qBittorrent</title><link>https://blog.ceba.tech/2022/07/nas-4-omv-docker-qbittorrent/</link><pubDate>Sat, 09 Jul 2022 01:20:19 +0000</pubDate><guid>https://blog.ceba.tech/2022/07/nas-4-omv-docker-qbittorrent/</guid><description>&lt;img src="https://blog.ceba.tech/2022/07/nas-4-omv-docker-qbittorrent/bg.png" alt="Featured image of post 搞台 NAS (4)：Openmediavault 通过 Docker 部署 qBittorrent" /&gt;&lt;p&gt;在前两篇文章中，我们安装了 Openmediavault、部署了 ZFS 文件系统，这次我们将会用 Docker 容器部署 BT/PT 下载应用——qBittorrent。NAS 下载 BT/PT 是我的核心需求，使用 Docker 部署这类应用应该算是常规操作。&lt;/p&gt;
&lt;p&gt;OMV 部分总共分为三篇文章，这是第 3 篇：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.ceba.tech/2022/07/NAS-2-OMV-install-and-config/" &gt;Openmediavault 的安装与配置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.ceba.tech/2022/07/NAS-3-OMV-ZFS/" &gt;Openmediavault 部署 ZFS 文件系统&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Openmediavault 通过 Docker 部署 qBittorrent&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="安装-docker"&gt;安装 Docker
&lt;/h2&gt;&lt;p&gt;点击左侧“系统”、“omv-extras”、“Docker”，点击“安装”按钮，开始安装进程。安装完成后，回到同一界面，应该能看到提示状态是“已安装、运行中”，版本号应当不低于 20.10.17。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-docker-installed.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;如果发现版本号低于 20.10.17，请点击“移除”按钮，移除当前版本的 Docker。使用 ssh 连接到服务器，运行下面的命令安装 Docker：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="docker-hub-镜像加速"&gt;Docker Hub 镜像加速
&lt;/h3&gt;&lt;p&gt;推荐添加阿里云、中国科大的容器镜像，以加快 Docker Hub 上的镜像拉取速度。编辑 &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt; 这个文件，在其中添加如下一项：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;registry-mirrors&amp;#34;: [&amp;#34;https://ustc-edu-cn.mirror.aliyuncs.com/&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;修改后的文件形如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;data-root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/var/lib/docker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;registry-mirrors&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://ustc-edu-cn.mirror.aliyuncs.com/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后重启 Docker 服务：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo service docker restart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="踩到的坑与捉到的虫"&gt;踩到的坑与捉到的虫
&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;这段内容可以略过:)&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;我当初用上面的办法安装好 Docker 之后，发现我没有办法启动任何 Docker 容器，会报如下错误：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ceba&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="n"&gt;openmediavault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~$&lt;/span&gt; &lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;portainer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;daemon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AppArmor&lt;/span&gt; &lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="n"&gt;could&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;apparmor_parser&lt;/span&gt; &lt;span class="n"&gt;apparmor_parser&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;apparmor_parser&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;executable&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;PATH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;portainer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;我寻找了许多材料、尝试了许多办法来解决这个问题，包括缺少安装 apparmor，但都无济于事。后来找到了&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/43606-can-t-run-docker-containers-after-upgrade-to-v6-apparmor-missing/" target="_blank" rel="noopener"
&gt;这篇帖子&lt;/a&gt;，发现到我通过 OMV-Extras 插件安装的是一个巨大古老的 Docker 版本（v20.10.5）。于是根据帖子提示，手动执行了安装命令，终于解决了这一问题。&lt;/p&gt;
&lt;p&gt;但我还是很好奇为啥会装上这么古老的 Docker。我检查了 OMV-Extras 安装 Docker 时的输出，发现这个家伙竟然是从 Debian 源安装 &lt;code&gt;docker.io&lt;/code&gt;，而不是从 Docker 源安装 &lt;code&gt;docker-ce&lt;/code&gt;，前者已经是上古时代的东西了。&lt;/p&gt;
&lt;p&gt;我在 OMV-extras 的&lt;a class="link" href="https://github.com/OpenMediaVault-Plugin-Developers/openmediavault-omvextrasorg" target="_blank" rel="noopener"
&gt;仓库&lt;/a&gt;翻了翻，发现了下面&lt;a class="link" href="https://github.com/OpenMediaVault-Plugin-Developers/openmediavault-omvextrasorg/blob/731ce1884477e47635a41a09280a1a9844632e32/usr/sbin/omv-installdocker#L74-L84" target="_blank" rel="noopener"
&gt;这段代码&lt;/a&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; setDockerPackages&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;arch&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;i386&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; ! grep -q &lt;span class="s1"&gt;&amp;#39;download.docker.com&amp;#39;&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;omvextrasList&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# there is no i386 docker-ce package in the docker repos &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# if docker repos are disabled, use debian repos as well &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# use docker.io from Debian repo &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;dockerPackages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;docker.io docker-compose &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;dockerPackages&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;dockerPackages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;docker-ce &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;dockerPackages&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这段代码竟然直接根据源列表中是否含有 &lt;code&gt;download.docker.com&lt;/code&gt; 这个字符串来决定 Docker 包名……我之前更换 OMV-extras 软件源的时候就修改了 Docker 的镜像仓库，清华 TUNA 源里显然并不包含 &lt;code&gt;download.docker.com&lt;/code&gt; 这个字符串，于是 OMV-extras 就以为没有 Docker 源，选择了从 Debian 源安装。&lt;/p&gt;
&lt;p&gt;真相大白，于是跑去写了个 &lt;a class="link" href="https://github.com/OpenMediaVault-Plugin-Developers/openmediavault-omvextrasorg/issues/74" target="_blank" rel="noopener"
&gt;Issue&lt;/a&gt;。很快啊，不到二十分钟，人家就修完提交了，顺带也把 Issue 关掉了。&lt;/p&gt;
&lt;p&gt;现在大概是没有这个 bug 了。&lt;/p&gt;
&lt;h2 id="部署-qbittorrent"&gt;部署 qBittorrent
&lt;/h2&gt;&lt;p&gt;我们使用 linuxserver 制作的 &lt;a class="link" href="https://hub.docker.com/r/linuxserver/qbittorrent" target="_blank" rel="noopener"
&gt;linuxserver/qbittorrent&lt;/a&gt; 镜像，使用 docker compose 部署。&lt;/p&gt;
&lt;p&gt;通过 ssh 登入服务器，拉取 linuxserver/qbittorrent 镜像：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo docker pull linuxserver/qbittorrent:4.4.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后在主目录下建立 &lt;code&gt;qbittorrent&lt;/code&gt; 文件夹，在其中建立 &lt;code&gt;docker-compose.yml&lt;/code&gt;，内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2.1&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;qbittorrent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;linuxserver/qbittorrent:4.4.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;qbittorrent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;PUID=998 &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 数据卷所有者的 id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;PGID=100 &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 数据卷所属用户组的 id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;TZ=Asia/Shanghai &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 时区&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;WEBUI_PORT=8080 &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Web 界面端口，须和下方保持一致&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 数据卷挂载，帽号前面是宿主机，帽号后面是容器内&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/main/test/qbittorrent-config:/config &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 配置文件目录，根据需要修改帽号前内容&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;/main/test/downloads:/downloads &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 下载文件目录，根据需要修改帽号前内容&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Web 界面端口，须和上方保持一致&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;26881&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;26881&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# BT/PT 下载用通信端口，根据需要设置&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;26881&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;26881&lt;/span&gt;&lt;span class="l"&gt;/udp &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# BT/PT 下载用通信端口，根据需要设置&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;network_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;host &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 网络模式，改为 host 模式&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里我们选择了 qBittorrent 的 4.4.1 版本，它是 linux 下最后一个使用 Qt5 的版本。随后的版本使用了 Qt 6.3.0，但这个版本的 Qt6 存在 bug 导致 RSS 订阅功能不可用。最新的 qBittorrent 4.4.3 尚未更换 Qt 版本，只能先用这个较老的版本凑活凑活了。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;PUID&lt;/code&gt;、&lt;code&gt;PGID&lt;/code&gt; 是用于解决挂载数据卷权限问题的两个环境变量，PUID 设为数据卷所有者的 id，PGID 设为数据卷所属用户组的 id。在这里，数据卷所有者之前已改为 &lt;code&gt;admin&lt;/code&gt;，id 是 998；用户组是 &lt;code&gt;users&lt;/code&gt;，id 是 &lt;code&gt;100&lt;/code&gt;。可以通过 &lt;code&gt;id user&lt;/code&gt; 命令来查看。&lt;/p&gt;
&lt;p&gt;数据卷理论上可以挂载到任意位置，但通常都是会放在文件系统之中的，相对更加安全一些。这里就放在了 test 数据集下面的两个目录里。&lt;/p&gt;
&lt;p&gt;网络模式强烈改为 &lt;code&gt;host&lt;/code&gt; 模式，这样就会直接使用主机网卡，好处多多：可以直接使用 IPv6 地址，不用再碰 Docker 糟糕的 IPv6 支持；少过一层虚拟网卡，性能更好，连接性更优。PS：我当初找了一堆资料研究 Docker 怎么开 IPv6，后来发现用 host 模式直接解决了。&lt;/p&gt;
&lt;p&gt;准备好 &lt;code&gt;docker-compose.yml&lt;/code&gt; 文件后，在它所在的目录下（即 &lt;code&gt;qbittorrent&lt;/code&gt;）运行下面的指令，启动编组：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后就可以打开浏览器，访问 &lt;code&gt;&amp;lt;your_nas_ip&amp;gt;:8080&lt;/code&gt; 来看看能否打开 qBittorrent 的界面啦。默认的登陆用户是 &lt;code&gt;admin&lt;/code&gt;，密码是 &lt;code&gt;adminadmin&lt;/code&gt;。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="qbittorrent-login.png" style="width: 30em;"&gt;&lt;/p&gt;
&lt;p&gt;登录进去之后就可以随便玩耍了，随便塞个新番的 BT 种子试试看。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="qbittorrent-downloading.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h2 id="修改-hosts"&gt;修改 Hosts
&lt;/h2&gt;&lt;p&gt;考虑到网络环境，有必要给一些 BT、PT 网站手动设置 Hosts。&lt;code&gt;/etc/hosts&lt;/code&gt; 这个文件是由 OMV 自动管理的，需要稍稍绕点弯路。&lt;/p&gt;
&lt;p&gt;首先新建 &lt;code&gt;/etc/hosts2&lt;/code&gt; 文件，里面填好需要设置的 Hosts 内容。然后再新建文件 &lt;code&gt;/srv/salt/omv/deploy/hosts/20myentries.sls&lt;/code&gt;，内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yml" data-lang="yml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;append_custom_hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;file.append&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/etc/hosts&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;/etc/hosts2&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;随后运行 &lt;code&gt;sudo omv-salt deploy run hosts&lt;/code&gt; 命令，即可使上面的设置生效。可以再次查看 &lt;code&gt;/etc/hosts&lt;/code&gt; 文件，&lt;code&gt;hosts2&lt;/code&gt; 的内容应该已经填充到其中了。&lt;/p&gt;
&lt;h2 id="结语"&gt;结语
&lt;/h2&gt;&lt;p&gt;在完成 qBittorrent 的部署之后，openmediavault 的折腾之旅算是告一段落了。本来还应该折腾折腾虚拟化，但实在使不想搞了。希望这几篇文章能给想要使用 OMV 的同学一些帮助，让大家少踩一些坑。&lt;/p&gt;
&lt;p&gt;溜了溜了，这就去换 TrueNAS。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/43606-can-t-run-docker-containers-after-upgrade-to-v6-apparmor-missing/" target="_blank" rel="noopener"
&gt;Can&amp;rsquo;t run docker containers after upgrade to v6. AppArmor missing&amp;quot;&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/40928-something-went-wrong-trying-to-pull-and-start-portainer-on-omv-6/" target="_blank" rel="noopener"
&gt;Something went wrong trying to pull and start portainer on OMV 6&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/26395-can-t-get-any-dockers-to-run-without-privileged-mode-on-proxmox-kernel-please-he/&amp;amp;postID=208947#post208947" target="_blank" rel="noopener"
&gt;Can&amp;rsquo;t get any dockers to run without privileged mode on ProxMox kernel, please help&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/26437-docker-images-can-t-network-when-using-proxmox-kernel/" target="_blank" rel="noopener"
&gt;Docker images can&amp;rsquo;t network when using Proxmox kernel&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/33198-request-omv-only-partially-rewrite-etc-hosts/" target="_blank" rel="noopener"
&gt;Request: OMV only partially rewrite /etc/hosts&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/r/linuxserver/qbittorrent" target="_blank" rel="noopener"
&gt;linuxserver/qbittorrent&lt;/a&gt;. Docker Hub.&lt;/li&gt;
&lt;li&gt;Kavindu Narathota. &lt;a class="link" href="https://narathota.medium.com/lets-install-qbittorrent-on-docker-369360de0e04" target="_blank" rel="noopener"
&gt;Let’s install qBittorrent on Docker&lt;/a&gt;. medium.com.&lt;/li&gt;
&lt;li&gt;Elsa Granger. &lt;a class="link" href="https://www.elsagranger.com/docker-ipv6" target="_blank" rel="noopener"
&gt;Docker IPv6&lt;/a&gt;. &lt;a class="link" href="https://www.elsagranger.com" target="_blank" rel="noopener"
&gt;www.elsagranger.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;曾大仁. &lt;a class="link" href="https://zhuanlan.zhihu.com/p/342633966" target="_blank" rel="noopener"
&gt;docker 容器开启ipv6&lt;/a&gt;. 知乎.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.docker.com/config/daemon/ipv6/" target="_blank" rel="noopener"
&gt;Enable IPv6 support&lt;/a&gt;. Docker Document.&lt;/li&gt;
&lt;li&gt;ungleich virtualisation team. &lt;a class="link" href="https://ungleich.ch/u/blog/how-to-enable-ipv6-in-docker/" target="_blank" rel="noopener"
&gt;How to enable IPv6 in docker&lt;/a&gt;. ungleich.ch.&lt;/li&gt;
&lt;li&gt;咕咕鸽. &lt;a class="link" href="https://blog.laoda.de/archives/docker-qbittorrent-ipv6" target="_blank" rel="noopener"
&gt;【有用的小知识】Docker-qBittorrent 开启IPv6 笔记&lt;/a&gt;. blog.laoda.de.&lt;/li&gt;
&lt;li&gt;咕咕鸽. &lt;a class="link" href="https://blog.laoda.de/archives/docker-install-qbittorrent#%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B" target="_blank" rel="noopener"
&gt;【好玩的Docker项目】10分钟搭建你专属的下载神器——qbittorrent&lt;/a&gt;. blog.laoda.de.&lt;/li&gt;
&lt;li&gt;geniusjoe. &lt;a class="link" href="https://zhuanlan.zhihu.com/p/363378341" target="_blank" rel="noopener"
&gt;omv 家用 nas 搭建[2]， qbitttorrent 部署&lt;/a&gt;. 知乎.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/qbittorrent/qBittorrent/issues/16879" target="_blank" rel="noopener"
&gt;RSS feeds do not work with qt6&lt;/a&gt;. Github repo qbittorrent/qBittorrent Issue.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/OpenMediaVault-Plugin-Developers/openmediavault-omvextrasorg/issues/74" target="_blank" rel="noopener"
&gt;The way to determine Docker packages when install Docker&lt;/a&gt;. Github repo OpenMediaVault-Plugin-Developers/openmediavault-omvextrasorg Issue.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>搞台 NAS (3)：Openmediavault 部署 ZFS 文件系统</title><link>https://blog.ceba.tech/2022/07/nas-3-omv-zfs/</link><pubDate>Fri, 08 Jul 2022 21:45:50 +0000</pubDate><guid>https://blog.ceba.tech/2022/07/nas-3-omv-zfs/</guid><description>&lt;img src="https://blog.ceba.tech/2022/07/nas-3-omv-zfs/bg.png" alt="Featured image of post 搞台 NAS (3)：Openmediavault 部署 ZFS 文件系统" /&gt;&lt;p&gt;在上一篇文章，我们装好了 Openmediavault，完成了基本的配置，安装了 Openmediavault 插件，这次我们就可以开始尝试部署 ZFS 文件系统了。在 OMV 上使用软 RAID 加 ext4 或者 btrfs 是完全够用的，我这纯粹是听了群友的鬼话非要折腾 ZFS。ext4、btrfs 等其他文件系统的使用方法，可以参照参考资料中的介绍。&lt;/p&gt;
&lt;p&gt;OMV 部分总共分为三篇文章，这是第 2 篇：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.ceba.tech/2022/07/NAS-2-OMV-install-and-config/" &gt;Openmediavault 的安装与配置&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Openmediavault 部署 ZFS 文件系统&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.ceba.tech/2022/07/NAS-4-OMV-Docker-qBittorrent/" &gt;Openmediavault 通过 Docker 部署 qBittorrent&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="替换-proxmox-内核"&gt;替换 Proxmox 内核
&lt;/h2&gt;&lt;p&gt;Proxmox 内核（即 pve 内核）对 ZFS 文件系统的支持要更好。要使用 ZFS 文件系统，首先需要将 Debian 内核替换为 Proxmox 内核。&lt;/p&gt;
&lt;p&gt;PS：踩的坑之一，不换 Proxmox 内核，ZFS 跑不起来……&lt;/p&gt;
&lt;h3 id="安装-openmediavault-kernel-插件"&gt;安装 openmediavault-kernel 插件
&lt;/h3&gt;&lt;p&gt;登录 OMV 的 Web 管理界面，点击左侧“系统”、“插件”，在右侧搜索“proxmox”即可找到 openmediavault-kernel 插件。选中 openmediavault-kernel，点击“安装”按钮，确认安装。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-kernel.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;安装完成后，按下 &lt;code&gt;Ctrl + Shift + R&lt;/code&gt; 或者 &lt;code&gt;Ctrl + F5&lt;/code&gt; 强制刷新页面缓存，然后可以在左侧“系统”菜单下看到“内核”项。&lt;/p&gt;
&lt;h3 id="安装-proxmox-内核"&gt;安装 Proxmox 内核
&lt;/h3&gt;&lt;p&gt;点击左侧“系统”、“内核”，点击右侧“Proxmox”图标，选择“安装 Proxmox 内核”一项，开始安装进程。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-proxmox-1.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;安装完成后，刷新页面，可以看到 pve 内核已是默认。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-proxmox-2.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击右上角电源图标，重启系统。如果能够正常进入系统，就可以移除常规内核了。&lt;/p&gt;
&lt;h3 id="清理其他内核"&gt;清理其他内核
&lt;/h3&gt;&lt;p&gt;点击左侧“系统”、“内核”，点击右侧“Proxmox”图标，选择“移除非 Proxmox 内核”一项，开始清理其他内核。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-proxmox-3.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;刷新页面后，可看到只有 pve 内核了。这里可以考虑再重启系统一次。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-proxmox-4.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h2 id="安装-zfs-文件系统支持"&gt;安装 ZFS 文件系统支持
&lt;/h2&gt;&lt;h3 id="禁用-backports-源"&gt;禁用 backports 源
&lt;/h3&gt;&lt;p&gt;PS：踩的坑之二，不禁用 backports 源，ZFS 装不上……&lt;/p&gt;
&lt;p&gt;点击左侧“系统”、“omv-extras”、“设置”，取消勾选“Backports”选项，点击保存，二次确认应用。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-backports.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h3 id="安装-openmediavault-zfs-插件"&gt;安装 openmediavault-zfs 插件
&lt;/h3&gt;&lt;p&gt;点击左侧“系统”、“插件“，在右侧搜索“zfs”即可找到 openmediavault-zfs 插件。选中 openmediavault-zfs，点击“安装”按钮，确认安装。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-plugin.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;安装完成后，按下 &lt;code&gt;Ctrl + Shift + R&lt;/code&gt; 或者 &lt;code&gt;Ctrl + F5&lt;/code&gt; 强制刷新页面缓存，然后可以在左侧“存储器”菜单下看到“zfs”项。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-page.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h2 id="创建-zfs-存储池数据集"&gt;创建 ZFS 存储池、数据集
&lt;/h2&gt;&lt;p&gt;ZFS 文件系统中，有存储池、数据集、卷等概念。存储池是一组磁盘构成的逻辑卷，多个磁盘组成软 RAID 阵列；数据集则相当于存储池的一个子文件夹，可更改的选项会比存储池更多，通常用它来存储数据。&lt;/p&gt;
&lt;h3 id="擦除硬盘"&gt;擦除硬盘
&lt;/h3&gt;&lt;p&gt;创建存储池前需要先将磁盘擦除。登录 OMV 的 Web 管理界面，点击左侧“存储器”、“磁盘”，选中需要擦除的硬盘，点击“擦除”图标，二次确认擦除，选择“快速”模式即可。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-wipe-disk.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;重复上述步骤，将所有要放入 ZFS 存储池的磁盘都擦除。&lt;/p&gt;
&lt;h3 id="创建存储池"&gt;创建存储池
&lt;/h3&gt;&lt;p&gt;点击左侧“存储器”、“zfs”、“池”，点击加号图标，选择“添加池”一项，进入创建存储池页面。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-add-pool-1.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;在创建存储池页面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;名称：存储池的名称，根据个人喜好，我这里叫 &lt;code&gt;main&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;池类型：RAID 类型，通常根据磁盘数量选择，磁盘应当是同品牌、同型号、同大小的。我这里只有 2 块盘，所以选择“镜像”；&lt;/li&gt;
&lt;li&gt;设备：勾选上一步中擦除过的设备；&lt;/li&gt;
&lt;li&gt;挂载点：可以留空，系统会自动设置，也可以根据习惯自行设置；&lt;/li&gt;
&lt;li&gt;设备别名：“以 ID”，不要改；&lt;/li&gt;
&lt;li&gt;强制创建：磁盘大小不同时才需要，这里不勾选；&lt;/li&gt;
&lt;li&gt;设置ashift：注释都说了不要改；&lt;/li&gt;
&lt;li&gt;压缩：可以勾上，压缩类型选默认的“zf4”就好，不会占用太多资源。&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-add-pool-2.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击“保存”按钮创建存储池，二次确认应用设置。可以看到存储池已经在列表中了，挂载点是 &lt;code&gt;/main&lt;/code&gt;，可以用命令行访问这个目录看看。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-add-pool-3.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h3 id="创建数据集"&gt;创建数据集
&lt;/h3&gt;&lt;p&gt;OMV 里面，ZFS 的数据集被称作“文件系统”。点击左侧“存储器”、“zfs”、“池”，勾选刚刚创建的存储池，点击加号图标，选择“添加文件系统快照卷”选项。&lt;/p&gt;
&lt;p&gt;PS：这里的“添加文件系统快照卷”指的是“添加文件系统、快照、卷”，并不存在某个东西叫“文件系统快照卷”……&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-add-dataset-1.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;在弹出的对话框里：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;类型：选择“文件系统”，即数据集；&lt;/li&gt;
&lt;li&gt;前缀：存储池的名称，不需要修改；&lt;/li&gt;
&lt;li&gt;名称：根据需要起名，我这里叫 &lt;code&gt;test&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;挂载点：同样可以留空。&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-add-dataset-2.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击“保存”按钮创建数据集，二次确认应用设置。可以看到数据卷已经在列表中了，挂载点是 &lt;code&gt;/main/test&lt;/code&gt;，可以用命令行访问这个目录看看。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-add-dataset-3.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h2 id="设置共享"&gt;设置共享
&lt;/h2&gt;&lt;p&gt;设置好共享后，就可以在局域网内访问 NAS 上的存储空间了。我的主力机器是 Windows 的，这里主要介绍 SMB 协议的共享。&lt;/p&gt;
&lt;h3 id="调整存储池-acl-设置"&gt;调整存储池 ACL 设置
&lt;/h3&gt;&lt;p&gt;ZFS 插件默认禁用了 ACL 权限控制，这会对之后共享文件夹的设置产生一定的影响，需要手动开启。&lt;/p&gt;
&lt;p&gt;点击左侧“存储器”、“zfs”、“池”，选中之前创建的存储池，点击“特性”图标，进入特性页面。修改以下几个参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aclmode：改为 &lt;code&gt;groupmask&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;aclinherit：确认为 &lt;code&gt;restricted&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;acltype：改为 &lt;code&gt;posix&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面这些修改都需要先选中修改项，再到上方点击“编辑”按钮，然后再手动输入值，保存。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-zfs-acl.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h3 id="新建用户"&gt;新建用户
&lt;/h3&gt;&lt;p&gt;为了访问共享文件，我们需要创建一个新用户。点击左侧“用户”、“用户”，点击“新建|导入”图标，选择“创建”项。填入以下信息：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户名：自己选择一个用户名，这里使用 &lt;code&gt;asdf&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;密码：自己选择一个密码；&lt;/li&gt;
&lt;li&gt;用户组：留空即可，系统会自动加入 &lt;code&gt;users&lt;/code&gt; 用户组。&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-user-create.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击保存，二次确认应用，即可看到新建的用户出现在列表之中。&lt;/p&gt;
&lt;h3 id="设置共享文件夹和权限"&gt;设置共享文件夹和权限
&lt;/h3&gt;&lt;p&gt;点击左侧“存储器”、“共享文件夹”，点击“创建”图标。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-shared-folders.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;在打开的页面中，设置如下参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;名称：共享文件夹的名称，可以和数据集保持一致；&lt;/li&gt;
&lt;li&gt;文件系统：选择之前创建的数据集；&lt;/li&gt;
&lt;li&gt;相对路径：选择共享文件夹本身，显示出来应当是 &lt;code&gt;/&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;权限：默认即可，或根据自己需要修改；&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-shared-folders-create.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击保存，二次确认应用，即可看到创建的共享文件夹出现于列表之中。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-shared-folders-2.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;选中刚刚创建的共享文件夹，点击“访问控制列表”按钮，在进入的页面中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;找到刚刚创建的 &lt;code&gt;asdf&lt;/code&gt; 用户，将之权限改为“读/写”；&lt;/li&gt;
&lt;li&gt;将下方的所有者从 &lt;code&gt;root&lt;/code&gt; 改为 &lt;code&gt;admin&lt;/code&gt;；
&lt;ul&gt;
&lt;li&gt;OMV 其他文件系统默认的所有者即是 &lt;code&gt;admin&lt;/code&gt;，推荐手动调整一下；&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;将用户组的权限改为“读/写/执行”；&lt;/li&gt;
&lt;li&gt;勾选下方的“取代”和“递归”选项。&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-acl.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击保存即可。&lt;/p&gt;
&lt;h3 id="设置-smb-共享"&gt;设置 SMB 共享
&lt;/h3&gt;&lt;p&gt;点击左侧“服务”、“SMB”、“设置”，勾选“已启动”项。点击下方保存，二次确认应用，即可打开 SMB 服务。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-smb-settings.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击左侧“服务”、“SMB”、“共享”，点击“创建”按钮，设置如下项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;共享文件夹：选择刚才创建的共享文件夹；&lt;/li&gt;
&lt;li&gt;公开：选择“否”或者“允许访客”均可；&lt;/li&gt;
&lt;li&gt;勾选“继承ACL”、“继承权限”。&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-smb-create.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击保存，二次确认应用，SMB 设置就 OK 了。&lt;/p&gt;
&lt;h3 id="连接和测试"&gt;连接和测试
&lt;/h3&gt;&lt;p&gt;在本地机器上，打开 Windows 资源管理器，通过以下两种方法之一访问：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;打开“网络”文件夹，找到“OPENMEDIAVAULT”（安装时设置的主机名）项目，双击进入；&lt;/li&gt;
&lt;li&gt;在地址栏中输入 &lt;code&gt;\\&amp;lt;your_nas_ip&amp;gt;&lt;/code&gt;（两个反斜杠 + IP地址），按回车进入。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;随后会弹出窗口请求用户名和密码，输入此前创建的用户即可登录。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="windows-network.png" style="width: 30em;"&gt;&lt;/p&gt;
&lt;p&gt;尝试复制文件到 NAS，或者从 NAS 复制文件，速度能够基本跑满千兆以太网。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="speed-copy-to.png" style="width: 25em;"&gt;&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="speed-copy-from.png" style="width: 25em;"&gt;&lt;/p&gt;
&lt;h2 id="结语"&gt;结语
&lt;/h2&gt;&lt;p&gt;到这一步，NAS 算是达到一个可用的状态了，同样是非常麻烦。部署 ZFS 文件系统踩了巨大多的坑。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Dannyda. &lt;a class="link" href="https://dannyda.com/2022/05/02/how-to-fix-openmediavault-zfs-pool-acl-privileges-error-failed-to-execute-command-export-operation-not-supported/" target="_blank" rel="noopener"
&gt;How to Fix OpenMediaVault ZFS pool ACL/Privileges Error (Failed to execute command ‘export…Operation not supported)&lt;/a&gt;. dannyda.com.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.oracle.com/cd/E19120-01/open.solaris/817-2271/gbaaz/index.html" target="_blank" rel="noopener"
&gt;ACL Property Modes&lt;/a&gt;. Solaris ZFS Administration Guide.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/26395-can-t-get-any-dockers-to-run-without-privileged-mode-on-proxmox-kernel-please-he/&amp;amp;postID=208947#post208947" target="_blank" rel="noopener"
&gt;Filesystems&lt;/a&gt;. openmediavault 6.x documentation.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/43077-omv6-0-kernel-regular-vs-proxmox-for-zfs/" target="_blank" rel="noopener"
&gt;OMV6.0 Kernel Regular Vs Proxmox for ZFS&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;raulfg3. &lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/7633-howto-instal-zfs-plugin-use-zfs-on-omv/" target="_blank" rel="noopener"
&gt;HOWTO Instal ZFS-Plugin &amp;amp; use ZFS on OMV&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/41983-omv-6-error-when-installing-openmediavault-zfs-6-0-5/" target="_blank" rel="noopener"
&gt;OMV 6: Error when installing openmediavault-zfs 6.0.5&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/43274-omv6-unable-to-install-openmediavault-zfs-6-0-9/&amp;amp;postID=315318&amp;amp;highlight=zfs#post315318" target="_blank" rel="noopener"
&gt;OMV6: Unable to install openmediavault-zfs 6.0.9&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/43740-latest-update-fails-compiling-zfs-module-kernel-5-18/&amp;amp;postID=317487&amp;amp;highlight=zfs#post317487" target="_blank" rel="noopener"
&gt;latest update fails compiling zfs module (kernel 5.18)&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;司波图. &lt;a class="link" href="https://www.bilibili.com/video/BV1C7411G7t4" target="_blank" rel="noopener"
&gt;【教程】OMV5下实现Freenas及unRAID相同的文件系统（司波图）——OMV系列教程02，SnapRaid，联合文件系统，ZFS&lt;/a&gt;. Bilibili.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>搞台 NAS (2)：Openmediavault 的安装与配置</title><link>https://blog.ceba.tech/2022/07/nas-2-omv-install-and-config/</link><pubDate>Fri, 08 Jul 2022 03:20:26 +0000</pubDate><guid>https://blog.ceba.tech/2022/07/nas-2-omv-install-and-config/</guid><description>&lt;img src="https://blog.ceba.tech/2022/07/nas-2-omv-install-and-config/bg.png" alt="Featured image of post 搞台 NAS (2)：Openmediavault 的安装与配置" /&gt;&lt;p&gt;在准备好硬件之后，就该选择一个合适的 NAS 系统了。原先选择的是群友推荐的 TrueNAS SCALE，安装之后发现它 Docker 功能限制很大，于是换成了 Openmediavault（简称 omv）。在折腾了好几天踩了无数坑之后，发现 TrueNAS 的不少限制完全可以绕开，又打算换回 TrueNAS 了。&lt;/p&gt;
&lt;p&gt;OMV 部分总共分为三篇文章，这是第 1 篇：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Openmediavault 的安装与配置&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.ceba.tech/2022/07/NAS-3-OMV-ZFS/" &gt;Openmediavault 部署 ZFS 文件系统&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.ceba.tech/2022/07/NAS-4-OMV-Docker-qBittorrent/" &gt;Openmediavault 通过 Docker 部署 qBittorrent&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="获取系统镜像制作启动-u-盘"&gt;获取系统镜像、制作启动 U 盘
&lt;/h2&gt;&lt;p&gt;目前，Openmediavault 有基于 Debian 10 的 5.X 和基于 Debian 11 的 6.X 两个现役的大版本，我们这里选择较新的后者。打开 &lt;a class="link" href="https://www.openmediavault.org/download.html" target="_blank" rel="noopener"
&gt;OMV 官方网站的下载页&lt;/a&gt;，下载 Stable 版本的 ISO 镜像，完成后用 SHA265 校验一下文件的完整性。我这里镜像的版本是 &lt;code&gt;6.0.24&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;使用 rufus 或者类似工具，将 ISO 文件烧入 U 盘。我这里使用 UEFI 启动，分区类型选择 GPT；烧录时会提示选择 ISO 还是 DD 模式，推荐选择速度更快的 DD 模式。&lt;/p&gt;
&lt;h2 id="安装系统"&gt;安装系统
&lt;/h2&gt;&lt;p&gt;将服务器插上网线和电源，插入烧好镜像的 U 盘，开机选择 U 盘启动。随后会出现 OMV 的 LOGO 和启动选择项，选择 Install 回车进入安装程序：&lt;/p&gt;
&lt;ol&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;/li&gt;
&lt;li&gt;root 用户密码和确认：推荐留空以禁用，不建议直接使用 root 用户；&lt;/li&gt;
&lt;li&gt;设置初始用户全名和用户名：自定义，我这里取 &lt;code&gt;ceba&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;li&gt;Debian 仓库镜像主机名：这里推荐清华大学 TUNA，地址是 &lt;code&gt;mirrors.tuna.tsinghua.edu.cn&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;Debian 仓库镜像目录：对于清华大学 TUNA 源，默认即可；&lt;/li&gt;
&lt;li&gt;HTTP 代理信息：这里不需要，留空；&lt;/li&gt;
&lt;li&gt;结束安装进程：回车选择继续，结束。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;系统会自动重新启动，默认启动项应该会被自动修改为 Openmediavault。启动后会进入 Debian 的登陆界面，上面有提示当前服务器 IP 地址，可以用来访问 Web 管理界面。&lt;/p&gt;
&lt;p&gt;PS：安装系统的时候需要外接显示器，但我手头并没有 DP 接口的显示器，只好找了条 DP 转 Type-C 的视频线接到便携屏上。另外，没得采集卡，所以没图。&lt;/p&gt;
&lt;h2 id="初始化配置"&gt;初始化配置
&lt;/h2&gt;&lt;p&gt;打开浏览器，输入机器登陆界面看到的 IP，打开 Web 管理界面的登陆页面。这里也可以尝试输入 &lt;code&gt;openmediavault.local&lt;/code&gt;（即之前设置的主机名+域名），如果网络环境合适也可以打开 Web 管理界面。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-login.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;Web 管理界面的用户名是 &lt;code&gt;admin&lt;/code&gt;，初始密码是 &lt;code&gt;openmediavault&lt;/code&gt;，&amp;lsquo;&amp;lsquo;&amp;lsquo;不是&amp;rsquo;&amp;lsquo;&amp;lsquo;此前设置的 Debian 用户名和密码。输入用户密码后即可进入系统。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-dashboard.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h3 id="修改管理界面密码"&gt;修改管理界面密码
&lt;/h3&gt;&lt;p&gt;点击右上角设置图标、“更改密码”，输入新的密码后点击保存。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-change-password.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h3 id="修改网络配置"&gt;修改网络配置
&lt;/h3&gt;&lt;p&gt;根据我家的网络环境，我需要把 IPv4 地址改为静态地址，并且启用 IPv6。点击左侧“网络”、“接口”，在右侧选中需要修改的接口。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-network-1.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;然后点击编辑按钮，进入编辑界面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IPv4：方式改为“静态”，地址、子网掩码、网关根据需要填写；&lt;/li&gt;
&lt;li&gt;IPv6：方式改为“自动”。&lt;/li&gt;
&lt;li&gt;DNS：根据需要填写，我这里填写网关地址。&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-network-2.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;填写完成后滑倒最下方，点击“保存”。随后页面上方会弹出黄色框，提示需要应用设置，点击右侧对勾图标，勾选“确认”后点击“是”按钮。随后网络配置会立即应用，大概率会卡在“正在应用”界面，需要重新输入地址进入 Web 管理界面。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-config-apply.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;PS：OMV 的几乎所有配置都需要二次确认应用。请在操作后稍等一会儿，看看会不会弹出黄色提示框。&lt;/p&gt;
&lt;h3 id="设置时区"&gt;设置时区
&lt;/h3&gt;&lt;p&gt;点击左侧“系统”、“时间和日期”，在“时区”一栏选择 &lt;code&gt;Asia/Shanghai&lt;/code&gt;。点击保存，二次确认应用。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-time-zone.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h3 id="设置自动登出时间"&gt;设置自动登出时间
&lt;/h3&gt;&lt;p&gt;OMV 默认的自动登出时间是 5 分钟，可以调长一些。点击左侧“系统”、“工作台”，在“自动登出”一栏选择希望的时间，例如 60 分钟。点击保存，二次确认应用。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-workbench.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h2 id="进阶配置"&gt;进阶配置
&lt;/h2&gt;&lt;p&gt;之后不少工作需要 ssh 到服务器进行，请准备一个 ssh 客户端。我这里使用 Windows Terminal 通过 Powershell 或者 WSL 登录。&lt;/p&gt;
&lt;h3 id="配置-ssh-用户"&gt;配置 ssh 用户
&lt;/h3&gt;&lt;p&gt;要通过 ssh 连接到服务器，需要将用户放入 &lt;code&gt;ssh&lt;/code&gt; 用户组才可使用 ssh 登录。&lt;/p&gt;
&lt;p&gt;点击左侧“用户”、“用户”，选中安装时创建的初始用户，点击“编辑”图标。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-user-config-1.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;点击“用户组”一行，在 &lt;code&gt;ssh&lt;/code&gt; 处打勾，在最下方点击“保存”按钮，二次确认应用修改。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-user-config-2.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;随后就可以尝试用 ssh 登陆了。&lt;/p&gt;
&lt;h3 id="通过-ssh-登录"&gt;通过 ssh 登录
&lt;/h3&gt;&lt;p&gt;在终端中，输入下面的命令通过 ssh 登录服务器，其中 &lt;code&gt;&amp;lt;your_user_name&amp;gt;&lt;/code&gt; 是初始用户名、&lt;code&gt;&amp;lt;your_nas_ip&amp;gt;&lt;/code&gt; 是服务器 IP 地址：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh &amp;lt;your_user_name&amp;gt;@&amp;lt;your_nas_ip&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;通过下面的命令将公钥拷贝到服务器，则可以免密码登录服务器：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-copy-id &amp;lt;your_user_name&amp;gt;@&amp;lt;your_nas_ip&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="调整-ssh-配置"&gt;调整 ssh 配置
&lt;/h3&gt;&lt;p&gt;点击左侧“服务”、“SSH”，取消“允许 root 登录”、“密码认证”，勾选“公钥认证”，以提升服务器安全性。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-ssh-config.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;h3 id="配置-omv-源"&gt;配置 OMV 源
&lt;/h3&gt;&lt;p&gt;清华大学 TUNA 源提供了 Openmediavault 的镜像，推荐使用它来增快下载速度。&lt;/p&gt;
&lt;p&gt;通过 ssh 登录服务器后，执行下面的命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 进入 root 用户&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo su
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 设置 OMV 软件源环境变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-env &lt;span class="nb"&gt;set&lt;/span&gt; OMV_APT_REPOSITORY_URL &lt;span class="s2"&gt;&amp;#34;https://mirrors.tuna.tsinghua.edu.cn/OpenMediaVault/public&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-env &lt;span class="nb"&gt;set&lt;/span&gt; OMV_APT_ALT_REPOSITORY_URL &lt;span class="s2"&gt;&amp;#34;https://mirrors.tuna.tsinghua.edu.cn/OpenMediaVault/packages&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-env &lt;span class="nb"&gt;set&lt;/span&gt; OMV_APT_KERNEL_BACKPORTS_REPOSITORY_URL &lt;span class="s2"&gt;&amp;#34;https://mirrors.tuna.tsinghua.edu.cn/debian&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-env &lt;span class="nb"&gt;set&lt;/span&gt; OMV_APT_SECURITY_REPOSITORY_URL &lt;span class="s2"&gt;&amp;#34;https://mirrors.tuna.tsinghua.edu.cn/debian-security&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使环境变量生效&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-salt stage run all
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;使环境变量生效一步可能会耗费较长的时间（约 2 分钟），请耐心等待。之后可以手动检查 &lt;code&gt;/etc/apt/source.list.d/&lt;/code&gt; 目录下的几个文件，看软件源是否成功更改。&lt;/p&gt;
&lt;h3 id="安装更新"&gt;安装更新
&lt;/h3&gt;&lt;p&gt;点击左侧“系统”、“更新管理”、“更新”，首先点击“检测是否有更新”图标（图案是搜索），然后点击“安装更新”图标（图案是下载）、确认。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-update.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;当然也可以用命令行完成这些工作：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt upgrade
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="安装-omv-extrasorg"&gt;安装 OMV-Extras.org
&lt;/h2&gt;&lt;p&gt;OMV-Extras.org 是 OMV 的增强插件，后续部署 ZFS 和 Docker 都需要它。&lt;/p&gt;
&lt;p&gt;安装 OMV-Extras 需要管理员权限，下面的操作都需要通过 &lt;code&gt;sudo su&lt;/code&gt; 命令，在 root 用户下进行。&lt;/p&gt;
&lt;h3 id="配置代理"&gt;配置代理
&lt;/h3&gt;&lt;p&gt;OMV-Extras 安装需要访问 Github。考虑到我这里的网络环境，需要使用 HTTP 代理来保证安装顺利。&lt;/p&gt;
&lt;p&gt;首先，配置好代理服务器，允许局域网连接。&lt;/p&gt;
&lt;p&gt;SSH 到服务器，在主目录下新建 &lt;code&gt;proxy.sh&lt;/code&gt;，内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://&amp;lt;your_proxy_ip&amp;gt;:&amp;lt;your_proxy_port&amp;gt;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://&amp;lt;your_proxy_ip&amp;gt;:&amp;lt;your_proxy_port&amp;gt;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;ftp_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://&amp;lt;your_proxy_ip&amp;gt;:&amp;lt;your_proxy_port&amp;gt;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;no_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;127.0.0.1,localhost&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# For curl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://&amp;lt;your_proxy_ip&amp;gt;:&amp;lt;your_proxy_port&amp;gt;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://&amp;lt;your_proxy_ip&amp;gt;:&amp;lt;your_proxy_port&amp;gt;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;FTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;http://&amp;lt;your_proxy_ip&amp;gt;:&amp;lt;your_proxy_port&amp;gt;/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;NO_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;127.0.0.1,localhost&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;运行下面的命令，让代理生效：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; proxy.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后测试一下代理是否能够正常连接，如果能看到正在连接代理服务器的相关输出，则说明代理正常。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://github.co
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;PS：这个方法是用来临时使用代理的，退出登陆后代理设置就失效了。也可以用 OMV 的 Web 管理界面设置代理，但我折腾半天发现没这个方便。&lt;/p&gt;
&lt;h3 id="安装"&gt;安装
&lt;/h3&gt;&lt;p&gt;执行下面的命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget -O - https://github.com/OpenMediaVault-Plugin-Developers/packages/raw/master/install | bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;打开 OMV 的 Web 管理界面，按下 &lt;code&gt;Ctrl + Shift + R&lt;/code&gt; 或者 &lt;code&gt;Ctrl + F5&lt;/code&gt; 强制刷新页面缓存。然后可以在左侧“系统”菜单下看到“omv-extras”项，说明安装成功。&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img src="omv-extras.png" style="width: 45em;"&gt;&lt;/p&gt;
&lt;p&gt;PS：强制刷新 Web 管理界面是常规操作，能解决很多奇怪问题。&lt;/p&gt;
&lt;h3 id="设置-omv-extras-的镜像"&gt;设置 OMV-Extras 的镜像
&lt;/h3&gt;&lt;p&gt;OMV-Extras 引入了一些新的软件源，我们同样可以将之换成清华大学 TUNA 源来加快下载速度。&lt;/p&gt;
&lt;p&gt;通过 ssh 登录服务器后，执行下面的命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 进入 root 用户&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo su
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 设置 OMV 软件源环境变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-env &lt;span class="nb"&gt;set&lt;/span&gt; OMV_EXTRAS_APT_REPOSITORY_URL &lt;span class="s2"&gt;&amp;#34;https://mirrors.tuna.tsinghua.edu.cn/OpenMediaVault/openmediavault-plugin-developers&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-env &lt;span class="nb"&gt;set&lt;/span&gt; OMV_DOCKER_APT_REPOSITORY_URL &lt;span class="s2"&gt;&amp;#34;https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-env &lt;span class="nb"&gt;set&lt;/span&gt; OMV_PROXMOX_APT_REPOSITORY_URL &lt;span class="s2"&gt;&amp;#34;https://mirrors.tuna.tsinghua.edu.cn/proxmox/debian&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 使环境变量生效&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;omv-salt stage run all
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;和之前相同，使环境变量生效一步可能会耗费较长的时间（约 2 分钟），请耐心等待。同样可以手动检查 &lt;code&gt;/etc/apt/source.list.d/&lt;/code&gt; 目录下的几个文件，看软件源是否成功更改。&lt;/p&gt;
&lt;h2 id="结语"&gt;结语
&lt;/h2&gt;&lt;p&gt;OK，OMV 的基本安装和配置算是告一段落了，可以说是非常麻烦。接下来，我会在 OMV 上部署 ZFS 文件系统，然后用 Docker 部署 qBittorrent，让 NAS 正式工作起来。&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://wiki.omv-extras.org/doku.php?id=omv6_new_user_guide" target="_blank" rel="noopener"
&gt;Openmediavault 6 New User Guide&lt;/a&gt;. OMV-Extras.org.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://openmediavault.readthedocs.io/" target="_blank" rel="noopener"
&gt;openmediavault 6.x documentation&lt;/a&gt;. openmediavault.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://mirrors.tuna.tsinghua.edu.cn/help/openmediavault/" target="_blank" rel="noopener"
&gt;OpenMediaVault 镜像使用帮助&lt;/a&gt;. 清华大学开源软件镜像站.&lt;/li&gt;
&lt;li&gt;ryecoaaron. &lt;a class="link" href="https://forum.openmediavault.org/index.php?thread/21269-solutions-to-common-problems/" target="_blank" rel="noopener"
&gt;Solutions to common problems&lt;/a&gt;. Openmediavault Forum.&lt;/li&gt;
&lt;li&gt;Josphat Mutai. &lt;a class="link" href="https://computingforgeeks.com/how-to-set-system-proxy-on-debian-linux/" target="_blank" rel="noopener"
&gt;How To Set System Proxy on Debian 11/10&lt;/a&gt;. Computing for Geeks.&lt;/li&gt;
&lt;li&gt;司波图. &lt;a class="link" href="https://www.bilibili.com/video/BV15J411s7Z4" target="_blank" rel="noopener"
&gt;除了群晖用什么？另一个开源免费易用NAS系统——OMV&lt;/a&gt;. Bilibili.&lt;/li&gt;
&lt;li&gt;司波图. &lt;a class="link" href="https://www.bilibili.com/video/BV1FJ411s7xR?spm_id_from=333.999.0.0&amp;amp;vd_source=d289bdc6fc71f5e3444f1cb48300c74c" target="_blank" rel="noopener"
&gt;【教程】蜗牛星际安装开源NAS系统Openmediavault及初始化配置（司波图）——OMV系列教程01&lt;/a&gt;. Bilibili.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>搞台 NAS (1)：硬件篇</title><link>https://blog.ceba.tech/2022/07/nas-1-hardware/</link><pubDate>Thu, 07 Jul 2022 02:29:33 +0000</pubDate><guid>https://blog.ceba.tech/2022/07/nas-1-hardware/</guid><description>&lt;img src="https://blog.ceba.tech/2022/07/nas-1-hardware/bg.png" alt="Featured image of post 搞台 NAS (1)：硬件篇" /&gt;&lt;p&gt;最近，电脑硬盘全线飙红，笔记本内置的 512 GB 固态和外挂的 6 TB 机械硬盘都被塞满了东西。虽然还有一块 4 TB 的 3.5 寸机械硬盘、一块 2 TB 的 2.5 寸机械硬盘，但它们没法一直挂在电脑上，已经沦为冷备份盘了。是时候搞一台 NAS（Network Attached Storage，网络附接存储）了。&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="disk_status.png" style="width: 45em;"&gt;
&lt;/div&gt;
&lt;h2 id="需求分析"&gt;需求分析
&lt;/h2&gt;&lt;p&gt;我目前笔记本外接的 6 TB 机械硬盘主要是用来挂 BT 和 PT 的，主要是动画的 BDRip、BDMV 和新番，它们至少用掉了 5~6 TB 的空间。这些年攒下的杂七杂八的数据、资料、程序，手机和电脑的硬盘备份，以及家里的各种照片，也需要地方来存储。&lt;/p&gt;
&lt;p&gt;对于我来说，NAS 必须要能够稳定运行，最好是企业级的整机，尽量不考虑灵车。&lt;/p&gt;
&lt;h2 id="选择与折腾"&gt;选择与折腾
&lt;/h2&gt;&lt;p&gt;一开始考虑过星际蜗牛，后来发现这是灵车，遂作罢；群晖、私有云之类的机器的可玩性不够高，也不考虑。最后在群友的推荐下发现了 HPE MicroServer Gen10，经过一番考察，选定了这个看起来还蛮好看的机器。后来才发现 Gen10 的下一代 Gen10 Plus 比 Gen10 紧凑很多，而且平台功能和性能也更强，不过看了看价格选择 Gen10 还是合理的。&lt;/p&gt;
&lt;p&gt;机器配置方面，选择了 X3421 CPU 的高配，8G 内存，原机带有 4 块 1 TB 的希捷硬盘。本来是可以选择不要这 4 块硬盘的，不过只能便宜 400 块钱，觉得不如留下来作冷备份盘。&lt;/p&gt;
&lt;p&gt;到手之后，感觉这机器做工蛮不错，前脸也相当好看。机箱上一大一小两个风扇，小的是电源风扇，大的给硬盘和 CPU 散热。两个千兆网口，对于我的网络环境是足够用了。显示器接口甚是豪华，有两个 DP 和 1 个 VGA 接口，不过对 NAS 来说不太会经常用它们了。安装硬盘没有专门的架子，而是在硬盘周围拧4颗螺丝，然后顺着硬盘架上的槽滑进去。两个 PCIe 接口都可以插 x16 的卡，不过带宽只有 x8 和 x1，而且不支持 PCIe 拆分，装 NVME 固态就有些水土不服。&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="machine.jpg" style="width: 45em;"&gt;
&lt;/div&gt;
&lt;p&gt;由于原机内存只有 8 GB，对于服务器（尤其是跑 ZFS 文件系统的 TrueNAS）来说有些不够用，因此升级成了 16 GB × 2 共计 32 GB 内存。一开始下单了 2 条 32 GB 的 REG ECC 内存，到手后发现点不亮。查阅文档发现，这机器支持的是纯 ECC 内存（UDIMM）而不是 REG ECC 内存（RDIMM），只能把这两条内存退货，然后重新下单 2 条 16 GB 的纯 ECC（UDIMM）内存。REG ECC 内存比纯 ECC 内存便宜好多，两条 32 GB REG ECC 内存的价格和两条 16 GB 纯 ECC 内存几乎没差……&lt;/p&gt;
&lt;p&gt;机械硬盘方面，选择了 2 块西部数据的 16 TB 企业级氦气盘，型号是 WUH721816ALE6L4。本来我是个希捷党，但奈何西数的 16 TB 盘价格实在是太香了。不过有点后悔没有搞 4 块，填不满 MicroServer 的 4 个硬盘槽，也不好组空间损失更小的 RAID 阵列。&lt;/p&gt;
&lt;p&gt;固态硬盘方面，搞了一块致态 TiPlus5000 512 GB 和一块拆机三星 PM951 128 GB。致态这块用的是国内长江存储的颗粒，价格也非常合适。不过 512 GB 用作 TrueNAS 的启动盘有些大了，因此又搞了一块三星的拆机盘。其实系统盘搞个傲腾的 16 GB 小盘或者 U 盘也不是不行。搞了绿联和其他杂牌的 3 块 NVME 转 PCIe 的转接卡，它们的指示灯与机箱前面的绿色指示灯刚好构成了 RGB。&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="all_hardware.jpg" style="width: 33em;"&gt;
&lt;/div&gt;
&lt;p&gt;另外，MicroServer Gen10 上是有一个笔记本光驱位的。于是我就在淘宝搞了一套光驱的固定铁片，附带一个光驱位 2.5 寸硬盘架。&lt;/p&gt;
&lt;h2 id="硬件清单"&gt;硬件清单
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;HPE ProLiant MicroServer Gen10，￥3499.00&lt;/li&gt;
&lt;li&gt;2× 三星 16 GB 2Rx8 2400T UDIMM 内存，￥880.00&lt;/li&gt;
&lt;li&gt;2× 西部数据 16 TB WUH721816ALE6L4 硬盘，￥￥3007.90&lt;/li&gt;
&lt;li&gt;致态 TiPlus5000 512 GB 固态硬盘，￥339.00&lt;/li&gt;
&lt;li&gt;三星 PM951 128 GB 固态硬盘（拆机），￥108.00&lt;/li&gt;
&lt;li&gt;光驱位硬盘架、固定铁片、线，￥55.00&lt;/li&gt;
&lt;li&gt;3× NVME 转 PCIe 转接卡，￥60.9&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;总计 ￥7949.80。&lt;/p&gt;</description></item><item><title>使用 Traefik 作为服务网关</title><link>https://blog.ceba.tech/2021/12/treafik-as-gateway/</link><pubDate>Fri, 17 Dec 2021 02:21:43 +0000</pubDate><guid>https://blog.ceba.tech/2021/12/treafik-as-gateway/</guid><description>&lt;p&gt;前一阵子在折腾服务器的时候，偶然读到了苏洋老师的文章，了解了 Traefik，搞明白了该怎样用 Docker 部署服务。随后，我照猫画虎搭起来了 Traefik 和 Docker，并成功部署了 MediaWiki 和一个静态网站。&lt;/p&gt;
&lt;p&gt;这篇文章记录一下搭建 Traefik 的过程，并部署一个简单的静态网站。&lt;/p&gt;
&lt;h2 id="什么是-traefik"&gt;什么是 Traefik
&lt;/h2&gt;&lt;p&gt;Traefik 是一个开源的边缘路由软件，能够自动发现服务，方便地实现反向代理、负载均衡。&lt;/p&gt;
&lt;p&gt;具体来说，它可以接收系统收到的请求，并将它们分派到合适的服务去处理。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2021/12/treafik-as-gateway/traefik-architecture.png"
width="2875"
height="1501"
srcset="https://blog.ceba.tech/2021/12/treafik-as-gateway/traefik-architecture_hu_cc5c15d36b84cec3.png 480w, https://blog.ceba.tech/2021/12/treafik-as-gateway/traefik-architecture_hu_6524a9b382f25c00.png 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="191"
data-flex-basis="459px"
&gt;&lt;/p&gt;
&lt;h2 id="安装配置-traefik"&gt;安装配置 Traefik
&lt;/h2&gt;&lt;p&gt;我采用了裸机部署 Traefik 的方案，而没有将 Traefik 部署在 Docker 容器中。主要考虑到我是用的是单体云主机，裸机部署服务网关可以获得更好的性能。&lt;/p&gt;
&lt;h3 id="安装"&gt;安装
&lt;/h3&gt;&lt;p&gt;我们这里选择二进制应用文件安装的方式。在 Traefik 的 Github 仓库里找到编译好的二进制文件，下载解压之后放入 &lt;code&gt;/usr/bin&lt;/code&gt; 文件夹中：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://github.com/traefik/traefik/releases/download/v2.5.4/traefik_v2.5.4_linux_amd64.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tar zxvf traefik_v2.5.4_linux_amd64.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mv traefik /usr/bin/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后验证系统能否找着 Traefik，并检查 Traefik 版本：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;which traefik
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;traefik version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;我这里使用的 Traefik 版本是：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Codename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;livarot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Go&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;go1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;17.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Built&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="n"&gt;T17&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="n"&gt;Z&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ne"&gt;OS&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Arch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;amd64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="配置"&gt;配置
&lt;/h3&gt;&lt;p&gt;首先创建 Traefik 配置和值日的目录：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;midir -p /data/basic/traefik/{logs,conf}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这一步主要是参照苏洋老师的做法，实际上将配置文件放在 &lt;code&gt;/etc/traefik/&lt;/code&gt;、&lt;code&gt;~/.config&lt;/code&gt; 等文件夹就可以，不一定要单独建立文件夹。&lt;/p&gt;
&lt;p&gt;然后参照文档，编写配置文件 &lt;code&gt;traefik.toml&lt;/code&gt;，放在 &lt;code&gt;/data/basic/traefik/&lt;/code&gt; 目录下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;global&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;checkNewVersion&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c"&gt;# 禁用检查新版本&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;sendAnonymousUsage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c"&gt;# 禁用发送匿名监测记录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# http 的默认入口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;:80&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# https 的默认入口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;:443&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# 额外的 http 入口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;:8088&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# 额外的 http 入口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;:8089&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# 后端服务提供平台&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;exposedByDefault&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c"&gt;# 默认不暴露容器，除非其设置了 traefik.enable=true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;traefik&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# 连接容器使用的 Docker 网络&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# 配置文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;watch&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c"&gt;# 监视文件变化&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;directory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/data/basic/traefik/conf&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;dashboard&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c"&gt;# 启用看板&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;insecure&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c"&gt;# 禁用 8080 端口的看板入口&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;debug&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c"&gt;# 允许 ping&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;INFO&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;format&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;common&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/data/basic/traefik/logs/traefik.log&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;accessLog&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/data/basic/traefik/logs/access.log&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;bufferingSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;写配置文件的时候，主要还是要看原始文档。有不少配置项采用默认值就完全 OK。&lt;/p&gt;
&lt;p&gt;启动 Traefik，验证配置：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;traefik --configFile /data/basic/traefik/traefik.toml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;访问服务器的 IP，如果看到 &lt;code&gt;404 page not found&lt;/code&gt;，说明已经成功了。&lt;/p&gt;
&lt;h3 id="守护进程"&gt;守护进程
&lt;/h3&gt;&lt;p&gt;在容器环境中保持应用持续运行只需要一句 &lt;code&gt;--restart=always&lt;/code&gt;，但在裸机环境下的事情会略微麻烦一些。&lt;/p&gt;
&lt;p&gt;这里采用 supervisor 来担当守护进程，用 APT 安装：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install supervisor
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后给 Traefik 编写进程守护配置文件，保存到 &lt;code&gt;/etc/supervisor/conf.d/traefik.conf&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[program:traefik]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;command=traefik --configFile /data/basic/traefik/traefik.toml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;user=root
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;autostart=true
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startsecs=3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;startretries=100
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;autorestart=true
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stderr_logfile=/data/basic/traefik/logs/supervisor-traefik-error.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stderr_logfile_maxbytes=50MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stderr_logfile_backups=10
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stdout_logfile=/data/basic/traefik/logs/supervisor-traefik-access.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stdout_logfile_maxbytes=50MB
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;stdout_logfile_backups=10
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;重启进程守护服务，可以看到 Traefik 已经开始运行。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;service supervisor restart
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ps -ef | grep traefik
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此后，可以用下面的这些命令来启动、停止、重启 Traefik：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo supervisorctl start traefik
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo supervisorctl stop traefik
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo supervisorctl restart traefik
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="部署静态网站"&gt;部署静态网站
&lt;/h2&gt;&lt;p&gt;这里采用 Apache HTTP 服务器的官方镜像 httpd 部署一个静态网站，来展示透过 Traefik 部署 Web 服务的流程。&lt;/p&gt;
&lt;h3 id="准备工作目录"&gt;准备工作目录
&lt;/h3&gt;&lt;p&gt;首先创建一个应用的工作目录 &lt;code&gt;homepage&lt;/code&gt;，然后将静态网站的文件放在 &lt;code&gt;www&lt;/code&gt; 子文件夹下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir homepage
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir homepage/www
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="编写容器编排文件"&gt;编写容器编排文件
&lt;/h3&gt;&lt;p&gt;为静态网站应用编写一个 Docker compose 的编排文件：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;3&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;homepage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HTTP_IMAGE}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;always&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.enable=true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.homepage.rule=Host(`${HTTP_DOMAINS}`)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik.http.routers.homepage.entrypoints=${HTTP_ENTRY}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;traefik&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;expose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./www:/usr/local/apache2/htdocs/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;traefik&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;external&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个文件主要做了这么几件事情：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;指定服务名称和镜像，并保持持续运行；&lt;/li&gt;
&lt;li&gt;通过 &lt;code&gt;labels&lt;/code&gt; 属性通知 Traefik 该应用的路由规则；&lt;/li&gt;
&lt;li&gt;暴露 80 端口，并挂载网页文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了方便修改，这里参数化了部分内容，将之放到 &lt;code&gt;.env&lt;/code&gt; 文件中：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP_IMAGE=httpd:2.4-alpine
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP_DOMAINS=www.ceba.tech
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP_ENTRY=http, http1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后工作目录执行命令，启动应用：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你修改了编排文件，可以重复执行上面的命令，Docker compose 会自动更新容器配置。&lt;/p&gt;
&lt;p&gt;在这个应用中，我们实际上只用到了一个容器，上述的编排文件完全可以转化成单条 Docker 命令。但是包含如此多参数的 Docker 命令一定又臭又长，使用结构化的编排文件反而更加方便。&lt;/p&gt;
&lt;h3 id="关于自定义配置的补充"&gt;关于自定义配置的补充
&lt;/h3&gt;&lt;p&gt;对于静态网站来说，使用 httpd 的默认配置应当是足够了。但如果需要，我们还可以对 apache2 做进一步的配置。&lt;/p&gt;
&lt;p&gt;首先，执行下面的命令，获取一份配置文件：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run --rm httpd:2.4 cat /usr/local/apache2/conf/httpd.conf &amp;gt; my-httpd.conf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后，修改编排文件，将自定义配置文件挂载进去：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;homepage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./www:/usr/local/apache2/htdocs/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./my-httpd.conf:/usr/local/apache2/conf/httpd.conf&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="后记"&gt;后记
&lt;/h2&gt;&lt;p&gt;搭好服务快一个月了，这才动笔记一记搭建的过程。&lt;/p&gt;
&lt;p&gt;之后还会写一篇文章，讲讲 MediaWiki 部署的过程和踩的坑。希望别咕。&lt;/p&gt;
&lt;p&gt;最近可能会尝试以容器化的方式搭建一个 &lt;a class="link" href="https://www.magicbug.co.uk/cloudlog/" target="_blank" rel="noopener"
&gt;Cloudlog&lt;/a&gt;。希望别咕。&lt;/p&gt;
&lt;h2 id="参考文献"&gt;参考文献
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://soulteary.com/2020/01/28/traefik-2-user-guide-pleasant-development-experience.html" target="_blank" rel="noopener"
&gt;Traefik 2 使用指南，愉悦的开发体验&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://soulteary.com/2020/02/01/configure-traefik-v2-based-web-server.html" target="_blank" rel="noopener"
&gt;配置基于Traefik v2的 Web 服务器 - 苏洋博客&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://doc.traefik.io/traefik/" target="_blank" rel="noopener"
&gt;Traefik 文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://hub.docker.com/_/httpd" target="_blank" rel="noopener"
&gt;Docker httpd 镜像文档&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Ubuntu 20.04 基础环境搭建</title><link>https://blog.ceba.tech/2021/11/ubuntu-setting-up/</link><pubDate>Thu, 04 Nov 2021 01:40:27 +0000</pubDate><guid>https://blog.ceba.tech/2021/11/ubuntu-setting-up/</guid><description>&lt;p&gt;手头有台腾讯云学生机一直闲置，最近准备用起来。这篇文章记录一下 Ubuntu 20.04 系统下基础环境搭建的整个过程。&lt;/p&gt;
&lt;h2 id="环境搭建过程"&gt;环境搭建过程
&lt;/h2&gt;&lt;h3 id="升级系统"&gt;升级系统
&lt;/h3&gt;&lt;p&gt;对于一些某些安装古老系统却又不方便重装系统的机器，需要跨大版本升级：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo &lt;span class="k"&gt;do&lt;/span&gt;-release-upgrade
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="配置软件源安装更新"&gt;配置软件源、安装更新
&lt;/h3&gt;&lt;p&gt;修改镜像源是必须的，需要根据机器地域决定。这里列出几个我常用的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;USTC：&lt;code&gt;https://mirrors.ustc.edu.cn/ubuntu/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;腾讯云：&lt;code&gt;https://mirrors.cloud.tencent.com/ubuntu/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;腾讯云内网：&lt;code&gt;http://mirrors.tencentyun.com/ubuntu/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;阿里云：&lt;code&gt;https://mirrors.aliyun.com/ubuntu/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;编辑系统源列表文件，将 &lt;code&gt;archive.ubuntu.com&lt;/code&gt; 域名替换为上面的即可。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo vim /etc/apt/sources.list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;随后更新软件列表、安装更新的软件。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt upgrade -y
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;有些软件的更新过程可能需要还需要交互，需要注意一下。&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3 id="安装常用软件和语言包"&gt;安装常用软件和语言包
&lt;/h3&gt;&lt;p&gt;安装一些常用软件，虽然大部分可能云主机的镜像都带了。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install git wget curl unzip vim -y
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;安装中文语言包，防止出现奇怪乱码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install language-pack-zh-hant language-pack-zh-hans -y
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="配置时区"&gt;配置时区
&lt;/h3&gt;&lt;p&gt;配置系统时区，防止出现奇怪时间问题：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dpkg-reconfigure tzdata
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="配置-ssh"&gt;配置 SSH
&lt;/h3&gt;&lt;p&gt;将本地密钥复制到远程主机：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-copy-id &amp;lt;host_address&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;配置远程主机禁用密码登录、禁用 &lt;code&gt;root&lt;/code&gt; 用户登录。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo vim /etc/ssh/sshd_config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 添加下面的配置项&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PermitRootLogin no
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PasswordAuthentication no
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;重启 SSH 服务以应用设置。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo service ssh restart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="安装-docker"&gt;安装 Docker
&lt;/h3&gt;&lt;h4 id="docker-本体"&gt;Docker 本体
&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;注意参照官方文档：https://docs.docker.com/engine/install/ubuntu/&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;添加 Docker 官方 GPG 密钥：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;curl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fsSL&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;gpg&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;gpg&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;dearmor&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;keyrings&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;archive&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;keyring&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gpg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;添加 Docker 镜像源，将命令中 &lt;code&gt;https://download.docker.com/linux/ubuntu&lt;/code&gt; 替换为国内源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;USTC：&lt;code&gt;http://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;腾讯云：&lt;code&gt;https://mirrors.cloud.tencent.com/docker-ce/linux/ubuntu/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;腾讯云内网：&lt;code&gt;https://mirrors.tencentyun.com/docker-ce/linux/ubuntu/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;阿里云：&lt;code&gt;http://mirrors.aliyun.com/docker-ce/linux/ubuntu&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 原始命令&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg --print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;lsb_release -cs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 国内镜像&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;deb [arch=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;dpkg --print-architecture&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] http://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;lsb_release -cs&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;安装 Docker 本体。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install docker-ce docker-ce-cli containerd.io
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="安装-docker-compose"&gt;安装 Docker Compose
&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;注意参考官方文档：https://docs.docker.com/compose/install/&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;直接运行以下命令，由于没有镜像，可能会很慢。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo curl -L &lt;span class="s2"&gt;&amp;#34;https://github.com/docker/compose/releases/download/1.29.2/docker-compose-&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;uname -s&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;uname -m&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; -o /usr/local/bin/docker-compose
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo chmod +x /usr/local/bin/docker-compose
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="配置-docker-容器镜像加速源"&gt;配置 Docker 容器镜像加速源
&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;参照腾讯云文档：https://cloud.tencent.com/document/product/1207/45596&lt;br&gt;
或阿里云文档：https://help.aliyun.com/document_detail/60750.html&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;编辑文件 &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt;，添加内容：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;registry-mirrors&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://mirror.ccs.tencentyun.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;重启 Docker 服务&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo service docker restart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="验证-docker-安装"&gt;验证 Docker 安装
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo docker run hello-world
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="后记"&gt;后记
&lt;/h2&gt;&lt;p&gt;目前准备在这个机器上搭一个 MediaWiki 和一个 CloudLog，估计还得花费一段时间研究研究 Docker 和 Docker Compose 的高级用法。&lt;/p&gt;
&lt;h2 id="参考"&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://soulteary.com/2019/04/06/configure-ubuntu-18-04.html" target="_blank" rel="noopener"
&gt;Ubuntu 18.04 基础系统配置 - 苏洋博客&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Python 列表、变量以及参数传递——从删除列表第一个元素说起</title><link>https://blog.ceba.tech/2020/12/summary-of-python-list-and-var/</link><pubDate>Fri, 18 Dec 2020 16:45:11 +0000</pubDate><guid>https://blog.ceba.tech/2020/12/summary-of-python-list-and-var/</guid><description>&lt;p&gt;Python 的列表、变量以及参数传递一直都是一个挺让人头疼的问题。什么时候是值传递，什么时候是引用传递，总是傻傻搞不清。&lt;/p&gt;
&lt;p&gt;举个例子来说，下面三段代码都希望能够删除列表第一个元素，但为什么前两个能实现功能，但第三个不行呢？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Example 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;old_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;delete_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output: [1, 2, 3, 4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Example 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;old_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;old_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output: [1, 2, 3, 4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Example 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bad_delete_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;new_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;old_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bad_delete_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output: [0, 1, 2, 3, 4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;为了解决这个问题，我们需要对 Python 的变量有一个基本的认识：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python 中的变量都是对内存中某个对象的引用。
&lt;ul&gt;
&lt;li&gt;一般变量（不可更改对象）是对数据对象的引用，列表、字典（可更改对象）是对一般变量（不可更改对象）的引用。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Python 的函数参数传递总是“值传递”，或者说，传递的总是对内存中某个对象的引用关系。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;基于这样的初步认识，我们再来依次分析一下上面的三段代码。&lt;/p&gt;
&lt;h3 id="例子-1"&gt;例子 1
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Example 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;old_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;delete_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output: [1, 2, 3, 4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;当第 5 行 &lt;code&gt;old_list = [0, 1, 2, 3, 4]&lt;/code&gt; 这段代码执行过后，内存中是这样的：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="1.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;p&gt;当我们调用 &lt;code&gt;delete_head&lt;/code&gt; 函数的时候，Python 解释器将我们传入的参数 &lt;code&gt;old_list&lt;/code&gt; 复制了一份成为 &lt;code&gt;new_list&lt;/code&gt;，像这样：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="2.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;p&gt;这里我们再次强调，Python 始终是“值传递”；而这里的“值”，指的是引用关系。&lt;/p&gt;
&lt;p&gt;接下来，程序执行到第 3 行 &lt;code&gt;del new_list[0]&lt;/code&gt;。&lt;code&gt;del&lt;/code&gt; 表示从内存中删掉一个变量，同时删除链接到它的引用关系。我们将与 &lt;code&gt;new_list[0]&lt;/code&gt; 指向的变量、相关的引用关系标红：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="3.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;这里对于 &lt;code&gt;Data 0&lt;/code&gt;，没有其他的变量引用到它，因此这个数据对象也会被销毁。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;当完成删除后，内存中就是这样的：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="4.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;p&gt;很显然，这改变了 &lt;code&gt;old_list&lt;/code&gt; 内容，符合我们的期望。&lt;/p&gt;
&lt;h3 id="例子-2"&gt;例子 2
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Example 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;old_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;old_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output: [1, 2, 3, 4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;列表初始化、函数调用的传参和例子 1 相似，我们得到这样的内存结构：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="2.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;p&gt;现在，&lt;code&gt;new_list[1:]&lt;/code&gt; 语句会复制一份新的列表，内存会变成这样：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="5.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;p&gt;之后，我们通过 &lt;code&gt;return&lt;/code&gt;，将这个列表赋值给了 &lt;code&gt;old_list&lt;/code&gt;，如图：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="6.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;p&gt;于是，这个程序成功地改变了 &lt;code&gt;old_list&lt;/code&gt; 内容，符合我们的期望。&lt;/p&gt;
&lt;h3 id="例子-3"&gt;例子 3
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Example 3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bad_delete_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;new_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;old_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bad_delete_head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output: [0, 1, 2, 3, 4]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对于这个程序，直到 &lt;code&gt;new_list[1:]&lt;/code&gt; 都与例子 2 一模一样。在 &lt;code&gt;new_list[1:]&lt;/code&gt; 复制一份新的列表之后：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="5.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;p&gt;接下来，程序将复制后的列表赋值给了 &lt;code&gt;new_list&lt;/code&gt;，然后函数结束，&lt;code&gt;new_list&lt;/code&gt; 被释放：&lt;/p&gt;
&lt;div style="text-align: center;"&gt;
&lt;img src="7.svg" style="width: 30em;"&gt;
&lt;/div&gt;
&lt;p&gt;在这个过程中，&lt;code&gt;old_list&lt;/code&gt; 是始终没有被修改的，使得最后结果是错误的。&lt;/p&gt;
&lt;h2 id="后记"&gt;后记
&lt;/h2&gt;&lt;p&gt;今天一个同学在 QQ 上问我了这样的一个问题，于是我就跑去查了些材料、画了些图，然后给他作了解答。想着好不容易画的图不能这么轻易浪费，于是将回答整理了一下，形成了这篇文章。&lt;/p&gt;
&lt;p&gt;当然，这篇文章只提到了列表的参数传递，并没有提到普通变量的传递，而且我也不确定内容是否完全正确……如果有什么错误或者不太恰当的地方，还请指出。&lt;/p&gt;
&lt;p&gt;$\empty$&lt;/p&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.cnblogs.com/wuzm/p/12017301.html" target="_blank" rel="noopener"
&gt;Python 中的变量引用小结 - 朱砂痣&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.w3schools.com/python/ref_keyword_del.asp" target="_blank" rel="noopener"
&gt;Python del Keyword - w3schools.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.csdn.net/love1code/article/details/47276683" target="_blank" rel="noopener"
&gt;Python 中 del 的用法 - love1code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>ThinkVision M14 便携显示器维修记</title><link>https://blog.ceba.tech/2020/12/repairing-my-portable-display/</link><pubDate>Fri, 04 Dec 2020 16:28:11 +0000</pubDate><guid>https://blog.ceba.tech/2020/12/repairing-my-portable-display/</guid><description>&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/bg.jpg" alt="Featured image of post ThinkVision M14 便携显示器维修记" /&gt;&lt;p&gt;前两天把便携屏整碎了，屏幕正中央一块击打痕迹，向四个方向扩散条纹（忘了拍照）。今年初才花一千二买的东西，这还没用到一年，直接买个新的太肉疼了，不如先看看能不能自己修好。&lt;/p&gt;
&lt;p&gt;于是噌的一下就拿出螺丝刀，很快啊，就准备把屏拆了。上来就是左撬、右划，想去找卡扣和螺丝孔。结果发现这屏不讲武德，正面壳是双面胶贴上的麦拉片，屏幕也是双面胶贴到背板上去的。那就没有办法了，只能靠持续用力撕开胶带。本以为足够小心翼翼了，屏整个拆下之后，花的部分从十字扩展到了半个屏，彻底报废。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/1.jpg"
width="2134"
height="1600"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/1_hu_a33a70c2d84c4cae.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/1_hu_c34e3ad0ce2b4f1c.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;p&gt;仔细端详这块屏幕，非常纤薄，厚度大概只有 2 mm。屏幕和背板严丝合缝，通过三条泡沫双面胶粘接。看起来背板应该是铝合金用 CNC 雕刻出来的，然后喷了一层类肤质的漆。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/2.jpg"
width="2134"
height="1600"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/2_hu_8238b0d89b6d6267.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/2_hu_3fc98bc9760b17c2.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;p&gt;既然屏都拆下来了，顺带着也把主控板拆下来看看。主控部分的盖子是由螺丝固定的，藏在几个脚垫的下面。主控芯片是瑞昱（Realtek）的，具体型号忘记了，外壳上还专门给它贴了一小块导热胶。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/3.jpg"
width="2134"
height="1600"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/3_hu_45ae0ca1a5029b7b.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/3_hu_4c976bb6b119e78b.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;p&gt;屏幕的型号是 N140HCE-EN2，上淘宝按图索骥，找了好几家终于找到了这款屏幕，320 元，果断下单。随后又买了要用的几种规格的 3M 黑色泡沫双面胶。等快递的时候突然想起来没买贴屏线用的醋酸布胶带……试图在跳蚤市场收，然而并没有收到，于是又下单买了一卷醋酸布胶带。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/4.jpg"
width="2134"
height="1600"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/4_hu_72d90721da238897.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/4_hu_afd1449353208c98.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;p&gt;等了几天之后，配件终于到齐，开工组装。装起来倒是没什么难度，线插好、胶带贴好、把屏放进背板、把麦拉片贴上……屏幕终于满血复活了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/5.jpg"
width="2134"
height="1600"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/5_hu_c61c092e83aaccec.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/5_hu_533e0ebfb651b954.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/6.jpg"
width="2134"
height="1600"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/6_hu_8cc2f9d240e97e58.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/6_hu_58117aae5bc05065.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/9.jpg"
width="2134"
height="1600"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/9_hu_d6d395d1b85e48b3.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/9_hu_328786f63f28c517.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/10.jpg"
width="2134"
height="1600"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/10_hu_6359a0c6b367b511.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/10_hu_f39741c6d8269cd7.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="133"
data-flex-basis="320px"
&gt;&lt;/p&gt;
&lt;h3 id="后记"&gt;后记
&lt;/h3&gt;&lt;p&gt;在屏幕碎掉的同时，我把原装的 Type-C 也搞丢了。买线的时候见识到了 Type-C 线的群魔乱舞，最后选择了 DELL 的拆机线。&lt;/p&gt;
&lt;p&gt;之前我买过一个 HDMI 转 Type-C 的转接线，用来把便携屏给其他设备用。买回来发现电脑上没啥子问题，但树莓派上就是不好用，估计是 HDMI 口供电不足，带不动 HDMI 转 Type-C 的转接芯片。这回又买了一个支持供电的转接线，试了一下非常好使，树莓派啥的都可以正常使用了。&lt;/p&gt;
&lt;p&gt;上淘宝的时候发现 ThinkVision 又出了一款新的便携屏 M14t，把之前的 M14 的痛点全补上了。十点触控、4096压感、Type-C口支持数据传输，有点心动，想买……&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-1.jpg"
width="1011"
height="716"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-1_hu_6b7d4cce5d4627dd.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-1_hu_f97b3ed7f553a277.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="141"
data-flex-basis="338px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-2.jpg"
width="1200"
height="500"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-2_hu_b5533deeff5de5fd.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-2_hu_85d35523b2640a88.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="240"
data-flex-basis="576px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-3.jpg"
width="900"
height="507"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-3_hu_2baae51798818251.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-3_hu_57e20cc85a388e2a.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="177"
data-flex-basis="426px"
&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-4.jpg"
width="900"
height="507"
srcset="https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-4_hu_a895da9d125dbcdc.jpg 480w, https://blog.ceba.tech/2020/12/repairing-my-portable-display/M14t-4_hu_3f4cee3bd7d7ea6a.jpg 1024w"
loading="lazy"
class="gallery-image"
data-flex-grow="177"
data-flex-basis="426px"
&gt;&lt;/p&gt;</description></item></channel></rss>