<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>2025 on Ricky</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/</link><description>Recent content in 2025 on Ricky</description><generator>Hugo -- gohugo.io</generator><language>zh-tw</language><lastBuildDate>Tue, 30 Dec 2025 11:33:23 +0800</lastBuildDate><atom:link href="https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/index.xml" rel="self" type="application/rss+xml"/><item><title>為什麼它正在執行？</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251230-witr/</link><pubDate>Tue, 30 Dec 2025 11:33:23 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251230-witr/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/pranshuparmar/witr" target="_blank" rel="noopener">為什麼它正在執行？&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>用公開 URL 將本機 Web 伺服器暴露到網際網路。</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251227-tunnelto/</link><pubDate>Sat, 27 Dec 2025 15:24:41 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251227-tunnelto/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/agrinman/tunnelto" target="_blank" rel="noopener">用公開 URL 將本機 Web 伺服器暴露到網際網路。&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Rainman 工程體系八問：面試時如何識別卓越工程文化</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251222-rainman-eng-culture/</link><pubDate>Mon, 22 Dec 2025 08:40:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251222-rainman-eng-culture/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://deusyu.app/posts/rainman-eng-culture/" target="_blank" rel="noopener">Rainman 工程體系八問：面試時如何識別卓越工程文化&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>CI/CD 工具：用的是鼓勵協作的 GitLab/GitHub，還是層層設卡的 Gerrit/Jenkins？&lt;/li>
&lt;li>審批流程：一個合併請求（MR）要幾層老闆簽字才能通過？&lt;/li>
&lt;li>環境隔離：有獨立的 Dev/Test/Prod 環境嗎？能否一鍵切換與部署？&lt;/li>
&lt;li>部署鏈路：從程式碼寫完到使用者可見，需要幾步？是自動化還是手動化？&lt;/li>
&lt;li>監控體系：告警能直接指出問題根因，還是全靠工程師半夜人肉翻日誌？&lt;/li>
&lt;li>配置管理：是支援灰度發布的集中化管理，還是散落在程式碼各處靠人工修改？&lt;/li>
&lt;li>測試覆蓋：有可靠的自動化測試「免疫系統」，還是把 bug 當 feature，讓線上使用者幫你測？&lt;/li>
&lt;li>回滾機制：線上服務「炸了」，是 5 分鐘內能從容回滾，還是需要全組通宵「陪葬」？&lt;/li>
&lt;/ol></description></item><item><title>快速且強大的日誌檢視與處理器，能把 JSON logs 或 logfmt logs 轉成清楚易讀的格式。</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251214-high-performance-log-viewer/</link><pubDate>Sun, 14 Dec 2025 21:06:20 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251214-high-performance-log-viewer/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/pamburus/hl" target="_blank" rel="noopener">快速且強大的日誌檢視與處理器，能把 JSON logs 或 logfmt logs 轉成清楚易讀的格式。&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>把你的程式碼庫轉成單一的 LLM 提示詞。</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251211-convert-your-codebase-into-a-single-llm-prompt/</link><pubDate>Thu, 11 Dec 2025 13:16:46 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251211-convert-your-codebase-into-a-single-llm-prompt/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/mufeedvh/code2prompt" target="_blank" rel="noopener">把你的程式碼庫轉成單一的 LLM 提示詞。&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>如何在Surface Go 2安裝Fedora Linux，提昇低階平板效能</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251211-install-linux-on-surface-go-2/</link><pubDate>Thu, 11 Dec 2025 10:18:47 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251211-install-linux-on-surface-go-2/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ivonblog.com/posts/install-linux-on-surface-go-2/" target="_blank" rel="noopener">如何在 Surface Go 2 安裝 Fedora Linux，提昇低階平板效能&lt;/a>
&lt;blockquote>
&lt;p>Surface Go 2 (Intel Pentium 4425Y，4G/64G) Wifi 版&lt;/p>
&lt;p>關於 Surface Go 2 的硬體支援程度，參閱 Github 的這個表格：&lt;a href="https://github.com/linux-surface/linux-surface/wiki/Supported-Devices-and-Features#feature-matrix" target="_blank" rel="noopener">Supported Devices and Features&lt;/a>&lt;/p>&lt;/blockquote>
&lt;/li>
&lt;/ul>
&lt;h3 id="製作-linux-開機碟">製作 Linux 開機碟&lt;/h3>
&lt;ul>
&lt;li>到 &lt;a href="https://www.fedoraproject.org/kde/" target="_blank" rel="noopener">Fedora KDE&lt;/a> 官網下載 ISO&lt;/li>
&lt;li>然後用 &lt;a href="https://ivonblog.com/posts/ventoy-linux-installation/" target="_blank" rel="noopener">Ventoy&lt;/a> 製作開機碟。&lt;/li>
&lt;li>因為 Surface Go 2 的連接埠只有 Type-C，你可能要準備擴充基座。它不能夠從 SD 卡開機。&lt;/li>
&lt;/ul>
&lt;h3 id="安裝-linux">安裝 Linux&lt;/h3>
&lt;ul>
&lt;li>將 Surface Go 2 關機。&lt;/li>
&lt;li>長按開機鍵與音量上鍵，進入 UEFI。這個界面是可以觸控的，不用接上鍵盤，但之後安裝 Linux 可能還是需要使用實體鍵盤操作。&lt;/li>
&lt;li>雖然 Fedora 支援 Secure Boot，還是建議關閉 Secure Boot，免得安裝驅動需要手動簽名。&lt;/li>
&lt;li>將開機順序設定為隨身碟&lt;/li>
&lt;li>開機，依照畫面指示安裝。選擇清除整個磁碟，安裝 Fedora。&lt;/li>
&lt;li>關於中文輸入法，請安裝 Fcitx5
&lt;ul>
&lt;li>&lt;code>sudo dnf install fcitx5 fcitx5-chewing fcitx5-gtk3 fcitx5-gtk4 fcitx5-qt fcitx5-qt6 fcitx5-configtool&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>小技巧：Fedora 預設啟用 zRAM，如果 Surface Go 的 RAM 太小，編輯 &lt;code>/etc/systemd/zram-generator.conf&lt;/code> 提高 SWAP 數值，增加可用的 RAM，單位為 MB。
&lt;ul>
&lt;li>&lt;code>[zram0]&lt;/code>&lt;/li>
&lt;li>&lt;code>zram-size = 8192&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="加裝-linux-surface-核心">加裝 linux-surface 核心&lt;/h3>
&lt;ul>
&lt;li>依照 &lt;a href="https://github.com/linux-surface/linux-surface/wiki/Installation-and-Setup" target="_blank" rel="noopener">Github&lt;/a> 指示安裝。Fedora 的作法是新增 linux-surface 團隊經營的套件庫到系統
&lt;ul>
&lt;li>&lt;code>sudo dnf config-manager addrepo --from-repofile=https://pkg.surfacelinux.com/fedora/linux-surface.repo&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>安裝 linux-surface 核心，重開機
&lt;ul>
&lt;li>&lt;code>sudo dnf install --allowerasing kernel-surface iptsd libwacom-surface&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>uname -a&lt;/code> 確認目前的核心是否切換成功，應該會顯示 &lt;code>linux-surface&lt;/code>&lt;/li>
&lt;li>由於 Fedora 系統核心更新頻率比較高，新版核心可能會覆蓋 linux-surface 的核心。故安裝 linux-surface 套件之後會自動啟用 &lt;code>linux-surface-default-watchdog.path&lt;/code> 服務，確保開機啟動的都是 linux-surface 核心。&lt;/li>
&lt;/ul>
&lt;h3 id="kde-桌面的虛擬鍵盤使用方式">KDE 桌面的虛擬鍵盤使用方式&lt;/h3>
&lt;p>在系統設定 → 鍵盤 → 虛擬鍵盤啟用。需要注意的是這個鍵盤無法跟 Fcitx5 一起使用。&lt;/p></description></item><item><title>VsCode 整合 DevSpace 進行 debug !</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251210-10377156/</link><pubDate>Wed, 10 Dec 2025 15:16:12 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251210-10377156/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ithelp.ithome.com.tw/articles/10377156" target="_blank" rel="noopener">VsCode 整合 DevSpace 進行 debug !&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/devspace-sh/devspace" target="_blank" rel="noopener">DevSpace&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安裝必要工具-">安裝必要工具 📦&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 確認 Go 版本&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go version
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 Delve 除錯器&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go install github.com/go-delve/delve/cmd/dlv@latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 確認 DevSpace 版本&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>devspace version
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安裝 VSCode Go 擴充功能&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>code --install-extension golang.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>code --install-extension devspace.devspace
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="專案結構設計-">專案結構設計 📁&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── cmd
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── main.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── devspace.yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── Dockerfile.dev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── Dockerfile.prod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── go.mod
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── go.sum
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── internal
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── handler.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── model.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── service.go
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── k8s
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── dev
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── deployment.yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── service.yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>└── start-dev.sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="準備-go-應用程式-">準備 Go 應用程式 🚀&lt;/h4>
&lt;p>首先，讓我們建立一個簡單但實用的 Go 應用程式，包含幾個 API 端點方便我們測試 Break Points&lt;/p></description></item><item><title>使用 Fail2Ban + nftables 強化伺服器</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251208-fail2ban/</link><pubDate>Mon, 08 Dec 2025 16:45:51 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251208-fail2ban/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://tao.zz.ac/homelab/fail2ban.html" target="_blank" rel="noopener">使用 Fail2Ban + nftables 強化伺服器&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>parqeye</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251118-parqeye/</link><pubDate>Tue, 18 Nov 2025 20:49:44 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251118-parqeye/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/kaushiksrini/parqeye" target="_blank" rel="noopener">parqeye&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安裝方式">安裝方式&lt;/h3>
&lt;ul>
&lt;li>&lt;code>cargo install parqeye&lt;/code>&lt;/li>
&lt;li>&lt;code>brew install kaushiksrini/parqeye/parqeye&lt;/code>&lt;/li>
&lt;/ul></description></item><item><title>Mosdns-X</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251109-mosdns-x/</link><pubDate>Sun, 09 Nov 2025 20:32:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251109-mosdns-x/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://github.com/pmkol/mosdns-x" target="_blank" rel="noopener">Mosdns-X&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.ibytebox.com/archives/OxpX7FQ1" target="_blank" rel="noopener">讓 Linux 系統的 DNS 更快更乾淨：部署 Mosdns-X&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安裝">安裝&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>bash &amp;lt;&lt;span style="color:#f92672">(&lt;/span>curl -sL https://raw.githubusercontent.com/lidebyte/bashshell/refs/heads/main/mosdns-x-manager.sh&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="設定">設定&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo tee /etc/mosdns-x/config.yaml &amp;gt; /dev/null &lt;span style="color:#e6db74">&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"># mosdns-x 并发查询（无分流）配置
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">log:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> level: info
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> file: /var/log/mosdns-x/mosdns-x.log
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">plugins:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # 缓存插件
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - tag: cache
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> type: cache
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> args:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> size: 1024
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> lazy_cache_ttl: 1800
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # 并发上游：取最先返回的可用答案
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - tag: forward_all
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> type: fast_forward
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> args:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> upstream:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # 阿里
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;udp://223.5.5.5&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;tls://dns.alidns.com&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # DNSPod / doh.pub
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;udp://119.29.29.29&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;tls://dot.pub&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # Cloudflare
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;udp://1.1.1.1&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;tls://cloudflare-dns.com&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # Google
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;udp://8.8.8.8&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: &amp;#34;tls://dns.google&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> # 主流水线：小缓存 → 并发优选
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - tag: main
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> type: sequence
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> args:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> exec:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - cache
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - forward_all
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"># 监听（双栈 UDP/TCP 53）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">servers:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - exec: main
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> listeners:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: :53
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> protocol: udp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> - addr: :53
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> protocol: tcp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="systemd">systemd&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo tee /etc/systemd/system/mosdns.service &amp;gt; /dev/null &lt;span style="color:#e6db74">&amp;lt;&amp;lt;&amp;#39;EOF&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">[Unit]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">Description=Mosdns-X DNS Accelerator
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">After=network.target
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">[Service]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">Type=simple
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">User=root
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">Group=root
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">ExecStart=/usr/local/bin/mosdns-x start --as-service -d /usr/local/bin -c /etc/mosdns-x/config.yaml
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">Restart=always
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">RestartSec=5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">StandardOutput=journal
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">StandardError=journal
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">SyslogIdentifier=mosdns
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">[Install]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">WantedBy=multi-user.target
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">EOF&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo systemctl daemon-reload
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo systemctl enable --now mosdns
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 备份系统 DNS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo cp -n /etc/resolv.conf /etc/resolv.conf.mosdns-backup
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 改为使用本地 Mosdns-X&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo -e &lt;span style="color:#e6db74">&amp;#34;nameserver 127.0.0.1\noptions edns0&amp;#34;&lt;/span> | sudo tee /etc/resolv.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 若 53 端口被 systemd-resolved 占用，可禁用它&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo systemctl disable --now systemd-resolved 2&amp;gt;/dev/null &lt;span style="color:#f92672">||&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 如果想顺便加锁（防止被 DHCP 修改），加上 chattr 一起执行：&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo -e &lt;span style="color:#e6db74">&amp;#34;nameserver 127.0.0.1\n&amp;#34;&lt;/span> &amp;gt; /etc/resolv.conf &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> chattr +i /etc/resolv.conf
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看进程状态&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo systemctl status mosdns --no-pager
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 测试解析速度（第二次命中缓存更快）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dig +stats www.google.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>dig +stats www.baidu.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 查看实时日志&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tail -f /var/log/mosdns-x/mosdns-x.log
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>go-synctest</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251107-go-synctest/</link><pubDate>Fri, 07 Nov 2025 14:06:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251107-go-synctest/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ganhua.wang/go-synctest" target="_blank" rel="noopener">go-synctest&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">func&lt;/span> &lt;span style="color:#a6e22e">TestAfterFunc&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">testing&lt;/span>.&lt;span style="color:#a6e22e">T&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">synctest&lt;/span>.&lt;span style="color:#a6e22e">Test&lt;/span>(&lt;span style="color:#a6e22e">t&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#a6e22e">testing&lt;/span>.&lt;span style="color:#a6e22e">T&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#a6e22e">cancel&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">WithCancel&lt;/span>(&lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">Background&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">called&lt;/span> &lt;span style="color:#f92672">:=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">context&lt;/span>.&lt;span style="color:#a6e22e">AfterFunc&lt;/span>(&lt;span style="color:#a6e22e">ctx&lt;/span>, &lt;span style="color:#66d9ef">func&lt;/span>() { &lt;span style="color:#a6e22e">called&lt;/span> = &lt;span style="color:#66d9ef">true&lt;/span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">synctest&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>() &lt;span style="color:#75715e">// 等到所有 goroutine 都卡住&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#a6e22e">called&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">t&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;AfterFunc 在 cancel 前就被呼叫&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">cancel&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">synctest&lt;/span>.&lt;span style="color:#a6e22e">Wait&lt;/span>() &lt;span style="color:#75715e">// 再等一次&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> !&lt;span style="color:#a6e22e">called&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#a6e22e">t&lt;/span>.&lt;span style="color:#a6e22e">Fatal&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;AfterFunc 沒有在 cancel 後被呼叫&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>onion-mirror</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251030-onion-mirror/</link><pubDate>Thu, 30 Oct 2025 17:49:44 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251030-onion-mirror/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://flower.codes/2025/10/23/onion-mirror.html" target="_blank" rel="noopener">onion-mirror&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="安裝-tor">安裝 Tor&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo apt update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt install tor
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="設定-tor">設定 Tor&lt;/h3>
&lt;pre tabindex="0">&lt;code># Disable SOCKS proxy since we aren&amp;#39;t making outbound connections
# through Tor
SocksPort 0
# Make sure Tor runs as a daemon (i.e. in the background)
RunAsDaemon 1
# Setup the hidden service on port 80, this is where we tell Tor to
# create a .onion service for our web server
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80
# Disable inbound connections, since we aren&amp;#39;t running a relay or
# exit node
ORPort 0
# Disable directory services, since we won&amp;#39;t be mirroring directory
# information to other Tor nodes
DirPort 0
&lt;/code>&lt;/pre>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo systemctl restart tor
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="取得你的-onion-位址">取得你的 .onion 位址&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo cat /var/lib/tor/hidden_service/hostname
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="設定-caddy">設定 Caddy&lt;/h3>
&lt;pre tabindex="0">&lt;code>http://jytkco7clxwj4hhzaydhk4kr3hwzsdzyvtsc6zn2ivog5uma5pxowzad.onion:80 {
# Set up a reverse proxy, or serve static files, etc.
}
&lt;/code>&lt;/pre>&lt;h3 id="公告你的-onion-位址">公告你的 .onion 位址&lt;/h3>
&lt;pre tabindex="0">&lt;code>header {
Onion-Location http://jytkco7clxwj4hhzaydhk4kr3hwzsdzyvtsc6zn2ivog5uma5pxowzad.onion{uri}
}
&lt;/code>&lt;/pre></description></item><item><title>NGINX 原生 ACME 支持：从根本上重塑 TLS 自动化部署</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251020-nginx-acme-module/</link><pubDate>Mon, 20 Oct 2025 16:31:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251020-nginx-acme-module/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://sconts.com/post/nginx-native-acme-support/" target="_blank" rel="noopener">NGINX 原生 ACME 支持：从根本上重塑 TLS 自动化部署&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="ngx_http_acme_module">&lt;code>ngx_http_acme_module&lt;/code>&lt;/h2>
&lt;ul>
&lt;li>NGINX 1.25.1&lt;/li>
&lt;/ul>
&lt;h2 id="pre-install">pre-install&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 在 Debian/Ubuntu 系统上安装基础编译工具和 NGINX 依赖&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt install build-essential libpcre3-dev zlib1g-dev libssl-dev pkg-config libclang-dev git -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 安装 Rust 工具链 (cargo 和 rustc)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>curl --proto &lt;span style="color:#e6db74">&amp;#39;=https&amp;#39;&lt;/span> --tlsv1.2 -sSf https://sh.rustup.rs | sh
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>source $HOME/.cargo/env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>mkdir -pv /app/nginx/&lt;span style="color:#f92672">{&lt;/span>logs,conf,cache, acme&lt;span style="color:#f92672">}&lt;/span> /app/nginx-build
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd /app/nginx-build
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 克隆 ACME 模块的源码&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git clone https://github.com/nginx/nginx-acme.git /app/nginx-build/nginx-acme
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 或者&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># git clone git@github.com:nginx/nginx-acme.git /app/nginx-build/nginx-acme&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 下载 NGINX 源码（请替换为您需要的版本）&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>wget https://nginx.org/download/nginx-1.28.0.tar.gz
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tar -zxf nginx-1.28.0.tar.gz
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="compile">compile&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>cd nginx-1.28.0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./configure &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --prefix&lt;span style="color:#f92672">=&lt;/span>/app/nginx &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --error-log-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/error.log &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-log-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/access.log &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --pid-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/nginx.pid &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --lock-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/nginx.lock &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-client-body-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/client_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-proxy-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/proxy_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-fastcgi-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/fastcgi_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-uwsgi-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/uwsgi_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --http-scgi-temp-path&lt;span style="color:#f92672">=&lt;/span>/app/nginx/cache/scgi_temp &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --user&lt;span style="color:#f92672">=&lt;/span>nginx &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --group&lt;span style="color:#f92672">=&lt;/span>nginx &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-compat &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-file-aio &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-threads &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_addition_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_auth_request_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_dav_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_flv_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_gunzip_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_gzip_static_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_mp4_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_random_index_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_realip_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_secure_link_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_slice_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_ssl_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_stub_status_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_sub_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_v2_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-http_v3_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-mail &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-mail_ssl_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-stream &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-stream_realip_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-stream_ssl_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-stream_ssl_preread_module &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-cc-opt&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;-g -O2 -ffile-prefix-map=/home/builder/debuild/nginx-1.28.0/debian/debuild-base/nginx-1.28.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC&amp;#39;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --with-ld-opt&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie&amp;#39;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> --add-dynamic-module&lt;span style="color:#f92672">=&lt;/span>/app/nginx-build/nginx-acme
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>make &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> make modules &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> &lt;span style="color:#ae81ff">\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> make install
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 运行配置脚本，这里的关键是 --add-dynamic-module&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 注意：您需要在这里包含您当前 NGINX 已有的所有编译参数，可以通过 nginx -V 查看&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># 编译模块，注意是 make modules 而不是 make install&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="config">config&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /app/nginx/conf/nginx.conf
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">user&lt;/span> &lt;span style="color:#e6db74">nginx&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">error_log&lt;/span> &lt;span style="color:#e6db74">error.log&lt;/span> &lt;span style="color:#e6db74">debug&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">pid&lt;/span> &lt;span style="color:#e6db74">nginx.pid&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">load_module&lt;/span> &lt;span style="color:#e6db74">modules/ngx_http_acme_module.so&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">events&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">worker_connections&lt;/span> &lt;span style="color:#ae81ff">1024&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">multi_accept&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">http&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">include&lt;/span> &lt;span style="color:#e6db74">mime.types&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">default_type&lt;/span> &lt;span style="color:#e6db74">application/octet-stream&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">log_format&lt;/span> &lt;span style="color:#e6db74">main&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&lt;/span>$remote_addr &lt;span style="color:#e6db74">-&lt;/span> $remote_user &lt;span style="color:#e6db74">[&lt;/span>$time_local] &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$host&amp;#34; &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$request&amp;#34; &lt;span style="color:#e6db74">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;&lt;/span>$status $body_bytes_sent &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$http_referer&amp;#34; &lt;span style="color:#e6db74">&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#39;&amp;#34;&lt;/span>$http_user_agent&amp;#34; &lt;span style="color:#e6db74">&amp;#34;&lt;/span>$http_x_forwarded_for&amp;#34;&amp;#39;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">access_log&lt;/span> &lt;span style="color:#e6db74">access.log&lt;/span> &lt;span style="color:#e6db74">main&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">sendfile&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">tcp_nopush&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">charset&lt;/span> &lt;span style="color:#e6db74">utf-8&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">keepalive_timeout&lt;/span> &lt;span style="color:#ae81ff">65&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gzip&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">resolver&lt;/span> 8.8.8.8 1.1.1.1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 定义一个名为 letsencrypt 的 ACME 颁发机构实例
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">acme_issuer&lt;/span> &lt;span style="color:#e6db74">letsencrypt&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 指定 ACME 服务提供商的目录 URL，这里是 Let&amp;#39;s Encrypt 的生产环境
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">uri&lt;/span> &lt;span style="color:#e6db74">https://acme-v02.api.letsencrypt.org/directory&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 提供一个联系邮箱，用于接收 CA 的重要通知（如证书即将过期）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">contact&lt;/span> &lt;span style="color:#e6db74">mailto:security-alerts@aidig.co&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 指定状态文件的存储路径，用于保存 ACME 账户密钥，非常重要
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">state_path&lt;/span> &lt;span style="color:#e6db74">acme/letsencrypt&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 同意服务条款，对于 Let&amp;#39;s Encrypt 等 CA 这是必需的步骤
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">accept_terms_of_service&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 可选指令 acme_shared_zone，用于存储所有配置的证书颁发者的证书、私钥和挑战数据。该区域默认大小为 256K，可根据需要增加
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">acme_shared_zone&lt;/span> &lt;span style="color:#e6db74">zone=acme_shared:1M&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">443&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">ssl.aidig.co&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 步骤一：声明此 server 块启用 ACME，并指定使用上面定义的 letsencrypt 颁发机构
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">acme_certificate&lt;/span> &lt;span style="color:#e6db74">letsencrypt&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># 步骤二：使用动态变量加载由 ACME 模块在内存中管理的证书和私钥
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">ssl_certificate&lt;/span> $acme_certificate;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_key&lt;/span> $acme_certificate_key;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_cache&lt;/span> &lt;span style="color:#e6db74">max=2&lt;/span>; &lt;span style="color:#75715e"># required ngx 1.27.4+
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">default_type&lt;/span> &lt;span style="color:#e6db74">text/plain&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">200&lt;/span> &lt;span style="color:#e6db74">&amp;#39;OK&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">80&lt;/span> &lt;span style="color:#e6db74">default_server&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">_&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># ACME 模块会自动处理 /.well-known/acme-challenge/ 的请求，此 location 用于处理所有其他请求
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">301&lt;/span> &lt;span style="color:#e6db74">https://&lt;/span>$host$request_uri;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>降低家用 Web 服務被通報的機率</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251002-hide-web/</link><pubDate>Thu, 02 Oct 2025 09:54:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20251002-hide-web/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://tao.zz.ac/homelab/hide-web.html" target="_blank" rel="noopener">降低家用 Web 服務被通報的機率&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>透過明文協議嘗試請求 HTTPS 服務時，Nginx 會回傳特殊的 497 狀態碼。若發生此錯誤，我們希望 Nginx 直接關閉連線，不回傳任何回應。這需要另一個非標準狀態碼 444。綜合兩種狀態碼，我們需要在 server 中加入如下設定：&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">error_page&lt;/span> &lt;span style="color:#ae81ff">497&lt;/span> &lt;span style="color:#e6db74">@close&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">location&lt;/span> &lt;span style="color:#e6db74">@close&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">444&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用 error_page 指令為 497 狀態碼設定虛擬路徑 @close，Nginx 在處理 @close 時發現要回傳 444，於是直接關閉連線。&lt;/p>
&lt;p>此時你再用 curl 造訪對應埠口會看到如下錯誤：&lt;/p>
&lt;p>curl &lt;a href="http://example.zz.ac:5678" target="_blank" rel="noopener">http://example.zz.ac:5678&lt;/a>
curl: (52) Empty reply from server&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">5678&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#e6db74">[::]:5678&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">example.zz.ac&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate&lt;/span> &lt;span style="color:#e6db74">...&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_key&lt;/span> &lt;span style="color:#e6db74">..&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">error_page&lt;/span> &lt;span style="color:#ae81ff">497&lt;/span> &lt;span style="color:#e6db74">@close&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">@close&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">444&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">5678&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span> &lt;span style="color:#e6db74">default_server&lt;/span>;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#e6db74">[::]:5678&lt;/span> &lt;span style="color:#e6db74">ssl&lt;/span> &lt;span style="color:#e6db74">default_server&lt;/span>;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">server_name&lt;/span> &lt;span style="color:#e6db74">_&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate&lt;/span> &lt;span style="color:#e6db74">...&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ssl_certificate_key&lt;/span> &lt;span style="color:#e6db74">..&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">return&lt;/span> &lt;span style="color:#ae81ff">444&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Privacy Badger：EFF 推出的免費瀏覽器擴充套件，用來阻止網路監控追蹤</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250929-eff-browser-extension/</link><pubDate>Mon, 29 Sep 2025 16:41:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250929-eff-browser-extension/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://privacybadger.org/" target="_blank" rel="noopener">Privacy Badger：EFF 推出的免費瀏覽器擴充套件，用來阻止網路監控追蹤&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>用 Golang 從零打造容器（Liz Rice）</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250910-containers-from-scratch-by-golang-feat-liz-rice/</link><pubDate>Wed, 10 Sep 2025 09:50:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250910-containers-from-scratch-by-golang-feat-liz-rice/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://baconyao.notion.site/Containers-From-Scratch-by-Golang-feat-Liz-Rice-2638a3a7d9d48053ae1dce0763fb52e8" target="_blank" rel="noopener">用 Golang 從零打造容器（Liz Rice）&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/baconYao/container-from-scratch-golang" target="_blank" rel="noopener">container-from-scratch-golang&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>隨著我們擴充這個小程式的功能，會依序探索以下主題，讓我們建立一個非正式環境的容器模擬。&lt;/p>
&lt;ol>
&lt;li>UTS Namespace&lt;/li>
&lt;li>Chroot&lt;/li>
&lt;li>PID Namespace&lt;/li>
&lt;li>Mount Namespace&lt;/li>
&lt;li>Control Group&lt;/li>
&lt;li>Rootless Container&lt;/li>
&lt;/ol></description></item><item><title>淺談 Go Iterator</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250906-golang-iterator/</link><pubDate>Sat, 06 Sep 2025 21:30:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250906-golang-iterator/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ganhua.wang/go-iterator" target="_blank" rel="noopener">淺談 Go Iterator&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">Seq&lt;/span>[&lt;span style="color:#a6e22e">V&lt;/span> &lt;span style="color:#66d9ef">any&lt;/span>] &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">yield&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">V&lt;/span>) &lt;span style="color:#66d9ef">bool&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">type&lt;/span> &lt;span style="color:#a6e22e">Seq2&lt;/span>[&lt;span style="color:#a6e22e">K&lt;/span>, &lt;span style="color:#a6e22e">V&lt;/span> &lt;span style="color:#66d9ef">any&lt;/span>] &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">yield&lt;/span> &lt;span style="color:#66d9ef">func&lt;/span>(&lt;span style="color:#a6e22e">K&lt;/span>, &lt;span style="color:#a6e22e">V&lt;/span>) &lt;span style="color:#66d9ef">bool&lt;/span>)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>Docker 容器無法存取外網？nftables 下的 NAT 配置指南</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250903-linux-docker-nftables/</link><pubDate>Wed, 03 Sep 2025 09:03:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250903-linux-docker-nftables/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.ibytebox.com/archives/docker-rong-qi-wu-fa-fang-wen-wai-wang-nftables-xia-de-nat-pei-zhi-zhi-nan" target="_blank" rel="noopener">Docker 容器無法存取外網？nftables 下的 NAT 配置指南&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>獨立伺服器 CPU 頻率最大化配置指南</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250902-linux-cpu-performance/</link><pubDate>Tue, 02 Sep 2025 08:24:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250902-linux-cpu-performance/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.ibytebox.com/archives/02cf4c4a-0af7-43f1-bb65-ccdb54a52306" target="_blank" rel="noopener">獨立伺服器 CPU 頻率最大化配置指南&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="看看-cpu-現在用哪種模式">看看 CPU 現在用哪種模式&lt;/h2>
&lt;p>前提條件
系統：Linux（Debian、Ubuntu、Proxmox 等都行）&lt;/p>
&lt;p>權限：root&lt;/p>
&lt;p>CPU：支援動態調頻（Intel Xeon、AMD EPYC / Ryzen 等）&lt;/p>
&lt;h3 id="governor">governor&lt;/h3>
&lt;p>&lt;code>cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor&lt;/code>&lt;/p>
&lt;ul>
&lt;li>powersave：省電小綿羊（頻率鎖低，省電但沒力）&lt;/li>
&lt;li>ondemand：按需加速（要用時才升頻，可能反應慢半拍）&lt;/li>
&lt;li>performance：全程高能（我們要的就是它！💪）&lt;/li>
&lt;/ul>
&lt;h3 id="確認核心到底用哪種驅動intel--amd">確認核心到底用哪種驅動（Intel / AMD）&lt;/h3>
&lt;p>&lt;code>cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver&lt;/code>&lt;/p>
&lt;h2 id="暫時拉滿效能">暫時拉滿效能&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span> cpu in /sys/devices/system/cpu/cpu&lt;span style="color:#f92672">[&lt;/span>0-9&lt;span style="color:#f92672">]&lt;/span>*; &lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> echo performance &amp;gt; $cpu/cpufreq/scaling_governor
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="重啟後也保持高能">重啟後也保持高能&lt;/h2>
&lt;h3 id="方案-a最穩妥推薦">方案 A：最穩妥推薦&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>apt install cpufrequtils -y
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#39;GOVERNOR=&amp;#34;performance&amp;#34;&amp;#39;&lt;/span> &amp;gt;/etc/default/cpufrequtils
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>systemctl enable cpufrequtils
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>systemctl start cpufrequtils
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="方案-bsystemd-自訂服務">方案 B：systemd 自訂服務&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># /etc/systemd/system/cpu-performance.service&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Unit&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Description&lt;span style="color:#f92672">=&lt;/span>Set CPU governor to performance
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>After&lt;span style="color:#f92672">=&lt;/span>multi-user.target
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Service&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Type&lt;span style="color:#f92672">=&lt;/span>oneshot
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>ExecStart&lt;span style="color:#f92672">=&lt;/span>/bin/bash -c &lt;span style="color:#e6db74">&amp;#39;for cpu in /sys/devices/system/cpu/cpu[0-9]*; do echo performance &amp;gt; $cpu/cpufreq/scaling_governor; done&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>Install&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>WantedBy&lt;span style="color:#f92672">=&lt;/span>multi-user.target
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>systemctl daemon-reexec
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>systemctl daemon-reload
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>systemctl enable --now cpu-performance.service
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>6首國際最強公認催眠曲</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250829-music/</link><pubDate>Fri, 29 Aug 2025 15:58:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250829-music/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.instagram.com/p/DNakVD4P_t9" target="_blank" rel="noopener">6 首國際最強公認催眠曲&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>Marconi Union - Weightless&lt;/li>
&lt;li>432Hz (深度治癒身心靈 連接宇宙能量)&lt;/li>
&lt;li>Clair de Lune&lt;/li>
&lt;li>Deep sleep delta waves - Binaural beats sleep (30 分鐘版本)&lt;/li>
&lt;li>Erik SATIE - Gymnopédie No. 1 (鋼琴慢速版)&lt;/li>
&lt;li>Himalayan Healing - Tibetan Singing Bowls Meditation (15 分鐘版本)&lt;/li>
&lt;/ol></description></item><item><title>透過LinuxServer.io打包的Docker映像檔，將桌面程式轉成網頁版，透過瀏覽器即可使用</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250801-linuxserver.io/</link><pubDate>Fri, 01 Aug 2025 15:52:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250801-linuxserver.io/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ivonblog.com/posts/linuxserver-io-docker-applications/" target="_blank" rel="noopener">透過 LinuxServer.io 打包的 Docker 映像檔，將桌面程式轉成網頁版，透過瀏覽器即可使用&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.linuxserver.io/our-images" target="_blank" rel="noopener">LinuxServer.io 官網&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Gluetun：讓Docker容器走VPN連線，沒網路就斷線，使用教學</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250801-gluetun-vpn-docker/</link><pubDate>Fri, 01 Aug 2025 15:51:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250801-gluetun-vpn-docker/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ivonblog.com/posts/gluetun-vpn-docker/" target="_blank" rel="noopener">Gluetun：讓 Docker 容器走 VPN 連線，沒網路就斷線，使用教學&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="gluetun">Gluetun&lt;/h2>
&lt;ul>
&lt;li>OpenVPN&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gluetun&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">qmcgaw/gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cap_add&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">NET_ADMIN&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">devices&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/dev/net/tun:/dev/net/tun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8888&lt;/span>:&lt;span style="color:#ae81ff">8888&lt;/span>&lt;span style="color:#ae81ff">/tcp&lt;/span> &lt;span style="color:#75715e"># HTTP proxy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8388&lt;/span>:&lt;span style="color:#ae81ff">8388&lt;/span>&lt;span style="color:#ae81ff">/tcp&lt;/span> &lt;span style="color:#75715e"># Shadowsocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8388&lt;/span>:&lt;span style="color:#ae81ff">8388&lt;/span>&lt;span style="color:#ae81ff">/udp&lt;/span> &lt;span style="color:#75715e"># Shadowsocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/home/user/gluetun:/gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>: &lt;span style="color:#75715e"># 按照VPN供應商的OpenVPN設定檔填寫&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">VPN_SERVICE_PROVIDER=protonvpn&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">VPN_TYPE=openvpn&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">OPENVPN_USER=&lt;/span> &lt;span style="color:#75715e"># OpenVPN帳號&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">OPENVPN_PASSWORD=&lt;/span> &lt;span style="color:#75715e"># OpenVPN密碼&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">SERVER_COUNTRIES=United Kingdom&lt;/span> &lt;span style="color:#75715e"># 指定伺服器所在國家，以逗號分隔&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">networks&lt;/span>: &lt;span style="color:#75715e"># (選擇性) 固定Gluetun容器的IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ipv4_address&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">networks&lt;/span>: &lt;span style="color:#75715e"># (選擇性) 固定Gluetun容器的IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">driver&lt;/span>: &lt;span style="color:#ae81ff">bridge&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ipam&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">subnet&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.0&lt;/span>&lt;span style="color:#ae81ff">/16&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gateway&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.5&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>WireGuard&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">services&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gluetun&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">image&lt;/span>: &lt;span style="color:#ae81ff">qmcgaw/gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">container_name&lt;/span>: &lt;span style="color:#ae81ff">gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">restart&lt;/span>: &lt;span style="color:#ae81ff">unless-stopped&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cap_add&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">NET_ADMIN&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">devices&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/dev/net/tun:/dev/net/tun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ports&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8888&lt;/span>:&lt;span style="color:#ae81ff">8888&lt;/span>&lt;span style="color:#ae81ff">/tcp&lt;/span> &lt;span style="color:#75715e"># HTTP proxy&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8388&lt;/span>:&lt;span style="color:#ae81ff">8388&lt;/span>&lt;span style="color:#ae81ff">/tcp&lt;/span> &lt;span style="color:#75715e"># Shadowsocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">8388&lt;/span>:&lt;span style="color:#ae81ff">8388&lt;/span>&lt;span style="color:#ae81ff">/udp&lt;/span> &lt;span style="color:#75715e"># Shadowsocks&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">volumes&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">/home/user/gluetun:/gluetun&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">environment&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">VPN_SERVICE_PROVIDER=protonvpn&lt;/span> &lt;span style="color:#75715e"># 按照VPN供應商的WireGuard設定檔填寫&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">VPN_TYPE=wireguard&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WIREGUARD_PRESHARED_KEY=&lt;/span> &lt;span style="color:#75715e"># 預共享密鑰&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WIREGUARD_PRIVATE_KEY=&lt;/span> &lt;span style="color:#75715e"># 私鑰&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">WIREGUARD_ADDRESSES=&lt;/span> &lt;span style="color:#75715e"># 填IPV4與IPV6位址，以逗號分隔&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">SERVER_COUNTRIES=United Kingdom&lt;/span> &lt;span style="color:#75715e"># 指定伺服器所在國家，以逗號分隔&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">networks&lt;/span>: &lt;span style="color:#75715e"># (選擇性) 固定Gluetun容器的IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ipv4_address&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">networks&lt;/span>: &lt;span style="color:#75715e"># (選擇性) 固定Gluetun容器的IP&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">network&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">driver&lt;/span>: &lt;span style="color:#ae81ff">bridge&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ipam&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">config&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">subnet&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.0&lt;/span>&lt;span style="color:#ae81ff">/16&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">gateway&lt;/span>: &lt;span style="color:#ae81ff">172.27.0.5&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="讓容器走-gluetun-的-vpn-連線">讓容器走 Gluetun 的 VPN 連線&lt;/h2>
&lt;ul>
&lt;li>如果容器服務跟 Gluetun 寫在同一個 docker-compose：加入網路模式 network_mode: &amp;ldquo;service:gluetun&amp;rdquo;&lt;/li>
&lt;li>如果該容器跟 Gluetun 不是寫在同一個 docker-compose：加入 network_mode: &amp;ldquo;container:gluetun&amp;rdquo;&lt;/li>
&lt;li>開啟 Gluetun 的 docker-compose 檔案，把 service 用到的通訊埠(ex:8080)加回來&lt;/li>
&lt;li>依序啟動 Gluetun 和 走 Gluetun 的 VPN 連線的服務&lt;/li>
&lt;li>容器公共 IP 應當跟您選擇的 VPN 伺服器一致&lt;/li>
&lt;/ul></description></item><item><title>Go实战指南：使用 go-redis 执行 Lua 脚本</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250722-go-redis-lua/</link><pubDate>Tue, 22 Jul 2025 16:56:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250722-go-redis-lua/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.liwenzhou.com/posts/Go/go-redis-lua/" target="_blank" rel="noopener">Go 实战指南：使用 go-redis 执行 Lua 脚本&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>Redis command &lt;code>Eval&lt;/code>&lt;/li>
&lt;li>Redis package &lt;code>redis.NewScript&lt;/code>, &lt;code>script.Run&lt;/code>&lt;/li>
&lt;/ol></description></item><item><title>TIL：Bash 腳本的 timeout</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250612-bash-timeout/</link><pubDate>Thu, 12 Jun 2025 09:04:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250612-bash-timeout/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://heitorpb.github.io/bla/timeout/" target="_blank" rel="noopener">TIL：Bash 腳本的 timeout&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>timeout 1m ./until.sh&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>包一層&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>timeout 1m bash -c &lt;span style="color:#e6db74">&amp;#34;until curl --silent --fail-with-body 10.0.0.1:8080/health; do
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> sleep 1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">done&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>TaigiTube 台語水管</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250508-taigitube/</link><pubDate>Thu, 08 May 2025 08:43:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250508-taigitube/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://taigitube.com/" target="_blank" rel="noopener">TaigiTube 台語水管&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>我用 Zip Bomb 來保護我的伺服器</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250503-zipbomb-protection/</link><pubDate>Sat, 03 May 2025 11:24:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250503-zipbomb-protection/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://idiallo.com/blog/zipbomb-protection" target="_blank" rel="noopener">我用 Zip Bomb 來保護我的伺服器&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>發生的情況是：對方收到檔案後，讀取標頭得知這是壓縮檔，因此嘗試解壓那個 1MB 的檔案來找他們要的內容。但檔案會不斷膨脹，直到耗盡記憶體、伺服器崩潰。1MB 的檔案會解壓成 1GB，這已足以讓多數機器人失敗。不過對於那些死纏爛打的腳本，我就給它 10MB 的檔案，解壓後會變成 10GB，立刻把腳本搞掛。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>dd if=/dev/zero bs=1G count=10 | gzip -c &amp;gt; 10GB.gz&lt;/code>&lt;/p>
&lt;ul>
&lt;li>&lt;code>dd&lt;/code>：用於複製或轉換資料的指令。&lt;/li>
&lt;li>&lt;code>if&lt;/code>：輸入檔案，這裡指定 &lt;code>/dev/zero&lt;/code>，它會產生無限的零位元組串流。&lt;/li>
&lt;li>&lt;code>bs&lt;/code>：區塊大小，設為 1GB（1G），代表 dd 會以 1GB 為單位讀寫。&lt;/li>
&lt;li>&lt;code>count=10&lt;/code>：代表處理 10 個區塊、每個 1GB，因此會產生 10GB 的零資料。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>middleware&lt;/p>
&lt;/li>
&lt;/ul>
&lt;pre tabindex="0">&lt;code>if (ipIsBlackListed() || isMalicious()) {
header(&amp;#34;Content-Encoding: gzip&amp;#34;);
header(&amp;#34;Content-Length: &amp;#34;. filesize(ZIP_BOMB_FILE_10G)); // 10 MB
readfile(ZIP_BOMB_FILE_10G);
exit;
}
&lt;/code>&lt;/pre></description></item><item><title>人人都需要一個 HTTP proxy 來 debug</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250425-everyone-need-a-http-proxy-to-debug/</link><pubDate>Fri, 25 Apr 2025 16:58:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250425-everyone-need-a-http-proxy-to-debug/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.huli.tw/2025/04/23/everyone-need-a-http-proxy-to-debug/" target="_blank" rel="noopener">人人都需要一個 HTTP proxy 來 debug&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>&lt;a href="https://www.charlesproxy.com/" target="_blank" rel="noopener">Charles&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://portswigger.net/burp/communitydownload" target="_blank" rel="noopener">Burp Suite&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://mitmproxy.org/" target="_blank" rel="noopener">mitmproxy&lt;/a>&lt;/li>
&lt;/ol></description></item><item><title>為什麼大寫字母的 QR Code 會比小寫字母的更小？</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250423-why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/</link><pubDate>Wed, 23 Apr 2025 15:45:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250423-why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/</guid><description>&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://shkspr.mobi/blog/2025/02/why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/" target="_blank" rel="noopener">為什麼大寫字母的 QR Code 會比小寫字母的更小？&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如果你想讓包含 URL 的二維碼擁有盡可能小的實體尺寸，請確保文字全部大寫。&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>Marp教學：Markdown搭配VS Code做簡報，快速輸出為PPTX或PDF，提昇做簡報效率</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250408-vscode-marp-presentation/</link><pubDate>Tue, 08 Apr 2025 09:12:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250408-vscode-marp-presentation/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://ivonblog.com/posts/vscode-marp-presentation/" target="_blank" rel="noopener">Marp 教學：Markdown 搭配 VS Code 做簡報，快速輸出為 PPTX 或 PDF，提昇做簡報效率&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>Install &amp;lsquo;Marp for VS Code&amp;rsquo;&lt;/li>
&lt;li>在 Markdown 最前面的 FrontMatter，插入以下屬性，啟用 Marp，並開啟顯示頁數功能&lt;/li>
&lt;/ol>
&lt;pre tabindex="0">&lt;code>---
marp:true
paginate: true
---
&lt;/code>&lt;/pre>&lt;ol start="3">
&lt;li>Markdown 文字都是直排排列的，需要換行請加上&lt;code>\&lt;/code>。&lt;/li>
&lt;li>輸入三條橫線&lt;code>---&lt;/code>分隔投影片。&lt;/li>
&lt;li>插入註解請用&lt;code>&amp;lt;!-- --&amp;gt;&lt;/code>語法。&lt;/li>
&lt;/ol></description></item><item><title>Go Protobuf：新的 Opaque API</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250407-protobuf-opaque/</link><pubDate>Mon, 07 Apr 2025 13:53:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250407-protobuf-opaque/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.liwenzhou.com/posts/Go/protobuf-opaque/" target="_blank" rel="noopener">[译]Go Protobuf：新的 Opaque API&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-diff" data-lang="diff">&lt;span style="display:flex;">&lt;span>protoc --proto_path=. \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> --go_out=./ \
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">+ --go_opt=default_api_level=API_OPAQUE \
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>macOS 使用技巧與小訣竅</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250307-macos-tips/</link><pubDate>Fri, 07 Mar 2025 16:05:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250307-macos-tips/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://saurabhs.org/macos-tips" target="_blank" rel="noopener">macOS 使用技巧與小訣竅&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="一般">一般&lt;/h3>
&lt;h4 id="原生-ui-習慣">原生 UI 習慣&lt;/h4>
&lt;ul>
&lt;li>按 ⇧⌘/ 可搜尋目前應用程式的所有選單項目，接著用上下箭頭瀏覽結果，按 &lt;code>Return&lt;/code> 執行該選單動作。&lt;/li>
&lt;li>按 ⌃F2 將鍵盤焦點移到應用程式的選單列，輸入選單標題的前幾個字母即可跳到該選單。&lt;/li>
&lt;li>展開樹狀清單時按住 &lt;code>Option&lt;/code> 可遞迴展開所有子項（最容易測試的地方是 Finder 的列表檢視）。&lt;/li>
&lt;li>在對話框/工作表上，按 &lt;code>Command&lt;/code> 加按鈕的首字母可直接按下該按鈕。⌘. 等同於 &lt;code>Escape&lt;/code>。&lt;/li>
&lt;li>按住 &lt;code>Control&lt;/code> 與 &lt;code>Option&lt;/code> 點擊視窗，可切換焦點但不把視窗置頂。&lt;/li>
&lt;li>拖曳工具列圖示時按住 &lt;code>Command&lt;/code> 可改變位置。&lt;/li>
&lt;li>預設在捲軸上點擊會部分捲動到該位置；按住 &lt;code>Option&lt;/code> 點擊捲軸可直接跳到點擊處。&lt;/li>
&lt;li>拖曳捲軸滑塊時按住 &lt;code>Option&lt;/code> 可慢速捲動。&lt;/li>
&lt;li>在可捲動區域，用上下鍵小幅捲動；按住 &lt;code>Option&lt;/code> 可大幅捲動，按住 &lt;code>Command&lt;/code> 則捲到開頭或結尾。&lt;/li>
&lt;li>按 Page Up/Page Down 時按住 &lt;code>Option&lt;/code>，捲動同時移動游標。&lt;/li>
&lt;li>在 Tab 鍵被視為輸入的欄位中，按 &lt;code>Control-Tab&lt;/code> 和 &lt;code>Control-Shift-Tab&lt;/code> 可移動到前一或下一個控制項。&lt;/li>
&lt;li>游標停在單字上時按 ⌃⌘D 可顯示行內字典解釋。&lt;/li>
&lt;li>按 ⌃F6 可把焦點移到浮動視窗。&lt;/li>
&lt;li>快速尋找文字：選取文字後按 ⌘E，再按 ⌘G。&lt;/li>
&lt;li>按 ⌃⌫ 可只刪除上一個字元的重音符號（例如 é 變成 e）。&lt;/li>
&lt;li>在字體視窗輸入 &lt;code>*X&lt;/code> 可縮放目前字體大小，例如 &lt;code>*1.5&lt;/code>。&lt;/li>
&lt;li>輸入文字時，按 ⌥⇧K（美式鍵盤）可插入蘋果標誌。&lt;/li>
&lt;li>拖曳子母畫面（PiP）視窗時按住 &lt;code>Command&lt;/code>，可自由移動而不會吸附到螢幕角落。&lt;/li>
&lt;/ul>
&lt;h4 id="截圖">截圖&lt;/h4>
&lt;ul>
&lt;li>按下 ⇧⌘4 並拖曳選取截圖區域時，按住 &lt;code>Option&lt;/code> 可從中心縮放，按住 &lt;code>Shift&lt;/code> 可只調整單一軸向。畫好區域後，按住空白鍵並拖曳可移動選取區域。&lt;/li>
&lt;li>按下 ⇧⌘4 後截圖時按住 &lt;code>Control&lt;/code>，可複製到剪貼簿而非儲存檔案。&lt;/li>
&lt;li>按下 ⇧⌘4 後按空白鍵可選擇視窗截圖，截圖時按住 &lt;code>Option&lt;/code> 可移除視窗陰影。&lt;/li>
&lt;li>在浮動截圖預覽上按右鍵可使用更多動作。&lt;/li>
&lt;/ul>
&lt;h4 id="開啟儲存對話框">開啟/儲存對話框&lt;/h4>
&lt;ul>
&lt;li>將 Finder 中的檔案或資料夾拖到開啟/儲存對話框，可直接跳到該位置。&lt;/li>
&lt;li>在儲存對話框按 ⌘= 可切換精簡與展開版面。&lt;/li>
&lt;li>在儲存對話框，按 ⌘⌫ 啟用 Delete，⌘D 啟用 Don&amp;rsquo;t Save，⌘.（或 &lt;code>Esc&lt;/code>）啟用 Cancel。&lt;/li>
&lt;li>按 &lt;code>~&lt;/code> 會開啟 Go To File 對話框並預填家目錄；按 &lt;code>/&lt;/code> 則預填根目錄。&lt;/li>
&lt;li>按 ⌘R 可在 Finder 顯示選取項目。&lt;/li>
&lt;/ul>
&lt;h4 id="mission-control--視窗管理">Mission Control / 視窗管理&lt;/h4>
&lt;ul>
&lt;li>視窗未啟用時，按住 &lt;code>Command&lt;/code> 可操作它而不會讓它變成前景視窗。&lt;/li>
&lt;li>按 Mission Control 功能鍵時按住 &lt;code>Control&lt;/code>，只顯示目前應用程式的視窗；按住 &lt;code>Command&lt;/code> 則顯示桌面。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 雙擊視窗角落可把視窗擴展填滿螢幕。&lt;/li>
&lt;li>&lt;code>Option&lt;/code> 點擊可切換視窗並隱藏前一個應用程式；&lt;code>Command-Option&lt;/code> 點擊可切換視窗並隱藏其他應用程式。&lt;/li>
&lt;li>在 Command-Tab 切換器中，按上下箭頭（或數字鍵 1）可查看該應用程式的視窗。&lt;/li>
&lt;li>在 Command-Tab 切換器中，按住 &lt;code>Option&lt;/code> 切換到應用程式，可解除最小化該應用程式的所有視窗。&lt;/li>
&lt;li>按 ⌘` 可在前景應用程式的視窗間循環切換。&lt;/li>
&lt;li>按 ⌃F4 可在目前桌面空間的所有應用程式視窗間循環切換。&lt;/li>
&lt;li>把視窗拖到螢幕頂部並向上推，可在 Mission Control 中選取該視窗。&lt;/li>
&lt;li>按 ⌥⌘W，或按住 &lt;code>Option&lt;/code> 點擊紅色關閉鍵，可關閉前景應用程式的所有視窗。&lt;/li>
&lt;li>按 ⌥⌘M，或按住 &lt;code>Option&lt;/code> 點擊黃色最小化鍵，可最小化前景應用程式的所有視窗。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 點擊綠色縮放鍵可填滿螢幕，而不是進入全螢幕。&lt;/li>
&lt;li>在系統設定中配置熱角時，按住 &lt;code>Control&lt;/code>、&lt;code>Option&lt;/code>、&lt;code>Command&lt;/code> 或 &lt;code>Shift&lt;/code> 可讓角落只在按住這些按鍵時才會觸發。&lt;/li>
&lt;li>在觸控板上，用兩指輕點（不是點擊）Dock 上的應用程式圖示，可顯示該應用程式的所有視窗；也可在該圖示上使用 App Exposé 手勢。&lt;/li>
&lt;li>調整視窗大小時按住 &lt;code>Option&lt;/code> 可從中心縮放；按住 &lt;code>Shift&lt;/code> 可鎖定長寬比。&lt;/li>
&lt;li>雙擊視窗邊框可把該邊延伸填滿螢幕；按住 &lt;code>Option&lt;/code> 雙擊則可同時延伸兩側。&lt;/li>
&lt;li>在 Mission Control 中，對一組應用程式視窗向上捲動可展開到單一視窗；游標停在視窗上按空白鍵可放大。&lt;/li>
&lt;li>在 Mission Control 中，Option 點擊另一個桌面空間可切換到該空間並保持 Mission Control 開啟。&lt;/li>
&lt;li>在 Mission Control 中，拖曳視窗下方的應用程式圖示可將該應用程式的所有視窗移到另一個空間。&lt;/li>
&lt;li>在 Mission Control 的應用程式視窗模式下，按 &lt;code>Tab&lt;/code> 與 &lt;code>Shift-Tab&lt;/code> 可切換應用程式。&lt;/li>
&lt;li>視窗若在其他空間被最小化，按住 &lt;code>Command&lt;/code> 再解除最小化可讓它回到目前空間。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 解除最小化視窗，可同時解除最小化該應用程式的所有視窗。&lt;/li>
&lt;li>若某應用在多個空間有視窗，重複點 Dock 圖示可在這些空間間切換。&lt;/li>
&lt;li>若啟用切換桌面空間的快捷鍵，按住快捷鍵並拖曳視窗可把視窗移到該空間。&lt;/li>
&lt;li>在幕前調度中，按住 &lt;code>Shift&lt;/code> 點擊視窗可將其加入目前舞台，而不是取代。&lt;/li>
&lt;/ul>
&lt;h4 id="功能鍵">功能鍵&lt;/h4>
&lt;ul>
&lt;li>調整音量或亮度時按住 &lt;code>Shift&lt;/code> 與 &lt;code>Option&lt;/code> 可做更細微的調整。&lt;/li>
&lt;li>調整亮度時按住 &lt;code>Option&lt;/code> 可快速開啟顯示器設定；調整音量時按住 &lt;code>Option&lt;/code> 可快速開啟聲音設定。&lt;/li>
&lt;li>調整音量時按住 &lt;code>Shift&lt;/code> 可預覽音量。&lt;/li>
&lt;li>連接外接螢幕時，調整亮度時按住 &lt;code>Control&lt;/code> 可調整非目前顯示器的亮度。&lt;/li>
&lt;li>按住 Mission Control 功能鍵不放，鬆開時會自動退出 Mission Control。&lt;/li>
&lt;/ul>
&lt;h4 id="選單列--通知中心">選單列 / 通知中心&lt;/h4>
&lt;ul>
&lt;li>按住 &lt;code>Option&lt;/code> 開啟 Wi-Fi 與藍牙選單可顯示更多選項。&lt;/li>
&lt;li>拖曳選單列圖示時按住 &lt;code>Command&lt;/code> 可改變位置。&lt;/li>
&lt;li>從控制中心拖曳圖示到選單列可新增選單列項目。&lt;/li>
&lt;li>Option 點擊選單列的日期時間可切換請勿打擾。&lt;/li>
&lt;li>右鍵點擊小工具可變更大小。&lt;/li>
&lt;li>在觸控板上，用兩指橫向滑過通知可將其移除。&lt;/li>
&lt;/ul>
&lt;h3 id="finder">Finder&lt;/h3>
&lt;ul>
&lt;li>複製檔案後按 ⌥⌘V 可移動檔案而非貼上副本。&lt;/li>
&lt;li>選取多個檔案時按 ⌃⌘N 可建立包含這些項目的新資料夾。&lt;/li>
&lt;li>按 &lt;code>Tab&lt;/code> 與 &lt;code>Shift-Tab&lt;/code> 可依字母順序瀏覽檔案，無視目前排序方式（僅限圖示與列表檢視）。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 啟動 Quick Look 可直接進入全螢幕。&lt;/li>
&lt;li>以多個檔案開啟 Quick Look 後，按 ⌘⏎ 可顯示所有項目的格狀檢視，用方向鍵選取並按 Return 聚焦。&lt;/li>
&lt;li>在 Quick Look 中，右鍵點擊「Open with」可選擇不同的開啟應用程式。&lt;/li>
&lt;li>在欄位檢視中，按住 &lt;code>Option&lt;/code> 拖曳欄位寬度可同時調整所有欄位。&lt;/li>
&lt;li>在欄位檢視中，雙擊欄位分隔線可自動調整該欄寬度；按住 &lt;code>Option&lt;/code> 雙擊可自動調整所有欄位。&lt;/li>
&lt;li>在欄位檢視中，點擊資料夾底部的空白區可回到上一層資料夾。&lt;/li>
&lt;li>在欄位檢視中，當你位於深層目錄時，按 &lt;code>Shift-Tab&lt;/code> 與 &lt;code>Tab&lt;/code> 可在不丟失路徑的情況下切換父層目錄。&lt;/li>
&lt;li>拖曳檔案時按住 &lt;code>Option&lt;/code> 可建立副本，按住 &lt;code>Command&lt;/code> 與 &lt;code>Option&lt;/code> 則會建立捷徑。&lt;/li>
&lt;li>在列表檢視中，按 ⌘+ 與 ⌘- 可放大或縮小列高。&lt;/li>
&lt;li>在列表檢視中，按 ⌥↑ 與 ⌥↓ 可選取最上或最下的項目。&lt;/li>
&lt;li>在列表檢視中，按左右箭頭可折疊或展開目錄；選取檔案時按左鍵可回到父層目錄。&lt;/li>
&lt;li>按 ⌘I 可開啟目前檔案的檢查器；按 ⌥⌘I 則開啟會隨選取變化的浮動檢查器。&lt;/li>
&lt;li>按 ⌥⌘C 可複製目前選取檔案的完整路徑。&lt;/li>
&lt;li>按 ⇧⌘. 可切換顯示隱藏檔案。&lt;/li>
&lt;li>按 ⌥⌘⌫ 可立即刪除檔案而不送進垃圾桶。&lt;/li>
&lt;li>拖曳資料夾到另一個資料夾上時按住 &lt;code>Option&lt;/code> 可合併資料夾。&lt;/li>
&lt;li>複製新圖示後，開啟檢查器（⌘I），選取左上角資料夾圖示並按 ⌘V 可設定自訂圖示。&lt;/li>
&lt;li>將選取文字拖到 Finder 視窗，可快速建立文字剪貼並儲存（文字剪貼是無法編輯、且不需命名的文字檔）。&lt;/li>
&lt;li>按 ⌥⌘O 可開啟所選檔案並自動關閉 Finder 視窗。&lt;/li>
&lt;li>按 ⌥⇧⌘V 可貼上項目並保留檔案權限標記。&lt;/li>
&lt;li>在圖示檢視中拖曳圖示時按住 &lt;code>Command&lt;/code> 可對齊格線。&lt;/li>
&lt;li>在 Finder Dock 圖示上按住 &lt;code>Option&lt;/code> 右鍵並選擇 Relaunch 可重新啟動 Finder。&lt;/li>
&lt;li>拖曳資料夾到新分頁按鈕（需已有多個分頁）可在新分頁開啟該資料夾。&lt;/li>
&lt;li>按 ⌃⌘↑ 可在新視窗開啟父層資料夾。&lt;/li>
&lt;li>若工具列被隱藏（⌥⌘T），Finder 會在新視窗開啟資料夾。&lt;/li>
&lt;li>選取圖片後按 ⌘R 可順時針旋轉，按 ⌘L 可逆時針旋轉。&lt;/li>
&lt;/ul>
&lt;h3 id="dock">Dock&lt;/h3>
&lt;ul>
&lt;li>按 ⌥⌘D 可顯示或隱藏 Dock。&lt;/li>
&lt;li>按 ⌃F3 將鍵盤焦點移到 Dock，再用左右箭頭選取應用程式，或輸入應用程式前幾個字母，按 &lt;code>Enter&lt;/code> 開啟；按上箭頭可打開該應用程式的選單。&lt;/li>
&lt;li>按住 &lt;code>Control&lt;/code> 與 &lt;code>Shift&lt;/code> 在 Dock 上移動滑鼠可暫時開啟放大效果。&lt;/li>
&lt;li>拖曳 Dock 的縮放把手時按住 &lt;code>Shift&lt;/code> 可快速把 Dock 移到不同螢幕邊緣。&lt;/li>
&lt;li>調整 Dock 大小時按住 &lt;code>Option&lt;/code> 可用 16 點的倍數縮放。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 與 &lt;code>Command&lt;/code> 點擊正在執行的 Dock 圖示，可隱藏其他應用程式。&lt;/li>
&lt;li>將檔案拖到 Dock 上的應用程式圖示可用指定應用程式開啟；若預設不支援該檔案類型，拖曳時按住 &lt;code>Option&lt;/code> 與 &lt;code>Command&lt;/code> 可強制開啟。&lt;/li>
&lt;li>Dock 圖示持續彈跳時，把游標移到圖示上可停止彈跳。&lt;/li>
&lt;li>右鍵點擊 Dock 圖示時按住 &lt;code>Control&lt;/code> 與 &lt;code>Command&lt;/code> 可只顯示預設系統選單項目。&lt;/li>
&lt;li>按住 &lt;code>Option&lt;/code> 與 &lt;code>Command&lt;/code> 點擊 Dock 中的資料夾可在新的 Finder 視窗開啟。&lt;/li>
&lt;li>在堆疊中開啟多個項目時，按住 &lt;code>Option&lt;/code> 點選可在背景開啟，堆疊不會關閉。&lt;/li>
&lt;li>開啟堆疊後，把游標移到項目上並按空白鍵可用 Quick Look 預覽。&lt;/li>
&lt;li>右鍵點擊 Launchpad 圖示可從行內選單開啟應用程式。&lt;/li>
&lt;li>在 Launchpad 中按住 &lt;code>Option&lt;/code> 可進入抖動模式，重新排列或刪除應用程式。&lt;/li>
&lt;li>要把 AirDrop 加到 Dock，請在 Finder 前往 &lt;code>/System/Library/CoreServices/Finder.app/Contents/Applications&lt;/code>，並把 AirDrop 圖示拖到 Dock。&lt;/li>
&lt;/ul>
&lt;h3 id="spotlight">Spotlight&lt;/h3>
&lt;ul>
&lt;li>按 ⌘B 可用目前的查詢搜尋網頁。&lt;/li>
&lt;li>按 ⌘C 可複製所選檔案的完整路徑，或複製目前計算結果。&lt;/li>
&lt;li>按 ⌘D 可用目前查詢開啟字典。&lt;/li>
&lt;li>按 ⌘L 可跳到結果中的字典區塊（若存在）。&lt;/li>
&lt;li>按 ⌘⏎ 或 ⌘R 可在 Finder 顯示所選檔案。&lt;/li>
&lt;li>使用 &lt;code>name:&lt;/code> 篩選只搜尋檔名。&lt;/li>
&lt;li>使用 &lt;code>kind:folder&lt;/code> 只搜尋資料夾名稱。&lt;/li>
&lt;li>按住 &lt;code>Command&lt;/code> 可顯示目前選取檔案的路徑。&lt;/li>
&lt;/ul>
&lt;h3 id="safari">Safari&lt;/h3>
&lt;ul>
&lt;li>分頁群組會以空間方式整理分頁；使用 ⌥⌘{↑,↓,←,→} 可在 2D 空間中瀏覽分頁。&lt;/li>
&lt;li>播放影片時，右鍵點擊網址列或分頁上的喇叭圖示可進入子母畫面（PiP）。&lt;/li>
&lt;li>關閉分頁時按住 &lt;code>Option&lt;/code> 可關閉其他分頁，僅保留目前分頁。&lt;/li>
&lt;li>點擊並按住返回鍵可查看近期瀏覽記錄；按住 &lt;code>Option&lt;/code> 可顯示 URL 而非標題。&lt;/li>
&lt;li>把選取文字拖到 Safari 的 Dock 圖示可快速搜尋網頁。&lt;/li>
&lt;li>按 ⇧⌘T 可重新開啟最近關閉的分頁或視窗。&lt;/li>
&lt;li>按住工具列的新分頁圖示可查看最近關閉的分頁。&lt;/li>
&lt;li>在網址列開頭按空白鍵可變更搜尋引擎並查看近期網頁搜尋。&lt;/li>
&lt;li>在 Spotlight 搜尋中加入 &lt;code>kind:bookmark&lt;/code> 可搜尋 Safari 書籤與瀏覽記錄。&lt;/li>
&lt;li>&lt;code>Shift&lt;/code> 點擊連結可加入閱讀列表。&lt;/li>
&lt;li>點擊並按住書籤列的書籤可編輯顯示標題。&lt;/li>
&lt;li>Option 點擊重新整理圖示或按 ⌥⌘R 可強制重新載入目前網頁。&lt;/li>
&lt;li>右鍵點擊網址列的閱讀器圖示，可讓目前網站的所有頁面自動開啟閱讀模式。&lt;/li>
&lt;li>執行網頁搜尋並在同一分頁開啟結果後，按 ⌥⌘S 可回到搜尋結果頁。&lt;/li>
&lt;li>按 ⇧⌘I 可建立包含目前頁面內容的新郵件。&lt;/li>
&lt;li>在 History &amp;gt; Clear History 上按住 &lt;code>Option&lt;/code> 可只清除瀏覽記錄並保留網站資料。&lt;/li>
&lt;li>游標停在連結上按 ⌃⌘D 可顯示連結的行內預覽。&lt;/li>
&lt;/ul>
&lt;h3 id="mail">Mail&lt;/h3>
&lt;ul>
&lt;li>在左側欄以 &lt;code>Command&lt;/code> 點擊多個信箱可同時檢視其郵件。&lt;/li>
&lt;li>回覆或轉寄前先選取訊息中的部分文字，可只在新訊息中包含該段落。&lt;/li>
&lt;li>將檔案拖到 Mail 的 Dock 圖示可建立新郵件並附上該檔案。&lt;/li>
&lt;li>按 ⌥⇧⌘N 可建立新分頁。&lt;/li>
&lt;li>在訊息結尾按空白鍵可前往下一封訊息；在訊息開頭按住 &lt;code>Shift&lt;/code> 再按空白鍵可回到上一封訊息。&lt;/li>
&lt;li>開始輸入寄件者、主旨或內文的前幾個字元可快速跳到該訊息。&lt;/li>
&lt;li>按 ⌥⌘↑ 與 ⌥⌘↓ 可跳到最上或最下的訊息。&lt;/li>
&lt;li>將重要郵件拖到 Finder 可保留額外備份。&lt;/li>
&lt;li>若郵件退信，可在退信上使用 &lt;code>Message &amp;gt; Send Again&lt;/code> 改寄到其他地址。&lt;/li>
&lt;li>拖曳郵件到資料夾時按住 Command 可同時加入多個資料夾。&lt;/li>
&lt;li>按 ⇧⌘C 可替郵件標記顏色。&lt;/li>
&lt;li>把郵件拖到 Notes 或 Reminders 可新增連結。&lt;/li>
&lt;li>回覆郵件時按 ⌘R 與 ⇧⌘R 可在回覆與回覆全部之間切換。&lt;/li>
&lt;li>按 ⌥⌫ 可刪除郵件且不會自動開啟下一封。&lt;/li>
&lt;li>&lt;code>Command&lt;/code> 點擊目前選取的郵件可取消選取。&lt;/li>
&lt;li>若郵件已被回覆，可點訊息列表中的回覆圖示在新視窗開啟回覆。&lt;/li>
&lt;li>建立新信箱時，在名稱中加入斜線可建立巢狀信箱。&lt;/li>
&lt;li>After performing a search, select a mailbox from the left sidebar to filter the search to that mailbox.&lt;/li>
&lt;li>Hold &lt;code>Shift&lt;/code> while launching Mail to reset the index.&lt;/li>
&lt;/ul>
&lt;h3 id="preview">Preview&lt;/h3>
&lt;ul>
&lt;li>Press ` to bring up a magnifier, and then press &lt;code>+&lt;/code> and &lt;code>-&lt;/code> to resize it.&lt;/li>
&lt;li>In a PDF document, re-order the pages in the document by re-ordering the pages in the sidebar.&lt;/li>
&lt;li>Merge two PDF documents by dragging pages from one document&amp;rsquo;s sidebar to the other document&amp;rsquo;s sidebar.&lt;/li>
&lt;li>In the save dialog for an image, hold &lt;code>Option&lt;/code> while opening the Format menu to access an extended list of formats.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> and the Space bar to activate the pan tool.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while in text selection mode to switch to rectangular text selection.&lt;/li>
&lt;/ul>
&lt;h3 id="calendar">Calendar&lt;/h3>
&lt;ul>
&lt;li>Hold &lt;code>Shift&lt;/code> while dragging an event to set a more precise time instead of snapping to 15-minute intervals.&lt;/li>
&lt;li>Click and hold the &lt;code>Accept&lt;/code> button in a calendar invite to change which calendar the event is accepted to.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while pressing the &lt;code>Accept&lt;/code> button in a calendar invite to accept all events.&lt;/li>
&lt;li>Hold &lt;code>Command&lt;/code> while clicking any calendar&amp;rsquo;s checkbox in the left sidebar to show or hide all calendars.&lt;/li>
&lt;li>Hold &lt;code>Command&lt;/code> and &lt;code>Option&lt;/code> while clicking a calendar&amp;rsquo;s checkbox to only show that calendar.&lt;/li>
&lt;li>Add &lt;code>kind:event&lt;/code> to Spotlight searches to search calendar events.&lt;/li>
&lt;li>Resize the mini-calendar in the bottom-left to preview more months.&lt;/li>
&lt;li>With an event selected, press ⌃⌥↑ and ⌃⌥↓ to adjust the time of the event. This also works with multiple events selected.&lt;/li>
&lt;li>In Week view, press ⌥⌘← and ⌥⌘→ to shift the view by a single day.&lt;/li>
&lt;/ul>
&lt;h3 id="messages">Messages&lt;/h3>
&lt;ul>
&lt;li>Press ⌘R to directly reply to the latest message in the conversation.
Press ⇧⌘R to reply to the latest thread in the conversation.&lt;/li>
&lt;li>Press ⌘T to bring up the tapback selector for the latest message. Use the 1-6 number keys to select a reaction.&lt;/li>
&lt;li>Press ⌘E to edit the latest sent message.&lt;/li>
&lt;li>Press ⌥↑ and ⌥↓ in the message input field to cycle through previously sent messages.&lt;/li>
&lt;li>Press ⌘1-9 to jump to a pinned conversation.&lt;/li>
&lt;li>Right-click on a message and select Show Times to view exact timestamps for each message.&lt;/li>
&lt;li>Right-click the Messages icon in the Dock to quickly view and jump to unread conversations.&lt;/li>
&lt;/ul>
&lt;h3 id="photos">Photos&lt;/h3>
&lt;ul>
&lt;li>Drag an item to the &amp;ldquo;My Albums&amp;rdquo; header section to quickly create an album with that item.&lt;/li>
&lt;li>After adding an item to an album, use ⌃⌘A to add other items to that same album.&lt;/li>
&lt;li>When editing an image, hold down the &lt;code>M&lt;/code> key to compare the modifications to the original.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while launching Photos to choose a different photo library to open.&lt;/li>
&lt;li>Drag a photo from the Photos app into a Finder window to quickly export the photo, or into the Mail or Messages app to attach the photo.&lt;/li>
&lt;li>When editing an image, double-click an adjustment slider to reset it.&lt;/li>
&lt;li>When editing an image, hold &lt;code>Option&lt;/code> while holding the pointer over an adjustment slider to extend the adjustment range.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while clicking the rotate button to reverse the rotation direction.&lt;/li>
&lt;li>Hold &lt;code>Shift&lt;/code> while cropping a photo to maintain the current aspect ratio, and hold &lt;code>Option&lt;/code> to crop from the center of the photo.&lt;/li>
&lt;/ul>
&lt;h3 id="textedit">TextEdit&lt;/h3>
&lt;ul>
&lt;li>In rich text mode, press &lt;code>Option-Tab&lt;/code> to insert an outlined list.&lt;/li>
&lt;li>Press &lt;code>Option-Escape&lt;/code> to autocomplete the current word.&lt;/li>
&lt;li>Press ⌃⌥⌘P in the find text field (⌘F) to access special search tokens.&lt;/li>
&lt;li>Hold &lt;code>Option&lt;/code> while selecting text to make vertical text selections.&lt;/li>
&lt;li>The select line dialog (⌘L) supports the following formats:
&lt;code>1-3&lt;/code> selects lines 1-3 in the document
&lt;code>+2&lt;/code> selects the 2nd line below the cursor
&lt;code>-2&lt;/code> selects the 2nd line above the cursor
&lt;code>+2-4&lt;/code> selects 3 lines, starting from 2 lines below the cursor
&lt;code>-2-4&lt;/code> selects 3 lines, starting from 2 lines above the cursor&lt;/li>
&lt;/ul>
&lt;h3 id="terminal">Terminal&lt;/h3>
&lt;ul>
&lt;li>Press ⇧⌘A to select the output from the previous command.&lt;/li>
&lt;li>Press ⌘L to clear the output from the previous command.&lt;/li>
&lt;li>Press ⌃⌘V to paste and format text that is properly escaped for the shell.&lt;/li>
&lt;li>Press ⌃T while a command is executing to view runtime statistics about the execution so far.&lt;/li>
&lt;li>Press ⌘{↑,↓} to select the previous/next commands. Then press ⇧⌘A to select the output of the currently selected command.&lt;/li>
&lt;li>Press ⇧⌘I to set a title for the current window and tab.&lt;/li>
&lt;li>Drag a file or folder into a Terminal window to insert its full path. Alternatively, copy a file or folder in Finder and paste it in Terminal to insert its path.&lt;/li>
&lt;/ul>
&lt;h3 id="calculator">Calculator&lt;/h3>
&lt;ul>
&lt;li>Press ⌘T to open a new window that keeps a running history of calculations.&lt;/li>
&lt;li>Press ⌘R to enable Reverse Polish notation (RPN) mode.&lt;/li>
&lt;li>Press &lt;code>p&lt;/code> to insert pi.&lt;/li>
&lt;li>Right-click the number display and select &amp;ldquo;Large Type&amp;rdquo; to view the current result in a large overlay window.&lt;/li>
&lt;li>Use the Convert menu to perform various unit conversions.&lt;/li>
&lt;li>In Programmer view (⌘3), click the individual binary bits to toggle between 0 and 1.&lt;/li>
&lt;/ul>
&lt;h3 id="quicktime-player">QuickTime Player&lt;/h3>
&lt;ul>
&lt;li>Grab a single frame from a video by pausing on the desired frame (using the Left and Right arrow keys to navigate individual frames) and pressing ⌘C.&lt;/li>
&lt;/ul>
&lt;h3 id="photo-booth">Photo Booth&lt;/h3>
&lt;ul>
&lt;li>Hold &lt;code>Option&lt;/code> while taking a picture to skip the countdown.&lt;/li>
&lt;li>Hold &lt;code>Shift&lt;/code> while taking a picture to disable the screen flash.&lt;/li>
&lt;li>When choosing one of the distortion effects (on the third page), click and drag the cursor on the image preview to change the effects origin.&lt;/li>
&lt;/ul></description></item><item><title>Git 核心開發者如何設定 Git</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250307-how-git-core-devs-configure-git/</link><pubDate>Fri, 07 Mar 2025 15:46:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250307-how-git-core-devs-configure-git/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://blog.gitbutler.com/how-git-core-devs-configure-git/" target="_blank" rel="noopener">Git 核心開發者如何設定 Git&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># clearly makes git better&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>column&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ui &lt;span style="color:#f92672">=&lt;/span> auto
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>branch&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sort &lt;span style="color:#f92672">=&lt;/span> -committerdate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>tag&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sort &lt;span style="color:#f92672">=&lt;/span> version:refname
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>init&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> defaultBranch &lt;span style="color:#f92672">=&lt;/span> main
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>diff&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> algorithm &lt;span style="color:#f92672">=&lt;/span> histogram
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> colorMoved &lt;span style="color:#f92672">=&lt;/span> plain
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> mnemonicPrefix &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> renames &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>push&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> default &lt;span style="color:#f92672">=&lt;/span> simple
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autoSetupRemote &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> followTags &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>fetch&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> prune &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> pruneTags &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> all &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># why the hell not?&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>help&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autocorrect &lt;span style="color:#f92672">=&lt;/span> prompt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>commit&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> verbose &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>rerere&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> enabled &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autoupdate &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>core&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> excludesfile &lt;span style="color:#f92672">=&lt;/span> ~/.gitignore
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>rebase&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autoSquash &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> autoStash &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> updateRefs &lt;span style="color:#f92672">=&lt;/span> true
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># a matter of taste (uncomment if you dare)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>core&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># fsmonitor = true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># untrackedCache = true&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>merge&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># (just &amp;#39;diff3&amp;#39; if git version &amp;lt; 2.3)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># conflictstyle = zdiff3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>pull&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># rebase = true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>設定多個 GitHub 帳號的 SSH 金鑰</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250211-configure-ssh-keys-for-multiple-github-accounts/</link><pubDate>Tue, 11 Feb 2025 15:06:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250211-configure-ssh-keys-for-multiple-github-accounts/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://stevenharman.net/configure-ssh-keys-for-multiple-github-accounts" target="_blank" rel="noopener">設定多個 GitHub 帳號的 SSH 金鑰&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="使用不同的-host-值">使用不同的 Host 值&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>Host github.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> HostName github.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> User git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> IdentityFile ~/.ssh/id_fry_ed25519
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Host github-plnx
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> HostName github.com
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> User git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> IdentityFile ~/.ssh/id_fry_plnx_ed25519
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Instead of the actual URL&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ git clone git@github.com:planet-express/delivery_service.git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Substitue in our custom Host value for the `github.com` part&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>$ git clone git@github-plnx:planet-express/delivery_service.git
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="自動替換-host">自動替換 Host&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>include&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> path &lt;span style="color:#f92672">=&lt;/span> ~/.gitconfig_custom
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># See custom `Host github-plnx` in ~/.ssh/config&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>url &lt;span style="color:#e6db74">&amp;#34;github-plnx:planet-express&amp;#34;&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> insteadOf &lt;span style="color:#f92672">=&lt;/span> git@github.com:planet-express
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>我覺得好用的 iTerm2 功能</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250209-iterm2-features-i-find-useful/</link><pubDate>Sun, 09 Feb 2025 08:52:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250209-iterm2-features-i-find-useful/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://danielde.dev/blog/iterm2-features-i-find-useful" target="_blank" rel="noopener">我覺得好用的 iTerm2 功能&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>顯示時間戳記 ==&amp;gt; &lt;code>⌘+Shift+E&lt;/code>&lt;/li>
&lt;li>在下一個提示時提醒 ==&amp;gt; &lt;code>⌘+Option+A&lt;/code>&lt;/li>
&lt;li>在提示之間跳轉 ==&amp;gt; &lt;code>⌘+Shift+Down&lt;/code>&lt;/li>
&lt;li>逐行捲動快捷鍵 ==&amp;gt; &lt;code>⌘+Up&lt;/code> and &lt;code>⌘+Down&lt;/code>&lt;/li>
&lt;li>用快捷鍵重新排列分頁 ==&amp;gt; &lt;code>Ctrl+Shift+B&lt;/code> and &lt;code>Ctrl+Shift+F&lt;/code>&lt;/li>
&lt;/ol></description></item><item><title>GitLab CI 可以自動檢測程式碼品質！SonarQube 程式碼品質檢測怎麼做？</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250206-go-sonarqube/</link><pubDate>Thu, 06 Feb 2025 12:01:22 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250206-go-sonarqube/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://medium.com/@martina.says/gitlab-ci-%E5%8F%AF%E4%BB%A5%E8%87%AA%E5%8B%95%E6%AA%A2%E6%B8%AC%E7%A8%8B%E5%BC%8F%E7%A2%BC%E5%93%81%E8%B3%AA-sonarqube-%E7%A8%8B%E5%BC%8F%E7%A2%BC%E5%93%81%E8%B3%AA%E6%AA%A2%E6%B8%AC%E6%80%8E%E9%BA%BC%E5%81%9A-7002bd0dcc5a" target="_blank" rel="noopener">GitLab CI 可以自動檢測程式碼品質！SonarQube 程式碼品質檢測怎麼做？&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/tedmax100/Go_GitLab_SonarQube_Example" target="_blank" rel="noopener">Go_GitLab_SonarQube_Example&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>GraphQL 內省查詢</title><link>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250102-gql-introspection-query/</link><pubDate>Thu, 02 Jan 2025 15:32:00 +0800</pubDate><guid>https://9855cc0f.linzeyan.pages.dev/zh-tw/posts/2025/20250102-gql-introspection-query/</guid><description>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-graphql" data-lang="graphql">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">query&lt;/span> &lt;span style="color:#a6e22e">IntrospectionQuery&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> __schema {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">query&lt;/span>&lt;span style="color:#a6e22e">Type&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">mutation&lt;/span>&lt;span style="color:#a6e22e">Type&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">subscription&lt;/span>&lt;span style="color:#a6e22e">Type&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span>&lt;span style="color:#a6e22e">s&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">...&lt;/span>FullType
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">directive&lt;/span>s {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> description
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> locations
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> args {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">...&lt;/span>InputValue
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fragment&lt;/span> &lt;span style="color:#a6e22e">FullType&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span> __Type {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> description
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields(includeDeprecated: &lt;span style="color:#a6e22e">true&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> description
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> args {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">...&lt;/span>InputValue
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">...&lt;/span>&lt;span style="color:#a6e22e">TypeRef&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> isDeprecated
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> deprecationReason
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">input&lt;/span>&lt;span style="color:#a6e22e">Fields&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">...&lt;/span>InputValue
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">interface&lt;/span>&lt;span style="color:#a6e22e">s&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">...&lt;/span>TypeRef
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">enum&lt;/span>&lt;span style="color:#a6e22e">Values&lt;/span>(includeDeprecated: &lt;span style="color:#a6e22e">true&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> description
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> isDeprecated
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> deprecationReason
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> possibleTypes {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">...&lt;/span>TypeRef
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fragment&lt;/span> &lt;span style="color:#a6e22e">InputValue&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span> __InputValue {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> description
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">type&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">...&lt;/span>&lt;span style="color:#a6e22e">TypeRef&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> defaultValue
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fragment&lt;/span> &lt;span style="color:#a6e22e">TypeRef&lt;/span> &lt;span style="color:#66d9ef">on&lt;/span> __Type {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ofType {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ofType {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ofType {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ofType {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ofType {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ofType {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ofType {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> kind
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item></channel></rss>