<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Docker on 亂筆</title>
        <link>https://blog.l3zc.com/zh-hant-tw/tags/docker/</link>
        <description>Recent content in Docker on 亂筆</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-hant-tw</language>
        <lastBuildDate>Wed, 08 Jul 2026 17:02:34 +0800</lastBuildDate><atom:link href="https://blog.l3zc.com/zh-hant-tw/tags/docker/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>拋棄所謂「客戶端」，直接使用 Mihomo 內核</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2025/07/switch-to-pure-mihomo-kernel/</link>
            <pubDate>Thu, 03 Jul 2025 10:30:00 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2025/07/switch-to-pure-mihomo-kernel/</guid>
            <description>&lt;img src=&#34;https://blog.l3zc.com/2025/07/switch-to-pure-mihomo-kernel/cover_hu_1a93b6f26c22bbfe.webp&#34; alt=&#34;Featured image of post 拋棄所謂「客戶端」，直接使用 Mihomo 內核&#34; /&gt;&lt;p&gt;自從開始使用 Clash/Mihomo，我和大多數人一樣選擇了基於其內核的圖形化客戶端——圖方便。實際上，這些 Mihomo 客戶端本質上都差不多：內核都是同一個，他們主要負責提供一個易用的界面、管理配置文件、訂閱更新，以及 GUI 下的系統代理設置。基於這一點，我認為判斷一個 Mihomo 客戶端優劣的關鍵，便是看它的「覆寫」功能做得如何。每一個通過客戶端下載或者訂閱的配置文件，都會經過一系列「覆寫」過程，比如更換 &lt;code&gt;mixed-port&lt;/code&gt;、添加 &lt;code&gt;sniffer&lt;/code&gt; 配置等，最後生成用於啟動 Mihomo 內核的最終配置。&lt;/p&gt;&#xA;&lt;p&gt;然而，並非所有客戶端都能勝任這一核心工作。比如 ShellCrash，其覆寫功能經常莫名其妙出岔子，說到底還是實現得太粗糙。如果連覆蓋和修改配置都做不好，這種客戶端實在難稱合格。&lt;/p&gt;&#xA;&lt;p&gt;與其依賴這些&lt;del&gt;屎一樣的&lt;/del&gt;不盡如人意的 Mihomo 客戶端，不如自己動手，直接自己編寫、管理配置文件交給內核啟動，而不是依賴「黑箱」一般的各種「客戶端」，不僅更純淨、更穩定，而且更可控。&lt;/p&gt;&#xA;&lt;h2 id=&#34;需要的預備知識&#34;&gt;需要的預備知識&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;基本的 Linux 操作&lt;/li&gt;&#xA;&lt;li&gt;知道如何使用 CLI 編輯器，如 nano&lt;/li&gt;&#xA;&lt;li&gt;已經搭建 Substore（可選）&lt;/li&gt;&#xA;&lt;li&gt;默認使用 root 用戶操作，非 root 用戶請自行注意提權&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;安裝-mihomo-內核&#34;&gt;安裝 Mihomo 內核&#xA;&lt;/h2&gt;&lt;p&gt;對於基於 Debian 的分支，可以使用預編譯的&lt;code&gt;.deb&lt;/code&gt;包安裝，對於其他使用&lt;code&gt;systemd&lt;/code&gt;的系統，下載&lt;a class=&#34;link&#34; href=&#34;https://github.com/MetaCubeX/mihomo/releases&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;編譯好的二進制文件&lt;/a&gt;，重命名為&lt;code&gt;mihomo&lt;/code&gt;，放到&lt;code&gt;/usr/local/bin&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;curl -o /usr/local/bin/mihomo &lt;下載鏈接&gt;&#xA;chmod +x /usr/local/bin/mihomo&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然後新建&lt;code&gt;/etc/systemd/system/mihomo.service&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-systemd&#34;&gt;[Unit]&#xA;Description=mihomo Daemon, Another Clash Kernel.&#xA;After=network.target NetworkManager.service systemd-networkd.service iwd.service&#xA;&#xA;[Service]&#xA;Type=simple&#xA;LimitNPROC=500&#xA;LimitNOFILE=1000000&#xA;CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_TIME CAP_SYS_PTRACE CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE&#xA;AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SYS_TIME CAP_SYS_PTRACE CAP_DAC_READ_SEARCH CAP_DAC_OVERRIDE&#xA;Restart=always&#xA;ExecStartPre=/usr/bin/sleep 1s&#xA;ExecStart=/usr/local/bin/mihomo -d /etc/mihomo&#xA;ExecReload=/bin/kill -HUP $MAINPID&#xA;&#xA;[Install]&#xA;WantedBy=multi-user.target&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用&lt;code&gt;systemctl daemon-reload&lt;/code&gt;重新加載&lt;code&gt;systemd&lt;/code&gt;，此時還沒有配置文件，不能直接啟動內核，但可以使用&lt;code&gt;systemctl enable mihomo&lt;/code&gt;讓內核開機自啟，方便後續使用。&lt;/p&gt;&#xA;&lt;h2 id=&#34;配置文件&#34;&gt;配置文件&#xA;&lt;/h2&gt;&lt;p&gt;內核啟動時會加載&lt;code&gt;/etc/mihomo/config.yaml&lt;/code&gt;，沒有了黑箱一樣的礙事「客戶端」，配置文件可以隨心所欲的定製。部分機場會下發完整的配置文件，直接用&lt;code&gt;curl&lt;/code&gt;下載即可。&lt;/p&gt;&#xA;&lt;p&gt;對於訂閱的管理，我目前使用 Substore，我之前分享過&lt;a class=&#34;link&#34; href=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/&#34; &gt;「最速 Substore 訂閱管理指南」&lt;/a&gt;，可以直接參考這篇文章來定製自己的訂閱。為了實現純內核啟動，現在我的 Substore &lt;a class=&#34;link&#34; href=&#34;https://github.com/powerfullz/override-rules/blob/main/convert.js&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;JS 格式覆寫&lt;/a&gt;已經加入了&lt;code&gt;full&lt;/code&gt;參數，可以生成完整的配置文件，包括各種端口設置、統一延遲和外部控制器等，開箱即用。&lt;/p&gt;&#xA;&lt;p&gt;在 Substore 配置完成以後便可以下載配置文件並啟動內核：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;sudo curl -o /etc/mihomo/config.yaml 配置文件鏈接&#xA;sudo systemctl start mihomo&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;自定義覆寫&#34;&gt;自定義覆寫&#xA;&lt;/h3&gt;&lt;p&gt;我的配置文件不能滿足你的所有需求？沒問題！你可以自己添加覆寫，想要什麼加什麼。&lt;/p&gt;&#xA;&lt;p&gt;我用過各種覆寫規則，後來也開始自己從零開始編寫覆寫規則，即使使用自己的覆寫規則能滿足 99% 的場景，但有極個別的域名還是會在規則中有遺漏，更不用說用別人寫的覆寫規則了。這些遺漏的規則大多是形如我服務器的非標準端口 SSH 的前置代理等相對隱私的規則，直接上傳到 Github 公開顯然不太合適，那麼在自定義規則的基礎上再添加覆寫就成了唯一的選擇。&lt;/p&gt;&#xA;&lt;p&gt;好在 Substore 可以添加多個腳本操作，只需要在生成配置文件時額外添加一個腳本操作就能解決我們的問題。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-js&#34;&gt;function main(config) {&#xA;  config[&#34;rules&#34;].unshift(&#34;DOMAIN-SUFFIX,xxx,DIRECT&#34;)&#xA;  return config&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;需要注意的是覆寫&lt;code&gt;rules&lt;/code&gt;時必須要使用&lt;code&gt;.unshift()&lt;/code&gt;放在最前面，而不是用&lt;code&gt;.push()&lt;/code&gt;放到最後面，因為放在&lt;code&gt;MATCH&lt;/code&gt;後面的規則是永遠都匹配不到的。&lt;/p&gt;&#xA;&lt;h3 id=&#34;自定義配置文件&#34;&gt;自定義配置文件&#xA;&lt;/h3&gt;&lt;p&gt;完全不喜歡我的覆寫規則？不會用/不喜歡用 Substore？沒問題！你也可以參考 &lt;a class=&#34;link&#34; href=&#34;https://wiki.metacubex.one/config/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Mihomo 文檔&lt;/a&gt;，自己從頭開始手搓配置文件：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;mode: rule&#xA;mixed-port: 7890&#xA;redir-port: 7892&#xA;tproxy-port: 7893&#xA;allow-lan: true&#xA;log-level: info&#xA;ipv6: true&#xA;external-controller: 127.0.0.1:8000&#xA;# secret: yoursecret&#xA;unified-delay: true&#xA;routing-mark: 7894&#xA;tcp-concurrent: true&#xA;disable-keep-alive: true # 推薦在給移動設備代理時啟用，可以解決待機異常耗電的問題&#xA;&#xA;dns:&#xA;  # 你的 DNS 配置&#xA;&#xA;sniffer:&#xA;  # 你的域名嗅探配置&#xA;&#xA;geodata-mode: true&#xA;geox-url:&#xA;  # 自定義 Geodata 文件 URL&#xA;&#xA;proxy-providers:&#xA;  # 你的機場訂閱&#xA;&#xA;rule-providers:&#xA;  # 外部規則&#xA;&#xA;rules:&#xA;  # 分流規則&#xA;&#xA;proxy-groups:&#xA;  # 自定義代理分組&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;管理面板&#34;&gt;管理面板&#xA;&lt;/h2&gt;&lt;p&gt;管理面板可以根據個人喜好選擇，以 Zashboard 為例，我在使用 mihomo 自帶的&lt;code&gt;external-ui&lt;/code&gt;時遇到了一些莫名其妙的問題，所以乾脆直接運行一個 Docker 容器，畢竟這東西就真的只是一個 Web 面板，只要確保內核 API 使用 HTTP 時，Web 面板也使用 HTTP 即可，如果此時 Web 面板使用 HTTPS，則會因為 CORS 策略問題無法連接。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;$ mkdir zashboard &amp;&amp; cd zashboard&#xA;$ nano compose.yml&#xA;$ docker compose up -d&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;compose.yml&lt;/code&gt;內容：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;services:&#xA;  zashboard:&#xA;    image: ghcr.io/zephyruso/zashboard:latest&#xA;    ports:&#xA;      - &#34;8899:80&#34;&#xA;    restart: &#34;unless-stopped&#34;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;自動維護&#34;&gt;自動維護&#xA;&lt;/h2&gt;&lt;p&gt;內核已經運行起來，自動更新訂閱這種功能怎麼實現？&lt;/p&gt;&#xA;&lt;p&gt;答曰：自行編寫一個 Shell 腳本，配合 Crontab 即可實現自動更新訂閱的功能。例如我希望每天凌晨 3 點自動更新訂閱並重啟服務，遂編寫&lt;code&gt;/etc/mihomo/auto_update.sh&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;#!/bin/bash&#xA;&#xA;# === 配置信息 ===&#xA;CONFIG_URL=&#34;&#34;&#xA;CONFIG_PATH=&#34;/etc/mihomo/config.yaml&#34;&#xA;BACKUP_DIR=&#34;/etc/mihomo&#34;&#xA;BACKUP_PREFIX=&#34;config.yaml&#34;&#xA;MAX_BACKUPS=7&#xA;TMP_PATH=&#34;/tmp/config.yaml.tmp&#34;&#xA;LOG_FILE=&#34;/var/log/mihomo_update.log&#34;&#xA;&#xA;# === 日誌 ===&#xA;log() {&#xA;    echo &#34;$(date &#39;+%F %T&#39;) $1&#34; | tee -a &#34;$LOG_FILE&#34;&#xA;}&#xA;&#xA;# === 備份現有配置，並自動清理舊備份 ===&#xA;backup_config() {&#xA;    if [ -f &#34;$CONFIG_PATH&#34; ]; then&#xA;        backup_file=&#34;$BACKUP_DIR/${BACKUP_PREFIX}.$(date &#39;+%Y%m%d_%H%M%S&#39;).bak&#34;&#xA;        cp &#34;$CONFIG_PATH&#34; &#34;$backup_file&#34;&#xA;        log &#34;配置文件已備份到 $backup_file&#34;&#xA;        # 清理多餘的備份，只保留最新的 $MAX_BACKUPS 個&#xA;        old_backups=$(ls -1t $BACKUP_DIR/${BACKUP_PREFIX}.*.bak 2&gt;/dev/null | tail -n +$(($MAX_BACKUPS+1)))&#xA;        for f in $old_backups; do&#xA;            rm -f &#34;$f&#34; &amp;&amp; log &#34;已刪除舊備份 $f&#34;&#xA;        done&#xA;    else&#xA;        log &#34;未找到現有配置文件，無需備份&#34;&#xA;    fi&#xA;}&#xA;&#xA;# === 下載新配置 ===&#xA;download_config() {&#xA;    log &#34;開始下載新配置...&#34;&#xA;    curl -fsSL -o &#34;$TMP_PATH&#34; &#34;$CONFIG_URL&#34;&#xA;    if [ $? -ne 0 ]; then&#xA;        log &#34;下載配置失敗，請檢查網絡或地址&#34;&#xA;        return 1&#xA;    fi&#xA;    # 基本校驗：檢測文件體積&#xA;    if [ ! -s &#34;$TMP_PATH&#34; ]; then&#xA;        log &#34;下載文件為空，停止更新&#34;&#xA;        return 2&#xA;    fi&#xA;    log &#34;配置下載完成&#34;&#xA;    return 0&#xA;}&#xA;&#xA;# === 更新配置文件 ===&#xA;replace_config() {&#xA;    mv &#34;$TMP_PATH&#34; &#34;$CONFIG_PATH&#34;&#xA;    log &#34;配置文件已更新&#34;&#xA;}&#xA;&#xA;# === 重啟 mihomo 服務 ===&#xA;restart_service() {&#xA;    systemctl restart mihomo&#xA;    if [ $? -eq 0 ]; then&#xA;        log &#34;mihomo 服務已重啟&#34;&#xA;    else&#xA;        log &#34;mihomo 服務重啟失敗，請手動檢查&#34;&#xA;    fi&#xA;}&#xA;&#xA;main() {&#xA;    backup_config&#xA;&#xA;    download_config&#xA;    DL_STATUS=$?&#xA;    if [ &#34;$DL_STATUS&#34; -ne 0 ]; then&#xA;        log &#34;操作終止：配置文件未更新，保留原有配置&#34;&#xA;        exit 1&#xA;    fi&#xA;&#xA;    replace_config&#xA;&#xA;    restart_service&#xA;&#xA;    log &#34;=== 更新流程完成 ===&#34;&#xA;}&#xA;&#xA;main &#34;$@&#34;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用&lt;code&gt;crontab -e&lt;/code&gt;編輯 Crontab，設置如下 Crontab 即可在每天凌晨三點自動更新配置：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-crontab&#34;&gt;0 3 * * * /etc/mihomo/update_config.sh&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;防火牆&#34;&gt;防火牆&#xA;&lt;/h2&gt;&lt;p&gt;手動配置防火牆把流量劫持到 Mihomo 內核其實並不是什麼難事，我之前在「&lt;a class=&#34;link&#34; href=&#34;https://blog.l3zc.com/2025/04/tailscale-setup-recap/#%E5%9C%A8-exit-node-%E5%8A%AB%E6%8C%81%E6%B5%81%E9%87%8F&#34; &gt;從入門到進階：Tailscale + ShellCrash 異地組網和科學上網&lt;/a&gt;」（以下簡稱「Tailscale 那篇文章」中的兩個小節中提到過具體的操作方法，這裡只提操作，不做解說。&lt;/p&gt;&#xA;&lt;p&gt;根據我的情況，我需要把&lt;code&gt;tailscale0&lt;/code&gt;上的網卡的所有流量劫持到 Mihomo 內核，其它的情況（例如本機代理）操作也大同小異。如果只是想劫持 TCP 流量，那麼用&lt;code&gt;iptables&lt;/code&gt;的 REDIRECT 功能已經足夠，但若還想劫持 UDP、QUIC 等流量，則必須用到 Tproxy。&lt;strong&gt;最後，不要忘了 IPV6。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;以下是我的防火牆配置：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;# 創建自定義鏈&#xA;iptables -t mangle -N MIHOMO&#xA;&#xA;# 根據自己的需要忽略本地流量&#xA;iptables -t mangle -A MIHOMO -d 127.0.0.1/8 -j RETURN&#xA;iptables -t mangle -A MIHOMO -d 100.64.0.0/10 -j RETURN&#xA;iptables -t mangle -A MIHOMO -d 192.168.1.0/24 -j RETURN&#xA;iptables -t mangle -A MIHOMO -d 172.17.0.0/16 -j RETURN&#xA;&#xA;# mark UDP 和 TCP 到代理&#xA;iptables -t mangle -A MIHOMO -p tcp -j TPROXY --on-port 7893 --tproxy-mark 233&#xA;iptables -t mangle -A MIHOMO -p udp -j TPROXY --on-port 7893 --tproxy-mark 233&#xA;&#xA;# 接口跳轉&#xA;iptables -t mangle -A PREROUTING -i tailscale0 -j MIHOMO&#xA;&#xA;# 路由表配置&#xA;echo &#34;233 mihomo&#34; | tee -a /etc/iproute2/rt_tables&#xA;ip rule add fwmark 233 lookup mihomo&#xA;ip route add local 0.0.0.0/0 dev lo table mihomo&#xA;&#xA;# IPv6&#xA;# 創建鏈&#xA;ip6tables -t mangle -N MIHOMO6&#xA;&#xA;# 跳過本地地址&#xA;ip6tables -t mangle -A MIHOMO6 -d ::1/128 -j RETURN&#xA;ip6tables -t mangle -A MIHOMO6 -d fd7a:115c:a1e0::/48 -j RETURN&#xA;&#xA;# 標記 TCP/UDP&#xA;ip6tables -t mangle -A MIHOMO6 -i tailscale0 -p tcp -j TPROXY --on-port 7893 --tproxy-mark 233&#xA;ip6tables -t mangle -A MIHOMO6 -i tailscale0 -p udp -j TPROXY --on-port 7893 --tproxy-mark 233&#xA;&#xA;# 接口跳轉&#xA;ip6tables -t mangle -A PREROUTING -i tailscale0 -j MIHOMO6&#xA;&#xA;# 路由表配置&#xA;echo &#34;233 mihomo&#34; | tee -a /etc/iproute2/rt_tables&#xA;ip -6 rule add fwmark 233 lookup mihomo&#xA;ip -6 route add local ::/0 dev lo table mihomo&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;大多數系統默認不會保存防火牆規則，關於規則持久化的內容我已經分別在 Tailscale 那篇文章的「&lt;a class=&#34;link&#34; href=&#34;https://blog.l3zc.com/2025/04/tailscale-setup-recap/#%E8%B7%AF%E7%94%B1%E8%A7%84%E5%88%99%E6%8C%81%E4%B9%85%E5%8C%96&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;路由規則持久化&lt;/a&gt;」和「&lt;a class=&#34;link&#34; href=&#34;https://blog.l3zc.com/2025/04/tailscale-setup-recap/#iptables-%E8%A7%84%E5%88%99%E6%8C%81%E4%B9%85%E5%8C%96&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;iptables 規則持久化&lt;/a&gt;」兩小節做了詳細說明，直接參考即可。&lt;/p&gt;&#xA;&lt;h3 id=&#34;本機代理怎麼配置&#34;&gt;本機代理怎麼配置？&#xA;&lt;/h3&gt;&lt;p&gt;大多數代理軟件默認的配置（其實就是 ShellCrash 的默認配置）是 REDIRECT，用它也基本能滿足大多數需求，REDIRECT 的示例如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;# IPv4 劫持 eth0&#xA;iptables -t nat -A PREROUTING -i eth0 -p tcp -j REDIRECT --to-ports 7892&#xA;&#xA;# IPv6 劫持 eth0&#xA;ip6tables -t nat -A PREROUTING -i eth0 -p tcp -j REDIRECT --to-ports 7892&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;其中 7892 要和 Mihomo 配置中的&lt;code&gt;redir-port&lt;/code&gt;一致，&lt;code&gt;eth0&lt;/code&gt;就是想要劫持的 Interface，相比 Tproxy 那可真是簡單太多了。&lt;/p&gt;&#xA;&lt;p&gt;實際上我個人並不喜歡用把本機所有流量都劫持到防火牆，我更喜歡在需要時直接通過環境變量、&lt;code&gt;proxy-chains&lt;/code&gt;和各種軟件自帶的代理配置把流量指向 Mihomo 內核，例如想讓 Docker 走代理，則可以直接編輯 Docker 的&lt;code&gt;/etc/docker/daemon.json&lt;/code&gt;來指定代理，而不是直接一股腦把網卡上的所有流量都劫持到代理：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&#xA;  &#34;proxies&#34;: {&#xA;    &#34;http-proxy&#34;: &#34;http://127.0.0.1:7890&#34;,&#xA;    &#34;https-proxy&#34;: &#34;http://127.0.0.1:7890&#34;,&#xA;    &#34;no-proxy&#34;: &#34;127.0.0.0/8&#34;&#xA;  }&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;這麼折騰何必呢用客戶端不香嗎&#34;&gt;這麼折騰，何必呢？用客戶端不香嗎？&#xA;&lt;/h2&gt;&lt;p&gt;別問，問就是玩虛空終端玩的。&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>最速 Substore 訂閱管理指南</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2025/03/clash-subscription-convert/</link>
            <pubDate>Fri, 07 Mar 2025 10:54:29 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2025/03/clash-subscription-convert/</guid>
            <description>&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-8_hu_92098803a4bf150d.webp&#34; alt=&#34;Featured image of post 最速 Substore 訂閱管理指南&#34; /&gt;&lt;p&gt;當我趁著春節各家機場的促銷訂閱多個機場之後，如何充分利用每個節點就變成了說難不難說簡單也不簡單的問題，我當然可以訂閱各家機場提供的配置文件，然後在他們之間切換，但這樣未免也太麻煩了。更何況我還有自建節點，我可不想為了這一個節點專門去開一個新的配置。&lt;/p&gt;&#xA;&lt;p&gt;Sub-Store 很好的解決了這個問題，它可以從多個訂閱中抽取節點信息，通過正則表達式或者 JS 整理它們，最後輸出一個整合了所有節點信息的訂閱。&lt;/p&gt;&#xA;&lt;p&gt;部署它可以直接使用 xream 打包好的鏡像，這個鏡像整合了前後端，如果在公網部署，記得更改一下後端路徑，否則你的配置文件很可能會被盜用。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;services:&#xA;  sub-store:&#xA;    image: xream/sub-store&#xA;    container_name: substore&#xA;    restart: always&#xA;    environment:&#xA;      - SUB_STORE_CRON=55 23 * * *&#xA;      - SUB_STORE_FRONTEND_BACKEND_PATH=/super-random-path&#xA;    ports:&#xA;      - &#34;3001:3001&#34;&#xA;    volumes:&#xA;      - ./data:/opt/app/data&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;反代 3001 端口即可訪問 Substore 的前端，這裡以 Caddy 為例：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-caddyfile&#34;&gt;sub-domain.example.com {&#xA;        reverse_proxy :3001&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;當然，初次進入前端別忘了新增後端地址，這時的後端地址取決於之前 compose file 裡的設置，在本文的例子中，後端地址為&lt;code&gt;https://sub-domain.example.com/super-random-path&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;組合訂閱的管理&#34;&gt;組合訂閱的管理&#xA;&lt;/h2&gt;&lt;p&gt;添加所有機場上游和自建節點之後，就可以開始把它們全都加進單個組合訂閱，但各個機場對節點的命名五花八門，默認情況下看起來非常雜亂，甚至不同機場之間的節點還有重名的可能。好在 Sub-Store 有通過腳本對節點進行批量重命名操作的功能，這裡推薦&lt;a class=&#34;link&#34; href=&#34;https://github.com/Keywos/rule/blob/main/rename.js&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;一個腳本&lt;/a&gt;，能夠幫我們為所有的機場節點重命名。&lt;/p&gt;&#xA;&lt;p&gt;欲使用這個腳本，只需在編輯訂閱時將以下地址粘貼到腳本操作處即可。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;https://raw.githubusercontent.com/Keywos/rule/main/rename.js&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image_hu_8310153db045f240.webp&#34; alt=&#34;節點操作&#34; /&gt;&#xA; &#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-1_hu_333de5a5c288737.webp&#34; alt=&#34;整理完成的節點列表&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;最後再進行一些你喜歡的節點操作，可以整理出一個統一規範的節點列表。&lt;/p&gt;&#xA;&lt;h2 id=&#34;生成-clash-配置&#34;&gt;生成 Clash 配置&#xA;&lt;/h2&gt;&lt;p&gt;現在雖然已經有了節點列表，但現在生成的配置文件並不包含任何規則，需要自行編寫或者拉取第三方規則。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-2_hu_755a17a55a5da685.webp&#34; alt=&#34;選擇 Mihomo 配置&#34; /&gt;&#xA; &#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-3_hu_244966c33439c095.webp&#34; alt=&#34;編輯信息&#34; /&gt;&#xA; &#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-4_hu_c92302b1defa984b.webp&#34; alt=&#34;生成分享鏈接&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-6_hu_c37bf30e1b9005a7.webp&#34; alt=&#34;腳本操作&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;轉到 Substore 的文件管理，創建一份新的 Mihomo 配置：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;「來源」選擇組合訂閱，並在訂閱名稱上選擇你的訂閱組&lt;/li&gt;&#xA;&lt;li&gt;在腳本操作中填入自己的覆寫配置&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;這是我自己的覆寫規則 &lt;a class=&#34;link&#34; href=&#34;https://github.com/powerfullz/override-rules&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;powerfullz/override-rules&lt;/a&gt;，為 Mihomo/Substore 設計，核心特色如下：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;集成 &lt;a class=&#34;link&#34; href=&#34;https://github.com/SukkaW/Surge&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;SukkaW/Surge&lt;/a&gt; 與 &lt;a class=&#34;link&#34; href=&#34;https://github.com/217heidai/adblockfilters&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;217heidai/adblockfilters&lt;/a&gt; 等優質規則，兼容性強，覆蓋面廣。&lt;/li&gt;&#xA;&lt;li&gt;針對 Truth Social、E-Hentai、TikTok、加密貨幣等場景，新增專用分流規則，滿足多樣化需求。&lt;/li&gt;&#xA;&lt;li&gt;精簡冗餘，結構清晰，維護便捷。&lt;/li&gt;&#xA;&lt;li&gt;深度融合 &lt;a class=&#34;link&#34; href=&#34;https://github.com/Loyalsoldier/v2ray-rules-dat&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Loyalsoldier/v2ray-rules-dat&lt;/a&gt; GeoSite/GeoIP，分流更精準。&lt;/li&gt;&#xA;&lt;li&gt;IP 規則默認添加 &lt;code&gt;no-resolve&lt;/code&gt;，有效減少本地 DNS 解析，提升速度與隱私。&lt;/li&gt;&#xA;&lt;li&gt;動態覆寫：自動識別節點國家/地區，僅生成實際存在的分組，節點名稱實時枚舉，配置更智能。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;javascript-格式覆寫&#34;&gt;JavaScript 格式覆寫&#xA;&lt;/h3&gt;&lt;p&gt;複製 JavaScript 格式覆寫文件的鏈接&lt;code&gt;https://cdn.jsdelivr.net/gh/powerfullz/override-rules@1/convert.min.js&lt;/code&gt;，並根據需要在後面附加參數，格式如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;https://cdn.jsdelivr.net/gh/powerfullz/override-rules@1/convert.min.js#參數1=true&amp;參數2=true&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;目前支持如下參數：&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;參數&lt;/th&gt;&#xA;          &lt;th&gt;功能&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;loadbalance&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;啟用國家/地區節點組的負載均衡&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;landing&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;啟用落地節點功能&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;ipv6&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;啟用 IPv6 支持&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;full&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;生成針對純內核使用場景的完整配置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;keepalive&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;啟用 TCP KeepAlive&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;quic&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;允許 QUIC 流量&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;fakeip&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;DNS 增強模式使用 fake-ip&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;regex&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;各國家代理組改用 include-all + 正則過濾模式&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;threshold&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;國家/地區節點數量小於該值時不顯示分組（默認 0）&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;例如，若有負載均衡和 IPv6 需求，最終的覆寫腳本鏈接為：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;https://cdn.jsdelivr.net/gh/powerfullz/override-rules@1/convert.min.js#loadbalance=true&amp;ipv6=true&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;將最終的覆寫腳本鏈接粘貼到腳本操作處，使用 Substore 的生成預覽功能確認沒有問題後即可保存。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-7_hu_a9aea54492dfed6c.webp&#34; alt=&#34;新建一個腳本操作並粘貼最終的訂閱鏈接&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;yaml-格式覆寫&#34;&gt;YAML 格式覆寫&#xA;&lt;/h3&gt;&lt;p&gt;&lt;del&gt;YAML 格式覆寫我自己已經不用了，隨緣維護，但歡迎 PR&lt;/del&gt;&lt;/p&gt;&#xA;&lt;p&gt;寫了個 Github Actions 自動根據 JS 格式覆寫生成 YAML 格式覆寫，所以現在 YAML 格式又開始維護了。&lt;/p&gt;&#xA;&lt;p&gt;除了直接引用 convert.js 動態覆寫，你也可以使用倉庫中預先生成好的 32 份 YAML 格式覆寫——它們都放在 yamls/ 目錄裡，由 GitHub Actions 在每次推送後自動重新生成、覆蓋。適用於諸如 Clash Verge 等不支持 JS 覆寫的客戶端和轉換服務。&lt;/p&gt;&#xA;&lt;p&gt;文件命名規則：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;config_lb-{0|1}_landing-{0|1}_ipv6-{0|1}_full-{0|1}_keepalive-{0|1}_fakeip-{0|1}_quic-{0|1}.yaml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;示例（開啟 full，其餘關閉）：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;https://raw.githubusercontent.com/powerfullz/override-rules/refs/heads/main/yamls/config_lb-0_landing-0_ipv6-0_full-1_keepalive-0_fakeip-0_quic-0.yaml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;CI 只是套用一份假的&lt;code&gt;fake_proxies.json&lt;/code&gt;來生成覆寫，所以不可能實現 JS 覆寫自動根據節點匹配生成對應代理組的功能，只能把所有地區節點組都放進去。如果你已經搭建 Substore，並且想要「動態識別國家 + 傳參」的靈活性，還是推薦使用 JS 覆寫。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-6_hu_c37bf30e1b9005a7.webp&#34; alt=&#34;填入對應的 RAW 鏈接&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;生成下載鏈接&#34;&gt;生成下載鏈接&#xA;&lt;/h2&gt;&lt;p&gt;保存成功後點擊分享按鈕生成分享鏈接，設置分享有效期後點擊「創建分享」，生成的鏈接即最終成型的 Mihomo 配置文件，將其作為訂閱鏈接在你的代理軟件內訂閱就大功告成了。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2025/03/clash-subscription-convert/image-8_hu_92098803a4bf150d.webp&#34; alt=&#34;最終效果&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;部分機場 UDP 性能差，開啟後可能出現體驗降級。&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;開啟後可能有助於解決 TUN 模式無法上網的問題。&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:3&#34;&gt;&#xA;&lt;p&gt;各國家代理組改用 &lt;code&gt;include-all&lt;/code&gt; + 正則過濾模式，由 Mihomo 內核在運行時按正則動態篩選節點，而非在腳本執行時枚舉節點名稱（默認 false）&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
        </item><item>
            <title>OBS 多路推流折騰記：那些本不必要的麻煩</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2024/09/my-multi-streaming-setup/</link>
            <pubDate>Wed, 18 Sep 2024 06:16:51 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2024/09/my-multi-streaming-setup/</guid>
            <description>&lt;img src=&#34;https://blog.l3zc.com/2024/09/my-multi-streaming-setup/cover_hu_891493d684eb454d.webp&#34; alt=&#34;Featured image of post OBS 多路推流折騰記：那些本不必要的麻煩&#34; /&gt;&lt;p&gt;長話短說，最近我開始直播我的遊戲實況，我並不指望有多少人看，Just, Why not? 再者每個直播平臺都會有直播回放。相當於免費保存我每一次遊戲的錄像，何樂而不為？&lt;/p&gt;&#xA;&lt;p&gt;扯遠了，如你所見，近期我有了多平臺同時直播的需求，然而 OBS 本身顯然不支持同時推流，同時也因為不支持設置代理的特點和眾所周知的原因，無法推流到 twitch.tv，於是我開始尋找解決方案。&lt;/p&gt;&#xA;&lt;h2 id=&#34;明確需求&#34;&gt;明確需求&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;多路平臺同時直播&lt;/li&gt;&#xA;&lt;li&gt;最好對性能影響小&lt;/li&gt;&#xA;&lt;li&gt;其中一路需要推流需要代理&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;多路推流&#34;&gt;多路推流&#xA;&lt;/h2&gt;&lt;p&gt;多路推流有現成的插件可用：&lt;a class=&#34;link&#34; href=&#34;https://github.com/sorayuki/obs-multi-rtmp&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Github&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;在 Release 頁面下載&lt;code&gt;.exe&lt;/code&gt;安裝包，安裝完成後記得在「停靠窗口」菜單裡勾選「多路推流」。這時候默認會彈出一個獨立窗口，可以趁這個機會順便調整一下 OBS 的佈局。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/my-multi-streaming-setup/image_hu_b8b674a93b9f86bc.webp&#34; alt=&#34;啟用多路推流面板&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;插件的設置也沒什麼好說的，用在原版 OBS 的填法在這個插件裡如法炮製即可。&lt;/p&gt;&#xA;&lt;h3 id=&#34;bilibili-直播姬&#34;&gt;Bilibili 直播姬&#xA;&lt;/h3&gt;&lt;p&gt;莫名其妙，B 站小於 50 粉絲的 Up 主只能使用直播姬開播，其他國內平臺做出類似規定者大概也不在少數，啟用第三方推流模式之後，直播面板會顯示推流的配置。此時的不需要按照直播姬給出的推流地址進行配置，因為直播姬莫名其妙的給了一個每次都會變的內網 IP，直接以&lt;code&gt;127.0.0.1&lt;/code&gt;或者&lt;code&gt;localhost&lt;/code&gt;替換即可。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/my-multi-streaming-setup/image-2_hu_71c45766ee560a9.webp&#34; alt=&#34;Bilibili 直播姬的第三方推流模式&#34; /&gt;&#xA; &#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/my-multi-streaming-setup/image-1_hu_17dc4c09eb0ae0af.webp&#34; alt=&#34;插件的設置&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;推流到-twitch&#34;&gt;推流到 Twitch&#xA;&lt;/h2&gt;&lt;p&gt;推流到 Twitch 則會因為 GFW 多出很多不必要的麻煩。&lt;/p&gt;&#xA;&lt;p&gt;OBS 本身並不支持設置代理，起初我打算用 Clash 的 TAP 模式強制代理 OBS 的流量，而 Clash 的 TAP 並不監聽 rtmp 流量，宣告失敗。我決定直接架設一個轉發服務器，這個服務器需要既可以與 Twitch 通信，又可以不受 GFW 的干擾。&lt;/p&gt;&#xA;&lt;p&gt;在網上查到一些信息，Caddy 似乎不支持 RTMP 協議，而 &lt;code&gt;nginx-rtmp&lt;/code&gt; 插件則專門為 RTMP 協議設計。這幾乎是唯一的選擇。&lt;/p&gt;&#xA;&lt;p&gt;部署的前提：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;熟悉基本的 Linux 命令行操作。&lt;/li&gt;&#xA;&lt;li&gt;服務器已經安裝好&lt;code&gt;docker&lt;/code&gt;和&lt;code&gt;docker compose&lt;/code&gt;插件。&lt;/li&gt;&#xA;&lt;li&gt;有合適的命令行文本編輯器，比如&lt;code&gt;nvim&lt;/code&gt;或者絕大部分 distro 自帶的&lt;code&gt;nano&lt;/code&gt;。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;新建目錄：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;mkdir nginx-rtmp &amp;&amp; cd nginx-rtmp&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;創建&lt;code&gt;docker-compose.yml&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;services:&#xA;  nginx-rtmp:&#xA;    image: tiangolo/nginx-rtmp:latest&#xA;    container_name: nginx_rtmp&#xA;    ports:&#xA;      - &#34;1935:1935&#34; # RTMP port&#xA;    volumes:&#xA;      - ./nginx.conf:/etc/nginx/nginx.conf&#xA;    restart: unless-stopped&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;創建&lt;code&gt;nginx.conf&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-nginx&#34;&gt;worker_processes  auto;&#xA;&#xA;events {&#xA;    worker_connections  1024;&#xA;}&#xA;&#xA;rtmp {&#xA;    server {&#xA;        listen 1935;&#xA;        chunk_size 4096;&#xA;&#xA;        application live {&#xA;            live on;&#xA;            push rtmp://live.twitch.tv/app/{Twitch 主直播密鑰};&#xA;        }&#xA;    }&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;啟動編排：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;docker compose up -d&#xA;# 老版本 compose 插件則是 docker-compose up&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;當然，別忘了開放防火牆端口。我的防火牆參考了 &lt;a class=&#34;link&#34; href=&#34;https://github.com/chaifeng/ufw-docker#solving-ufw-and-docker-issues&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;To Fix The Docker and UFW Security Flaw Without Disabling Iptables&lt;/a&gt; 一文中提到的配置，相應地，開放端口的命令如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ufw route allow proto tcp from any to any port 1935&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;配置完成後，OBS 內的推流目標地址填入&lt;code&gt;rtmp://服務器ip/live&lt;/code&gt;，推流碼填寫任意值均可。設置完成後即可開始推流。&lt;/p&gt;&#xA;&lt;h3 id=&#34;netch&#34;&gt;Netch&#xA;&lt;/h3&gt;&lt;p&gt;如果沒有服務器，亦可以使用 Netch 代理 OBS 進程進行推流。&lt;/p&gt;&#xA;&lt;p&gt;首先下載 Netch 1.9.2 版本，注意一定要是 1.9.2 版本。添加一個進程模式，將 OBS 文件夾加入，隨後啟用該進程模式的代理即可。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/my-multi-streaming-setup/image-3_hu_fab77139607785da.webp&#34; alt=&#34;創建一個進程模式&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;尾聲&#34;&gt;尾聲&#xA;&lt;/h2&gt;&lt;p&gt;這次為了在同時在 Twitch 和 B 站上推流，遇到了很多原本不必要的麻煩。我可以怪 OBS 沒有內置代理功能，也可以怪 Clash Verge 等代理工具不支持 RTMP，轉來轉去，最終要怪的，還得是 GFW。雖然最後的結果還算令人滿意，僅僅為了推流而折騰這些東西的體驗實在是稱不上良好。也許我今後我應該去研究修改 Mihomo 內核，讓其支持 RTMP 協議，亦或是自己寫一套獨立的實現單獨轉發 OBS 的流量，不論如何，在這片土地上，想要暢快的直播，道阻且長。&lt;/p&gt;&#xA;&lt;p&gt;最後，歡迎關注我的 Twitch 頻道: &lt;a class=&#34;link&#34; href=&#34;https://www.twitch.tv/powerfullz233&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://www.twitch.tv/powerfullz233&lt;/a&gt;&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>docker-mailserver 郵件服務器搭建記錄</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2024/09/docker-mailserver-deployment-recap/</link>
            <pubDate>Fri, 06 Sep 2024 03:57:18 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2024/09/docker-mailserver-deployment-recap/</guid>
            <description>&lt;img src=&#34;https://blog.l3zc.com/2024/09/docker-mailserver-deployment-recap/docker-mailserver_hu_a649605529f354c4.webp&#34; alt=&#34;Featured image of post docker-mailserver 郵件服務器搭建記錄&#34; /&gt;&lt;p&gt;某天早上醒來，發現收件箱裡多了封郵件，通知我的郵箱在韓國登錄，當時認為只是偶爾的 IP 誤判，也就沒有多想。可接下來幾天，時不時又有新的郵件進來，而且每次 IP 都不一樣，這下可就有些問題了，再不採取行動，怕不是郵箱真的要被拿去群發郵件。於是趕緊刪掉了域名的 MX、SPF、DMARC 記錄，尋找新的解決方案。&lt;/p&gt;&#xA;&lt;p&gt;我原本只是想改改密碼，結果呢，騰訊企業郵箱改密碼的入口真的巨能藏，到處都找不到。算了，遷移，何必受這氣。&lt;/p&gt;&#xA;&lt;p&gt;於是就有了這篇文章，從最開始的開放防火牆端口開始，到最後的優化送達率，我將分享我搭建 docker-mailserver 郵件服務器的經驗，希望能幫你少踩些坑。&lt;/p&gt;&#xA;&lt;h2 id=&#34;搭建-docker-mailserver-郵件服務器前的準備&#34;&gt;搭建 docker-mailserver 郵件服務器前的準備&#xA;&lt;/h2&gt;&lt;h3 id=&#34;防火牆的處理&#34;&gt;防火牆的處理&#xA;&lt;/h3&gt;&lt;p&gt;首先先開放防火牆的郵件服務常用端口，分別是&lt;code&gt;25&lt;/code&gt;、&lt;code&gt;143&lt;/code&gt;、&lt;code&gt;465&lt;/code&gt;、&lt;code&gt;587&lt;/code&gt;、&lt;code&gt;993&lt;/code&gt;，各分支開放端口的操作不同，請自行谷歌或詢問 AI，以 Ubuntu 使用的&lt;code&gt;ufw&lt;/code&gt;為例：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;ufw allow 25&#xA;ufw allow 143&#xA;ufw allow 465&#xA;ufw allow 587&#xA;ufw allow 993&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;我的防火牆比較特殊，用到了&lt;code&gt;ufw&lt;/code&gt;和 &lt;a class=&#34;link&#34; href=&#34;https://github.com/chaifeng/ufw-docker#solving-ufw-and-docker-issues&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;To Fix The Docker and UFW Security Flaw Without Disabling Iptables&lt;/a&gt; 一文中提到的配置。所以當我想要把 Docker 容器的端口暴露在外時需要做出額外的配置。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;# 開放郵件服務器所需的端口&#xA;ufw route allow proto tcp from any to any port 25&#xA;ufw route allow proto tcp from any to any port 143&#xA;ufw route allow proto tcp from any to any port 465&#xA;ufw route allow proto tcp from any to any port 587&#xA;ufw route allow proto tcp from any to any port 993&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;驗證你的服務器是否具備搭建條件&#34;&gt;驗證你的服務器是否具備搭建條件&#xA;&lt;/h3&gt;&lt;p&gt;很多服務器，尤其是各種廉價的 VPS，並不適合搭建 docker-mailserver，各大郵件服務商為了過濾垃圾郵件，索性將所有曾經有過 Spam 行為的 IP 全部列入黑名單。如果你的 IP 被某個 Spammer 使用過，而恰好又被你的服務器提供商分配給了你，而你折騰了幾個小時的郵件服務器卻愣是收不到郵件，最後發現竟是 IP 被列入黑名單的原因，我不知道你會作何感想。&lt;/p&gt;&#xA;&lt;p&gt;有的服務器提供商的 IP 乍一看確實不在郵件黑名單中，但實際上搭建好之後還是無法發送郵件，為什麼？因為服務器提供商擔心 IP 被濫用，索性將郵件服務的端口全都封鎖了。&lt;/p&gt;&#xA;&lt;p&gt;使用如下腳本檢測你的服務器是否具備搭建郵件服務器的條件：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;bash &lt;(curl -sL IP.Check.Place)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/docker-mailserver-deployment-recap/image-3_hu_6dacc5e9abb4b1ca.webp&#34; alt=&#34;不能搭建郵件服務器&#34; /&gt;&#xA; &#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/docker-mailserver-deployment-recap/image-4_hu_fb1b1c9dd78cde41.webp&#34; alt=&#34;可以搭建郵件服務器&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;如果在這一步發現你的服務器不適合搭建甚至不能搭建&lt;code&gt;docker-mailserver&lt;/code&gt;，那就趁早打住吧，想辦法換一個更乾淨、限制更少的 IP 再說。&lt;/p&gt;&#xA;&lt;h2 id=&#34;搭建過程&#34;&gt;搭建過程&#xA;&lt;/h2&gt;&lt;h3 id=&#34;拉取配置文件&#34;&gt;拉取配置文件&#xA;&lt;/h3&gt;&lt;p&gt;docker-mailserver 需要配置的配置文件有兩個，&lt;code&gt;compose.yaml&lt;/code&gt;和&lt;code&gt;mailserver.env&lt;/code&gt;，分別拉取配置文件：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;mkdir mailserver &amp;&amp; cd mailserver&#xA;sudo apt install wget&#xA;wget -O compose.yaml &#34;https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/master/compose.yaml&#34;&#xA;wget -O mailserver.env &#34;https://github.com/docker-mailserver/docker-mailserver/blob/master/mailserver.env&#34;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;根據需求，可以修改不同的配置，下面是我修改的部分：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;POSTMASTER_ADDRESS=webmaster@l3zc.com&#xA;TZ=Asia/Shanghai&#xA;SSL_TYPE=manual&#xA;SSL_CERT_PATH=/certs/cert.crt&#xA;SSL_KEY_PATH=/certs/cert.key&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;用-caddy-準備和自動維護-tls-證書&#34;&gt;用 Caddy 準備和自動維護 TLS 證書&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&#xA;&lt;/h3&gt;&lt;p&gt;因為我已經在使用 Caddy，所以我這次就打算直接使用 Caddy 來自動維護證書。根據項目的官方文檔，我只需要在 Caddyfile 裡新增一個子域名，Caddy 就可以自動幫我維護證書。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-caddyfile&#34;&gt;mail.example.com {&#xA;  tls internal {&#xA;    # ?? 這不是直接生成的內部證書麼&#xA;    key_type rsa2048&#xA;  }&#xA;&#xA;  # Optional, can be useful for troubleshooting&#xA;  # connection to Caddy with correct certificate:&#xA;  respond &#34;Hello DMS&#34;&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;當我更新完 DNS 記錄，實際操作起來發現，我的情況比較特殊：我這臺服務器上並沒有用到 Caddy 的自動申請證書功能，而是使用了15年有效期的泛域名 Cloudflare Origin Certificate。即使我不為這個子域名指定證書文件，Caddy 也會在加載這張泛域名證書後認為無需再申請新的證書。這就很尷尬了，用 Caddy 的時候 Cloudflare Origin Certificate 和郵件服務器只能二選一。只好安裝了&lt;code&gt;dns.providers.cloudflare&lt;/code&gt;，並放棄使用 Cloudflare Origin Certificate，轉而讓 Caddy 自動為每個子域名申請和維護 TLS/SSL 證書，反正都是自動的，眼不見心不煩。&lt;/p&gt;&#xA;&lt;p&gt;安裝&lt;code&gt;dns.providers.cloudflare&lt;/code&gt;後的全局配置：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-caddyfile&#34;&gt;{&#xA;        acme_dns cloudflare {API_KEY}&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最後把 Caddy 的證書存儲位置映射到 docker-mailserver 容器內。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;volumes:&#xA;  - /home/user/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.tld/:/certs/&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果 Caddy 以 root 用戶運行，則證書的位置應當為&lt;code&gt;/root/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.tld/&lt;/code&gt;，做出相應的修改即可。&lt;/p&gt;&#xA;&lt;p&gt;然後就是之前提到過的配置，我將證書存儲位置映射到了容器內的&lt;code&gt;/certs/&lt;/code&gt;目錄，所以配置為：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;SSL_CERT_PATH=/certs/cert.crt&#xA;SSL_KEY_PATH=/certs/cert.key&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;首次啟動容器&#34;&gt;首次啟動容器&#xA;&lt;/h3&gt;&lt;p&gt;首次啟動容器需要立即（120 秒內）創建新的 Postmaster 賬號。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;docker compose up -d&#xA;docker exec -it &lt;CONTAINER NAME&gt; setup email add &lt;postmaster@yourdomain.tld&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;優化送達率&#34;&gt;優化送達率&#xA;&lt;/h2&gt;&lt;h3 id=&#34;dns-記錄&#34;&gt;DNS 記錄&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;一條 A 記錄，名稱隨意（假設為&lt;code&gt;mail&lt;/code&gt;），指向服務器 IP（Cloudflare 需使用「僅 DNS」）&lt;/li&gt;&#xA;&lt;li&gt;一條 MX 記錄，Apex 域（@），指向&lt;code&gt;mail.yourdomain.tld&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;一條 TXT 記錄（SPF），Apex 域（@），可以在&lt;a class=&#34;link&#34; href=&#34;https://mxtoolbox.com/SPFRecordGenerator.aspx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;這裡&lt;/a&gt;生成(可選)。&lt;/li&gt;&#xA;&lt;li&gt;一條 TXT 記錄（DMARC），名稱&lt;code&gt;_dmarc&lt;/code&gt;，可以在&lt;a class=&#34;link&#34; href=&#34;https://mxtoolbox.com/DMARCRecordGenerator.aspx&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;這裡&lt;/a&gt;生成（可選）。&lt;/li&gt;&#xA;&lt;li&gt;一條 TXT 記錄（DKIM），名稱&lt;code&gt;mail._domainkey&lt;/code&gt;，具體配置在後文（可選）。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;dkim-spf-和-dmarc&#34;&gt;DKIM, SPF 和 DMARC&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&#xA;&lt;/h3&gt;&lt;p&gt;什麼是 DKIM，SPF 和 DMARC？簡單來說，DKIM 是一個數字簽名機制；SPF 類似於「員工名單」，記錄所有合法的發件服務器；DMARC 則用於指示收件方的服務器如何處理未通過 DKIM 和 SPF 驗證的郵件。&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&#xA;&lt;p&gt;首先設置 DKIM，在服務器上生成公私鑰對。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;docker exec -it &lt;CONTAINER NAME&gt; setup config dkim&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;生成後的公私鑰對可以在映射的容器目錄&lt;code&gt;./docker-data/dms/config/opendkim/keys/&lt;/code&gt;下找到。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/docker-mailserver-deployment-recap/image_hu_1f64fffc01f8db13.webp&#34; alt=&#34;mail.txt 便是公鑰的 DNS Zone file&#34; /&gt;&#xA; &#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/docker-mailserver-deployment-recap/image-1_hu_d6c86630e3947c78.webp&#34; alt=&#34;Cloudflare 的導入入口&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;下載 mail.txt（複製其內所有內容粘貼到本地文件也可以），將其導入到 Cloudflare Dashboard 即可完成 DKIM 設置。需要注意配置完成 DKIM 後需要重啟容器才能生效。&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;docker compose up -d --force-recreate&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;前面提到 SPF 相當於一個「員工名單」，既然我合法的發件服務器只有一臺，那麼 DNS 填寫如下設置即可。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;&#34;v=spf1 mx ~all&#34;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;再就是 DMARC，可以使用前面提到的模板生成，這裡不再贅述。&lt;/p&gt;&#xA;&lt;p&gt;如果你的域名服務商擁有自己的設置嚮導（例如 Cloudflare），亦可以使用它們簡化設置流程。&lt;/p&gt;&#xA;&lt;h2 id=&#34;客戶端設置&#34;&gt;客戶端設置&#xA;&lt;/h2&gt;&lt;p&gt;客戶端設置相對就很簡單了，IMAP 和 SMTP 服務器都是&lt;code&gt;mail.yourdomain.ltd&lt;/code&gt;，開啟 SSL 後端口分別是 465 和 993，登錄即可。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/docker-mailserver-deployment-recap/image-2_hu_51756253bf099359.webp&#34; alt=&#34;設置示例&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;h2 id=&#34;善用-mailtester&#34;&gt;善用 MailTester&#xA;&lt;/h2&gt;&lt;p&gt;至此我們已經完成了搭建 docker-mailserver 郵件服務器的整個過程，在開始發送郵件之前，我們可以使用 &lt;a class=&#34;link&#34; href=&#34;https://www.mail-tester.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;MailTester&lt;/a&gt; 測試我們的配置是否正確。如果測試結果是 10/10，那麼我們的 docker-mailserver 郵件服務器應該會擁有漂亮的送達率，好好享受吧。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/09/docker-mailserver-deployment-recap/image-5_hu_6de856f3e3b52ca0.webp&#34; alt=&#34;完美的評分&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;如果不是 10/10，也不要著急，認真查看扣分的原因，對症下藥，一項一項解決即可。&lt;/p&gt;&#xA;&lt;h2 id=&#34;todo-list&#34;&gt;TODO-List&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 配套 WebUI&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;參考: &lt;a class=&#34;link&#34; href=&#34;https://docker-mailserver.github.io/docker-mailserver/latest/config/security/ssl/#caddy&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://docker-mailserver.github.io/docker-mailserver/latest/config/security/ssl/#caddy&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;參考: &lt;a class=&#34;link&#34; href=&#34;https://docker-mailserver.github.io/docker-mailserver/latest/config/best-practices/dkim_dmarc_spf/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://docker-mailserver.github.io/docker-mailserver/latest/config/best-practices/dkim_dmarc_spf/&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:3&#34;&gt;&#xA;&lt;p&gt;更加具體的介紹: &lt;a class=&#34;link&#34; href=&#34;https://www.cloudflare.com/learning/email-security/dmarc-dkim-spf/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://www.cloudflare.com/learning/email-security/dmarc-dkim-spf/&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:4&#34;&gt;&#xA;&lt;p&gt;在&lt;a class=&#34;link&#34; href=&#34;https://docker-mailserver.github.io/docker-mailserver/latest/config/best-practices/dkim_dmarc_spf/#generating-keys&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;官方文檔&lt;/a&gt;中有提及。&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
        </item><item>
            <title>Firefish 數據庫升級記錄</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2024/08/upgrading-firefish-database-docker/</link>
            <pubDate>Fri, 30 Aug 2024 04:45:12 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2024/08/upgrading-firefish-database-docker/</guid>
            <description>&lt;img src=&#34;https://blog.l3zc.com/2024/08/upgrading-firefish-database-docker/cover_hu_c0ecfda1e4670195.webp&#34; alt=&#34;Featured image of post Firefish 數據庫升級記錄&#34; /&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://social.l3zc.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;我的 Firefish 實例&lt;/a&gt;搭建於去年的 11 月，使用的數據庫版本自然不是最新的，確切的說，是 PGroonga 12，一個基於 5 年前的 Postgres 的遠古版本。為了避免今後的兼容性問題和安全問題，同時為了更好的性能，今天這數據庫是非升級不可。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/08/upgrading-firefish-database-docker/image_hu_49fb33e91bcaa665.webp&#34; alt=&#34;PostgreSQL 12 是在 2019 年發佈的&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;升級一個用 Docker 跑起來的數據庫和升級其他的 Docker 容器有很大不同，並不是拉取一個新的鏡像就可以宣告結束。因為 Postgres 幾乎每個大版本都有 Breaking Changes，新老版本產生的持久化文件並不兼容，如果直接拉取一個新的鏡像運行，數據庫是無法啟動的，必須要採用一定的手段進行數據的遷移。&lt;/p&gt;&#xA;&lt;p&gt;Postgres 有官方的升級工具&lt;code&gt;pg_upgrade&lt;/code&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;，這一次我不採用，因為我的數據庫跑了一年多，而且用的還是 5 年前的老版本，用這個工具我不確定會不會出問題。這次遷移，大致思路是先導出 SQL，再將導出的 SQL 導入新版本。&lt;/p&gt;&#xA;&lt;h2 id=&#34;升級前的部署概況&#34;&gt;升級前的部署概況&#xA;&lt;/h2&gt;&lt;p&gt;以下是一些升級前需要了解的配置信息：&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;項目&lt;/th&gt;&#xA;          &lt;th&gt;配置&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;實例部署方式&lt;/td&gt;&#xA;          &lt;td&gt;Docker Compose&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;數據庫容器名稱&lt;/td&gt;&#xA;          &lt;td&gt;firefish_db&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;升級前的數據庫容器鏡像&lt;/td&gt;&#xA;          &lt;td&gt;groonga/pgroonga:3.1.9-alpine-12-slim&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;數據庫用戶&lt;/td&gt;&#xA;          &lt;td&gt;example-firefish-user&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;數據庫名稱&lt;/td&gt;&#xA;          &lt;td&gt;firefish&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Docker Compose 的數據庫部分如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;db:&#xA;  restart: unless-stopped&#xA;  image: groonga/pgroonga:3.1.9-alpine-12-slim&#xA;  container_name: firefish_db&#xA;  networks:&#xA;    - calcnet&#xA;  env_file:&#xA;    - .config/docker.env&#xA;  volumes:&#xA;    - ./db:/var/lib/postgresql/data&#xA;  healthcheck:&#xA;    test: pg_isready --user=&#34;$${POSTGRES_USER}&#34; --dbname=&#34;$${POSTGRES_DB}&#34;&#xA;    interval: 5s&#xA;    timeout: 5s&#xA;    retries: 5&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;導出當前數據庫&#34;&gt;導出當前數據庫&#xA;&lt;/h2&gt;&lt;p&gt;對數據庫進行升級之前，首先下線 Firefish 的編排：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;docker compose down&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;單獨啟動數據庫容器，導出當前數據庫為 SQL：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;docker compose up -d db&#xA;docker exec -it firefish_db pg_dumpall -U example-firefish-user &gt; backup.sql&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;由於 Firefish 的數據庫比較大，導出過程可能需要很長一段時間，比如我的個人實例就用了十幾分鍾。&lt;/p&gt;&#xA;&lt;h2 id=&#34;導出文件的處理&#34;&gt;導出文件的處理&#xA;&lt;/h2&gt;&lt;p&gt;可能是由於新版的 Postgres 認證方式有所變更，如果直接向新數據庫導入之前導出的&lt;code&gt;backup.sql&lt;/code&gt;文件，就會改變新數據庫的 Authentication Scheme，導致之後 Firefish 連接數據庫時認證失敗。要避免這個問題需要對目前的&lt;code&gt;backup.sql&lt;/code&gt;進行一些處理，只抽取出其中的&lt;code&gt;firefish&lt;/code&gt;數據庫的部分，而不是直接導入所有數據。&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/bin/bash&#xA;[ $# -lt 2 ] &amp;&amp; { echo &#34;Usage: $0 &lt;postgresql dump&gt; &lt;dbname&gt;&#34;; exit 1; }&#xA;sed  &#34;/connect.*$2/,\$!d&#34; $1 | sed &#34;/PostgreSQL database dump complete/,\$d&#34;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;編輯一個 Shell 腳本為以上內容，保存至&lt;code&gt;script.sh&lt;/code&gt;，用以處理目前的&lt;code&gt;backup.sql&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;nvim script.sh  # 或者任何你喜歡的編輯器&#xA;chmod +x script.sh&#xA;./script.sh backup.sql firefish &gt;&gt; upgrade.sql&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;如果一切順利，當前目錄下就會出現一個名為&lt;code&gt;upgrade.sql&lt;/code&gt;的文件，可以打開它看一下，確保其被正確導出。&lt;/p&gt;&#xA;&lt;h2 id=&#34;向新數據庫導入現有數據&#34;&gt;向新數據庫導入現有數據&#xA;&lt;/h2&gt;&lt;p&gt;修改&lt;code&gt;docker-compose.yml&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;db:&#xA;  restart: unless-stopped&#xA;  image: groonga/pgroonga:3.2.2-alpine-16-slim # 最新的容器&#xA;  container_name: firefish_db&#xA;  networks:&#xA;    - calcnet&#xA;  env_file:&#xA;    - .config/docker.env&#xA;  volumes:&#xA;    - ./database:/var/lib/postgresql/data # 注意這一行的變動&#xA;  healthcheck:&#xA;    test: pg_isready --user=&#34;$${POSTGRES_USER}&#34; --dbname=&#34;$${POSTGRES_DB}&#34;&#xA;    interval: 5s&#xA;    timeout: 5s&#xA;    retries: 5&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;注意數據庫目錄映射配置由&lt;code&gt;./db:/var/lib/postgresql/data&lt;/code&gt;變為&lt;code&gt;./database:/var/lib/postgresql/data&lt;/code&gt;，這麼做是為了給新的數據庫一個 Fresh Start，同時也保存老的持久化數據，即使出現問題，也可以隨時用回老的數據庫。&lt;/p&gt;&#xA;&lt;p&gt;拉取並啟動新容器：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;docker compose pull&#xA;docker compose up db -d&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;向新數據庫導入&lt;code&gt;upgrade.sql&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;cat upgrade.sql | docker exec -i firefish_db psql -U example-firefish-user -d firefish&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;取決於數據庫的大小，導入過程也會持續較長的時間。&lt;/p&gt;&#xA;&lt;h2 id=&#34;收尾工作&#34;&gt;收尾工作&#xA;&lt;/h2&gt;&lt;p&gt;導入完成，啟動整個編排：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;docker compose stop db&#xA;docker compose up&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;導入後的首次啟動不建議帶&lt;code&gt;-d&lt;/code&gt;參數，建議不帶參數啟動，確保啟動過程沒有問題後再以&lt;code&gt;-d&lt;/code&gt;參數啟動。&lt;/p&gt;&#xA;&lt;p&gt;最後，登入剛剛啟動的 Firefish 實例，檢查是否有任何數據損失，沒有問題的話就大功告成啦🎉&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;官方文檔：https://www.postgresql.org/docs/current/pgupgrade.html&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;參考：https://thomasbandt.com/postgres-docker-major-version-upgrade&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
        </item><item>
            <title>科學上網：用 Caddy 反向代理 VLESS</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2024/08/caddy-vless-proxy/</link>
            <pubDate>Tue, 13 Aug 2024 08:24:26 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2024/08/caddy-vless-proxy/</guid>
            <description>&lt;img src=&#34;https://blog.l3zc.com/2024/08/caddy-vless-proxy/cover_hu_1cd20ddda32e23a.webp&#34; alt=&#34;Featured image of post 科學上網：用 Caddy 反向代理 VLESS&#34; /&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.l3zc.com/2024/08/aria2-downloading-server/&#34; &gt;上一篇文章&lt;/a&gt;提到，我搭建了一個基於 Aria2 的 BT 離線下載服務器。為了用 Caddy 反向代理部署好的容器，我把原來偷懶用一鍵腳本部署的 Trojan 給卸載了，問就是因為這腳本把 80 和 443 端口都佔用了，不卸載掉根本沒法繼續。&lt;/p&gt;&#xA;&lt;p&gt;於是離線下載服務器是搭建好了，可時不時需要的代理卻不得不下線。仔細一想，之前看到過有人 Cloudflare + V2Ray + WS 復活被牆的 VPS，既然是 WebSocket，還能用 Cloudflare 反代，那用 Caddy 反代又有何不可呢？況且 Caddy 還有自動 TLS，比起 Nginx + Certbot 的組合配置起來肯定更簡單。只要配置成功，我就可以在為 Caddy 留住 443 端口的同時跑代理了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;安裝-vless-和-caddy&#34;&gt;安裝 VLESS 和 Caddy&#xA;&lt;/h2&gt;&lt;p&gt;安裝VLESS 可以直接使用 &lt;a class=&#34;link&#34; href=&#34;https://github.com/v2fly/fhs-install-v2ray&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;v2fly/fhs-install-v2ray&lt;/a&gt; 一鍵腳本：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;# 安裝執行檔和 .dat 資料檔&#xA;bash &lt;(curl -L https://raw.githubusercontent.com/v2fly/fhs-install-v2ray/master/install-release.sh)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Caddy 的安裝請參考&lt;a class=&#34;link&#34; href=&#34;https://caddyserver.com/docs/install&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;官方教程&lt;/a&gt;，例如，我使用 Debian 12，則使用以下命令：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl&#xA;curl -1sLf &#39;https://dl.cloudsmith.io/public/caddy/stable/gpg.key&#39; | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg&#xA;curl -1sLf &#39;https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt&#39; | sudo tee /etc/apt/sources.list.d/caddy-stable.list&#xA;sudo apt update&#xA;sudo apt install caddy&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;配置-vless&#34;&gt;配置 VLESS&#xA;&lt;/h2&gt;&lt;p&gt;編輯&lt;code&gt;/usr/local/etc/v2ray/config.json&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&#xA;  &#34;log&#34;: {&#xA;    &#34;access&#34;: &#34;/var/log/v2ray/access.log&#34;,&#xA;    &#34;error&#34;: &#34;/var/log/v2ray/error.log&#34;,&#xA;    &#34;loglevel&#34;: &#34;warning&#34;&#xA;  },&#xA;  &#34;inbounds&#34;: [&#xA;    {&#xA;      &#34;port&#34;: 1234, //任意端口&#xA;      &#34;listen&#34;: &#34;127.0.0.1&#34;,&#xA;      &#34;protocol&#34;: &#34;vless&#34;,&#xA;      &#34;settings&#34;: {&#xA;        &#34;clients&#34;: [&#xA;          {&#xA;            &#34;id&#34;: &#34;super-random-uuid&#34;, //隨機生成一個 UUID 替換即可&#xA;            &#34;level&#34;: 0,&#xA;            &#34;email&#34;: &#34;example@example.com&#34;&#xA;          }&#xA;        ],&#xA;        &#34;decryption&#34;: &#34;none&#34;&#xA;      },&#xA;      &#34;streamSettings&#34;: {&#xA;        &#34;network&#34;: &#34;ws&#34;,&#xA;        &#34;security&#34;: &#34;none&#34;,&#xA;        &#34;wsSettings&#34;: {&#xA;          &#34;path&#34;: &#34;/&#34; // 需要與之後的 Caddy 配置保持相同&#xA;        }&#xA;      }&#xA;    }&#xA;  ],&#xA;  &#34;outbounds&#34;: [&#xA;    {&#xA;      &#34;protocol&#34;: &#34;freedom&#34;&#xA;    }&#xA;  ]&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;編輯完成後保存退出即可。&lt;/p&gt;&#xA;&lt;h2 id=&#34;配置-caddy&#34;&gt;配置 Caddy&#xA;&lt;/h2&gt;&lt;p&gt;在你喜歡的位置創建一個 Caddyfile，或者編輯已有的 Caddyfile，加入如下內容，反向代理剛才在 VLESS 配置文件中設置的端口：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-caddyfile&#34;&gt;yourdomain.com {&#xA;        # 用一個 Matcher 匹配所有指定路徑的 Websocket 請求&#xA;        @websockets {&#xA;                path /      # 與前面 VLESS 的 path 保持一致&#xA;                header Connection Upgrade&#xA;                header Upgrade websocket&#xA;        }&#xA;        reverse_proxy @websockets :1234&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;至此，服務端所有配置文件都編輯完畢。&lt;/p&gt;&#xA;&lt;h2 id=&#34;啟動服務&#34;&gt;啟動服務&#xA;&lt;/h2&gt;&lt;p&gt;啟動 VLESS，並設置開機自啟動：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;systemtcl enable v2ray &amp;&amp; systemctl start v2ray&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;啟動 Caddy/更新 Caddy 配置：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;caddy start&#xA;caddy reload  # 更新配置用&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;以上操作全部完成後，Caddy 反向代理 VLESS 就完成了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;客戶端設置&#34;&gt;客戶端設置&#xA;&lt;/h2&gt;&lt;p&gt;客戶端方面需要手動設置：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;地址是綁定給 VLESS 的域名。&lt;/li&gt;&#xA;&lt;li&gt;端口是 443&lt;/li&gt;&#xA;&lt;li&gt;TLS 打開&lt;/li&gt;&#xA;&lt;li&gt;傳輸方式選擇 websocket&lt;/li&gt;&#xA;&lt;li&gt;UUID 是之前填入 VLESS 配置文件的 UUID&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/08/caddy-vless-proxy/IMG_0003_hu_844bce19772c475.webp&#34; alt=&#34;Shadowrocket 設置&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;所有的客戶端設置大同小異，至於 Clash 的配置文件，可以參考 &lt;a class=&#34;link&#34; href=&#34;https://wiki.metacubex.one/config/proxies/vless/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Mihomo 文檔&lt;/a&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;，以下是我的示例配置文件：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;proxies:&#xA;  - name: &#34;A Random Name&#34;&#xA;    type: vless&#xA;    server: yourdomain.com&#xA;    port: 443&#xA;    udp: true&#xA;    uuid: super-random-uuid&#xA;    flow: xtls-rprx-vision&#xA;    packet-encoding: xudp&#xA;&#xA;    tls: true&#xA;    servername: yourdomain.com&#xA;    alpn:&#xA;      - h2&#xA;      - http/1.1&#xA;    skip-cert-verify: false&#xA;&#xA;    network: ws&#xA;&#xA;    smux:&#xA;      enabled: false&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;需要生成 Clash 配置文件可以使用 &lt;a class=&#34;link&#34; href=&#34;https://v2rayse.com/clash-template/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;V2RaySE 提供的工具&lt;/a&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;完成&#34;&gt;完成&#xA;&lt;/h2&gt;&lt;p&gt;好了，現在我們已經擁有了一個 VLESS 服務器，Caddy 會自動為我們申請和維護 TLS 證書，非常好用。&lt;/p&gt;&#xA;&lt;p&gt;只需要這麼小小折騰一下，我彷彿又找到了當年用一鍵腳本搭建 SSR 時的愉悅，好好享受這種能順利打開 google.com 時的興奮吧。&lt;/p&gt;&#xA;&lt;h2 id=&#34;todo-list&#34;&gt;TODO List&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 基本搭建&lt;/li&gt;&#xA;&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; 偽裝&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;畢竟繼承 Clash Meta 衣缽的 Mihomo 也算是 Clash 正統了。&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
        </item><item>
            <title>搭建一個 BT 離線下載服務器</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2024/08/aria2-downloading-server/</link>
            <pubDate>Sat, 10 Aug 2024 07:46:40 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2024/08/aria2-downloading-server/</guid>
            <description>&lt;img src=&#34;https://blog.l3zc.com/2024/08/aria2-downloading-server/cover_hu_935547325c8335d7.webp&#34; alt=&#34;Featured image of post 搭建一個 BT 離線下載服務器&#34; /&gt;&lt;p&gt;自從買了一些廉價 VPS 以後，手上就閒置了一臺 Azure 的學生機，除了用來跑個 Trojan 暫時沒有其他的用途。正好最近想要下一些 BT 資源，而國內的 BT 環境懂的都懂，遂決定用這臺接近閒置的機器離線下載 BT。&lt;/p&gt;&#xA;&lt;p&gt;首先聲明，所有 BT 下載行為需要自行承擔被版權投訴的風險。&lt;/p&gt;&#xA;&lt;h2 id=&#34;安裝-aria2&#34;&gt;安裝 Aria2&#xA;&lt;/h2&gt;&lt;p&gt;對於這些不是「基礎設施」的軟件，我更喜歡直接拉取一個 Docker 容器的方案。我採用了&lt;a class=&#34;link&#34; href=&#34;https://github.com/P3TERX/Aria2-Pro-Docker&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;P3TERX/Aria2-Pro-Docker&lt;/a&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;，這套已經修改好的 Docker 容器。Docker 容器部署起來如出一轍：首先編輯&lt;code&gt;docker-compose.yml&lt;/code&gt;，&lt;code&gt;docker compose up&lt;/code&gt;把所有容器都跑起來，最後反代暴露的端口即可。&lt;/p&gt;&#xA;&lt;p&gt;我的&lt;code&gt;docker-compose.yml&lt;/code&gt;如下&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;services:&#xA;  Aria2-Pro:&#xA;    container_name: aria2-pro&#xA;    image: p3terx/aria2-pro&#xA;    environment:&#xA;      - PUID=65534&#xA;      - PGID=65534&#xA;      - UMASK_SET=022&#xA;      - RPC_SECRET=replace-me # 記得修改這一行&#xA;      - RPC_PORT=6800&#xA;      - LISTEN_PORT=6888&#xA;      - DISK_CACHE=64M&#xA;      - IPV6_MODE=false&#xA;      - UPDATE_TRACKERS=true&#xA;      - CUSTOM_TRACKER_URL=&#xA;      - TZ=Asia/Shanghai&#xA;    volumes:&#xA;      - ./aria2-config:/config&#xA;      - ./aria2-downloads:/downloads&#xA;    network_mode: bridge # 如果你需要用到 IPV6 網絡，也可以使用 host 模式&#xA;    ports:&#xA;      - 6800:6800&#xA;      - 6888:6888&#xA;      - 6888:6888/udp&#xA;    restart: unless-stopped&#xA;    # 防止日誌塞滿硬盤&#xA;    logging:&#xA;      driver: json-file&#xA;      options:&#xA;        max-size: 1m&#xA;&#xA;  # 也可以使用其他面板&#xA;  AriaNg:&#xA;    container_name: ariang&#xA;    image: p3terx/ariang&#xA;    command: --port 6880 --ipv6&#xA;    network_mode: bridge&#xA;    ports:&#xA;      - 6880:6880&#xA;    restart: unless-stopped&#xA;    logging:&#xA;      driver: json-file&#xA;      options:&#xA;        max-size: 1m&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;用-caddy-反向代理&#34;&gt;用 Caddy 反向代理&#xA;&lt;/h2&gt;&lt;p&gt;之前的反向代理，我都是用的基於 Nginx 的方案，而在這段時間裡關於 Caddy 的好評不絕於耳，這次的我便換用了 Caddy，當然，主要也是想嘗試一些新東西、新技術。&lt;/p&gt;&#xA;&lt;p&gt;Caddy 的使用真的非常簡單，即使對新人也極其友好，例如，常用的反向代理本機某個端口，只需三行 Caddyfile 即可搞定。&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-caddyfile&#34;&gt;domain.com {&#xA;  reverse_proxy :1234&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;安裝 Caddy 請參考官方文檔，例如，我的服務器使用 Debian，則使用以下命令安裝：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl&#xA;curl -1sLf &#39;https://dl.cloudsmith.io/public/caddy/stable/gpg.key&#39; | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg&#xA;curl -1sLf &#39;https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt&#39; | sudo tee /etc/apt/sources.list.d/caddy-stable.list&#xA;sudo apt update&#xA;sudo apt install caddy&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;安裝完成後記得開放防火牆和從服務商策略組的 80 和 443 端口。&lt;/p&gt;&#xA;&lt;p&gt;在域名服務商處將要綁定的域名指向服務器，就可以開始寫 Caddyfile 了。我們需要反向代理三個端口，分別用作不同的用途。我的 Caddyfile 如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-caddyfile&#34;&gt;# Aria-NG 面板&#xA;download.l3zc.com {&#xA;  reverse_proxy :6880&#xA;}&#xA;&#xA;# Aria2 API&#xA;arapi.l3zc.com {&#xA;  reverse_proxy :6800&#xA;}&#xA;&#xA;# Alist&#xA;downloaded.l3zc.com {&#xA;  reverse_proxy :5244&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;看到如此簡潔的配置文件，不由得感嘆，相比於 Nginx，Caddy 用起來真是令人心情舒暢。寫入配置完成後，重新啟動 Caddy&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;，就可以開始欣賞 Caddy 自動幫你申請 SSL 證書配置好 HTTPS 的絕贊過程。至此，反向代理的部分也就完成了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;配置-aria-ng&#34;&gt;配置 Aria-NG&#xA;&lt;/h2&gt;&lt;p&gt;Aria-NG 只是一個前端面板，可以和任何 Aria2 後端通信，為此，我們需要給 Aria-NG 提供配置信息。進入剛剛反代好的 Aria-NG 面板，轉到 AriaNG 設置，填入配置信息。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/08/aria2-downloading-server/image-2_hu_d9233f39114b3449.webp&#34; alt=&#34;在 AriaNG 面板內填入配置信息&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;其中，RPC 地址是剛剛反代好的 RPC 地址，協議選擇 HTTPS，請求方法選擇 POST，RPC 密鑰是在&lt;code&gt;docker-compose.yml&lt;/code&gt;裡&lt;code&gt;replace-me&lt;/code&gt;處你所替換的值。&lt;/p&gt;&#xA;&lt;p&gt;若「Aria2 狀態」旁出現「已連接」，說明配置正確。&lt;/p&gt;&#xA;&lt;h2 id=&#34;用-alist-映射下載目錄&#34;&gt;用 Alist 映射下載目錄&#xA;&lt;/h2&gt;&lt;p&gt;我們通過 Alist 映射下載目錄，以更方便的查看、管理和下載服務器上已經下載好的文件。Alist 同樣也通過 Docker 部署，由於 Alist 本身在容器內運行們，無法訪問容器外的文件，部署時需要將 Aria2 的下載目錄提前 Bind 到 Alist 的容器下。&lt;/p&gt;&#xA;&lt;p&gt;我的&lt;code&gt;docker-compose.yml&lt;/code&gt;如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;services:&#xA;  alist:&#xA;    image: &#34;xhofe/alist:latest&#34;&#xA;    container_name: alist&#xA;    volumes:&#xA;      - &#34;/etc/alist:/opt/alist/data&#34;&#xA;      - &#34;/home/azureuser/aria2/aria2-downloads:/aria2-downloads&#34; #這裡需要視情況綁定你自己的目錄&#xA;    ports:&#xA;      - &#34;5244:5244&#34;&#xA;    environment:&#xA;      - PUID=0&#xA;      - PGID=0&#xA;      - UMASK=022&#xA;    restart: unless-stopped&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;第一次啟動 Alist 時，Alist 會隨機生成&lt;code&gt;admin&lt;/code&gt;用戶的密碼，所以，第一次啟動這套編排時，最好不要帶&lt;code&gt;-d&lt;/code&gt;參數，而是直接&lt;code&gt;docker compose up&lt;/code&gt;，並把容器啟動後的輸出妥善保存。如果不小心沒有保存管理員密碼，可以用這個命令重新隨機生成一個：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;docker exec -it alist ./alist admin random&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;成功登錄 Alist 之後就可以開始掛載目錄了。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2024/08/aria2-downloading-server/image_hu_fb55cbee3d7dca68.webp&#34; alt=&#34;掛載 Aria2 的下載目錄&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;驅動選擇本機存儲，掛載路徑需要注意，按照我的編排，我將容器外的&lt;code&gt;/home/azureuser/aria2/aria2-downloads&lt;/code&gt;目錄掛載到了容器內的&lt;code&gt;/aria2-downloads&lt;/code&gt;，所以掛載路徑應該是&lt;code&gt;/aria2-downloads&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;完成&#34;&gt;完成&#xA;&lt;/h2&gt;&lt;p&gt;現在所有的服務都已經部署上線了，打開 AriaNG 可以添加下載任務，下載好的文件可以打開 Alist 看到，下載，以及在線觀看。&lt;/p&gt;&#xA;&lt;p&gt;搭建這套服務之前，請仔細查看 VPS 提供商的服務條款，確保 BT 下載行為不會違規。以及，除了盧森堡等少數國家/地區，下載被 DMCA 保護的資源可能會遭到投訴，這些風險都需要你自行承擔。&lt;/p&gt;&#xA;&lt;p&gt;反正我這 Azure 的學生機也是白嫖的，被投訴回收了我也無所謂，不管怎樣，現在可以心無旁騖的享受找資源的快樂了。&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;當然也可以試一試&lt;a class=&#34;link&#34; href=&#34;https://github.com/SuperNG6/docker-aria2&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;SuperNG6/docker-aria2&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;參考原作者的&lt;a class=&#34;link&#34; href=&#34;https://github.com/P3TERX/Aria2-Pro-Docker/blob/master/docker-compose.yml&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:3&#34;&gt;&#xA;&lt;p&gt;&lt;code&gt;caddy stop&lt;/code&gt;和&lt;code&gt;caddy start&lt;/code&gt;，參考&lt;a class=&#34;link&#34; href=&#34;https://caddyserver.com/docs/getting-started#start-stop-run&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Caddy文檔&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
        </item><item>
            <title>最速 Firefish 部署指南</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2023/12/firefish-deploy/</link>
            <pubDate>Mon, 04 Dec 2023 09:17:56 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2023/12/firefish-deploy/</guid>
            <description>&lt;img src=&#34;https://blog-img.l3zc.com/firefishlogo.webp&#34; alt=&#34;Featured image of post 最速 Firefish 部署指南&#34; /&gt;&lt;h2 id=&#34;需要的環境&#34;&gt;需要的環境&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;Docker 和 Docker Compose&lt;/li&gt;&#xA;&lt;li&gt;任意 Web 服務器&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;最速教程&#34;&gt;最速教程&#xA;&lt;/h2&gt;&lt;p&gt;為 Firefish 準備一個目錄：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;mkdir firefish &amp;&amp; cd firefish&lt;/code&gt;&lt;/pre&gt;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;⚠️注意：近期 Firefish 更新頻繁，本文的&lt;code&gt;docker-compose.yml&lt;/code&gt;已經過時，請參考官方倉庫中的&lt;a class=&#34;link&#34; href=&#34;https://firefish.dev/firefish/firefish/-/blob/develop/docker-compose.example.yml&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;docker-compose.example.yml&lt;/a&gt;和&lt;a class=&#34;link&#34; href=&#34;https://firefish.dev/firefish/firefish/-/blob/develop/docs/notice-for-admins.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Notice for server administrators&lt;/a&gt;進行配置。&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;用你喜歡的文本編輯器創建&lt;code&gt;docker-compose.yml&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: &#34;3&#34;&#xA;&#xA;services:&#xA;  web:&#xA;    image: registry.joinfirefish.org/firefish/firefish:stable-amd64&#xA;    container_name: firefish_web&#xA;    restart: unless-stopped&#xA;    depends_on:&#xA;      - db&#xA;      - redis&#xA;      ### Uncomment one of the following to use a search engine&#xA;      #     - meilisearch&#xA;      - sonic&#xA;    ports:&#xA;      - &#34;6666:3000&#34; # 6666換成需要的端口&#xA;    networks:&#xA;      - calcnet&#xA;    #     - web&#xA;    environment:&#xA;      NODE_ENV: production&#xA;    volumes:&#xA;      - ./files:/firefish/files&#xA;      - ./.config:/firefish/.config:ro&#xA;&#xA;  redis:&#xA;    restart: unless-stopped&#xA;    image: redis:7.0-alpine&#xA;    container_name: firefish_redis&#xA;    networks:&#xA;      - calcnet&#xA;    volumes:&#xA;      - ./redis:/data&#xA;&#xA;  db:&#xA;    restart: unless-stopped&#xA;    image: postgres:12.2-alpine&#xA;    container_name: firefish_db&#xA;    networks:&#xA;      - calcnet&#xA;    env_file:&#xA;      - .config/docker.env&#xA;    volumes:&#xA;      - ./db:/var/lib/postgresql/data&#xA;&#xA;  ### Only one of the below should be used.&#xA;  ### Meilisearch is better overall, but resource-intensive. Sonic is a very light full text search engine.&#xA;&#xA;  #  meilisearch:&#xA;  #    container_name: meilisearch&#xA;  #    image: getmeili/meilisearch:v1.1.1&#xA;  #    environment:&#xA;  #      - MEILI_ENV=${MEILI_ENV:-development}&#xA;  #    ports:&#xA;  #      - &#34;7700:7700&#34;&#xA;  #    networks:&#xA;  #      - calcnet&#xA;  #    volumes:&#xA;  #      - ./meili_data:/meili_data&#xA;  #    restart: unless-stopped&#xA;&#xA;  sonic:&#xA;    restart: unless-stopped&#xA;    image: valeriansaliou/sonic:v1.4.0&#xA;    logging:&#xA;      driver: none&#xA;    networks:&#xA;      - calcnet&#xA;    volumes:&#xA;      - ./sonic:/var/lib/sonic/store&#xA;      - ./sonic/config.cfg:/etc/sonic.cfg:ro&#xA;&#xA;networks:&#xA;  calcnet:&#xA;  #  web:&#xA;  #    external:&#xA;  #      name: web&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;你也可以用 Melisearch，但這是最速指南，只講 Sonic。&lt;/p&gt;&#xA;&lt;p&gt;創建&lt;code&gt;.config&lt;/code&gt;目錄：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;mkdir .config &amp;&amp; cd .config&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;創建&lt;code&gt;docker.env&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# db settings&#xA;POSTGRES_PASSWORD=example-firefish-pass&#xA;POSTGRES_USER=example-firefish-user&#xA;POSTGRES_DB=firefish&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;創建&lt;code&gt;default.yml&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━&#xA;# Firefish configuration&#xA;#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━&#xA;&#xA;# After starting your server, please don&#39;t change the URL! Doing so will break federation.&#xA;&#xA;#   ┌─────┐&#xA;#───┘ URL └─────────────────────────────────────────────────────&#xA;&#xA;# Final accessible URL seen by a user.&#xA;url: https://你的域名/&#xA;port: 3000&#xA;&#xA;db:&#xA;  host: db&#xA;  port: 5432&#xA;  #ssl: false&#xA;  # Database name&#xA;  db: firefish&#xA;&#xA;  # Auth&#xA;  user: example-firefish-user&#xA;  pass: example-firefish-pass&#xA;&#xA;#   ┌─────────────────────┐&#xA;#───┘ Redis configuration └─────────────────────────────────────&#xA;&#xA;redis:&#xA;  host: redis&#xA;  port: 6379&#xA;&#xA;#   ┌─────────────────────┐&#xA;#───┘ Sonic configuration └─────────────────────────────────────&#xA;&#xA;sonic:&#xA;  host: sonic&#xA;  port: 1491&#xA;  auth: SecretPassword&#xA;  collection: notes&#xA;  bucket: default&#xA;&#xA;# Reserved usernames that only the administrator can register with&#xA;reservedUsernames: [&#34;root&#34;, &#34;admin&#34;, &#34;administrator&#34;, &#34;me&#34;, &#34;system&#34;]&#xA;&#xA;signToActivityPubGet: true&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;回到上一層目錄，創建&lt;code&gt;./sonic/config.cfg&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-toml&#34;&gt;# Sonic&#xA;# Fast, lightweight and schema-less search backend&#xA;# Configuration file&#xA;# Example: https://github.com/valeriansaliou/sonic/blob/master/config.cfg&#xA;&#xA;[server]&#xA;&#xA;log_level = &#34;debug&#34;&#xA;&#xA;[channel]&#xA;&#xA;inet = &#34;0.0.0.0:1491&#34;&#xA;tcp_timeout = 300&#xA;&#xA;auth_password = &#34;SecretPassword&#34;&#xA;&#xA;[channel.search]&#xA;&#xA;query_limit_default = 10&#xA;query_limit_maximum = 100&#xA;query_alternates_try = 4&#xA;&#xA;suggest_limit_default = 5&#xA;suggest_limit_maximum = 20&#xA;&#xA;list_limit_default = 100&#xA;list_limit_maximum = 500&#xA;&#xA;[store]&#xA;&#xA;[store.kv]&#xA;&#xA;path = &#34;./data/store/kv/&#34;&#xA;&#xA;retain_word_objects = 1000&#xA;&#xA;[store.kv.pool]&#xA;&#xA;inactive_after = 1800&#xA;&#xA;[store.kv.database]&#xA;&#xA;flush_after = 900&#xA;&#xA;compress = true&#xA;parallelism = 2&#xA;max_files = 100&#xA;max_compactions = 1&#xA;max_flushes = 1&#xA;write_buffer = 16384&#xA;write_ahead_log = true&#xA;&#xA;[store.fst]&#xA;&#xA;path = &#34;./data/store/fst/&#34;&#xA;&#xA;[store.fst.pool]&#xA;&#xA;inactive_after = 300&#xA;&#xA;[store.fst.graph]&#xA;&#xA;consolidate_after = 180&#xA;&#xA;max_size = 2048&#xA;max_words = 250000&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;全部創建好以後的目錄結構應該看起來像這樣：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;.&#xA;├── .config&#xA;│   ├── default.yml&#xA;│   └── docker.env&#xA;├── docker-compose.yml&#xA;└── sonic&#xA;    └── config.cfg&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最後執行&lt;code&gt;docker compose up&lt;/code&gt;，綁定域名、反代端口，實例就搭建完成了。&lt;/p&gt;&#xA;&lt;p&gt;Firefish 已經自動 Minify 了所有的前端文件，如果你使用 Cloudflare 或其他類似的服務，記得關掉 Auto Minify，否則會出現一些奇怪的問題。&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&#xA;&lt;p&gt;以上就是最速教程。&lt;/p&gt;&#xA;&lt;h2 id=&#34;一些問題&#34;&gt;一些問題&#xA;&lt;/h2&gt;&lt;p&gt;Q：&lt;code&gt;docker.env&lt;/code&gt;和&lt;code&gt;./sonic/config.cfg&lt;/code&gt;密碼和用戶名不改沒問題嗎？&lt;/p&gt;&#xA;&lt;p&gt;A：沒很大問題，因為兩個服務沒有暴露到公網上，僅做個人使用不改也沒什麼大事。&lt;/p&gt;&#xA;&lt;p&gt;Q：為什麼 network 要叫&lt;code&gt;calcnet&lt;/code&gt;？&lt;/p&gt;&#xA;&lt;p&gt;A：因為這個項目本來叫做 Calckey。&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/misskey-dev/misskey/issues/10328&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://github.com/misskey-dev/misskey/issues/10328&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
        </item><item>
            <title>重新撿起 RSS：RSSHub &#43; FreshRSS 建立我的信息流</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2023/07/rsshub-freshrss-information-flow/</link>
            <pubDate>Mon, 17 Jul 2023 20:33:00 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2023/07/rsshub-freshrss-information-flow/</guid>
            <description>&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/20231011105121_hu_fe5d2177608978ac.webp&#34; alt=&#34;Featured image of post 重新撿起 RSS：RSSHub + FreshRSS 建立我的信息流&#34; /&gt;&lt;p&gt;不知從什麼時候開始，我的生活就慢慢的被推薦算法淹沒，推薦視頻、猜你喜歡……，幾乎每天，我都或多或少的被他們所影響。我曾半開玩笑：「網速越快，其傳遞的信息就越少」，甚至有些一語成讖。這並不是互聯網能傳遞的信息變少了，而是越來越快的網速、越來越準的推薦算法養廢了我們，奪走了我們從網上獲取信息的能力與主動權。&lt;/p&gt;&#xA;&lt;p&gt;RSS 已是信息獲取手段中的老古董了，但它的體驗真的一點都不老古董：相反，用它來獲取信息，體驗極佳——不光無廣告，還能讓那些分散在一個一個網頁上的信息自動跑到你面前，豈不美哉？我沒有經歷過那個時代，但聽聞當年的大家，人人都拿著 Google Reader（Google 打造的 RSS 閱讀器）讀他們想讀的內容，倒也真想回到那個年代體驗一番。&lt;/p&gt;&#xA;&lt;p&gt;可惜 Google Reader 這一產品早就關停了，曾經大多數網站都提供的 RSS 訂閱源也悉數消失，想要重新拾起 RSS，就需要一點折騰了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;rsshub萬物皆可-rss&#34;&gt;RSSHub：萬物皆可 RSS&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/DIYgod/RSSHub&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;GitHub 倉庫&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;這是 &lt;del&gt;DIYDog&lt;/del&gt;DIYGod 大佬發起的項目，就和它的標語一樣，萬物皆可 RSS，這個項目能通過爬取網頁內容的方式生成 RSS 信息流，從而通過 RSS 訂閱本不支持 RSS 的網站。&lt;/p&gt;&#xA;&lt;p&gt;由於是爬取，難免會受到目標網頁反爬取策略的影響，而有的目標網頁（比如大陸的政府網站）會屏蔽他國 IP 的訪問，亦或者屏蔽掉風險 IP。這些因素就比較考驗機房了，但只要不是被特別「照顧」的 IP，一般問題不大。出於這些原因，我在分別在洛杉磯和上海部署了 RSSHub。&lt;/p&gt;&#xA;&lt;p&gt;Docker 部署 RSSHub 非常簡單，首先拉取已經寫好的&lt;code&gt;docker-compose.yml&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ mkdir rsshub &amp;&amp; cd rsshub&#xA;$ wget https://raw.githubusercontent.com/DIYgod/RSSHub/master/docker-compose.yml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;然後檢查有無需要修改的配置：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ vim docker-compose.yml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;我最終修改完成後，配置如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: &#34;3&#34;&#xA;&#xA;services:&#xA;  rsshub:&#xA;    image: diygod/rsshub:chromium-bundled&#xA;    restart: always&#xA;    ports:&#xA;      - &#34;1200:1200&#34;&#xA;    environment:&#xA;      NODE_ENV: production&#xA;      CACHE_TYPE: redis&#xA;      REDIS_URL: &#34;redis://redis:6379/&#34;&#xA;    depends_on:&#xA;      - redis&#xA;&#xA;  redis:&#xA;    image: redis:alpine&#xA;    restart: always&#xA;    volumes:&#xA;      - redis-data:/data&#xA;&#xA;volumes:&#xA;  redis-data:&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;為什麼要新建一個 Redis 鏡像？主要是懶得配置容器互聯，而 RSSHub 用 Redis 佔不了多少資源，遂直接寫進一個&lt;code&gt;docker-compose.yml&lt;/code&gt;裡，省去容器互聯的麻煩。&lt;/p&gt;&#xA;&lt;p&gt;啟動編排：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ docker compose up&#x9;&#x9;# 老的寫法是 docker-compose up&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;隨後使用 Nginx 反代&lt;code&gt;localhost:1200&lt;/code&gt;至域名，部署 SSL 證書，RSSHub 就全部搭建完成了。&lt;/p&gt;&#xA;&lt;h3 id=&#34;反爬嚴格網站的部分解決&#34;&gt;反爬嚴格網站的部分解決&#xA;&lt;/h3&gt;&lt;p&gt;前面已經提到由於 RSSHub 的工作原理是爬取，其勢必會受到不同網站反爬策略的影響。以 B 站為例，如果僅僅部署 RSSHub 而不採取任何措施，當你訂閱時，大概率會出現「521 - 風控校驗失敗」的提示。&lt;/p&gt;&#xA;&lt;p&gt;這時，先去查找 RSSHub 的文檔，看看相應的網站是否有 Cookie 可以被設置為容器的環境變量，對於大部分需求，只要環境變量配置正確，就可以有效緩解反爬問題。&lt;/p&gt;&#xA;&lt;p&gt;還是以 B 站為例，查閱 &lt;a class=&#34;link&#34; href=&#34;https://docs.rsshub.app/zh/deploy/config#bilibili&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;RSSHub 文檔&lt;/a&gt;，可以發現有一些額外的環境變量需要配置。&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/image_hu_9cc51819263ebfbf.webp&#34; alt=&#34;大量的網站需要額外配置&#34; /&gt;&#xA; &#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/image-1_hu_6ced6541588d6064.webp&#34; alt=&#34;複製 Cookie 字段&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;按照文檔，打開對應的&lt;a class=&#34;link&#34; href=&#34;https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=0&amp;amp;type=8&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;網頁&lt;/a&gt;，按下 F12 打開開發者工具，轉到「網絡」面板，刷新網頁，就可以找到 dynamic*new 請求，複製整個 Cookie（或者 SESSDATA=xxx；字段），修改&lt;code&gt;docker-compose.yml&lt;/code&gt;文件，將&lt;code&gt;BILIBILI_COOKIE*你的B站UID: &amp;quot;SESSDATA=xxx&amp;quot;&lt;/code&gt;添加到&lt;code&gt;environment&lt;/code&gt;部分，即可完成配置。&lt;/p&gt;&#xA;&lt;p&gt;配置好的&lt;code&gt;docker-compose.yml&lt;/code&gt;看起來像下面這樣：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: &#34;3&#34;&#xA;&#xA;services:&#xA;  rsshub:&#xA;    # two ways to enable puppeteer:&#xA;    # * comment out marked lines, then use this image instead: diygod/rsshub:chromium-bundled&#xA;    # * (consumes more disk space and memory) leave everything unchanged&#xA;    image: diygod/rsshub:chromium-bundled&#xA;    restart: always&#xA;    ports:&#xA;      - &#34;1200:1200&#34;&#xA;    environment:&#xA;      NODE_ENV: production&#xA;      CACHE_TYPE: redis&#xA;      REDIS_URL: &#34;redis://redis:6379/&#34;&#xA;      BILIBILI_COOKIE_你的B站UID: &#34;SESSDATA=xxx&#34;&#xA;    depends_on:&#xA;      - redis&#xA;&#xA;  redis:&#xA;    image: redis:alpine&#xA;    restart: always&#xA;    volumes:&#xA;      - redis-data:/data&#xA;&#xA;volumes:&#xA;  redis-data:&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;修改文件並保存，重啟編排：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ docker compose up -d --force-recreate&#xA;# docker-compose up -d --force-recreate&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;配置完成後，即可正常訂閱 B 站 Up 主投稿等相關路由。&lt;/p&gt;&#xA;&lt;h2 id=&#34;rss-閱讀器推薦&#34;&gt;RSS 閱讀器推薦&#xA;&lt;/h2&gt;&lt;p&gt;RSSHub 可以解決掉大多數訂閱源的問題，接下來推薦幾個 RSS 閱讀器，解決的是最後一步如何呈現到設備上的問題。&lt;/p&gt;&#xA;&lt;h3 id=&#34;windows&#34;&gt;Windows&#xA;&lt;/h3&gt;&lt;h4 id=&#34;fluent-reader&#34;&gt;Fluent Reader&#xA;&lt;/h4&gt;&lt;p&gt;我目前在用的 RSS 閱讀器，開源小巧，遵循 Fluent Design，如果需要 Windows 上的免費 RSS 閱讀器，那麼大概率就是它了。需要注意的是，這是開源軟件，但在應用商店裡需要付費才能下載，不想付費則可以直接在 GitHub 上下載其安裝包安裝，當然，如果喜歡，鼓勵大家支持這個項目。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/yang991178/fluent-reader&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Github倉庫&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;thunderbird&#34;&gt;ThunderBird&#xA;&lt;/h4&gt;&lt;p&gt;這個不是 RSS 閱讀器，但也提供了 RSS 功能，比較適合打造郵件 RSS All in one。&lt;/p&gt;&#xA;&lt;p&gt;ThunderBird 是由 Mozilla 基金會開發的一款開源郵件和新聞聚合客戶端，已經有快 20 年的歷史。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.thunderbird.net/zh-CN/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;官網&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;macos-和-ios&#34;&gt;MacOS 和 iOS&#xA;&lt;/h3&gt;&lt;h4 id=&#34;netnewswire&#34;&gt;NetNewsWire&#xA;&lt;/h4&gt;&lt;p&gt;開源，Swift UI 原生編寫，幾乎完美的 RSS 閱讀器，說實話我很驚訝這位作者維護這個項目的時間跨度。&lt;/p&gt;&#xA;&lt;p&gt;NetNewsWire 是由 Brent Simmon 出於愛好和支持 RSS 發展開發的 RSS 閱讀器，遺憾的是，由於是 Swift UI 編寫，只支持 Mac OS 和 iOS。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://netnewswire.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;官網&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/Ranchero-Software/NetNewsWire&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Github倉庫&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;reeder&#34;&gt;Reeder&#xA;&lt;/h4&gt;&lt;p&gt;這個就是收費 App 了，但功能做的很不錯。作為「骨灰級」應用，Reeder 一度被人稱為 iOS 與 macOS 上最好用的 RSS 閱讀器。不光設計精緻，還支持如桌面小組件等各種 Mac OS 和 iOS 上原生的功能，如果你的預算充足，可以考慮。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://reederapp.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;官網&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;fluent-reader-1&#34;&gt;Fluent Reader&#xA;&lt;/h4&gt;&lt;p&gt;又是之前提到的 Fluent Reader 也提供了 Mac 版本，實測在 Mac OS 上體驗也還不錯，在 iOS 上雖然看起來是原生 UI，但實際上是 React 寫的跨平臺版本，而且還需要收費，如果想要支持這個項目，可以考慮購買。&lt;/p&gt;&#xA;&lt;p&gt;鏈接：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/yang991178/fluent-reader&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Github倉庫&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/yang991178/fluent-reader-lite&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Github倉庫（Fluent Reader Lite）&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;linux&#34;&gt;Linux&#xA;&lt;/h3&gt;&lt;h4 id=&#34;newsflash&#34;&gt;NewsFlash&#xA;&lt;/h4&gt;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/image-20231107130507607_hu_65cba9f2338a5965.webp&#34; alt=&#34;NewsFlash 也是很現代化的 RSS 閱讀器&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&#xA;    &lt;blockquote&gt;&#xA;        &lt;p&gt;NewsFlash is a program designed to complement an already existing web-based RSS reader account.&lt;/p&gt;&#xA;&lt;p&gt;It combines all the advantages of web based services like syncing across all your devices with everything you expect from a modern desktop program: Desktop notifications, fast search and filtering, tagging, handy keyboard shortcuts and having access to all your articles for as long as you like.&lt;/p&gt;&#xA;&#xA;    &lt;/blockquote&gt;&#xA;&lt;p&gt;這是一個很現代化的 RSS 閱讀器，一般用 flatpak 安裝，也有人為其製作了 Snap 封裝的版本，不過幾乎不怎麼更新維護。它的界面很好看，對在線服務&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;支持的很全，而且是原生運行，非常推薦。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://gitlab.com/news-flash/news_flash_gtk&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Gitlab 倉庫&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://flathub.org/apps/io.gitlab.news_flash.NewsFlash&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Flathub頁面&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;fluent-reader-2&#34;&gt;Fluent Reader&#xA;&lt;/h4&gt;&lt;p&gt;又雙叒是 Fluent Reader，跨平臺這麼容易嗎。&lt;/p&gt;&#xA;&lt;p&gt;有人給它製做了 Snap 封裝的 App，Ubuntu 可以直接去應用商店下載使用。官方倉庫裡提供了 AppImage 給其它分支使用。&lt;/p&gt;&#xA;&lt;h3 id=&#34;安卓&#34;&gt;安卓&#xA;&lt;/h3&gt;&lt;h4 id=&#34;fluent-reader-3&#34;&gt;Fluent Reader&#xA;&lt;/h4&gt;&lt;p&gt;又雙叒叕是 Fluent Reader，在安卓上，Fluent Reader 依然是貼合 iOS 的 UI，用起來有點牛頭人的感覺，若不在意這一點，體驗倒還不錯。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/yang991178/fluent-reader-lite&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Github倉庫&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;feedme&#34;&gt;FeedMe&#xA;&lt;/h4&gt;&lt;p&gt;評論區網友的推薦，FeedMe 支持的服務繁多，功能齊全，界面也較為現代化，一樣支持 FreshRSS 等在線 API。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/seazon/FeedMe&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Github 倉庫&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;如果有其他好用的 RSS 閱讀器歡迎在評論區留言。&lt;/p&gt;&#xA;&lt;h2 id=&#34;總感覺還缺點什麼&#34;&gt;總感覺還缺點什麼？&#xA;&lt;/h2&gt;&lt;p&gt;理論上來說，解決了訂閱源的問題，還解決了呈現在設備上的問題，我們已經還原出 Google Reader 的體驗了，但我在實際使用中，總是覺得缺少了一些特性，體驗並不完整。&lt;/p&gt;&#xA;&lt;p&gt;這個特性就是「同步」。我所希望的，是我在 A 設備上閱讀，閱讀進度可以同步到 B 設備上，在 A 設備上收藏的文章，打開 B 設備，能原封不動的呈現在我眼前。&lt;/p&gt;&#xA;&lt;p&gt;同時，還有一個體驗上的要求：我希望我在拉取 Feed 時更加快速，不需要等待 RSSHub 抓取網頁。&lt;/p&gt;&#xA;&lt;p&gt;於是，一個自託管的 RSS 聚合服務就很有必要了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;以-freshrss-完善體驗&#34;&gt;以 FreshRSS 完善體驗&#xA;&lt;/h2&gt;&lt;p&gt;FreshRSS 是一個免費，自託管的 RSS 聚合器，相似的項目還有 Tiny Tiny RSS（TTRSS），選擇 FreshRSS 是因為它提供兩種 API，和各個 RSS 客戶端配合的更好。&lt;/p&gt;&#xA;&lt;p&gt;Github倉庫：https://github.com/FreshRSS/FreshRSS&lt;/p&gt;&#xA;&lt;h3 id=&#34;部署&#34;&gt;部署&#xA;&lt;/h3&gt;&lt;p&gt;部署 FreshRSS 的過程也很輕鬆。&lt;/p&gt;&#xA;&lt;p&gt;創建目錄：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ mkdir freshrss&#xA;$ cd freshrss&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;創建&lt;code&gt;docker-compose.yml&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ vim docker-compose.yml&#x9;&#x9;# 或者任意編輯器編輯&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: &#34;3&#34;&#xA;&#xA;services:&#xA;  freshrss:&#xA;    image: freshrss/freshrss:latest&#xA;    container_name: freshrss&#xA;    restart: unless-stopped&#xA;    ports:&#xA;      - &#34;9999:80&#34; # 將9999更改成需要的端口&#xA;    volumes:&#xA;      - ./data:/var/www/FreshRSS/data&#xA;      - ./extensions:/var/www/FreshRSS/extensions&#xA;    environment:&#xA;      PUID: 0&#xA;      PGID: 0&#xA;      CRON_MIN: &#34;1,31&#34;&#xA;      TZ: &#34;Asia/Shanghai&#34;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最後執行：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ docker compose up&#x9;&#x9;# 老的寫法是 docker-compose up&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;隨後反代端口，部署 SSL 證書。初始設置時，數據庫選現有的數據庫類型，如果沒有部署數據庫，直接選 SQLite 即可。至此，FreshRSS 部署完成。&lt;/p&gt;&#xA;&lt;p&gt;如果之前有訂閱源，將其以 OPML 格式導出，然後導入 FreshRSS 就可以獲得幾乎無縫的體驗。&lt;/p&gt;&#xA;&lt;p&gt;![FreshRSS](截屏2023-07-18 15.17.39.png)&lt;/p&gt;&#xA;&lt;p&gt;如果有現成的 PHP 環境而不想用 Docker 部署，還可以像安裝 Wordpress 一樣安裝好 FreshRSS。&lt;/p&gt;&#xA;&lt;h3 id=&#34;設置-freshrss&#34;&gt;設置 FreshRSS&#xA;&lt;/h3&gt;&lt;p&gt;RSSHub 充當的是提供訂閱源的中心，而 FreshRSS 充當的是一個閱讀訂閱源的「Hub」，幫助我們集中管理訂閱源，同步各設備間的閱讀進度。現在訂閱源已經集中管理起來，同步個設備間的閱讀進度就需要 FreshRSS 提供的 API 了。&lt;/p&gt;&#xA;&lt;p&gt;FreshRSS 提供 GReader 和 Fever 兩種 API，具體的啟用方法如下：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;登入 FreshRSS 進入「設置」-&amp;gt;「認證」開啟「允許API 訪問」&lt;/li&gt;&#xA;&lt;li&gt;進入「賬戶」在頁面底部設置一個 API 密鑰&lt;/li&gt;&#xA;&lt;li&gt;編輯&lt;code&gt;./freshrss/data/config.php&lt;/code&gt;中的&lt;code&gt;base_url&lt;/code&gt;，改為你的域名根目錄地址，比如我的就需要改成&lt;code&gt;https://rss.l3zc.com/&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;轉到&lt;code&gt;https://example.com/api/&lt;/code&gt;查看檢測是否通過&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/202307191728380_hu_79eea7556b5c32e2.webp&#34; alt=&#34;修改FreshRSS的配置示例1&#34; /&gt;&#xA; &#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/202307191730452_hu_8ae8bbb7a3c483e8.webp&#34; alt=&#34;FreshRSS config.php 文件&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/image-2_hu_f712acb70d70816.webp&#34; alt=&#34;FreshRSS API 測試全部通過&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;h3 id=&#34;設置各設備上的客戶端&#34;&gt;設置各設備上的客戶端&#xA;&lt;/h3&gt;&lt;h4 id=&#34;netnewswire-1&#34;&gt;NetNewsWire&#xA;&lt;/h4&gt;&lt;p&gt;部署完成後，在手機上和電腦上支持的應用裡使用設置好的用戶名和 API 密鑰登陸，就可以享受到全程絲滑的 RSS 體驗了，下面以 NetNewsWire 為例：&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/image-20230718154700897_hu_2a53167b6e15dc43.webp&#34; alt=&#34;NetNewsWire集成FreshRSS&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;打開NetNewsWire添加賬號的選項卡，NetNewsWire貼心的集成了FreshRSS，可以很方便的添加賬號：&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/image-20230718155048961_hu_903d369c25b91ab6.webp&#34; alt=&#34;登陸信息&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;NetNewsWire 要求 Greader 的 API，直接在 /api 上覆制就可以了。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/image-20230718155246945_hu_ab8381e7b6c06c9d.webp&#34; alt=&#34;NetNewsWire效果&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;h4 id=&#34;fluentreader&#34;&gt;FluentReader&#xA;&lt;/h4&gt;&lt;p&gt;在設置中選擇 Google Reader API：&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/202307191734756_hu_e9d3d2709f3fcf5c.webp&#34; alt=&#34;FluentReader設置&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;然後填入相關信息：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;API端點直接從&lt;code&gt;/api&lt;/code&gt;網頁上覆制 Google Reader API 的 API 端點即可&lt;/li&gt;&#xA;&lt;li&gt;用戶名填寫安裝 FreshRSS 時設置的用戶名&lt;/li&gt;&#xA;&lt;li&gt;密碼是前文設置的 API 秘鑰&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;即可設置完成。&lt;/p&gt;&#xA;&lt;p&gt;其他的客戶端設置大同小異，無外乎上面兩大類，可以參考上面的方法進行設置。&lt;/p&gt;&#xA;&lt;h2 id=&#34;rss-訂閱什麼呢&#34;&gt;RSS 訂閱什麼呢&#xA;&lt;/h2&gt;&lt;p&gt;我們已經裝好了 RSSHub，這極大的方便了我們的訂閱以及豐富了我們的訂閱源。RSSHub 的官方文檔中維護著一份詳細的支持列表，支持的項目不可謂不繁多：媒體、博客……甚至大學通知，Twitter 更新都能覆蓋。&lt;/p&gt;&#xA;&lt;p&gt;以訂閱「湖南省政府採購網」的「採購公告」為例，首先需要在 RSSHub 的文檔中找到「湖南省政府採購網」以獲取其訂閱的「路由」：&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&lt;img src=&#34;https://blog.l3zc.com/2023/07/rsshub-freshrss-information-flow/image-20230720180435763_hu_b43f0ffc897defdf.webp&#34; alt=&#34;湖南省政府採購網的RSSHub文檔&#34; /&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;查詢文檔可知我們所需要的路由是&lt;code&gt;/gov/hunan/notice/:type&lt;/code&gt;，其中&lt;code&gt;:type&lt;/code&gt;是一個必選參數，我們需要獲取的是「採購公告」所以&lt;code&gt;:type&lt;/code&gt;應該是&lt;code&gt;cg&lt;/code&gt;，最終需要的路由就是&lt;code&gt;/gov/hunan/notice/cg&lt;/code&gt;。將這個路由附加在我們部署（反代）RSSHub 的網址後，即可得到完整的訂閱地址，例如：部署rsshub的網址是&lt;code&gt;https://rsshub.app&lt;/code&gt;，則最終的訂閱地址為：&lt;code&gt;https://rsshub.app/gov/hunan/notice/cg&lt;/code&gt;，將其加入 FreshRSS 的訂閱即可。&lt;/p&gt;&#xA;&lt;p&gt;需要注意的是，FreshRSS 似乎不支持自動轉換訂閱鏈接裡的非 ASCII 字符，如果你的訂閱鏈接裡含有這些字符，如&lt;code&gt;https://rsshub.app/sspai/tag/派早報&lt;/code&gt;，則建議在瀏覽器內先訪問一下，再將轉換後的鏈接粘貼進 FreshRSS 以轉換鏈接中的非 ASCII 字符。&lt;/p&gt;&#xA;&lt;p&gt;對於原本就有 RSS 的網站，推薦使用 RSSHub Radar，這是一款瀏覽器插件，可以實現 RSS 訂閱源的自動嗅探，而不必在網站上四處尋找。推薦它是因為，它不光可以嗅探 RSS 鏈接，如果目標網站可以用 RSSHub 訂閱，這個插件可以自動匹配支持的 RSSHub 路由。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/DIYgod/RSSHub-Radar&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;Github 倉庫&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;最後&#34;&gt;最後……&#xA;&lt;/h2&gt;&lt;p&gt;經過了這一番折騰，基本體驗到了當時人人都用著 Google Reader 的樂趣。即便如此，屬於 Google Reader 的時代終究還是過去了，那個人人都可以從網上收穫純粹的知識與快樂的時代，也已然一去不復返。這些年來網速越來越快，但給我的上網體驗卻越來越差。大多數人都開始上網的時候，內容農場，推薦算法……只要有利可圖，互聯網精神，那個曾經作為互聯網基石的精神，就全被這些追逐利益的資本和官商勾結的政府拋在腦後。我甚至可以說：至少在中國，那個曾經「互聯網」的理想已死。&lt;/p&gt;&#xA;&lt;p&gt;RSS 的沒落只是大環境的縮影，「技術」固然需要進步，但沒有與之相匹配的「人文」，這種進步就會成為一場災難。以我們現在的狀態來看，賽博朋克真的離我們不遠——技術進步，不但不能消除不平等，反而會加劇壓迫與控制。&lt;/p&gt;&#xA;&lt;p&gt;即使大環境再怎麼黑暗，我們依然能看到一線生機，依然會有人去發揚幾乎被大環境拋在腦後但彌足珍貴的互聯網精神，散發光和熱，通過自己的方式捍衛互聯網的開放與自由。&lt;/p&gt;&#xA;&lt;p&gt;感謝所有這些開源項目的貢獻者，也向所有熱愛分享的同路人致敬。&lt;/p&gt;&#xA;&lt;h2 id=&#34;參考&#34;&gt;參考&#xA;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://sspai.com/post/63202&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://sspai.com/post/63202&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.rsshub.app/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://docs.rsshub.app/&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://typecho.l3zc.com/archives/20/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;https://typecho.l3zc.com/archives/20/&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;以及這篇文章裡所有提到的鏈接。&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;近期 RSSHub 經歷了一次大重構，相應地，新增的路由所需的環境變量配置可以在路由對應文檔處找到，而不需要翻閱「部分 RSS 模塊配置」這一部分。&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;無論是自託管還是非自託管。&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</description>
        </item><item>
            <title>Docker Minecraft 開服記</title>
            <link>https://blog.l3zc.com/zh-hant-tw/2023/06/build-a-mc-server-with-docker/</link>
            <pubDate>Fri, 09 Jun 2023 13:52:54 +0000</pubDate>
            <guid>https://blog.l3zc.com/zh-hant-tw/2023/06/build-a-mc-server-with-docker/</guid>
            <description>&lt;img src=&#34;https://blog-img.l3zc.com/Moby-Minecraft.webp&#34; alt=&#34;Featured image of post Docker Minecraft 開服記&#34; /&gt;&lt;p&gt;我大概從2013年開始接觸到了 Minecraft ，算下來，今年正好是我接觸 Minecraft 的第十個年頭。&lt;/p&gt;&#xA;&lt;p&gt;熟悉 Docker 以後，我著手開始把我現在跑的服務容器化，從某種意義上，這非常「優雅」——可以很方便的管理各個服務，還不用擔心各種環境不兼容的問題。&lt;/p&gt;&#xA;&lt;p&gt;暑假將至，為了方便和朋友們聯機玩 MC，遂自行搭建一個服務器，順便進一步熟悉 Docker 和 Docker Compose。&lt;/p&gt;&#xA;&lt;h2 id=&#34;服務器選擇&#34;&gt;服務器選擇&#xA;&lt;/h2&gt;&lt;p&gt;服務器有兩個要求，一是性能要足夠強，二是距離要足夠近，目前我手頭有三臺機器，分別位於香港和洛杉磯，不是性能不夠就是距離太遠，延遲太高。所以，都無法滿足需求。&lt;/p&gt;&#xA;&lt;p&gt;最近恰逢618，各大雲主機廠商都有活動，遂購入一臺某大廠輕量服務器，位於上海，2C4G5M，對於一個入門 MC 服務器來說完全足夠。當然，買了這一個服務器不可能只是跑跑 MC，別的一些對帶寬要求不高的服務我肯定也會放在上面。&lt;/p&gt;&#xA;&lt;p&gt;那麼直接 Deploy，似乎用的還是 AMD 的新 EPYC，還行。&lt;/p&gt;&#xA;&lt;h2 id=&#34;安裝-docker&#34;&gt;安裝 Docker&#xA;&lt;/h2&gt;&lt;p&gt;相比於一鍵腳本，我個人還是偏好手動安裝 Docker。個人為了方便直接用了 Root，這不是最佳實踐，儘可能用普通用戶並在必要的時候用&lt;code&gt;sudo&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;p&gt;添加 PGP 密鑰:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;向&lt;code&gt;source.list&lt;/code&gt;添加軟件源：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ echo \&#xA;  &#34;deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \&#xA;  $(lsb_release -cs) stable&#34; | sudo tee /etc/apt/sources.list.d/docker.list &gt; /dev/null&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;更新軟件包緩存並安裝 Docker：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ apt update&#xA;$ apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;啟動 Docker:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ systemctl enable docker&#xA;$ systemctl start docker&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;至此 Docker 已經安裝完成，順遍裝好了 Docker Compose。&lt;/p&gt;&#xA;&lt;h2 id=&#34;docker-換源&#34;&gt;Docker 換源&#xA;&lt;/h2&gt;&lt;p&gt;國內服務器這點非常蛋疼。&lt;/p&gt;&#xA;&lt;p&gt;換源還要有一個命令行的文本編輯器，於是我決定先裝個 Vim：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ apt install vim&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;編輯/創建&lt;code&gt;/etc/docker/daemon.json&lt;/code&gt;：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ vim /etc/docker/daemon.json&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;編輯成如下內容:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&#xA;  &#34;registry-mirrors&#34;: [&#34;https://mirror.ccs.tencentyun.com&#34;]&#xA;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;https://mirror.ccs.tencentyun.com&lt;/code&gt;是某大廠的內網鏡像，內網拉取速度極快，還不計流量，不在內網裡的服務器無法使用，應當換成下列鏡像：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;https://hub-mirror.c.163.com&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;https://ustc-edu-cn.mirror.aliyuncs.com&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;https://mirror.baidubce.com&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;隨後重啟 Docker 服務即可完成換源：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ systemctl restart docker&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;粗略部署&#34;&gt;粗略部署&#xA;&lt;/h2&gt;&lt;p&gt;我部署服務的原則是先 Get it to work，再 Polish。&lt;/p&gt;&#xA;&lt;p&gt;對於 MC 這種 community driven 的遊戲來說，社區的力量是強大的，基本上什麼樣的需求都能在社區裡找到對應的解決方案。我直接採用了 &lt;a class=&#34;link&#34; href=&#34;https://github.com/itzg/docker-minecraft-server&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;itzg/docker-minecraft-server&lt;/a&gt;。&lt;/p&gt;&#xA;&lt;p&gt;不得不吐槽的是，這個項目的文檔寫得實在是沒有那麼友好，摸索了一下，總算是把這個服務基本的跑起來了。這時我的&lt;code&gt;docker-compose.yml&lt;/code&gt;如下：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: &#34;3&#34;&#xA;&#xA;services:&#xA;  mc:&#xA;    image: itzg/minecraft-server&#xA;    ports:&#xA;      - 25565:25565&#xA;    environment:&#xA;      EULA: &#34;TRUE&#34;&#xA;    tty: true&#xA;    stdin_open: true&#xA;    restart: unless-stopped&#xA;    volumes:&#xA;      # attach a directory relative to the directory containing this compose file&#xA;      - ./minecraft-data:/data&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;這樣的 Docker Compose 配置能以最新的版本把一個基礎的 Vanilla Server 跑起來，只能勉強滿足幾個人的聯機需求，肯定也沒幾個人會將這樣的配置用到生產環境。&lt;/p&gt;&#xA;&lt;h2 id=&#34;進一步調整&#34;&gt;進一步調整&#xA;&lt;/h2&gt;&lt;p&gt;要進一步調整，要先確認調整的方向，否則就是無頭蒼蠅，誤打誤撞，沒有目標，十分痛苦。實際感受一番後，我大致整理出了此時配置的問題，有些是 Vanilla 客戶端的問題：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;版本不固定&lt;/li&gt;&#xA;&lt;li&gt;缺少基本的性能數據&lt;/li&gt;&#xA;&lt;li&gt;圖標和 MOTD 需要調整&lt;/li&gt;&#xA;&lt;li&gt;沒有白名單&lt;/li&gt;&#xA;&lt;li&gt;不能裝插件&lt;/li&gt;&#xA;&lt;li&gt;有正版驗證(無所謂，我有正版)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;有了這個方向，我就可以有目標的去調整這個 Server 的配置。接下來要做的，就是查閱這個項目的&lt;a class=&#34;link&#34; href=&#34;https://docker-minecraft-server.readthedocs.io/en/latest/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;文檔&lt;/a&gt;，做出自己需要的修改。&lt;/p&gt;&#xA;&lt;h3 id=&#34;固定版本&#34;&gt;固定版本&#xA;&lt;/h3&gt;&lt;p&gt;說實話 MC 的版本更新還挺頻繁的，前一個版本尚未體驗下一個版本就會出現。我暫時先固定這服務器的 MC 版本為&lt;code&gt;1.19.4&lt;/code&gt;，日後充分遊玩再慢慢升級。&lt;/p&gt;&#xA;&lt;p&gt;同時 Vanilla Server 實在是太垃圾，順便將其換成 PAPER 豈不美哉？分別設置&lt;code&gt;VERSION&lt;/code&gt;和&lt;code&gt;TYPE&lt;/code&gt;兩個環境變量即可。藉由 Paper 的優點，這樣也同時解決了服務器插件和性能數據的問題。&lt;/p&gt;&#xA;&lt;h3 id=&#34;白名單&#34;&gt;白名單&#xA;&lt;/h3&gt;&lt;p&gt;設置&lt;code&gt;ENABLE_WHITELIST&lt;/code&gt;和&lt;code&gt;ENFORCE_WHITELIST&lt;/code&gt;兩個環境變量，即可強制服務器核查白名單。同時，不要忘記將自己加入白名單，由於服務器的 OP 會被自動加入白名單，只需要將自己提前設置為 OP 即可，設置&lt;code&gt;OPS&lt;/code&gt;即可做到這一點。&lt;/p&gt;&#xA;&lt;h3 id=&#34;圖標和-motd&#34;&gt;圖標和 MOTD&#xA;&lt;/h3&gt;&lt;p&gt;設置&lt;code&gt;ICON&lt;/code&gt;和&lt;code&gt;MOTD&lt;/code&gt;兩個環境變量即可自定義服務器的圖標和標語。&lt;/p&gt;&#xA;&lt;h3 id=&#34;正版驗證&#34;&gt;正版驗證&#xA;&lt;/h3&gt;&lt;p&gt;設置&lt;code&gt;ONLINE_MODE&lt;/code&gt;變量即可控制正版驗證的開關。&lt;/p&gt;&#xA;&lt;p&gt;需要注意的是，關閉&lt;code&gt;ONLINE_MODE&lt;/code&gt;後，服務器會根據玩家的離線 UUID 判斷身份，離線 UUID 和在線 UUID 不同，此時添加 OP 和黑白名單都需要改用離線 UUID 進行。&lt;/p&gt;&#xA;&lt;h3 id=&#34;最終的-docker-composeyml&#34;&gt;最終的 docker-compose.yml&#xA;&lt;/h3&gt;&lt;pre&gt;&lt;code class=&#34;language-yaml&#34;&gt;version: &#34;3&#34;&#xA;&#xA;services:&#xA;  mc:&#xA;    image: itzg/minecraft-server&#xA;    ports:&#xA;      - 25565:25565&#xA;    environment:&#xA;      EULA: &#34;TRUE&#34;&#xA;      TYPE: &#34;PAPER&#34;&#xA;      VERSION: &#34;1.19.4&#34;&#xA;      VIEW_DISTANCE: 8&#xA;      ENABLE_WHITELIST: &#34;TRUE&#34;&#xA;      ENFORCE_WHITELIST: &#34;TRUE&#34;&#xA;      OPS: &#34;&#34;&#xA;      ONLINE_MODE: &#34;TRUE&#34;&#xA;      SERVER_NAME: &#34;Pub of NightCity&#34;&#xA;      MOTD: &#34;Want to have a drink?&#34;&#xA;      ICON: &#34;&#34;&#xA;      OVERRIDE_SERVER_PROPERTIES: &#34;TRUE&#34;&#xA;    tty: true&#xA;    stdin_open: true&#xA;    restart: unless-stopped&#xA;    volumes:&#xA;      # attach a directory relative to the directory containing this compose file&#xA;      - ./minecraft-data:/data&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;一些雜七雜八的事情&#34;&gt;一些雜七雜八的事情&#xA;&lt;/h2&gt;&lt;h3 id=&#34;rcon-的連接&#34;&gt;RCON 的連接&#xA;&lt;/h3&gt;&lt;p&gt;服務器運行後，若要在不進入遊戲的情況下管理服務器，就需要用到 RCON。方法很簡單，使用這個項目綁定的 rcon-cli 即可：&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-shell&#34;&gt;$ docker exec -i &lt;name_of_container&gt; rcon-cli&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;注意將&lt;code&gt;&amp;lt;name_of_container&amp;gt;&lt;/code&gt;換成自己的容器名。&lt;/p&gt;&#xA;&lt;p&gt;作者還推薦了一個叫做&lt;code&gt;rcon-web-admin&lt;/code&gt;的項目，打算過一陣子嘗試。&lt;/p&gt;&#xA;&lt;h3 id=&#34;安裝插件&#34;&gt;安裝插件&#xA;&lt;/h3&gt;&lt;p&gt;Paper 支持 Bukkit 的插件，還有自己的插件，插件數量上完全無需擔心。&lt;/p&gt;&#xA;&lt;p&gt;我們在配置&lt;code&gt;docker-compose.yml&lt;/code&gt;時，已經做了 bind 操作，會在&lt;code&gt;docker-compose.yml&lt;/code&gt;所在目錄的相對路徑下創建一個叫做&lt;code&gt;minecraft-data&lt;/code&gt;的文件夾，並綁定到容器的&lt;code&gt;data&lt;/code&gt;目錄，將下載好的插件&lt;code&gt;.jar&lt;/code&gt;文件丟進&lt;code&gt;./minecraft-data/plugins&lt;/code&gt;目錄就完成了插件的安裝。&lt;/p&gt;&#xA;&lt;p&gt;我選用了 World Edit，Grief Prevention 和 Dead Chest 三個插件，保證原汁原味的生存體驗。&lt;/p&gt;&#xA;&lt;h2 id=&#34;最後&#34;&gt;最後&#xA;&lt;/h2&gt;&lt;p&gt;如果你有開服經驗並且偏向手動修改&lt;code&gt;server.properties&lt;/code&gt;，將&lt;code&gt;OVERRIDE_SERVER_PROPERTIES&lt;/code&gt;設置為&lt;code&gt;FALSE&lt;/code&gt;即可將&lt;code&gt;server.properties&lt;/code&gt;的控制權交還到我們手中，這也是一種配置的手段。&lt;/p&gt;&#xA;&lt;p&gt;Docker 開服還是相對容易的，社區已經造好了輪子，免去了很多不必要的麻煩。稍後我會繼續 play around with the server，繼續探索這個遊戲無限的可能性。&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
