
自從上年11月開始推出小U自家的OpenWRT路由器以來,預載的Tailscale版本竟然一直停留在1.58版本,而官方版的Tailscale截至今日已經升級到1.68.2 計算小版本的話升級不止10次,但OpenWRT官方Package依然停留1.58。到底爲什麼會這樣?OpenWRT如何升級Tailscale。又是20分鐘快速文章,如有不足,敬請見諒。
什麼你還未有OpenWRT路由器?趕緊看看:
摘要節點
OpenWRT中的 Tailscale update 爲什麼這麼難?
OpenWRT是由社群維護的系統,Tailscale的套件爲什麼一直停留在半年,小U就沒有確實答案,但估計可以歸根是套件的維護者沒有更新,而又沒有新的志願者接過任務。
但其實Tailscale本身的執行程式Binary是包含了更新指令 tailscale update。在Linux系統,只需要執行 tailscale update,就可以自動升級tailscale版本。但爲什麼在Openwrt中會報錯:
opkg error: No space left on device #磁盤空間不足,無法升級
Openwrt 中的Tailscale 和“原生”的不同
仔細分析,小U發現 tailscale update 會自動按照平台(x86 / arm etc…) 抓取最新的程序壓縮包,用 1.68.1版本爲例,解壓縮這個升級壓縮包,發現裡面的程式竟然有50MB左右的大小:

那怪不得在儲存空間十分有限的無線路由器,會顯示空間不足。只有128MB ROM的Ups-WR30U (小米WR30U)爲例,本來可用空間就只有 ,那這個官方包當然是放不進去的。(有好幾十GB空間的軟路由例如Ups-Dragon和Ups-R2S就可以用tailscale update 順利升級)

那問題來了,原本OpenWRT PACKAGE裡面提供的那個Tailscale是如何裝上去的?
找到OpenWRT 正在運行的Tailscale執行文件,竟然只有20MB,比官方的小了一半不止:

而且Linux用戶還會發現一個奇怪的地方,在 tailscale update 下載的壓縮包中,tailscale 和 tailscaled 兩個執行程序是不同大小的,而在OpenWRT中,tailscale 是來自 tailscaled 的“鏈接”,類似Windows中的快捷方式,也就是兩個程式是完全相同的??!!
如何縮減Tailscale體積
順藤摸瓜,找到Tailscale官方有提到如何壓縮Tailscale運行程式的方法,針對 OpenWRT 這類型容量有限的嵌入式設備:
Smaller binaries for embedded devices · Tailscale Docs
文章介紹了縮減體積的幾個步驟:
首先,Tailscale 允許將客戶端 (tailscale)和守護進程 (tailscaled)合併為單一二進制文件,類似於 busybox 的工作方式。使用此標誌可以從建置的二進制文件中省略調試信息和較少使用的功能。最後,使用 UPX壓縮 可將 Tailscale 二進制文件的大小從 23MiB 壓縮至 4.5MiB,約為原始大小的 20%。这样的构建方式对于嵌入式设备(如OpenWrt路由器)非常有用,因为它可以节省磁盘空间。
UPX(Ultimate Packer for Executables)是一個免費且開源的可執行文件壓縮工具,支持來自不同操作系統的多種文件格式。它的主要特點是高壓縮比,可以在保持可執行功能的同時大幅節省存儲空間。UPX 通常可以將程序和 DLL 文件的大小減少約 50% 到 70%,從而降低磁盤空間、網絡加載時間、下載時間以及其他分發和存儲成本。使用 UPX 壓縮的程序和庫是完全自包含的。
這和我們在Openwrt上看到的情況完全一樣:tailscale 和 tailscaled 被合併了一個執行Binary。也就是說,我們能按照以上的方法,自行把最新版本的Tailscale文件壓縮並替換到Openwrt裡面,就可以升級了!
但是,人手去進行以上步驟,需要你十分熟悉GO語言的編譯環境,以及使用UPX壓縮工具,這對於新手來說都十分勸退。有沒有可以站在巨人肩上的方法?
使用現成的已壓縮的TAILSCALE程式
GL.iNet 的論壇志願者 Admon 就設計了一套在GL.iNet路由器上用的Tailscale “迷你瘦身”升級版程式。此程式包含一個一鍵升級腳本,會自動抓取這個Github倉庫最新版本的Tailscale“迷你瘦身版”。
但是我們無需用到GL.iNET的任何相關腳本和設定,我們只要Tailscale“迷你瘦身版”就可以手動將Openwrt的Tailscale版本升級。因此,所有牌子的OpenWRT路由器,都可以受惠到以下這個升級方法。
手動升級OpenWRT TAILSCALE的方法
第一步,我們下載最新版本的已壓縮的TAILSCALE程式
因爲 Ups-WR30U 和 Ups-AX6000 都是linux-arm64架構的,所以下載這一個 binary程式:
Releases · Admonstrator/glinet-tailscale-updater (github.com)
沒有用過Linux的用戶會好奇爲什麼沒有 .exe 的結尾,在Linux中是沒有的,可以直接執行。

第二步:我們要仿照OpenWRT的已有Tailscale
重命名 tailscaled-linux-arm64 爲 tailscaled。
第三步:停止現在Tailscale 的運行
到 System -> Startup -> Tailscale STOP

第四步:上傳 tailscaled 覆蓋原有的 tailscaled
使用 WinSCP 或 Finalshell 上傳壓縮瘦身版本的 tailscaled

最後重啓路由器,這時候執行 tailscale status 就會顯示是 1.68.1 版本。
暫時測試沒有發現壓縮版有何問題。
使用這個第三方Tailscale程式安全嗎?
小U不對任何第三方軟體做擔保,請大家自己分析衡量。以下是小U的分析:
這個壓縮版的Tailscale是透過以下的github action 自動排程編譯腳本自動生成的,解釋如下:
name: Build smaller Tailscale binary
on:
schedule:
- cron: '30 0/12 * * *'
workflow_dispatch:
env:
SOFTWARE_NAME: "Tailscale"
FILE_NAME: "tailscaled"
REPO: "tailscale/tailscale"
REPO_SMALL: "Admonstrator/glinet-tailscale-updater"
GIT_AUTHOR_NAME: "Admonstator"
jobs:
check-versions:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
TAG: ${{ steps.tag.outputs.TAG }}
TAG_SMALL: ${{ steps.tag_small.outputs.TAG_SMALL }}
steps:
- name: Get latest ${{ env.SOFTWARE_NAME }} tag
id: tag
run: |
latest_tag=$(
curl -s "https://api.github.com/repos/${{ env.REPO }}/releases" \
| jq -r 'sort_by(.published_at) | last | .tag_name'
)
echo "TAG=$latest_tag" >> "$GITHUB_OUTPUT"
echo "Latest ${{ env.SOFTWARE_NAME }} Tag: $latest_tag"
- name: Get latest ${{ env.SOFTWARE_NAME }} Small tag
id: tag_small
run: |
latest_tag_small=$(
curl -s "https://api.github.com/repos/${{ env.REPO_SMALL }}/releases/latest" \
| grep -oP '"tag_name": "\K(.*)(?=")' || echo ""
)
echo "TAG_SMALL=$latest_tag_small" >> "$GITHUB_OUTPUT"
echo "Latest ${{ env.SOFTWARE_NAME }} Small Tag: $latest_tag_small"
build:
runs-on: ubuntu-latest
permissions:
contents: write
needs: check-versions
if: needs.check-versions.outputs.TAG_SMALL != needs.check-versions.outputs.TAG
env:
TAG: ${{ needs.check-versions.outputs.TAG }}
strategy:
matrix:
go-version: [stable]
os: [linux]
platform:
- amd64
- arm
- arm64
- mips
- mipsle
steps:
- name: Checkout ${{ env.SOFTWARE_NAME }} repository
uses: actions/checkout@v4
with:
repository: ${{ env.REPO }}
ref: ${{ env.TAG }}
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Download Go modules
run: go mod download
- name: Cross-compile
run: |
GOOS=${{ matrix.os }} GOARCH=${{ matrix.platform }} ./build_dist.sh \
--extra-small --box \
-o "${{ env.FILE_NAME }}-${{ matrix.os }}-${{ matrix.platform }}" ./cmd/${{ env.FILE_NAME }}
- name: Upload built binary
uses: actions/upload-artifact@v4
with:
name: ${{ env.FILE_NAME }}-${{ matrix.os }}-${{ matrix.platform }}
path: ./${{ env.FILE_NAME }}-${{ matrix.os }}-${{ matrix.platform }}
publish:
runs-on: ubuntu-latest
permissions:
contents: write
needs:
- build
- check-versions
if: needs.check-versions.outputs.TAG_SMALL != needs.check-versions.outputs.TAG
env:
TAG: ${{ needs.check-versions.outputs.TAG }}
steps:
- name: Get UPX latest version
id: get-upx-version
run: |
echo "UPX_VERSION=$(
curl -s https://api.github.com/repos/upx/upx/releases/latest \
| jq -r '.tag_name' \
| cut -c 2-
)" >> "$GITHUB_ENV"
- name: Download UPX
run: |
wget -q "https://github.com/upx/upx/releases/latest/download/upx-${{ env.UPX_VERSION }}-amd64_linux.tar.xz"
tar --to-stdout -xf "upx-${{ env.UPX_VERSION }}-amd64_linux.tar.xz" \
"upx-${{ env.UPX_VERSION }}-amd64_linux/upx" > "${PWD}/upx"
chmod -v +x "${PWD}/upx"
- name: Download built binaries
uses: actions/download-artifact@v4
with:
pattern: ${{ env.FILE_NAME }}-*
- name: Moving files
run: |
for dir in "${{ env.FILE_NAME }}-"*; do
mv -v "${dir}" "${dir}.d"
mv -v "${dir}.d/${{ env.FILE_NAME }}-"* .
rmdir -v "${dir}.d"
done
chmod -v +x "${{ env.FILE_NAME }}-"*
- name: Compress Binary with UPX
run: |
"${PWD}/upx" --lzma --best --no-progress "${{ env.FILE_NAME }}-"*
- name: Create checksums
run: |
sha256sum "${{ env.FILE_NAME }}-"* > "checksums.txt"
- name: Create version file
run: |
echo "${{ env.TAG }}" > "version.txt"
- name: Checkout ${{ env.SOFTWARE_NAME }} Small repository
uses: actions/checkout@v4
with:
path: tools
repository: ${{ env.REPO_SMALL }}
- name: Create tag in ${{ env.SOFTWARE_NAME }} Small repository
run: |
cd tools
if git rev-parse --quiet --verify "refs/tags/${{ env.TAG }}"; then
echo "Tag already exists"
exit 0
else
echo "Tag does not exist, creating"
git tag "${{ env.TAG }}"
git push --tags
fi
- name: Create Release
if: github.ref == 'refs/tags/${{ env.TAG }}'
uses: ncipollo/release-action@v1
with:
name: Small ${{ env.SOFTWARE_NAME }} ${{ env.TAG }}
tag: ${{ env.TAG }}
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
prerelease: false
artifacts: |
${{ env.FILE_NAME }}-*
checksums.txt
version.txt
body: |
Small ${{ env.SOFTWARE_NAME }} build ${{ env.TAG }}
For a complete changelog go to https://github.com/${{ env.REPO }}/releases/tag/${{ env.TAG }}
This release was created by:
* Building a combined binary of `tailscale` and `tailscaled`
* Using the build option `--extra-small`
* Compressing the binary with UPX
To use both programs, rename `tailscaled-OS-ARCH` to `tailscaled` and create a symbolic (`ln -sv tailscaled tailscale`)這段GitHub Actions的工作流程文件,旨在建立一個更小的Tailscale二進制文件。這是一個自動化的流程,包含定期檢查Tailscale和精簡版Tailscale的最新版本,並在發現新版本時進行編譯、壓縮和發佈。以下是對該流程的詳細說明:
首先,在時間表和手動觸發條件下執行工作流程。時間表設定為每12小時執行一次(CRON表達式:’30 0/12 * * *’)。
環境變量部分定義了各種所需的參數,包括軟體名稱、文件名稱、版本庫等。
任務1:check-versions
這個任務檢查兩個版本庫中最新的發佈版本。
- Get latest Tailscale tag:使用GitHub API獲取最新的Tailscale標籤(tag)。
- Get latest Tailscale Small tag:同樣地,獲取精簡版Tailscale的最新標籤。
任務2:build
這個任務負責編譯最新版本的Tailscale。
- Checkout Tailscale repository:檢出Tailscale版本庫的最新標籤。
- Setup Go:設置Go語言環境。
- Download Go modules:下載Go模組。
- Cross-compile:交叉編譯Tailscale,生成不同平台的二進制文件。
- Upload built binary:上傳編譯後的二進制文件。
任務3:publish
這個任務負責壓縮和發佈編譯後的二進制文件。
- Get UPX latest version:獲取最新版本的UPX(用於壓縮二進制文件)。
- Download UPX:下載並設置UPX。
- Download built binaries:下載之前編譯好的二進制文件。
- Moving files:移動和重命名文件。
- Compress Binary with UPX:使用UPX壓縮二進制文件。
- Create checksums:創建文件校驗和。
- Create version file:創建版本文件。
- Checkout Tailscale Small repository:檢出精簡版Tailscale版本庫。
- Create tag in Tailscale Small repository:在精簡版Tailscale版本庫中創建標籤。
- Create Release:在GitHub上創建新的發佈版本,包含編譯和壓縮後的二進制文件。
這個工作流程通過自動化編譯、壓縮和發佈過程,確保Tailscale的最新版本能夠快速有效地交付給用戶。
本文是小U的「玩開源、從OpenWRT開始」系列文章的其中一篇。自從Ups-WR30U開源路由器得到大家的熱烈支持,小U也收到了客戶的各種使用OpenWRT的問題查詢,順勢就着手把大家會遇到的,想要用的,都集結成這個系列的文章,希望讓各位從OpenWRT體驗和玩樂開源系統。不需要靠AI,你就能讓路由器變得更”聰明“!
- OpenWRT路由器WiFi名、密碼、速度的設定教學
- OpenWRT使用TailScale VPN教學
- 擋廣告神器「AdguardHome」在OpenWRT上使用方法教學
- 用OpenWRT劃分出訪客Guest LAN、隔離外網伺服器的兩種方法(不是無線訪客WIFI)
- OpenWRT防火牆:限制IP訪問Internet的最佳設置方法(無需打命令行)
- 一鍵連回家里內網:OpenWRT上部署Wireguard VPN服務器的三個要點、減少折騰時間
如果你還未有OpenWRT路由器,不妨從 Ups-WR30U 上手吧:




