<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>王小嗨的不老歌</title>
        <link>https://sogola.com/</link>
        <description>王小嗨的不老歌</description>
        <generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>high@sogola.com (王小嗨)</managingEditor>
            <webMaster>high@sogola.com (王小嗨)</webMaster><lastBuildDate>Tue, 16 Jan 2024 07:52:00 &#43;0800</lastBuildDate>
            <atom:link href="https://sogola.com/index.xml" rel="self" type="application/rss+xml" />
        <item>
    <title>網路受限下部署Fediverse實例GoToSocial</title>
    <link>https://sogola.com/posts/how-to-use-gotosocial/</link>
    <pubDate>Tue, 16 Jan 2024 07:52:00 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/how-to-use-gotosocial/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/how-to-use-gotosocial/1.png" referrerpolicy="no-referrer">
            </div><h2 id="緣起" class="headerLink">
    <a href="#%e7%b7%a3%e8%b5%b7" class="header-mark"></a>緣起</h2><p>帝國的旗幟隨風飄揚，新皇冉冉升起。盆地到雪山，稻田到工廠，白天到黑夜，祂的身影籠罩整片大地。城牆內外，禮樂崩壞，舊有秩序轟然倒塌，新人尚未現身。人們畏懼開口，每個人頭上都戴著枷鎖，自我放逐與驅逐他人成為日常生活。</p>
<p>言說，在何處言說，業已成為現代臣民的必修課。不消說封閉的社交網路的書報審查，長篇累牘的賣身契自不待言，有誰會甘願淪為賽博農奴，不知疲倦地為科技資本寡頭生產數據。那麼，我們何以為家？從馬一龍的肆意妄為，再到扎克伯格的生意經，互聯互通的聯邦社交網路似乎成為無奈之選。</p>
<p>在聯邦宇宙之中，一旦選擇加入一個實例，即意味著簽下契約，我們的帳戶隨時面臨管理者之鎚，與此同時，還要時刻擔心站點倒閉造成的數據丟失。相對應地，倘如對實例進行自託管，那只需追尋內心，同時承擔相應的風險。</p>
<p>於城牆之內，網路被阻擋是對臣民的恩澤。誠如口罩可以成為主權者的強制，但也讓人們有了戴口罩規避監視器的權利，網路受限使得臣民被迫武裝在賽博空間。有了武器，借助 <a href="https://www.cloudflare.com/products/tunnel/" target="_blank" rel="noopener noreferrer">Cloudflare Tunnel</a>，我們能夠輕鬆地於受限地區的家庭網路中部署 <a href="https://gotosocial.org/" target="_blank" rel="noopener noreferrer">GoToSocial</a>，在聯邦宇宙中互通交流。</p>
<p>GoToSocial 是一個使用 Golang 編寫的 ActivityPub 社交網絡伺服器。至於為什麼選擇 GoToSocial？因為它需要的資源足夠少，單板機足以運行，且開發者較為活躍。我的實例使用 <a href="https://www.docker.com/" target="_blank" rel="noopener noreferrer">docker</a> 部署在香橙派3B，那我們開始吧。</p>
<h2 id="部署" class="headerLink">
    <a href="#%e9%83%a8%e7%bd%b2" class="header-mark"></a>部署</h2><figure>
</figure>

<p>在網路受限的情況下，例如無法直接訪問 <a href="https://joinmastodon.org/" target="_blank" rel="noopener noreferrer">Mastodon</a> 的官方實例 <a href="https://mastodon.social/" target="_blank" rel="noopener noreferrer">mastodon.social</a>，我們需要依賴 Clash 作為跳板，以建立到聯邦宇宙的連接。同時，由於網路受限，無法獲得公網 IP，因此我們必須借助 Cloudflare Tunnel，將 GoToSocial 實例暴露在公共網絡上，以供訪問。</p>
<h3 id="安裝-docker部署-clash" class="headerLink">
    <a href="#%e5%ae%89%e8%a3%9d-docker%e9%83%a8%e7%bd%b2-clash" class="header-mark"></a>安裝 docker，部署 Clash</h3><p>由此可知，部署 clash 是首要步驟。要部署 clash 容器，首先要在系統上安裝 docker。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">curl -fsSL https://get.docker.com -o get-docker.sh
</span></span><span class="line"><span class="cl">sh get-docker.sh --mirror Aliyun
</span></span></code></pre></td></tr></table>
</div>
</div><p>使用以上命令，安裝 docker，並指定鏡像源為 Aliyun。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker network create -d macvlan \
</span></span><span class="line"><span class="cl">  --subnet=your_subnet/24 \
</span></span><span class="line"><span class="cl">  --gateway=your_router_ip \
</span></span><span class="line"><span class="cl">  -o parent=your_eth_name \
</span></span><span class="line"><span class="cl">  macvlan
</span></span></code></pre></td></tr></table>
</div>
</div><p>使用以上命令，在docker中創建一個 macvlan 网络，clash 容器連結到這個網路後，使用與主路由相同的網段。其中，parent 為設備的以太網網卡名稱。設置路由器 ip 為 192.168.1.1，以上的 subnet 為 192.168.1.0/24， gateway 為  192.168.1.1。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker run -d \
</span></span><span class="line"><span class="cl">  --name clash \
</span></span><span class="line"><span class="cl">  -e USER_ID=1000 \
</span></span><span class="line"><span class="cl">  -e GROUP_ID=1000 \
</span></span><span class="line"><span class="cl">  -v ~/docker/clash/config/proxy.yaml:/root/.config/clash/config.yaml \
</span></span><span class="line"><span class="cl">  -v ~/docker/clash/ui:/ui \
</span></span><span class="line"><span class="cl">  --restart=always \
</span></span><span class="line"><span class="cl">  --network=macvlan \
</span></span><span class="line"><span class="cl">  --ip=your_clash_ip \
</span></span><span class="line"><span class="cl">  --privileged \
</span></span><span class="line"><span class="cl">  --device=/dev/net/tun \
</span></span><span class="line"><span class="cl">  dreamacro/clash-premium:latest
</span></span></code></pre></td></tr></table>
</div>
</div><p>使用以上命令，部署 clash 容器。其中詳細配置，請參照文章「<a href="https://haoyu.love/blog1412.html" target="_blank" rel="noopener noreferrer">Docker Clash 旁路由网关模式透明代理</a>」，這裡不再贅述。</p>
<h3 id="部署-gotosocial" class="headerLink">
    <a href="#%e9%83%a8%e7%bd%b2-gotosocial" class="header-mark"></a>部署 GoToSocial</h3><p>完成 clash 的部署後，下載 GoToSocial 的配置文件 <a href="https://github.com/superseriousbusiness/gotosocial/blob/main/example/config.yaml" target="_blank" rel="noopener noreferrer">config.yaml</a>，修改以下內容。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl"># Both allow-ips and block-ips default to an empty array.
</span></span><span class="line"><span class="cl">  allow-ips: [&#34;your_device_ip/32&#34;]
</span></span><span class="line"><span class="cl">  block-ips: []
</span></span></code></pre></td></tr></table>
</div>
</div><p>完成修改後，將 config.yaml 拷貝至 <code>~/docker/gotosocial/</code>。其中 <code>your_device_ip</code> 為妳的伺服器在內網的IP地址。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker run -d \
</span></span><span class="line"><span class="cl">  --name gotosocial \
</span></span><span class="line"><span class="cl">  -p your_gotosocial_port:8080 \
</span></span><span class="line"><span class="cl">  -e GTS_HOST=your_gts_domain_name \
</span></span><span class="line"><span class="cl">  -e GTS_DB_TYPE=sqlite \
</span></span><span class="line"><span class="cl">  -e GTS_DB_ADDRESS=/gotosocial/storage/sqlite.db \
</span></span><span class="line"><span class="cl">  -e GTS_LETSENCRYPT_ENABLED=false \
</span></span><span class="line"><span class="cl">  -e TZ=Asia/Taipei \
</span></span><span class="line"><span class="cl">  -e USER_ID=1000 \
</span></span><span class="line"><span class="cl">  -e GROUP_ID=1000 \
</span></span><span class="line"><span class="cl">  -e HTTP_PROXY=socks5://your_clash_ip:your_clash_port \
</span></span><span class="line"><span class="cl">  -e HTTPS_PROXY=socks5://your_clash_ip:your_clash_port \
</span></span><span class="line"><span class="cl">  -v ~/docker/gotosocial/data:/gotosocial/storage \
</span></span><span class="line"><span class="cl">  -v ~/docker/gotosocial/config.yaml:/gotosocial/config.yaml \
</span></span><span class="line"><span class="cl">  --restart=always \
</span></span><span class="line"><span class="cl">  superseriousbusiness/gotosocial:latest \
</span></span><span class="line"><span class="cl">  /gotosocial --config-path ./config.yaml server start
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，部署 GoToSocial。其中 <code>GTS_HOST</code> 為 GoToSocial 的域名，這裡需要將域名添加至 Cloudflare，並域名服務商處將 DNS 修改為 Cloudflare 的 DNS。接下來，我們只需要將 GoToSocial 的本地端口連結至 Cloudflare Tunnel，就萬事大吉了。</p>
<h3 id="部署-cloudflare-tunnel" class="headerLink">
    <a href="#%e9%83%a8%e7%bd%b2-cloudflare-tunnel" class="header-mark"></a>部署 Cloudflare Tunnel</h3><p>要使用 Cloudflare Tunnel 服務，首先要登錄 Cloudflare，註冊 <a href="https://www.cloudflare.com/zero-trust/" target="_blank" rel="noopener noreferrer">Zero Trust</a>，選擇免費套餐即可。</p>
<figure>
</figure>

<p>完成註冊，進入 Zero Trust 後台，選擇 Tunnels 菜單，Create a tunnel （新建一個隧道）。</p>
<figure>
</figure>

<p>完成創建後，進入以上頁面，選擇 Docker，其中 <code>--token</code> 之後的字串為 <code>your_token</code>，請勿將該字串洩漏給任何第三方，以免相關服務被劫持。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker run -d \
</span></span><span class="line"><span class="cl">  --name cloudflare_tunnel \
</span></span><span class="line"><span class="cl">  -e USER_ID=1000 \
</span></span><span class="line"><span class="cl">  -e GROUP_ID=1000 \
</span></span><span class="line"><span class="cl">  -e HTTP_PROXY=socks5://your_clash_ip:your_clash_port \
</span></span><span class="line"><span class="cl">  -e HTTPS_PROXY=socks5://your_clash_ip:your_clash_port \
</span></span><span class="line"><span class="cl">  --restart=always \
</span></span><span class="line"><span class="cl">  cloudflare/cloudflared:latest-arm64 tunnel --no-autoupdate \
</span></span><span class="line"><span class="cl">  run --token your_token
</span></span></code></pre></td></tr></table>
</div>
</div><p>獲得 <code>your_token</code> 之後，使用以上命令部署 Cloudflare Tunnel。</p>
<figure>
</figure>

<p>回到 Cloudflare Tunnel 的後台，返回至隧道列表，進入至指定隧道的配置頁面。選擇公開服務，點擊增加一個新的公網域名。</p>
<figure>
</figure>

<p>於 Subdomain 初寫入想要的二級域名，亦可不寫；於 Domain 初選擇之前添加的域名；於 Type 初選擇 HTTP；於 URL 寫入 <code>your_device_ip:your_gotosocial_port</code>。</p>
<p>至此，我們部署已完成，若如無意外，我們的 GoToSocial 已進入聯邦宇宙。</p>
<h2 id="用戶設置與使用" class="headerLink">
    <a href="#%e7%94%a8%e6%88%b6%e8%a8%ad%e7%bd%ae%e8%88%87%e4%bd%bf%e7%94%a8" class="header-mark"></a>用戶設置與使用</h2><h3 id="設置" class="headerLink">
    <a href="#%e8%a8%ad%e7%bd%ae" class="header-mark"></a>設置</h3><p>日前，GoToSocial 並無完善的用戶管理頁面，需要使用命令行來管理用戶。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker exec -it gotosocial \
</span></span><span class="line"><span class="cl">  /gotosocial/gotosocial admin account create \
</span></span><span class="line"><span class="cl">  --username your_username \
</span></span><span class="line"><span class="cl">  --email your_email \
</span></span><span class="line"><span class="cl">  --password &#39;your_password&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>使用以上命令，創建一個用戶。完成用戶創建後，可以登錄 <code>your_domain_name/admin</code>，進行一些必要之用戶設置，比如暱稱、頭像等。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker exec -it your_container_name \
</span></span><span class="line"><span class="cl">  /gotosocial/gotosocial admin account promote \
</span></span><span class="line"><span class="cl">  --username your_username
</span></span></code></pre></td></tr></table>
</div>
</div><p>使用以上命令，將一個用戶提升至管理員。使用管理員帳戶登錄 <code>your_domain_name/admin</code>，可以進行一些全站設置。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker exec -it your_container_name \
</span></span><span class="line"><span class="cl">  /gotosocial/gotosocial admin account demote \
</span></span><span class="line"><span class="cl">  --username your_username
</span></span></code></pre></td></tr></table>
</div>
</div><p>使用以上命令，將一個管理員降級至普通用戶。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker exec -it your_container_name \
</span></span><span class="line"><span class="cl">  /gotosocial/gotosocial admin account password \
</span></span><span class="line"><span class="cl">  --username your_username \
</span></span><span class="line"><span class="cl">  --password your_new_password
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">使用以上命令，修改某個用戶的密碼。
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="使用" class="headerLink">
    <a href="#%e4%bd%bf%e7%94%a8" class="header-mark"></a>使用</h3><p>日前，GoToSocial 亦無一個網頁來進行內容發布與瀏覽，但它可以兼容 Mastodon 的一些客戶端，可訪問 <a href="https://joinmastodon.org/apps" target="_blank" rel="noopener noreferrer">Mastodon App</a> 列表查看更多。</p>
<p>我的聯邦宇宙帳戶為 <code>@yeahwong@hi.sogo.la</code>，歡迎關注。</p>
<h2 id="參考資料" class="headerLink">
    <a href="#%e5%8f%83%e8%80%83%e8%b3%87%e6%96%99" class="header-mark"></a>參考資料</h2><ul>
<li>
<p><a href="https://docs.gotosocial.org/en/latest/" target="_blank" rel="noopener noreferrer">GoToSocial Documentation</a></p>
</li>
<li>
<p><a href="https://tourcoder.com/how-to-use-gotosocial/" target="_blank" rel="noopener noreferrer">搭建自己的节点之 Gotosocial 篇</a></p>
</li>
</ul>
]]></description>
</item><item>
    <title>香橙派3B：丐版HomeLab之良品</title>
    <link>https://sogola.com/posts/orangepi-3b-as-homelab/</link>
    <pubDate>Sun, 31 Dec 2023 19:35:00 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/orangepi-3b-as-homelab/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/orangepi-3b-as-homelab/1.png" referrerpolicy="no-referrer">
            </div><h2 id="開始" class="headerLink">
    <a href="#%e9%96%8b%e5%a7%8b" class="header-mark"></a>開始</h2><p>互聯網資本寡頭所提供的各類雲服務，從社交媒體再到同步服務，人們愈發不再信任。「從來就沒有什麼救世主，也不靠神仙皇帝」，那些沒有受虐傾向的人們，那些沒有露體癖的人們，那些不甘被資本與權力宰制的人們，紛紛拿起開源武器，開始了數據的自我賦權，啟動了本地優先之策略。</p>
<p>歲月催人老，泰西2023年已然離去。9月底，本呆採購了一台香橙派作為HomeLab，它在我的出租屋已成功運行了兩個月。現給大家做一個報告，亦作為學習的記錄。</p>
<p>相較各類昂貴和功耗高的x86服務器， 功耗降低的arm架構的單板機是HomeLab之廉價選擇。樹莓派，大名鼎鼎，但它已成為理財產品，為大家所詬病，當然不在我的選擇範圍。思來想去，左等右等，我選購了國產廠商推出的香橙派3B的最高配8G版，它採用RK3566，性能足夠使用。後面，我又採購了電源適配器、SSD硬碟、U盤、散熱片、外殼等。</p>
<table>
<thead>
<tr>
<th>物件</th>
<th>採購平台</th>
<th>價格</th>
</tr>
</thead>
<tbody>
<tr>
<td>Orange Pi 3B 8G版</td>
<td>淘寶OrangePi官方店</td>
<td>305.72元</td>
</tr>
<tr>
<td>電源與電源線</td>
<td>淘寶某店鋪</td>
<td>16.32元</td>
</tr>
<tr>
<td>金屬外殼</td>
<td>淘寶某店鋪</td>
<td>62元</td>
</tr>
<tr>
<td>128G 2230 SSD硬碟 （二手）</td>
<td>拼多多某店鋪</td>
<td>36元</td>
</tr>
<tr>
<td>硬碟散熱銅片</td>
<td>淘寶某店鋪</td>
<td>11.64元</td>
</tr>
<tr>
<td>128G 金屬外殼U盤</td>
<td>京東京造自營店</td>
<td>45.9元</td>
</tr>
<tr>
<td>U盤散熱銅柱</td>
<td>淘寶某店鋪</td>
<td>33.16元</td>
</tr>
</tbody>
</table>
<p>以上，列舉了HomeLab實際運行的配件，並沒有包括螺絲刀、鉗子、串口線、採集卡、HDMI線、美工刀等，還有一個被折騰壞的壓克力外殼，好在很多器物都是可以重複再利用的。顯然，與各類二手礦難盒子相比，這並不便宜，但好在接口豐富，我看中了它可以直接插2230SSD硬碟，而且在拼多多購買的SSD硬碟好像也沒有通電多少次，感覺超值。</p>
<figure>
</figure>

<p>於此HomeLab之中，本地安裝<a href="https://www.armbian.com/" target="_blank" rel="noopener noreferrer">armbian</a>系統，部署了docker，運行了<a href="https://gotosocial.org/" target="_blank" rel="noopener noreferrer">gotosocial</a>、<a href="https://ipfs.tech/" target="_blank" rel="noopener noreferrer">IPFS</a>、clash、<a href="https://www.cloudflare.com/products/tunnel/" target="_blank" rel="noopener noreferrer">Cloudflare Tunnel</a>、<a href="https://github.com/whyour/qinglong" target="_blank" rel="noopener noreferrer">青龍面板</a>等容器，還在持續探索之中。</p>
<p>組裝完畢，我們開始吧。</p>
<h2 id="安裝操作系統" class="headerLink">
    <a href="#%e5%ae%89%e8%a3%9d%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%b5%b1" class="header-mark"></a>安裝操作系統</h2><p>根據的OrangePI<a href="http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-Pi-3B.html" target="_blank" rel="noopener noreferrer">官方用戶手冊</a>的指引，要將系統燒錄到NVMeSSD硬碟，首先需將bootloader燒錄至SPIFlash，才能確保系統從NVMeSSD硬碟啟動。那麼整個流程就簡單明確了，先將系統燒錄至SD卡，通電開機後；再將bootloader和系統分別燒錄至SPIFlash和NVMeSSD硬碟；最後，關機拔掉SD卡，再通電開機即可。</p>
<p>這裡，我採用armbian提供3B的社區維護版系統，SD卡的燒錄工具為<a href="https://github.com/balena-io/etcher" target="_blank" rel="noopener noreferrer">balenaEtcher</a>。下載好系統，安裝好燒錄工具即可開始作業。</p>
<figure>
</figure>

<p>SD卡連接至電腦後，打開balenaEtcher，在交互介面中選擇下載好鏡像文件和SD卡。</p>
<figure>
</figure>

<p>點擊Flash按鈕，等待燒錄完成。將SD從電腦彈出後，插入香橙派的SD卡卡槽，通電啟動。在路由器的後台，找到香橙派的本地IP。有了IP後，打開終端。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ssh root@your_ip_address
</span></span></code></pre></td></tr></table>
</div>
</div><p>armbian的root默認密碼為1234，根據提示選擇終端類型與語言、地區等，修改默認root密碼以及創建新用戶。完成初始化設置之後，在終端鍵入命令，進入armbian的設置介面。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo armbian-config
</span></span></code></pre></td></tr></table>
</div>
</div><figure>
</figure>

<p>選擇<code>System</code>選項。</p>
<figure>
</figure>

<p>選擇<code>Install</code>選項。</p>
<figure>
</figure>

<p>選擇<code>4</code>選項。</p>
<figure>
</figure>

<p>因為我們沒有插入U盤或者其它設置，故選擇選擇<code>1</code>選項。</p>
<figure>
</figure>

<p>選擇<code>Yes</code>選項，將NVMeSSD硬碟清除數據格式化。</p>
<figure>
</figure>

<p>待進度格式化進度跑完後，選擇<code>1</code>選項。<strong>注意</strong>：香橙派的bootloader不支援btrfs格式的系統從NVMeSSD硬碟啟動，只能選擇ext4格式。</p>
<figure>
</figure>

<p>耐心等待進度跑完，期間香橙派的藍色信號燈會快速閃爍。</p>
<figure>
</figure>

<p>NVMeSSD硬碟的寫出完成後，選擇<code>7</code>選項，將bootloader燒錄至SPIFlash。</p>
<figure>
</figure>

<p>選擇<code>Yes</code>選項，開始燒錄。</p>
<figure>
</figure>

<p>選擇<code>Power off</code>選項，關機。等到電源指示燈熄滅後，拔出SD卡，再次通電。這次，armbian將會從NVMeSSD硬碟啟動，啟動期間藍色指示燈會快速閃爍。待啟動完成，進入路由器後台，找到新的IP。</p>
<h2 id="一些基本設置" class="headerLink">
    <a href="#%e4%b8%80%e4%ba%9b%e5%9f%ba%e6%9c%ac%e8%a8%ad%e7%bd%ae" class="header-mark"></a>一些基本設置</h2><h3 id="修改軟件源" class="headerLink">
    <a href="#%e4%bf%ae%e6%94%b9%e8%bb%9f%e4%bb%b6%e6%ba%90" class="header-mark"></a>修改軟件源</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ssh root@your_new_ip_address
</span></span></code></pre></td></tr></table>
</div>
</div><p>受限於國朝網路，需要將軟件源切換至<a href="https://mirrors.tuna.tsinghua.edu.cn/" target="_blank" rel="noopener noreferrer">北平清華大學的鏡像</a>，才能獲得良好的速度。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/apt/sources.list.d/armbian.list
</span></span></code></pre></td></tr></table>
</div>
</div><p>將<code>http://apt.armbian.com</code>替換為<code>https://mirrors.tuna.tsinghua.edu.cn/armbian</code>。</p>
<p>編輯sources.list。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">nano /etc/apt/sources.list
</span></span></code></pre></td></tr></table>
</div>
</div><p>先講原有內容註釋掉，然後至北平清華大學的<a href="https://mirrors.tuna.tsinghua.edu.cn/help/debian/" target="_blank" rel="noopener noreferrer">Debian軟件源</a>，選擇相應的版本，粘貼至sources.list後，保存退出。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt update &amp;&amp; sudo apt upgrade
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，更新軟體列表，根據提示鍵入<code>y</code>，更新軟體。</p>
<h3 id="ssh設置" class="headerLink">
    <a href="#ssh%e8%a8%ad%e7%bd%ae" class="header-mark"></a>SSH設置</h3><p>為安全起見，這裡我們修改SSH的默認端口，取消root登錄，並取消密碼登錄，改為密鑰登錄。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">mkdir -p ~/.ssh
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，創建文件夾<code>.ssh</code>。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">touch ~/.ssh/authorized_keys
</span></span><span class="line"><span class="cl">nano ~/.ssh/authorized_keys
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，創建authorized_keys文件，並將公鑰粘貼至此。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">chmod 700 ~/.ssh
</span></span><span class="line"><span class="cl">chmod 600 ~/.ssh/authorized_keys
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，修改文件夾及文件的權限。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/ssh/sshd_config
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，編輯SSH的配置文件。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">port your_ssh_port_number #SSH端口號
</span></span><span class="line"><span class="cl">PermitRootLogin no #拒絕root登錄
</span></span><span class="line"><span class="cl">PubkeyAuthentication yes #允許密鑰登錄
</span></span><span class="line"><span class="cl">PasswordAuthentication no #拒絕密鑰登錄
</span></span></code></pre></td></tr></table>
</div>
</div><p>修改以上內容，保存並退出。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo systemctl restart ssh
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，重啟SSH服務後，就可以使用密鑰登錄了。</p>
<h3 id="開啟smaba服務" class="headerLink">
    <a href="#%e9%96%8b%e5%95%9fsmaba%e6%9c%8d%e5%8b%99" class="header-mark"></a>開啟smaba服務</h3><p>為方便在電腦中管理香橙派的文件，我們需部署smaba服務，以獲得遠端管理香橙派的文件有管理本地文件的同等體驗。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt install samba
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，安裝samba軟體。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo smbpasswd -a $USER
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，為當前用戶創建samba登錄密碼。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/samba/smb.conf
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，編輯samba的配置文件。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="p">[</span><span class="n">global</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">   <span class="n">workgroup</span> <span class="o">=</span> <span class="n">WORKGROUP</span>
</span></span><span class="line"><span class="cl">   <span class="n">server</span> <span class="n">string</span> <span class="o">=</span> <span class="n">orange</span> <span class="n">pi</span> <span class="mi">3</span><span class="n">b</span>
</span></span><span class="line"><span class="cl">   <span class="n">security</span> <span class="o">=</span> <span class="n">user</span>
</span></span><span class="line"><span class="cl">   <span class="n">map</span> <span class="n">to</span> <span class="n">guest</span> <span class="o">=</span> <span class="n">Bad</span> <span class="n">User</span>
</span></span><span class="line"><span class="cl">   <span class="n">encrypt</span> <span class="n">passwords</span> <span class="o">=</span> <span class="n">yes</span>
</span></span><span class="line"><span class="cl">   <span class="n">passdb</span> <span class="n">backend</span> <span class="o">=</span> <span class="n">tdbsam</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">   <span class="nb">min</span> <span class="n">protocol</span> <span class="o">=</span> <span class="n">SMB2</span>
</span></span><span class="line"><span class="cl">   <span class="n">client</span> <span class="nb">min</span> <span class="n">protocol</span> <span class="o">=</span> <span class="n">SMB2</span>
</span></span><span class="line"><span class="cl">   <span class="n">client</span> <span class="nb">max</span> <span class="n">protocol</span> <span class="o">=</span> <span class="n">SMB3</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">   <span class="c1"># local master = no</span>
</span></span><span class="line"><span class="cl">   <span class="c1"># preferred master = no</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">   <span class="nb">log</span> <span class="n">file</span> <span class="o">=</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nb">log</span><span class="o">/</span><span class="n">samba</span><span class="o">/</span><span class="nb">log</span><span class="o">.%</span><span class="n">m</span>
</span></span><span class="line"><span class="cl">   <span class="nb">max</span> <span class="nb">log</span> <span class="n">size</span> <span class="o">=</span> <span class="mi">50</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">[</span><span class="n">orangepi</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">   <span class="n">comment</span> <span class="o">=</span> <span class="n">User</span> <span class="n">Files</span>
</span></span><span class="line"><span class="cl">   <span class="n">path</span> <span class="o">=</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">your_username</span>
</span></span><span class="line"><span class="cl">   <span class="n">browseable</span> <span class="o">=</span> <span class="n">yes</span>
</span></span><span class="line"><span class="cl">   <span class="n">writeable</span> <span class="o">=</span> <span class="n">yes</span>
</span></span><span class="line"><span class="cl">   <span class="n">guest</span> <span class="n">ok</span> <span class="o">=</span> <span class="n">no</span>
</span></span><span class="line"><span class="cl">   <span class="n">create</span> <span class="n">mask</span> <span class="o">=</span> <span class="mi">0664</span>
</span></span><span class="line"><span class="cl">   <span class="n">directory</span> <span class="n">mask</span> <span class="o">=</span> <span class="mi">0775</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>修改`your_username&quot;為正確的用戶名，以上內容替換至配置文件中。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo systemctl start smbd
</span></span><span class="line"><span class="cl">sudo systemctl enable smbd
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，啟動samba，並設置為開機啟動。</p>
<h3 id="防火牆" class="headerLink">
    <a href="#%e9%98%b2%e7%81%ab%e7%89%86" class="header-mark"></a>防火牆</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt install ufw
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，安裝防火牆軟體ufw。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo ufw allow 139/tcp
</span></span><span class="line"><span class="cl">sudo ufw allow 445/tcp
</span></span><span class="line"><span class="cl">#以上，允許samba服務通過防火牆
</span></span><span class="line"><span class="cl">sudo ufw allow your_ssh_port_number/tcp
</span></span><span class="line"><span class="cl">#以上，允許SSH服務通過防火牆
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，將SSH和samba允許通過防火牆。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo ufw enable
</span></span><span class="line"><span class="cl">sudo systemctl enable ufw
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，啟動ufw防火牆，並設置為開機啟動。</p>
<h3 id="必要之設定" class="headerLink">
    <a href="#%e5%bf%85%e8%a6%81%e4%b9%8b%e8%a8%ad%e5%ae%9a" class="header-mark"></a>必要之設定</h3><h4 id="網路的吞吐參數" class="headerLink">
    <a href="#%e7%b6%b2%e8%b7%af%e7%9a%84%e5%90%9e%e5%90%90%e5%8f%83%e6%95%b8" class="header-mark"></a>網路的吞吐參數</h4><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">net.core.rmem_max=2500000
</span></span><span class="line"><span class="cl">net.core.wmem_max=2500000
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，修改網路吞吐參數，以便IPFS更好地運行。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/sysctl.conf
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，講前述修改網路參數的命令添加至sysctl.conf，以便重啟後繼續生效。</p>
<h4 id="網卡的混合模式" class="headerLink">
    <a href="#%e7%b6%b2%e5%8d%a1%e7%9a%84%e6%b7%b7%e5%90%88%e6%a8%a1%e5%bc%8f" class="header-mark"></a>網卡的混合模式</h4><p>運行<code>ip link</code>，找到設備的乙太網接口名稱。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo ip link set your_eth_name promisc on
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，開啟網卡混合模式。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/rc.local
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，編輯<code>rc.local</code>文件。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo ip link set your_eth_name promisc on
</span></span></code></pre></td></tr></table>
</div>
</div><p>在<code>exit 0</code>行之前，添加以上內容，保存並關閉文件。</p>
<h4 id="刪除無線網卡" class="headerLink">
    <a href="#%e5%88%aa%e9%99%a4%e7%84%a1%e7%b7%9a%e7%b6%b2%e5%8d%a1" class="header-mark"></a>刪除無線網卡</h4><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo systemctl disable wpa_supplicant
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，禁用WiFi，節約用電和資源佔用。</p>
<h2 id="數據備份" class="headerLink">
    <a href="#%e6%95%b8%e6%93%9a%e5%82%99%e4%bb%bd" class="header-mark"></a>數據備份</h2><p>數據容災是必修課，良好的數據備份體驗是許多人使用各類雲服務的理由，那打造一個好的HomeLab，就需確保數據有容災能力。這裡，我們使用rsync軟體，採用阮一峰的提供的<a href="https://www.ruanyifeng.com/blog/2020/08/rsync.html" target="_blank" rel="noopener noreferrer">增量備份腳本</a>，將數據備份至U盤。</p>
<p>考慮U盤的發熱問題，這裡建議選購金屬外殼的U盤，並加裝散熱銅柱，可較好地散熱，以增加U盤的使用時間。</p>
<h3 id="掛載u盤" class="headerLink">
    <a href="#%e6%8e%9b%e8%bc%89u%e7%9b%a4" class="header-mark"></a>掛載U盤</h3><p>首先，將U盤插入香橙派的USB3.0接口，該接口顏色為藍色。</p>
<p>運行<code>lsblk</code>。</p>
<p>找到U盤的名字。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo mkfs.btrfs /dev/sda1
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，將U盤格式化btrfs文件系統。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo mkdir /mnt/backup
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，創建一個目錄，以便掛載U盤。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo mount /dev/sda1 /mnt/backups
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，挂载U盤至新創建的目錄。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo blkid /dev/sdb1
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，獲取<code>sdb1</code>的UUID。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo nano /etc/fstab
</span></span></code></pre></td></tr></table>
</div>
</div><p>編輯<code>/etc/fstab</code>文件。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">UUID=your_UUID /mnt/myusb btrfs defaults 0 0
</span></span></code></pre></td></tr></table>
</div>
</div><p>在<code>/etc/fstab</code>文件中添加以上內容為行。</p>
<h3 id="自動備份腳本" class="headerLink">
    <a href="#%e8%87%aa%e5%8b%95%e5%82%99%e4%bb%bd%e8%85%b3%e6%9c%ac" class="header-mark"></a>自動備份腳本</h3><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo apt install rsync
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，安裝rsync至armbian。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">nano ~/script/backup_script_usb.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，創建腳本文件。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="c1"># A script to perform incremental backups using rsync and retain only the last 28 backups</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">set</span> -o errexit
</span></span><span class="line"><span class="cl"><span class="nb">set</span> -o nounset
</span></span><span class="line"><span class="cl"><span class="nb">set</span> -o pipefail
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">readonly</span> <span class="nv">SOURCE_DIR</span><span class="o">=</span><span class="s2">&#34;/home/your_username/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">readonly</span> <span class="nv">BACKUP_DIR</span><span class="o">=</span><span class="s2">&#34;/mnt/backup&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">readonly</span> <span class="nv">DATETIME</span><span class="o">=</span><span class="s2">&#34;</span><span class="k">$(</span>date <span class="s1">&#39;+%Y-%m-%d_%H:%M:%S&#39;</span><span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">readonly</span> <span class="nv">BACKUP_PATH</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">DATETIME</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">readonly</span> <span class="nv">LATEST_LINK</span><span class="o">=</span><span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">/latest&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Perform the backup</span>
</span></span><span class="line"><span class="cl">rsync -av --delete --exclude<span class="o">=</span><span class="s2">&#34;.cache&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">SOURCE_DIR</span><span class="si">}</span><span class="s2">/&#34;</span> --link-dest <span class="s2">&#34;</span><span class="si">${</span><span class="nv">LATEST_LINK</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_PATH</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Remove old backups, keeping only the last 28</span>
</span></span><span class="line"><span class="cl">find <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_DIR</span><span class="si">}</span><span class="s2">&#34;</span> -mindepth <span class="m">1</span> -maxdepth <span class="m">1</span> -type d <span class="p">|</span> sort <span class="p">|</span> head -n -28 <span class="p">|</span> xargs rm -rf
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Remove the existing &#34;latest&#34; link and create a new one</span>
</span></span><span class="line"><span class="cl">rm -f <span class="s2">&#34;</span><span class="si">${</span><span class="nv">LATEST_LINK</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">ln -s <span class="s2">&#34;</span><span class="si">${</span><span class="nv">BACKUP_PATH</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">LATEST_LINK</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>講以上內容粘貼至腳本文件。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">chmod +x ~/script/backup_script_usb.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，為腳本賦予執行權限。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sudo crontab -e
</span></span></code></pre></td></tr></table>
</div>
</div><p>運行以上命令，編輯crontab。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">30 */6 * * * ~/script/backup_script_usb.sh  &gt;&gt; ~/script/log/backup_script_usb.log 2&gt;&amp;1
</span></span></code></pre></td></tr></table>
</div>
</div><p>將以上內容寫入crontab文件為行。</p>
<p>通過掛載U盤，並通過自動備份腳本，我們可以實現每日備份4次的增量備份，並將備份數據保持一週的時間。之後，本呆會將數據也備份至Nas，以增加容災能力。</p>
<h2 id="結束" class="headerLink">
    <a href="#%e7%b5%90%e6%9d%9f" class="header-mark"></a>結束</h2><figure>
</figure>

<p>以上，我們通過初步設置將丐版HomeLab配置完成。要實現本地優先之策略，我們需要將諸多服務部署至HomeLab，以造抵抗之器。後續，本呆會發文介紹目前所使用一些docker容器。</p>
<p>丐版HomeLab，夠用就好。這顆28nm的RK3566性能足以覆蓋基本的需求，倘若追求更強更好的配置，恐怕會陷入至消費主義的陷阱。也許每一互聯網移民都應有一個屬於自己的HomeLab，這也是初民之要義。反動學人福山都在用單板機，妳還在等什麼？</p>
]]></description>
</item><item>
    <title>我的博客方案：靜態網站與 IPFS</title>
    <link>https://sogola.com/posts/deploy-a-blog/</link>
    <pubDate>Sun, 23 Apr 2023 13:10:00 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/deploy-a-blog/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/deploy-a-blog/1.png" referrerpolicy="no-referrer">
            </div><h2 id="緣起" class="headerLink">
    <a href="#%e7%b7%a3%e8%b5%b7" class="header-mark"></a>緣起</h2><p>隨著前幾年多個出名的博客服務商終止運營，或者不再提供更新與維護，國文博客開始文藝復興，重新歸復到獨立建站，個中滋味大概只有國朝網民知曉。縱然外國亦有不少博客服務商，但在互聯網開始被爭霸之中的主權國家裹挾之今日，又有哪個主權國家更高尚一些嗎？除了內容自託管，我們別無選擇。</p>
<p>內容的完全控制和方便遷移，這是我託管博客的兩大目標。考慮到國朝網路運營商對 web 端口的屏蔽，如不映射到海外服務器，那麼在自家主機上開放 HTTP/HTTPS 服務，在可預見的未來都是不可能的。為了達成這樣的目標，我選擇靜態網站託管服務與分布式儲存兩種方案。</p>
<p>選擇靜態網站的一個理由是不需要考慮數據庫的維護。相較於動態網站使用數據庫來存儲網站內容和用戶數據，靜態網站以靜態文件的形式存儲內容，進而減少了維護成本。個人使用 wordpress 的過程也有曾遭受過黑客攻擊的經歷，缺少安防經驗也促使我不再使用動態網站。除此之外，靜態網站也更易遷移，選擇靜態網站可方便地將數據從一個託管服務提供商遷移到另一個。</p>
<p>而選擇分布式儲存是由於國內網路環境的限制而不得已的選擇，同時也能有效增強自己對數據的控制權。分布式網站有很多方案，其中比較知名的有 <a href="https://zeronet.io/" target="_blank" rel="noopener noreferrer">ZeroNet</a> 和 <a href="https://ipfs.tech/" target="_blank" rel="noopener noreferrer">IPFS</a>，但 zeronet 目前已停止更新，我們的選擇可能只有 IPFS
了。</p>
<p>IPFS 全稱為 InterPlanetary File System （星際文件系統），是一個基於內容尋址的分布式存儲方案，目前有 <a href="https://brave.com/" target="_blank" rel="noopener noreferrer">Brave瀏覽器</a> 支援使用 <a href="https://ens.domains/" target="_blank" rel="noopener noreferrer">ENS域名</a> 或者傳統域名進行訪問 IPFS 網站。</p>
<p>我的網誌已經歷十幾年，雖然文章不多，但也歷經折騰，然而卻不曾介紹過我的部署方案。是時候將我的部署方案公之於眾了，以下供大家參考與批判。</p>
<h2 id="靜態網站的部署" class="headerLink">
    <a href="#%e9%9d%9c%e6%85%8b%e7%b6%b2%e7%ab%99%e7%9a%84%e9%83%a8%e7%bd%b2" class="header-mark"></a>靜態網站的部署</h2><h3 id="使用-hugo-生成靜態網站" class="headerLink">
    <a href="#%e4%bd%bf%e7%94%a8-hugo-%e7%94%9f%e6%88%90%e9%9d%9c%e6%85%8b%e7%b6%b2%e7%ab%99" class="header-mark"></a>使用 hugo 生成靜態網站</h3><p>我的博客選擇是靜態網站生成器 <a href="https://gohugo.io/" target="_blank" rel="noopener noreferrer">hugo</a>  ，主題為 <a href="https://github.com/HEIGE-PCloud/DoIt" target="_blank" rel="noopener noreferrer">DoIt</a>， DoIT 的基本配置可參考其<a href="https://hugodoit.pages.dev/zh-cn/theme-documentation-basics/" target="_blank" rel="noopener noreferrer">官方網站</a>。</p>
<ul>
<li>網誌文章的 markdown 文件放入 <code>$PWD/yoursite/content/posts</code></li>
<li>簡單頁面的 markdown 文件放入 <code>$PWD/yoursite/content/</code></li>
</ul>
<p>md 文件的名稱就是改頁面的連結，示例如下：</p>
<ul>
<li><a href="https://sogola.com/posts/godsofsanhe1111/" target="_blank" rel="noopener noreferrer">三和大神的双十一怎么过？</a>: <code>$PWD/yoursite/content/posts/godsofsanhe1111.md</code></li>
<li><a href="https://sogola.com/about/" target="_blank" rel="noopener noreferrer">關於頁面</a>: <code>$PWD/yoursite/content/about.md</code></li>
</ul>
<p>對於使用 Hugo 創建博客文章，需要注意和普通 Markdown 文件的區別。在 Hugo 中，無法使用如同普通 markdown 文件般使用 # 來標記文章標題。相反，你需要在文件內使用前置參數進行標記。以下是一個示例前置參數：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">title: &#34;三和大神的双十一怎么过？&#34;
</span></span><span class="line"><span class="cl">date: 2019-11-11T11:52:18+08:00
</span></span><span class="line"><span class="cl">lastmod: 2020-06-16T15:58:26+08:00
</span></span><span class="line"><span class="cl">draft: false
</span></span><span class="line"><span class="cl">author: &#34;王小嗨&#34;
</span></span><span class="line"><span class="cl">summary: &#34;双十一，我去三和做了一晚快递日结。&#34;
</span></span><span class="line"><span class="cl">featuredImage: &#34;/images/godsofsanhe1111/20191111.1.jpg&#34;
</span></span><span class="line"><span class="cl">images: [&#34;/images/godsofsanhe1111/20191111.1.jpg&#34;]
</span></span><span class="line"><span class="cl">toc: false
</span></span><span class="line"><span class="cl">keepStatic: false
</span></span><span class="line"><span class="cl">auto: true
</span></span><span class="line"><span class="cl">categories: [&#34;Capitalism&#34;,&#34;Life&#34;]
</span></span><span class="line"><span class="cl">tags: [&#34;三和大神&#34;,&#34;日结&#34;,&#34;零工&#34;,&#34;快递&#34;]
</span></span><span class="line"><span class="cl">license: &#39;&lt;a rel=&#34;license external nofollow noopener noreffer&#34; href=&#34;https://creativecommons.org/licenses/by-nc/3.0/&#34; target=&#34;_blank&#34;&gt;CC BY-NC 3.0&lt;/a&gt;&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>在這個示例中，<code>title</code> 屬性標示了文章的標題，<code>date</code> 標示了文章的發布日期和時間，<code>lastmod</code> 標示文章最後修改的時間，<code>draft</code> 屬性表示文章是否是草稿狀態。另外，還有一些其他的屬性，比如前面列舉的 <code>author</code>、<code>summary</code>、<code>featuredImage</code> 等等。在這個標題之後，可以使用正常的 Markdown 語法來編寫文章的內容。其中圖片文件在 <code>$PWD/yoursite/static/images</code> 目錄。</p>
<p>在安装 hugo 程式，下載好 DoIt 主題， 完善 <code>config.toml</code> 配置文件，寫好妳的文章之後，cd 至 <code>$PWD/yoursite</code> ，運行 <code>hugo server -D</code> 可對博客網站預覽，若滿意，則運行 <code>hugo</code> 命令。在 <code>$PWD/yoursite/public</code> 目錄中，妳將會得到博客的所有靜態文件。</p>
<h3 id="將靜態網站上載至託管服務商" class="headerLink">
    <a href="#%e5%b0%87%e9%9d%9c%e6%85%8b%e7%b6%b2%e7%ab%99%e4%b8%8a%e8%bc%89%e8%87%b3%e8%a8%97%e7%ae%a1%e6%9c%8d%e5%8b%99%e5%95%86" class="header-mark"></a>將靜態網站上載至託管服務商</h3><p>有了整個網站的靜態文件，我們需將其上傳至託管服務商。目前，可供選擇服務商有好幾家，大部分服務商的免費方案都足夠個人博客使用。</p>
<ul>
<li><a href="https://vercel.com/" target="_blank" rel="noopener noreferrer">Vercel</a></li>
<li><a href="https://www.netlify.com/" target="_blank" rel="noopener noreferrer">Netlify</a></li>
<li><a href="https://pages.cloudflare.com/" target="_blank" rel="noopener noreferrer">Cloudflare Pages</a></li>
<li><a href="https://pages.github.com/" target="_blank" rel="noopener noreferrer">GitHub Pages</a></li>
<li><a href="https://fleek.co/" target="_blank" rel="noopener noreferrer">Fleek</a></li>
</ul>
<p>以上服務商，都支持綁定 GitHub 倉庫，它會自動拉取最新倉庫更新並保持同步。其中 Fleek ，不僅支持生成 http 頁面，還會將文件上傳至 IPFS 網路，給出 CID。</p>
<p>先在 GitHub 新建一個 repository， 與本地的 <code>$PWD/yoursite/public</code> 目錄進行關聯，並將博客文件上載至倉庫。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd $PWD/your_site/public
</span></span><span class="line"><span class="cl">git init
</span></span><span class="line"><span class="cl">git add .
</span></span><span class="line"><span class="cl">git commit -m &#34;deploy blog&#34;
</span></span><span class="line"><span class="cl">git branch -M main
</span></span><span class="line"><span class="cl">git remote add origin git@github.com:your_github_name/your_blog_repository.git
</span></span><span class="line"><span class="cl">git push -u origin main
</span></span></code></pre></td></tr></table>
</div>
</div><p>之後，有新博文之後，再重新運行 <code>hugo server -D</code> 預覽博客，若滿意，則運行 <code>hugo</code> 命令更新博客的靜態文件，再將其更新至 GitHub 倉庫。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">cd $PWD/yoursite/public
</span></span><span class="line"><span class="cl">git add .
</span></span><span class="line"><span class="cl">git commit -m &#34;blog update&#34;
</span></span><span class="line"><span class="cl">git push -u origin main
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>git push</code> 完成後，託管服務商會自動讀取倉庫更新，將其部署至服務器。</p>
<h3 id="綁定傳統域名" class="headerLink">
    <a href="#%e7%b6%81%e5%ae%9a%e5%82%b3%e7%b5%b1%e5%9f%9f%e5%90%8d" class="header-mark"></a>綁定傳統域名</h3><p>在託管服務商創建我們的博客項目並綁定 GitHub 倉庫後，通常服務商會提示我們綁定域名。如若沒有相關提示，也可以在其管理界面中方便地找到綁定域名的選項，按照其要求添加相關 DNS 記錄，比如 A 記錄 或者 CNAME 記錄。</p>
<p>為了更方便、更安全地管理域名的 DNS，建議使用 <a href="https://www.cloudflare.com/" target="_blank" rel="noopener noreferrer">Cloudflare</a> 服務。首先，在 Cloudflare 上添加域名，然後在域名服務商的管理界面中將 DNS 服務器變更為 Cloudflare 提供的 DNS 服務器，最後等待生效即可。</p>
<p>當然，如果不想購買域名的話，也可使用服務商提供的二級域名。但是，若使用自有域名，我們將更方便地將網站從一個服務商遷移至另一個，僅需更改 DNS 記錄即可。</p>
<h2 id="博客的ipfs部署方案" class="headerLink">
    <a href="#%e5%8d%9a%e5%ae%a2%e7%9a%84ipfs%e9%83%a8%e7%bd%b2%e6%96%b9%e6%a1%88" class="header-mark"></a>博客的IPFS部署方案</h2><h3 id="docker-安裝-ipfs" class="headerLink">
    <a href="#docker-%e5%ae%89%e8%a3%9d-ipfs" class="header-mark"></a>docker 安裝 IPFS</h3><p>將網誌託管給服務商固然很方便，這也增加了被審查與阻斷的風險。作為國朝臣民，我們天然地對任何服務商沒有信任。如果選擇 IPFS 方案託管網誌，這無疑將大大地治癒我們的書報檢查PTSD。但要特別注意：IPNS 並不匿蹤，書寫與言說就要承受利維坦之重，請審慎考量再使用鍵鼠。</p>
<p>IPFS 擁有一個域名系統 IPNS (InterPlanetary File System)，可讓我們更方便地配合域名使用 IPFS ， IPFS 託管網站的要義是用戶自己控制 IPNS 的 private key (私鑰)。儘管已有提供 IPNS 託管服務的選項，但這要付出信任成本。如若選擇自行生成與託管 IPNS Key ，這是一個 trustless 的抉擇，只要自己做好安全風險的管控。</p>
<p>要進行 IPFS 網站的自託管，首先要 安裝 IPFS 程式。因為需要 7*24 的不間斷服務，將 IPFS 安裝在功耗較低的小主機是一個好的選擇，所有選擇 docker 安裝 IPFS 是一個好的選項。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">docker</span> <span class="n">run</span> <span class="o">-</span><span class="n">d</span> <span class="o">--</span><span class="n">name</span> <span class="n">ipfs</span> \
</span></span><span class="line"><span class="cl">  <span class="o">-</span><span class="n">v</span> <span class="o">$</span><span class="n">PWD</span><span class="o">/</span><span class="n">docker</span><span class="o">/</span><span class="n">ipfs</span><span class="o">/</span><span class="n">ipfs</span><span class="p">:</span><span class="o">/</span><span class="n">data</span><span class="o">/</span><span class="n">ipfs</span> \
</span></span><span class="line"><span class="cl">  <span class="o">-</span><span class="n">v</span> <span class="o">$</span><span class="n">PWD</span><span class="o">/</span><span class="n">docker</span><span class="o">/</span><span class="n">ipfs</span><span class="o">/</span><span class="k">export</span><span class="p">:</span><span class="o">/</span><span class="k">export</span> \
</span></span><span class="line"><span class="cl">  <span class="o">-</span><span class="n">u</span> <span class="mi">1000</span><span class="p">:</span><span class="mi">1000</span> \
</span></span><span class="line"><span class="cl">  <span class="o">-</span><span class="n">p</span> <span class="mi">4001</span><span class="p">:</span><span class="mi">4001</span> \
</span></span><span class="line"><span class="cl">  <span class="o">-</span><span class="n">p</span> <span class="mi">8080</span><span class="p">:</span><span class="mi">8080</span> \
</span></span><span class="line"><span class="cl">  <span class="n">ipfs</span><span class="o">/</span><span class="n">go</span><span class="o">-</span><span class="n">ipfs</span><span class="p">:</span><span class="n">latest</span>  
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="生成-ipns-key-並綁定域名" class="headerLink">
    <a href="#%e7%94%9f%e6%88%90-ipns-key-%e4%b8%a6%e7%b6%81%e5%ae%9a%e5%9f%9f%e5%90%8d" class="header-mark"></a>生成 IPNS Key ，並綁定域名</h3><p>安裝完成後，進入 IPFS 容器的 Shell ，運行以下命令，將服務应用 lowpower 配置，這會優化 IPFS 資源的佔用情況。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ipfs config profile apply lowpower
</span></span></code></pre></td></tr></table>
</div>
</div><p>接著在 Shell 中， cd 至 <code>export</code> 目錄，運行以下命令，生成一個 IPNS key pair。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">ipfs key gen your_key_name
</span></span></code></pre></td></tr></table>
</div>
</div><p>記錄給出的 IPNS 的 public key (公鑰)，並使用以下命令將其導出。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">ipfs</span> <span class="n">key</span> <span class="k">export</span> <span class="n">your_key_name</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在文件管理中，進入至 <code>$PWD/docker/ipfs/export</code> ，將目錄中的 Key 文件妥善保管，以下是 IPFS KEY 管理的命令。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">ipfs</span> <span class="n">key</span> <span class="k">export</span> <span class="o">&lt;</span><span class="n">name</span><span class="o">&gt;</span>           <span class="o">-</span> <span class="n">Export</span> <span class="n">a</span> <span class="n">keypair</span>
</span></span><span class="line"><span class="cl"><span class="n">ipfs</span> <span class="n">key</span> <span class="n">gen</span> <span class="o">&lt;</span><span class="n">name</span><span class="o">&gt;</span>              <span class="o">-</span> <span class="n">Create</span> <span class="n">a</span> <span class="n">new</span> <span class="n">keypair</span>
</span></span><span class="line"><span class="cl"><span class="n">ipfs</span> <span class="n">key</span> <span class="n">import</span> <span class="o">&lt;</span><span class="n">name</span><span class="o">&gt;</span> <span class="o">&lt;</span><span class="n">key</span><span class="o">&gt;</span>     <span class="o">-</span> <span class="n">Import</span> <span class="n">a</span> <span class="n">key</span> <span class="ow">and</span> <span class="nb">prints</span> <span class="n">imported</span> <span class="n">key</span> <span class="n">id</span>
</span></span><span class="line"><span class="cl"><span class="n">ipfs</span> <span class="n">key</span> <span class="n">list</span>                    <span class="o">-</span> <span class="n">List</span> <span class="n">all</span> <span class="n">local</span> <span class="n">keypairs</span><span class="o">.</span>
</span></span><span class="line"><span class="cl"><span class="n">ipfs</span> <span class="n">key</span> <span class="n">rename</span> <span class="o">&lt;</span><span class="n">name</span><span class="o">&gt;</span> <span class="o">&lt;</span><span class="n">newName</span><span class="o">&gt;</span> <span class="o">-</span> <span class="n">Rename</span> <span class="n">a</span> <span class="n">keypair</span><span class="o">.</span>
</span></span><span class="line"><span class="cl"><span class="n">ipfs</span> <span class="n">key</span> <span class="n">rm</span> <span class="o">&lt;</span><span class="n">name</span><span class="o">&gt;...</span>            <span class="o">-</span> <span class="n">Remove</span> <span class="n">a</span> <span class="n">keypair</span><span class="o">.</span>
</span></span><span class="line"><span class="cl"><span class="n">ipfs</span> <span class="n">key</span> <span class="n">rotate</span>                  <span class="o">-</span> <span class="n">Rotates</span> <span class="n">the</span> <span class="n">IPFS</span> <span class="n">identity</span><span class="o">.</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>有了 IPNS Key 之後，就可將內容的 CID 發布到 IPNS 。如果直接訪問 IPFS 公鑰，當然也可以，但也這讓訪問者望而卻步，一大串字符讓人望而卻步。為了方便記憶，我們需要將 IPNS 與域名綁定，綁定方法可參考我的文章<a href="https://sogola.com/posts/planet/" target="_blank" rel="noopener noreferrer">Planet：一款IPFS静态站点生成器</a>中的域名绑定綁定部分。</p>
<h3 id="自動更新-ipns" class="headerLink">
    <a href="#%e8%87%aa%e5%8b%95%e6%9b%b4%e6%96%b0-ipns" class="header-mark"></a>自動更新 IPNS</h3><p>使用 IPFS 自託管靜態網站，主要是因為其分布式特性，它讓我們重拾萬維網之互聯真義。然而，由於個人博客的讀者不多，使用 IPFS 的用戶更是寥寥無幾，因此在 IPFS 自託管的同時，使用 remote pinning services 來提高網站的可用性是個不錯的選擇。</p>
<p>在介紹靜態網站託管服務商的時候，有提到 <a href="https://fleek.co/" target="_blank" rel="noopener noreferrer">Fleek</a> ，它就有提供 remote pinning services ，在生成動態網站的同時，可生成一個網站的 CID。</p>
<p>如果我們在每次更新網站後，從 Fleek 生成的域名讀取出它綁定的 CID，並在本地 pin 這個 CID，然後再將其發布至我們自己的 IPNS ，那麼我們就可以實現同時更新靜態網站服務商和 IPNS 託管。所以，我請 ChatGPT 寫了可自動這一系列操作的腳本，如下所示。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="c1">#</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Script: update-ipns.sh</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Description: Check if IPNS record needs to be updated and update it if necessary.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">set</span> -euo pipefail
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Function: get IPNS CID</span>
</span></span><span class="line"><span class="cl">get_ipns_cid<span class="o">()</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">ipns_name</span><span class="o">=</span><span class="nv">$1</span>
</span></span><span class="line"><span class="cl">  <span class="nb">local</span> <span class="nv">ipfs_container</span><span class="o">=</span><span class="nv">$2</span>
</span></span><span class="line"><span class="cl">  docker <span class="nb">exec</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">ipfs_container</span><span class="si">}</span><span class="s2">&#34;</span> ipfs resolve -r <span class="s2">&#34;/ipns/</span><span class="si">${</span><span class="nv">ipns_name</span><span class="si">}</span><span class="s2">&#34;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    <span class="p">|</span> tail -n1 <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>    <span class="p">|</span> awk <span class="s1">&#39;{ print $NF }&#39;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Variables: define container name, IPNS names and options</span>
</span></span><span class="line"><span class="cl"><span class="nv">IPFS_CONTAINER</span><span class="o">=</span><span class="s2">&#34;ipfs&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">SOGOLA_IPNS</span><span class="o">=</span><span class="s2">&#34;your_domain_name&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">FLEEK_IPNS</span><span class="o">=</span><span class="s2">&#34;your_fleek_site_name.on.fleek.co&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">PIN_OPTS</span><span class="o">=</span><span class="s2">&#34;--progress&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nv">PUBLISH_OPTS</span><span class="o">=</span><span class="s2">&#34;--key=your_ipns_public_key&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Check if the IPFS container is running</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> ! <span class="s2">&#34;</span><span class="k">$(</span>docker ps -q -f <span class="nv">name</span><span class="o">=</span><span class="si">${</span><span class="nv">IPFS_CONTAINER</span><span class="si">}</span><span class="k">)</span><span class="s2">&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">IPFS_CONTAINER</span><span class="si">}</span><span class="s2"> container is not running. Please start the container and try again.&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Get IPNS CID</span>
</span></span><span class="line"><span class="cl"><span class="nv">SOGOLA_CID</span><span class="o">=</span><span class="k">$(</span>get_ipns_cid <span class="s2">&#34;</span><span class="si">${</span><span class="nv">SOGOLA_IPNS</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">IPFS_CONTAINER</span><span class="si">}</span><span class="s2">&#34;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="nv">FLEEK_CID</span><span class="o">=</span><span class="k">$(</span>get_ipns_cid <span class="s2">&#34;</span><span class="si">${</span><span class="nv">FLEEK_IPNS</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">IPFS_CONTAINER</span><span class="si">}</span><span class="s2">&#34;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Check if IPNS record needs update</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">SOGOLA_CID</span><span class="si">}</span><span class="s2">&#34;</span> !<span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">FLEEK_CID</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># Publish new IPNS record</span>
</span></span><span class="line"><span class="cl">  docker <span class="nb">exec</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">IPFS_CONTAINER</span><span class="si">}</span><span class="s2">&#34;</span> ipfs name publish <span class="s2">&#34;</span><span class="si">${</span><span class="nv">PUBLISH_OPTS</span><span class="si">}</span><span class="s2">&#34;</span> --lifetime<span class="o">=</span>8766h -- <span class="s2">&#34;</span><span class="si">${</span><span class="nv">FLEEK_CID</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># Unpin the previous IPNS record</span>
</span></span><span class="line"><span class="cl">  docker <span class="nb">exec</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">IPFS_CONTAINER</span><span class="si">}</span><span class="s2">&#34;</span> ipfs pin rm <span class="s2">&#34;</span><span class="si">${</span><span class="nv">SOGOLA_CID</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># Pin the updated IPNS record</span>
</span></span><span class="line"><span class="cl">  docker <span class="nb">exec</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">IPFS_CONTAINER</span><span class="si">}</span><span class="s2">&#34;</span> ipfs pin add <span class="s2">&#34;</span><span class="si">${</span><span class="nv">PIN_OPTS</span><span class="si">}</span><span class="s2">&#34;</span> -- <span class="s2">&#34;</span><span class="si">${</span><span class="nv">FLEEK_CID</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;IPNS record updated successfully.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;IPNS record is already up-to-date, no need to update.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Add error handling</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> <span class="nv">$?</span> -eq <span class="m">0</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;Update completed.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;Error occurred while updating IPNS record. Please check.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>將上述腳本中的 SOGOLA_IPNS,FLEEK_IPNS,PUBLISH_OPTS 分別替換並保存為 <code>update-ipns.sh</code> ，使用自動化工具定時執行，即可使用 Git 更新博客後，實現靜態網站的 HTTP 與 IPFS 同時更新的功能。</p>
<p>如果覺得只有一個 remote pinning service 不保險的話，還可以使用 <a href="https://dashboard.4everland.org?invite=BB0BLBGV" target="_blank" rel="noopener noreferrer">4EVERLAND</a> ，這個服務商支持使用 IPNS 進行 PIN。</p>
<h2 id="總結" class="headerLink">
    <a href="#%e7%b8%bd%e7%b5%90" class="header-mark"></a>總結</h2><p>透過個間網站託管服務商，我們可以通過控制域名來遊走之間，輕鬆實現切換服務商。而通過自託管 IPFS ，拜分布式託管之幸，我們終可回歸到萬維網之本心，重新掌握我們自己的數據。</p>
<p>就撰寫這篇博文期間，我留意到<a href="https://www.solidot.org/story?sid=74728" target="_blank" rel="noopener noreferrer">一則新聞</a>，ICANN 和 Verisign 提议允许任何政府扣押域名。是時候，我們該嘗試無許可與去信任的 crypto 了。</p>
<blockquote>
<p>整治書報檢查制度的真正而根本的辦法，就是廢除書報檢查制度，因為這種制度本身是惡劣的，可是各種制度卻比人更有力量。我們的意見可能是正確的，也可能是不正確的，不過無論如何，新的檢查令終究會使普魯士的作者要么獲得更多的現實的自由，要么獲得更多的觀念的自由，也就是獲得更多的意識。</p>
<p>Rara temporum felicitas, ubi quae velis sentire et quae sentias dicere licet［當你能夠想你願意想的東西，並且能夠把你所想的東西說出來的時候，這是非常幸福的時候］。</p>
<p>————馬克思《評普魯士最近的書報檢查令》</p>
</blockquote>
<p>「清風不識字」，主權國家宰制一切。當言說成為禁忌，開設一個部落格已然成為罪證，我只祝福妳們成為幸福的人。那些獨立博客的作者有福了，因為妳們必然承受大地之重。</p>
]]></description>
</item><item>
    <title>《三體》與 iPhone 產線：國朝的工業與科幻的黃金時代</title>
    <link>https://sogola.com/posts/the-three-body-problem/</link>
    <pubDate>Tue, 11 Apr 2023 20:05:00 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/the-three-body-problem/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/the-three-body-problem/1.jpg" referrerpolicy="no-referrer">
            </div><blockquote>
<p>人們在自己生活的社會生產中發生一定的、必然的、不以他們的意志為轉移的關係，即同他們的物質生產力的一定發展階段相適合的生產關係。這些生產關係的總和構成社會的經濟結構，即有法律的和政治的上層建築豎立其上並有一定的社會意識形式與之相適應的現實基礎。物質生活的生產方式制約着整個社會生活、政治生活和精神生活的過程。不是人們的意識決定人們的存在，相反，是人們的社會存在決定人們的意識。</p>
<p>卡爾·馬克思《政治經濟訓序言》（1859）</p>
</blockquote>
<p>西元2006年至2007年，《三體》在《科幻世界》雜誌連載，期間 Apple 公司發佈第一代 iPhone；</p>
<p>2007年，《三體2》出版，2008年，Apple 公司發佈 iPhone 3g，並交由富士康代工，廣受關注；</p>
<p>2010年，Apple 公司發佈 iPhone 4，同年《三體3》出版，當年 iPhone 4大賣；</p>
<p>2010年期間，iPhone 的代工廠出現員工連續跳樓事件，引發社會廣泛關注。</p>
<p>《三體》的出版時間與世界工廠的巔峰時刻，如此接近。國朝科幻的黃金時代與國朝工業產業鏈的黃金時代，在移民工人的悲歌中交相呼應。真理在歷史中展開，正如至聖先師的教誨，人們的社會存在決定了人們的意識。</p>
<div class="bilibili"><iframe src="//player.bilibili.com/player.html?bvid=BV1gG4y1g7hy&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe></div>

<p>透過一則戴老師聊《三體》的短片，我驚訝地發現戴老師原來也追了《科幻世界》上《三體》的連載，而我很幸運能和戴老師一起追這個系列。那時候我還在念中學，起初，只有我和另一個同學看《科幻世界》，爾後風靡全班，這只不過是《三體》的連載從開始到高潮的過程。</p>
<p>各類社交媒體上充斥著對《三題》的情緒化表達，為了一部中學生讀本，《三體》的愛好者與鄙夷者吵得面紅耳赤，仿佛不表達一下自己的情緒，她們就會錯失自己的一部分。好的科幻文學作品大概可以算做工業黃金時代的神聖讚歌，讚歌是時代精神的低吟，它理應被更審慎地對待，而不是陷入到情緒對立。</p>
<p>至聖先師有言「手織機給我們帶來了封建領主，而蒸汽磨坊則帶來了產業資本家」。好的科幻作品，正如《三體》那樣，用連續的劇情將這個真理演繹出來了。</p>
<p>那些連手機電腦都玩不明白的人們，她們看不到這一真理在文學中的展開，眼中只有低劣的社會學理論（黑暗森林理論），她們像滿洲八旗治下的包衣一樣，總是否定科技進步帶來的變革，將偉大的發明視為奇技淫巧，而這些回響也不過是手織機、蒸汽磨坊的吵鬧雜音。</p>
<p>當然，盲目崇拜某一部作品，這與文化工業的粉絲經濟並無差別，對《三體》狂熱者的批判應該轉為批判文化工業的一般，因為這不過是消費主義在這些狂熱份子頭頂之上的顯靈。</p>
<p>前久，趁騰訊版《三體》電視劇的熱播，我又翻了翻三體，發現書裡面充斥著各種刻板印象，不過時光倒回西元2006年，誰又有多少進步思想呢？耶穌有言沒有罪的人，可以拿石頭砸死她了。騰訊劇版《三體》的精彩程度遠超我的想像，要知道，它一整季的預算只是網飛版一集的預算。中學時代，我看《科幻世界》雜誌連載的時候，萬萬沒想到，它會上國朝皇家電視台呀。</p>
<p>最後，讓我們冒充一下熱衷下大棋的「國師」：不知道非國語區觀眾喜不喜歡騰訊版《三體》，如果非國語觀眾也愛看的話，朝廷應該將孔子學院的經費撥給《三體》電視劇第二季。當然，我們對於小學生不要抱有任何幻想。這裡沒有大棋，只有臨時起意和形勢所迫。</p>
]]></description>
</item><item>
    <title>「簡中互聯網」：長城內愛國者的鏡花水月</title>
    <link>https://sogola.com/posts/simplified-chinese-internet/</link>
    <pubDate>Tue, 04 Apr 2023 22:11:00 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/simplified-chinese-internet/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/simplified-chinese-internet/1.png" referrerpolicy="no-referrer">
            </div><p>自從類比英文互聯網的「簡中互聯網」這一說法開始流行，從 Twitter 到睡前消息，人們總是用「簡中互聯網」來指代不同於英文互聯網的國內互聯網，可我們真的可以這樣大而化之嗎？要知道，包括新加坡、大馬華人在內，不少東南亞國家的華族都在使用簡化儒字，況且新加坡還有幾個頗具影響的國文媒體。</p>
<p>相比「簡中互聯網」，我更願意用「國朝互聯網」來指代，因為主權國家規定了互聯網的今日現狀，而語言有著更有寬廣的範圍。從常識出發，我們可以推定簡化字的互聯網的範圍大於國朝本部互聯網的範圍，正如英語互聯網的範圍大於米帝互聯網一樣。以某種特定語言於互聯網進行內容分發，從來都不是特定國的壟斷。</p>
<p>既然如此，為什麼還有國朝諸網民都在使用「簡中互聯網」一詞呢？我想大抵有以下兩個原因。</p>
<p>首先，在朝廷網信辦的領導下，國朝互聯網圈地自萌，網民坐井觀天，她們不知曉《聯合晚報》影響廣泛，更不曾體驗過 TikTok 的片刻歡樂，仿佛在這顆藍色星球上只有自己在使用簡化儒字。</p>
<p>其次，這是某種大國沙文主義在作祟。我不想老調重提列寧主義的名言，「愛國主義是流氓最後的避難所」，我更傾向於她們將自己的國家與文化神聖化，而神聖則意味著不可侵犯。</p>
<p>還有一個案例：對於春節英譯的爭論，究竟采用 Chinese New Year，還是 Lunar New Year。這幾年來，每到國曆新年，關於春節英譯的爭論可謂妖風陣陣，這個爭論就是將儒教文化進行國族神聖化的一個典範。諸多愛國者都將國曆新年狹隘為「中國新年」（Chinese New Year），就算陰曆（Lunar）一詞有些不足概括國曆，但它的範圍總比「中國新年」寬廣更多。</p>
<p>眾所週知，國曆新年是儒教文化圈的共同文化圖騰，它不僅是華人社會的節日，更是南北朝鮮、越南等地的傳統。倘若愛國者將其僭越為自己的國族獨有的文化，那麼這無疑是對大國沙文主義毫不客氣的表白，而「簡中互聯網」的稱謂則是大國沙文主義在國朝悄然流行的症候。</p>
<p>回顧近幾年，去全球化加劇，產業分工轉向「去中國化」，互聯網開始被主權國家所分割。不肖說國朝的防火長城，只看各國對 TikTok 的圍堵，還有騰訊主動將海外用戶註冊 WeChat 變得異常繁瑣，我們不能看出主權國家已將互聯網肢解成碎肉，變成自己的美餐。於支離破碎的互聯網之中，國朝網民完成了對「簡中互聯網」一詞的挪用。</p>
<p>誠然，拜書報檢查員所賜，愛國者的話語占領了國朝互聯網的討論空間，所有不同意見都被壓抑。防火長城內外，井然已是兩個世界。400毫米降水線以內，愛國者們怡然自得，滿眼所見皆是自身的映像，殊不知那一片洞天不過是鏡花水月。</p>
]]></description>
</item><item>
    <title>LH汽車站宛若疫情前的三和</title>
    <link>https://sogola.com/posts/lh-bus-station/</link>
    <pubDate>Sun, 26 Feb 2023 00:55:00 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/lh-bus-station/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/lh-bus-station/1.jpg" referrerpolicy="no-referrer">
            </div><p>昨夜九點半去LH汽車站溜達了一圈，好多老哥，熙熙攘攘，空氣中又有一點點焦躁，我彷彿回到了西元2019年的三和。剛到汽車站，就有差人及鄉勇排排站，走進人群，我才知道原來是驅逐在台階上休憩的老哥，隱約間，聽到鄉勇說道：這影響了市容。差人及鄉勇掃過整個廣場，頗有氣勢。</p>
<p>可偏偏有老哥不信邪，「執法要有有法可依，睡這裡並不違法」，周遭圍觀的老哥一陣起哄叫好。在老哥們的注視下，差人及鄉勇無奈地走開了。我拿起手機想抓拍幾張相片，剛剛沒拍幾張，就有老哥提醒不要亂拍，小心有老哥揪住妳不放，跟妳要兩百塊。我想到前幾年在三和被打的經歷，還是將手機乖乖地收起來。</p>
<p>今晚的南方有點冷，我將雙手插進兜裏，兩手緊貼大腿。剛到十點鐘，一位環衛大爺開著噴水三輪車來到廣場。這時候，一陣騷動彷彿漣漪一般，在廣場搖曳開來，「真他媽壞」，「睡覺都不讓睡」。水槍掃過台階，濕冷的氣息撲面而來，「拍下來，爆光她們」。水槍掃了一小截，就遭遇了一位已經打地鋪睡下的老哥，水槍聲響了下來。老哥起身假意收拾被褥，鄉勇趕了過來，老哥們也聚攏過來了。</p>
<p>人越聚越多，人群跳出來一位老哥，他索性坐在了台階之上。鄉勇質問老哥，老哥反問我們有錢的話，誰會願意睡在這裡呢。「誰不知道旅館二十塊一晚，可我們沒錢呢。」他越講越激動，揮舞起拳頭，鄉勇知難而退，人群中時而爆出一陣掌聲，時而爆出一陣哄笑。</p>
<p>不知什麼時候，環衛大爺早已悄然躲在角落，只剩灑水三輪車寡寂地留在原地。「維權！」「我們要吃飯，我們要睡覺！」「LH區的領導們，我們想反饋意見。」一些老哥吵吵地開玩笑似地在叫喚，這些聲音最終消散在了濕冷的空氣之中。</p>
<p>今年的工作不好找，一位老哥說他想去隔壁的DG市，旁邊的老哥勸戒道，全國哪裡不是這樣，這邊算人少了，別的地方人更多。有人說電子廠都去了越南，這時有老哥接話說等3、4月份的時候，也許Apple會有訂單，語氣中充滿了期望。老哥們議論著為什麼今年電子廠都沒訂單呀，「是因為戰爭，外國打仗了，我們老百姓遭殃了。」</p>
<p>環衛大爺收拾了一下噴水三輪車，一位老哥說「別噴了」，環衛大爺道：「收工回家。」今夜風大天冷，家裡暖和，可我們還會有家嗎？</p>
]]></description>
</item><item>
    <title>matters.news：一个故弄玄虚的伪去中心化站点</title>
    <link>https://sogola.com/posts/mattersnews/</link>
    <pubDate>Tue, 11 Oct 2022 17:30:00 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/mattersnews/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/mattersnews/1.png" referrerpolicy="no-referrer">
            </div><p>在展开之前，我们先要明确一点，web3的要义是个人主权，意即用户可以自主地控制自己的数据。</p>
<p>这里，我列举两点matters的做法。</p>
<ul>
<li>不许用户修改用户名和绑定的likerid和eth地址</li>
<li>诱导用户将IPFS认知为永久储存</li>
</ul>
<p>就连臭名昭著的微信都允许用户定期进行用户名的修改，可matters并未有任何修改用户名（Matters ID）或注销账户的选项。这与其宣称的「生態：自主、自由」完全背离。</p>
<p>事实上，所谓的 Matters ID，抑或账户与 likerid 与eth 地址的绑定，只是 matters.news 的数据库上的一串数字而已，并未存储在 blockchain 之上，完全不存在不能修改的技术问题。</p>
<p>早先，我有给 matters.news 发过电子邮件，要求解除likerid绑定，得到回复如下：</p>
<blockquote>
<p>Liker ID 目前無法解綁或更換。</p>
</blockquote>
<p>坦率地讲，使用过区块链钱包的人都知晓，目前的crypto世界是一片黑暗森林，没人可完全保证自己永久地掌控一个钱包地址，不能解除绑定，这不仅增加被盗钱包用户的风险，也给其它用户带来风险。</p>
<p>如此来看，用户在 matters.news 上毫无自主的权利。</p>
<p>倘若用户在 matters.news 上发布文章，再想删除的话，那么抱歉了，因为 matters.news 仅提供隐藏文章的选项，只能隐藏。对此，matters.news的解释是一旦储存在IPFS上就无法删除。如此敷衍的解释，只会诱导用户将IPFS认知为永久储存。</p>
<p>虽然一个文件一旦储存在IPFS之上，真的没法删除，但不代表这个文件不会消失，也不代表这个文件一定与这个用户在 matters.news 的数据之间存在绑定关系。</p>
<p>要知道，一个IPFS文件，如果长久的没有节点对其进行存储，自然就会消失。嗯，互联网是没有记忆的。但 matters.news 将储存在IPFS之上的文件用户进行永恒绑定，这是打算自行付费将全站文章存储到天荒地老？</p>
<figure>
</figure>

<p>亦有<a href="https://matters.news/@mthree/130425-%E5%85%AC%E5%91%8A-%E7%AE%A1%E7%90%86%E5%91%98%E6%81%B6%E6%84%8F%E5%88%A0%E9%99%A4%E6%9C%AC%E4%BA%BA%E6%96%87%E7%AB%A0-bafyreibia52hidunyzn5s2hsgtxozz5ugf4qhqhxv2k2an5vieefk4ijni" target="_blank" rel="noopener noreferrer">用户反应</a> matters.news 「管理员」将其文章恶意隐藏，它们丝毫不掩饰其中心化平台的狰狞面目。「去中心化的創作社群與內容生態」，看起来像个地狱笑话。</p>
<p>最近一段时间，matters.news 在其首页疯狂推送NFT等诈骗信息，也许是时候该NFT祛魅了。</p>
<p>这样的平台，我反正不会去使用。</p>
]]></description>
</item><item>
    <title>Planet：一款IPFS静态站点生成器</title>
    <link>https://sogola.com/posts/planet/</link>
    <pubDate>Sat, 03 Sep 2022 11:52:18 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/planet/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/planet/1.png" referrerpolicy="no-referrer">
            </div><p>对于不少人来说，搭建一个自己的网站是件不好入手的事情。抛开一系列眼花缭乱的技术术语，还需搞定服务器、域名、建站工具等等，这些都要气力去认知与实践。况且随着互联网寡头横行霸道，似乎发布或拥有一个网志站点已变为画蛇添足的笨蛋行为。</p>
<p>万幸，分布式网路虽英雄末路，但还未乘鹤西去，已有开发者将发布分布式网站做成了一件用户操作友好的事情。妳只需在macOS上安装Planet，就可将IPFS作为托管服务器，几下点击就可发布一个网志站点。</p>
<h2 id="planet的缘起" class="headerLink">
    <a href="#planet%e7%9a%84%e7%bc%98%e8%b5%b7" class="header-mark"></a>Planet的缘起</h2><p>Planet的创始人Livid也是大型程序员交友网站<a href="https://www.v2ex.com/" target="_blank" rel="noopener noreferrer">v2ex</a>的创始人，在Planet发布前的<a href="https://www.xiaoyuzhoufm.com/episode/626ba660bf39836fd02b78e9" target="_blank" rel="noopener noreferrer">一档播客访谈</a>
中，Livid称维护v2ex的服务器与数据库是一件漫长且痛苦的事情，并表示如果再开发一款程序，自己不会选择再托管用户的数据。</p>
<blockquote>
<p>星际文件系统（Interplanetary File System，缩写为IPFS）是一个旨在实现文件的分布式存储、共享和持久化的网络传输协议。[2]它是一种内容可寻址（英语：Content-addressable storage）的对等超媒体分发协议。在IPFS网络中的节点构成一个分布式文件系统。</p>
<p>——<a href="https://zh.m.wikipedia.org/zh-hans/%E6%98%9F%E9%99%85%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F" target="_blank" rel="noopener noreferrer">维基百科「星际文件系统」词条</a></p>
</blockquote>
<p>IPFS作为分布式网路技术，并且可实现用户自己托管自己的数据，这让Livid看到了光亮，遂有了开发Planet的想法。西元2022年07月11日，Livid在v2ex<a href="https://www.v2ex.com/t/857404" target="_blank" rel="noopener noreferrer">发帖</a>，「如果你之前用过 IPFS 或者 ENS，你可能会想要试试我们在做的这个App」，Planet正式上线。</p>
<p>Livid在访谈中表示，底层协议的迭代已经成熟，分布式站点完全可能，Planet会做一个用户友好的进入分布式的入口。</p>
<h2 id="站点的访问" class="headerLink">
    <a href="#%e7%ab%99%e7%82%b9%e7%9a%84%e8%ae%bf%e9%97%ae" class="header-mark"></a>站点的访问</h2><p>在开始使用Planet部署自己的分布式站点之前，我们有必要有了解一下访问一个万维网站点的过程。</p>
<figure><figcaption>
            <h4>浏览器访问万维网过程的简易示意图</h4>
        </figcaption>
</figure>

<p>在访问传统万维网站点的过程中，首先浏览器要跟DNS服务器请求服务器地址，我们可以把这个过程想象成在手机地图中输入商家名称，获得商家地址；然后，有服务器地址，浏览器就可以与服务器建立连接，我们可以把这个过程想象成有商家地址，我们就可以乘坐共同交通前往与返回；最后，当建立了连接，客户浏览器就可以发送需要的文件，服务器收到了这个请求，就会将相应的文件返回给浏览器，浏览器得到文件就可以将内容显示给用户，我们可以将这个过程想象成我们在外送app上点了一个红烧肉，商家收到了订单，做好后就发送给用户。</p>
<figure><figcaption>
            <h4>世界上第一台服务器</h4>
        </figcaption>
</figure>

<p>也许有人会问，什么是服务器呢？事实上，服务器就是一台电脑，任何联网的设备都可以成为一台服务器，妳的手机或电脑都可以作为服务器供她人访问。被提姆·柏内兹-李在CERN所使用的这台NeXT计算机成为了世界上第一台网页服务器，上面写着「这台机器是服务器，不要关闭电源」。</p>
<p>然而，时至今日，互联网寡头大行其道，加之国内糟糕的联网环境，已经很少人在家中自行搭建站点服务器了。我们平时所访问站点更多是托管在云服务器商（阿里云、亚马逊云等等）之上，这与万维网的理念完全背离，回滚到电台广播的时代。「偷听敌台」，「私建电台」，已然成为抗命行为。</p>
<p>那么，Planet生成的IPFS站点有什么不同？</p>
<figure><figcaption>
            <h4>浏览器通过ENS域名访问IPFS站点的简易示意图</h4>
        </figcaption>
</figure>

<p>我们可以简单地认为IPNS代替了传统域名和DNS服务器，IPFS代替了服务器。</p>
<p>一个网站主要使用由域名与服务器构成，与传统站点不同，IPFS的域名与服务器可完全实现分布式。IPNS是IPFS生态中的一个重要组件，全称是 Interplanetary Name System，一个去中心化的类似域名的系统。IPNS可绑定在一些去中心域名，也可绑定在传统域名域名中。而由于IPFS是一个分布式文件存储系统，所以使用IPFS作为站点服务器，也就实现了服务器的分布式。</p>
<h2 id="开始使用" class="headerLink">
    <a href="#%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8" class="header-mark"></a>开始使用</h2><figure><figcaption>
            <h4>点击「Download for Mac」下载</h4>
        </figcaption>
</figure>

<p>Planet是一个开源的macOS原生App，我们通过它的<a href="https://www.planetable.xyz/" target="_blank" rel="noopener noreferrer">官網</a>与<a href="https://github.com/Planetable/Planet" target="_blank" rel="noopener noreferrer">GitHub</a>进行下载。</p>
<p>下载安装完成后，打开Planet，它会自动follow这两个站点：</p>
<ul>
<li>vitalik.eth - Ethereum 的创始人之一</li>
<li>Planetable.eth - Planet 项目的博客</li>
</ul>
<figure><figcaption>
            <h4>点击主界面下方的加号</h4>
        </figcaption>
</figure>

<figure><figcaption>
            <h4>写入名字与简介，选择模版，创建自己的Planet</h4>
        </figcaption>
</figure>

<figure><figcaption>
            <h4>点击撰写按钮</h4>
        </figcaption>
</figure>

<figure><figcaption>
            <h4>写入网志内容，并点击发布</h4>
        </figcaption>
</figure>

<p>发布完第一个篇文章之后，妳的 Planet 就会被发布为一个 IPNS。右键点击侧栏里你的站点，选择 Copy IPNS。然后你就会在剪贴板中获得像这样的一串东西：</p>
<figure><figcaption>
            <h4>Copy IPNS</h4>
        </figcaption>
</figure>

<p>k51qzi5uqu5dhxd50115dn1hfvuwiqwej3dki72uyopetqua71i6lp96pem0a6</p>
<p>然后妳把这串IPNS发给其它Planet用户，她们就可以收到来自妳的更新了。</p>
<p>妳用Planet发布的网站，也可能可以通过各种 Public Gateway 访问，比如这是你当前正在阅读的这篇文章在各个 Gateway 上的地址（URL 拼接规则是 Public Gateway 域名 + /ipns/ + Planet.ipns + / + Article.UUID）：</p>
<ul>
<li>ipfs.io</li>
<li>dweb.link</li>
<li>cf-ipfs.com</li>
</ul>
<h2 id="域名绑定" class="headerLink">
    <a href="#%e5%9f%9f%e5%90%8d%e7%bb%91%e5%ae%9a" class="header-mark"></a>域名绑定</h2><h3 id="传统域名绑定" class="headerLink">
    <a href="#%e4%bc%a0%e7%bb%9f%e5%9f%9f%e5%90%8d%e7%bb%91%e5%ae%9a" class="header-mark"></a>传统域名绑定</h3><p>绑定传统域名，需要使用的是<a href="https://docs.ipfs.tech/concepts/dnslink/" target="_blank" rel="noopener noreferrer">DNSlink</a>服务，大概的意思就是在DNS上写入txt记录，以供读取。因为使用到传统的DNS服务，所以IPNS关联到传统域名，并非是一个去中心的解决方案。</p>
<figure>
</figure>

<p>例如，绑定Planet到sogola.com主域名，</p>
<p>IPNS的地址：</p>
<p>k51qzi5uqu5dhxd50115dn1hfvuwiqwej3dki72uyopetqua71i6lp96pem0a6</p>
<p>则到域名DNS管理页上创建一个txt记录</p>
<p>设置name值为：</p>
<ul>
<li>_dnslink</li>
</ul>
<p>设置Content值为：</p>
<ul>
<li>dnslink=/ipns/k51qzi5uqu5dhxd50115dn1hfvuwiqwej3dki72uyopetqua71i6lp96pem0a6</li>
</ul>
<figure>
</figure>

<p>例如，绑定Planet到www.sogola.com二级域名，</p>
<p>设置name值为：</p>
<ul>
<li>_dnslink.www</li>
</ul>
<p>设置Content值为：</p>
<ul>
<li>dnslink=/ipns/k51qzi5uqu5dhxd50115dn1hfvuwiqwej3dki72uyopetqua71i6lp96pem0a6</li>
</ul>
<figure>
</figure>

<p>等待DNS生效，使用原生支持IPFS的Brave浏览器就可以直接访问 ipns://sogola.com/ 。</p>
<figure>
</figure>

<p>如果在DNS中添加cloudflare的IPFS gateway，也可以使用普通浏览器的访问。</p>
<h3 id="ens绑定" class="headerLink">
    <a href="#ens%e7%bb%91%e5%ae%9a" class="header-mark"></a>ENS绑定</h3><p>使用ENS绑定IPNS，就是利用Ethereum账本作为DNS账本。在ENS合约之中，将IPNS地址记录到Content Hash，这样任何人都可以访问Ethereum账本，查询相应的ENS绑定的IPNS。</p>
<p>因为设定Content Hash会是一个 ENS 合约上的操作，所以这一步会有gas fee。但是之后妳在 Planet里发布新的内容，妳的IPNS不会发生改变，也不会再有gas fee的问题。</p>
<figure>
</figure>

<p>首先，打开ENS管理页面 <a href="https://app.ens.domains/" target="_blank" rel="noopener noreferrer">https://app.ens.domains/</a></p>
<p>ipns://k51qzi5uqu5dhxd50115dn1hfvuwiqwej3dki72uyopetqua71i6lp96pem0a6</p>
<p>然后，将IPNS写入Content Hash，并确定上链。</p>
<figure>
</figure>

<p>这里有一个小tip，如果妳并不着急解析立刻失效，可自定义Max base fee和Priority fee。在metamask中打开gas fee的高级管理选项，在确认操作的时候，编辑gas fee选项即可。</p>
<p>在完成了ENS绑定之后，也可以直接用类似下面这样的地址通过Public Gateway打开妳的 ENS：</p>
<ul>
<li><a href="https://ipfs.io/ipns/sogola.eth" target="_blank" rel="noopener noreferrer">https://ipfs.io/ipns/sogola.eth</a></li>
<li><a href="https://sogola.eth.limo" target="_blank" rel="noopener noreferrer">https://sogola.eth.limo</a></li>
</ul>
<figure>
</figure>

<p>在原生支持IPFS的Brave浏览器里，你甚至可以用 ipns://sogola.eth 这样的地址直接打开妳的IPFS站点。</p>
<h2 id="关于planet的疑问" class="headerLink">
    <a href="#%e5%85%b3%e4%ba%8eplanet%e7%9a%84%e7%96%91%e9%97%ae" class="header-mark"></a>关于Planet的疑问</h2><blockquote>
<p>阅读器用自己的格式渲染原文，可以让体验更一致，及对离线阅读更友好。但对于网站的原作者，会丢失原始网站的设计及影响源网站的利益。</p>
<p>—— Livid在Planet中的发言</p>
</blockquote>
<p>使用Planet订阅Planet、IPFS站点或RSS，会自动加载站点的原生样式，这样的做法无疑是在开发一款浏览器，而非阅读器。对于读者用户来讲，这不是一个好的体验，比较kindle这样的电纸书也不会不允许读者自定义图书的样式。至于创作者的收益与读者的便利，我想肯定应该会有一个平衡点，但将阅读器重新发明为浏览器，无疑不是一种好的选择。</p>
<p>因为IPFS的特性，Planet站点使用普通域名往往访问过慢，这时候每个用户要尽可能地获得更多follower。</p>
<p>对于这一点，Livid在用户聊天群中表示：将来可以成立一个数据DAO来提供托管服务，但目前的主要工作还是完善软件、扩大用户数量。</p>
<p>Planet目前只支援macOS，至于使用更为普遍的Windows，开发者好像并没有支援计划。桌面操作系统的份额，Windows是最大，分布式网路依靠用户数量壮大才能取胜，只支援macOS与扩大节点数量是存在矛盾的，我们只能寄希望于有其它开发者会开发一款兼容Windows的客户端。</p>
<p>如果使用过程中遇到什么问题，可进入Planet的中文用户群，Livid是一位热心的开发者，他很乐意与用户交流。</p>
<p><a href="https://t.me/&#43;5bl7FIsxeChlOWIz" target="_blank" rel="noopener noreferrer">https://t.me/+5bl7FIsxeChlOWIz</a></p>
<p>最后，衷心地祝福Planet做强做大，分布式永垂不朽。</p>
<h2 id="参考资料" class="headerLink">
    <a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-mark"></a>参考资料</h2><ul>
<li>Livid的Planet <a href="https://olivida.eth.limo" target="_blank" rel="noopener noreferrer">https://olivida.eth.limo</a></li>
</ul>
]]></description>
</item><item>
    <title>《区块链实战：从技术创新到商业模式》读书笔记</title>
    <link>https://sogola.com/posts/read-blockchain-in-action/</link>
    <pubDate>Fri, 18 Mar 2022 20:12:18 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/read-blockchain-in-action/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/read-blockchain-in-action/1.png" referrerpolicy="no-referrer">
            </div><p>西元2009年，bitcoin诞生，它是全球第一条真正可运行的区块链。</p>
<p>虽然我很早就知道了bitcoin，但关于blockchain，我知道的不多。那时候，有人在 twitter上宣称用电脑挖了几十个bitcoin，要免费赠送，可并没有人去领取。</p>
<p>直到2012年，bitcoin的价格已经足够吸引人，所以和所有人一样，我也怀揣着不劳而获的梦想，妄图使用我的Mac进行挖矿，奈何我的技术太菜，没能成功安装挖矿软件。</p>
<p>于是，我另辟蹊径，找到了一个只有点击广告就可以领取bitcoin的网站。每天点几次广告，只需要几分钟，我连续点了几天，领取了很少很少的bitcoin。就这点当年价格为几美分的bitcoin，居然可以在价格高位的时候有500多米元。</p>
<p>随着国朝封禁加密通证的交易，通证的交易已然成了一种被禁忌的游戏。禁忌意味着最原始的冲动，我最终还是没有按耐住寂寞，于前段时间注册了交易所，将个资上交，成为一名韭菜。在交易所，我将我的BTC置换成了ETH。</p>
<blockquote>
<p>区块链行业最常见的一种焦虑叫作FOMO（Fear Of Missing Out，即错失恐惧症），也就是担心错过了最佳的进入时机。一些投机者往往会利用人们的这种心理过度营销，蛊惑人们赶紧投入他们的“游戏”。破除这种焦虑的最佳方法就是对行业有足够深广的了解，建立自己的思考原则，寻找正确的参考资料。如果你恰好在读这本书，恭喜你——你大概率选择了正确的方向。</p>
</blockquote>
<p>去年以来，bitcoin从高位价格被腰斩，但它的价格仍足以让人狂热。一个合格的韭菜，必须要抵制FOMO情绪。</p>
<blockquote>
<p>传统平台的网络建设成本很大程度上消耗在选择、审查、维护可靠的节点和网络上，而区块链平台的网络运行成本主要消耗在计算上，因此有人说，区块链的世界是因为大家的信仰建立在对数学（算法）的信任之上。以比特币为例，其基于工作量证明的共识算法非常消耗电力资源，但如果按同等规模与一个银行的系统比较，会发现实际上比特币的设备和耗电成本可能低于整个银行系统运行IT系统的成本。</p>
</blockquote>
<p>坦率地讲，我始终认为BTC的价格超过10米元就是水分。但《区块链实战》认为BTC作为一种现金系统，它所消耗的能源所提供的服务，比非区块链技术所消耗的能源更少，这意味着对BTC浪费能源的污蔑是无效的。</p>
<blockquote>
<p>区块链是一种数据库，而且是一种分布式数据库。</p>
</blockquote>
<blockquote>
<p>自主账户体系更像是计算机系统产生之前的社会，我们每个人生而为人并不需要其他人和机构来证明。在现代文明社会，每个人的权利无须其他任何人赋予，因为人作为个体，其身份是自主的，也就是我们不需要任何其他人或者机构的“证明”、“认证”或“承认”，我们就是一个独立的个体。</p>
</blockquote>
<p>为什么加密技术如此迷人？因为它创制了一种去中心的网路，虽然稚嫩，但足以让我们看见了摆脱互联网资本寡头所控制的账户系统的星星之火。</p>
<p>暂且不谈加密通证交易的投机问题，仅考察区块链的技术瓶颈，我认为区块链技术目前有两大难点：</p>
<ol>
<li>TPS（每秒事务处理量）过低</li>
<li>储存量过低</li>
</ol>
<blockquote>
<p>即使在如此中心化的规则下，EOS从未达到百万级TPS的目标。目前，EOS主网经确认最快TPS为3 996，而在2019年天猫双十一狂欢节，支付宝自主研发的分布式数据库OceanBase每秒处理峰值达到6 100万次。自2018年6月15日主网上线以来，EOS出现了超级节点互相投票、抱团竞选的勾结现象，频发安全漏洞、治理问题，让业界对“EOS成为中心化倾向严重的伪公链”的预言成真。由EOS开启的一味追求高TPS的公链竞赛，为区块链技术和行业的健康发展带来了一定的消极影响。</p>
</blockquote>
<p>首先，关于TPS。《区块链实战》认为TPS是一个伪问题，因为区块链目前的应用不需要高TPS，而且高TPS与去中心化不兼容。其次，关于储存量过低，《区块链实战》认为并非所有数据都要上链，关键数据上链即可。</p>
<p>坦率地讲，我并不太认可《区块链实战》的说法。此书作者系某链的资本家，有广告嫌疑，其说法涉嫌为区块链资本进行恶意辩护。为了验证我的理论，我们有必要将zeronet项目与当下的区块链行业项目进行比对。</p>
<p>zeronet使用加密技术构建了账户系统，其账户系统使用 bitcoin技术，仅需要创制一个钱包地址。创制钱包地址不需要gas费，只有对账户所有者进行捐助才需上链，其它行为无需上链。zeronet的前端使用类bt的p2p，将整个前端与后端的数据库彻底分布式储存在用户终端，无需中心化的各种云服务商。</p>
<p>zeronet的做法，等于超越了区块链的应用范式，在zeronet的世界里，不存在TPS的问题。数据在用户终端的分布式储存的要义：所有数据归根结底储存了用户自己的终端，无需等待服务器的响应。用户在本地删改文件之后，通过类bt协议同步到友好的用户终端，因此zeronet成为一个异步网路。</p>
<p>反观各类区块链项目，从ETH基金会的etherscan，再到近久火热的opensea，其前端需要中心化的服务器，后端全部为链上数据。这种做法的后果，用户与在web2中一样有被审查的风险；后端数据全面上链导致TPS不够用，用户越多、越活跃，那么上链费用就愈加昂贵。</p>
<p>目前zeronet已然处于停滞状态，违背分布式理念的各类区块链项目却大行其道，令人唏嘘。那么，我们可以说《区块链实战》的作者是恶意传销。</p>
<p>对于解决区块链的储存量过低问题，有一个名为filecoin的项目值得关注。此项目是在ipfs协议构建一套激励机制。IPFS全称InterPlanetary File System，国文翻译应该是星际文件系统。</p>
<p>这个文件系统是针对HTTP而提出，HTTP全称为Hypertext Transfer Protocol，国文翻译应该是超文本传输协议，它是是互联网使用最为广告的网路协议，主要为解决两台通过链接互联网的主机传输文件而提出来的传输协议。ipfs为文件寻址，http为地址寻址。</p>
<p>HTTP协议创制于互联网早期，互联网先民并未想到这种协议会导致web站点的集中化趋势，而这个趋势与互联网的初衷相违背。互联网，internet，始建于北米军工复合体，它的发明是为了解决中心化的不能抗打击能力，分散化的网路可以有效抗击核子武器的攻击。</p>
<p>但web2的风潮，乃至其后诞生的云服务厂家，导致用户终端再也无法变为服务器，服务器变为巨头垄断的资产，所有网民都成为地主的佃农或农奴，要不交租，要不卖身为奴。</p>
<p>这与互联网的理内置理念完全相反。</p>
<p>如果从IPFS的远景来思考，IPFS要打造的系统为星际文件，而当下的互联网也不具备人类迈向太空时代的条件，因为当下的互联网是及时行乐，它要求人们当下消费当下满足。总之，要求进行及时传输的同步互联网无法进行火星与地球之间的互联网通讯。</p>
<p>我认为IPFS的最大问题在于它使用类git的方式进行版本控制，虽然git可以有效控制版本进行数据回滚等操作，IPFS有效地继承了这些优势，又有效地综合了BT、电驴等去中心化网路的优点，这是它的伟大创新 <del>，但是呢，我们都知道文件管理的要义在要及时去除冗余，降低储存成本，可IPFS没有删除功能，这导致在filecoin所建构出来IPFS网路上的垃圾数据越来越多，以至很多人都认为它只储存垃圾数据</del> (事实上，IPFS有文件回收机制，一个文件在一定时间内不被再读取，就会被本地客户端放弃，但这依然不能让用户简单地解决持续一个站点的最新文件在本地，但又不想保存冗余的过失文件)。</p>
<p>随着俄乌战争的进行，世界正在从新冷战转为新热战，单一主权国家的互联网随时离线成国家局域网状态。朝鲜就是例子，而俄国与印度也早已试验性切断与国际互联网的连接，这种切断不影响本国之内的通讯。在可预见的未来，单一主权国家只进行内部联网通讯的风险越来越大。</p>
<p>所以，无论从互联之理念，还是从考察当下主权国家之间的冲突，又或从人类必然走向的星际殖民的前景来看，当下这种及时同步的互联网是反动的，必须进行变革。</p>
<p>假定好的互联网应该建构在区块链之上，那么我们需要哪一种区块链呢？目前的区块链分为POW（工作量证明）工作机制与POS（权益证明）工作机制，且看《区块链实战》一书给出的介绍：</p>
<blockquote>
<p>工作量证明是一种应对服务与资源滥用，或是拒绝服务攻击的经济对策。一般要求用户进行一些耗时适当的复杂运算，并且答案能被服务方快速验算，以耗用的时间、设备与能源作为担保成本，来确保服务与资源是被真正的需求使用。这一概念最早由辛西娅·德沃克和莫尼·瑙尔于1993年发表的学术论文中提出，被用于经济领域统计。“工作量证明”一词由马库斯·雅各布森与阿里·尤尔斯在1999年计算机反垃圾邮件系统实现中提出。现在，工作量证明成为以比特币为代表的加密货币或区块链的主流共识机制。</p>
<p>权益证明（又称持有量证明）是2012年出现的共识机制。与要求验证者执行一定量的计算工作的工作量证明不同，权益证明要求一组验证者轮流对下一个区块进行提议和投票，每个验证者的投票权重取决于其持有权益证明的多少。权益证明的显著优势在于具备安全性，降低集中化的风险以及提升能效。</p>
</blockquote>
<p>关于POW，我有几个思考。</p>
<p>首先，面对断网，BTC无力解决，BTC需要的是同步的互联网，节点的出块必须及时告知其它节点，那这种电子现金网路最大应用范围只能是地月系统。</p>
<p>其次，BTC出块是靠算力来运行一个数学难题。从目前的发展结果来考察，我们会发现BTC的矿工呈现出规模化资本的状态，那我们可以断言BTC的网路与亚马逊云的不同之处在于亚马逊云控制在单一寡头手中，而BTC控制在众多矿业资本家手中。两个模式，不过是资本控制联网的两个方式罢了，并没有本质上的区别。靠算力进行权益奖励必然导致资本化，这已经是毋庸置疑的历史事实了。</p>
<p>最后，如果人类还会继续发展，没有放弃共产主义，那么通用型的量子计算机总会出现，到那时，BTC的网路如何依靠算力来计算权益将面临巨大挑战。</p>
<p>综上所述，我个人认为POW机制会被历史终结。</p>
<p>我目前最大的疑问：一个单独运行的设备在不与其它设备通信的情况下，是否能自行进行某种奖励的获取，再其稍后或延迟通讯之后，这种奖励可以获得其它设备的认可。POS或POW，哪种奖励机制能做到这一点？</p>
<p>最后，抛开《区块链实战》一书的广告部分，此书全面介绍了区块链的相关知识，书中还有智能合约部分的介绍也很意思，我认为这本书值得一读。</p>
<p><strong>注：</strong> 本文引用部分皆来自《区块链实战：从技术创新到商业模式》一书</p>
<p><strong>《区块链实战》豆瓣链接：</strong> <a href="https://book.douban.com/subject/35117863/" target="_blank" rel="noopener noreferrer">https://book.douban.com/subject/35117863/</a></p>
]]></description>
</item><item>
    <title>關於《一个农民工思考海德格尔是再正常不过的事》的一點點想法</title>
    <link>https://sogola.com/posts/a-migrant-worker-read-heidegger/</link>
    <pubDate>Mon, 22 Nov 2021 18:57:00 &#43;0800</pubDate><author>
        <name>王小嗨</name>
    </author><guid>https://sogola.com/posts/a-migrant-worker-read-heidegger/</guid>
    <description><![CDATA[<div class="featured-image">
                <img src="/images/a-migrant-worker-read-heidegger/1.jpeg" referrerpolicy="no-referrer">
            </div><h2 id="一" class="headerLink">
    <a href="#%e4%b8%80" class="header-mark"></a>一</h2><p>這兩天在微信朋友圈很多轉發騰訊資本控股的「穀雨實驗室」所刊發的<a href="https://mp.weixin.qq.com/s/5bjMfqgqEZNGr8ZHaRzGuA" target="_blank" rel="noopener noreferrer">《一个农民工思考海德格尔是再正常不过的事》</a>，本呆迷發現了一個有趣的誤認。</p>
<p>一個朋友誤認為文中受訪者提到的「清湖務工圖書室」是由「清湖學堂」開辦的，這裏有必要澄清一下，很抱歉，這個圖書室是官辦的，並不是「清湖學堂」開辦的。這圖書室從小北門出來就可以看到，在村里非常醒目。</p>
<p>事實上，「清湖學堂」在村里的小巷子裡，招牌小，非常難找。我第一次去參加活動，笨呆路癡，導航找不過去，問了來來往往很多人，都說沒聽過這個名字。工時長，身體乏，各式手機娛樂佔有休息時間，能有多少前線工人會留意到「清湖學堂」的活動呢？我不知，反正我有參加過幾次免費英文培訓班，外國老師讓自我介紹，大部分學員都是文員之類的，而非前線工人。</p>
<p>當然，如果文中受訪者是「清湖學堂」的「工友」，那就更好理解了。且不論這些反動哲學與《治國理政》到底有何區別，難道這類哲學與升官發財不是同一種意識形態的不同面向嗎？參加「清湖學堂」的朋友，很多人難道不是為了更好地晉升嗎？</p>
<p>哲學可以成為革命的武器，也可以變為麻醉人民的鴉片。文中受訪者的學哲學與升官發財，大概可以算作殊途同歸了。</p>
<p>此外，我有留意到受訪者說很嫌棄對岸用語，諸如「軟體」之類。我也有同事告訴我，她沒緣由很討厭傳統儒字，既使自己可以讀懂。在這裡，被剝削的身體生產了抵抗的無意識，而毋需「清湖學堂」們的教誨。</p>
<h2 id="二" class="headerLink">
    <a href="#%e4%ba%8c" class="header-mark"></a>二</h2><figure>
</figure>

<p>十幾年前，我進入家鄉一間小食品廠做工。每日清晨六點起床，媽媽早就給我準備好了早餐，我匆匆吃完，去趕公交。在車間，我面對巨大的機器，還有流水線，不知所措。帶我的小姐姐，教我怎麼做工，怎麼玩手機不被班長發現。</p>
<p>工閒時，我與前面工位的一位大哥聊老闆與工廠的關係，他說老闆死掉了，工廠可以照常運轉。下班後，天色早已漆黑，我拖著一身酸臭去等公交，我的小姐姐騎電瓶車路過，說要載我回家，我羞澀地說謝謝，不用了。</p>
<p>那時，我剛接觸馬克思主義，白天做工，晚上回家看徐禾的《政治經濟學概論》，越讀越興奮，原來資本家是這樣剝削工人的。直到深夜一兩點，合上書，我拿出mp3，聽著張廣天老師的歌，沉沉地失去意識。</p>
<p>後來，我又輾轉到了家鄉港口做保安。不許玩手機，我就拿著小紙條被單詞。休息時間，和遠方的同志聊馬克思，聊毛主席，聊精神分析和哲學，聊我們的過去和未來。仿佛世界就在眼前展開，即便我是一個辦公樓前的保安。</p>
<p>後來，去昆明唸書，很多朋友都說我的故事很勵志，保安去哲學系唸書，簡直是資本主義的神話。可這樣的經歷並沒有讓我欣喜，反而讓我更加認識到資本主義所提供的改變可能是多麼虛假，哲學系的老師有多無聊。</p>
<p>許多朋友都微信朋友圈討論騰訊穀雨那篇文中的哲學愛好者，我並不覺得業餘時間讀哲學有什麼神奇，這不過和打遊戲一樣，也是一個很平常的愛好。</p>
<p>每個真實都可以有許多敘事可能，比如妳說因為日常生活沒有改變的可能，一個工人在遊戲中開啟主體的行動性，從而開啟了改變的可能。坦率地說，這僅僅是一種意識形態說詞。</p>
<p>可問題在於，我們應該如何看到真實的實在，誰在創造財富，誰又在剝削。如果僅僅是業餘時間讀哲學，我不覺得這和業餘時間打遊戲有什麼區別。</p>
<p>相較大家更多討論地所謂「文化資本」與「階級凝視」，我個人認為谷雨受訪者所表達想進入學院專職做哲學意識形態工作者的想法更為有趣，這種想法顯然是一種資本主義價值敘事的典範。</p>
<p>一個移工對周遭世界與生活產生了困惑，不去讀馬列主義毛澤東思想，反而去讀學院裡的經院哲學，這不僅得不到任何答案，對自身的處境也並無益處。</p>
<p>從工人到哲學意識形態工作者，還是工人到有機知識分子，好像並沒有所謂的「左派」關心這個論點。</p>
<p>回到我自己，十多年來，我從工人到工人，經歷了發現新世界的欣喜，也有被背叛的幻滅。曾經的同志已然漸行漸遠，不過是一拍兩散。帝國的旗幟迎風飄揚，各自珍重，狗命要緊。</p>
]]></description>
</item></channel>
</rss>
