0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenWrt の Tailscale アップデートスクリプト

Last updated at Posted at 2024-10-06

TL;DR

この記事は、フラッシュメモリの容量がそこそこ(潤沢でも極少でもない)の OpenWrt 機器で Tailscale のアップデートをするための手順です。
(具体的には、 df -h /overlay での Size 表示が、 40MB ~ 80MB の OpenWrt 機器を想定しています。)

より厳しい容量環境下の場合、以下の記事を参考にしてください。

  1. Tailscale をインストールすると、ほとんど空き容量に余裕がなくなる → OpenWrt で縮小版 Tailscale を使用する
  2. Tailscale をインストールしなくても、10MB 程度の空き容量しかない → フラッシュメモリの空き容量が 10MB しかない OpenWrt で Tailscale を使用する

この記事の概要

フラッシュメモリの空き容量に余裕があれば、 OpenWrt 機器でも tailscale update で簡単に Tailscale のアップデートができるのですが、多くの OpenWrt 機器では tailscale update を実行するのに必要なフラッシュメモリがありません。

そこで以下の手順を実行するコードを作成したので紹介します。

  1. Tailscale の停止 ( service tailscale stop の実行)
  2. バイナリファイルを削除 ( /usr/sbin/tailscale , /usr/sbin/tailscaled の削除)
  3. https://pkgs.tailscale.com/stable/#static から tgz ファイルをダウンロード
  4. tgz ファイルを解凍しバイナリファイル ( tailscale , tailscaled ) を /usr/sbin/ に保存
  5. Tailscale の再開 ( service tailscale start の実行)
参考にしたコード

もともとは @myurar1a さんが書かれたコードを使って Tailscale のアップデートをしていたのですが、 Tailscale 再開時のオプション指定は不要なため、そこを考慮して @hide_seki さんが書かれた改良部分を取り入れてアップデートしました。

手順としては、Perplexity に相談しながらコードを書き、最終的には GPT-4o に英文への翻訳・校正とリファクタリングをしてもらっています。🎉

👉 公式のアップデート手順の `tailscale update` を実行し、 `no space left on device` が表示されてしまった場合の対応手順 😱

以下のコマンドを実行

rm /root/.cache/tailscale-update/tailscale*.tgz
rm /usr/sbin/tailscale*.new

ファイルの削除前後に df -h を実行して、空き容量が回復することを確認してください。🎉

注意事項

  • 今回のコードは 64-bit ARM CPU でしか動作しません。
    64-bit ARM CPU に限定した理由は以下の通り。

    • MIPS 系の CPU では Tailscale の実行は重すぎるはずなので、MIPS 系の CPU は除外
    • 32-bit ARM CPU は世代的に古く、現行の MIPS 以上に演算能力が低いので、こちらも除外
    • AMD64 の CPU であれば、tailscale update が実行できる程度に容量に余裕があるはずなので、これも除外

  • Tailscale を使って SSH 接続していても今回のコードの実行はできますが、以下の表示が出た後 1 分程度反応がなくなるはずです。
    (Subnet route 経由でも同様です。)

    👉 service tailscale stop が実行された時点でいったん接続が切れますが、そのまま待っていれば回復するはずです。

    logpolicy: using system state directory "/var/lib/tailscale"
    dns: [rc=unknown ret=direct]
    dns: using "direct" mode
    dns: using *dns.directManager
    dns: inotify addwatch: context canceled
    linuxfw: clear ip6tables: exec: "ip6tables": executable file not found in $PATH
    flushing log.
    logger closing down
    

  • コードの最後で実行される tailscale set --auto-update=false によって、 Tailscale の自動アップデートを無効化しています。

    👉 auto-update を無効化する理由は、 Auto-updatesOn/OffTailnet ごとに設定されるため、誤って適用されてしまい、知らないうちに no space left on device となってしまうことを避けるためです。

  • curljq も使っていないので、素の OpenWrt で動作します。🎉

使用方法

以下のコードを

  1. /etc/config/update_tailscale.sh に保存して
  2. chmod +x /etc/config/update_tailscale.sh で実行権限を付与します
#!/bin/sh

ARCH=arm64

# Determine if the device is running OpenWrt by checking for the existence of `/etc/openwrt_release`
openwrt_exists=false
if [ -f /etc/openwrt_release ]; then
  openwrt_exists=true
fi

# Determine if the CPU architecture is ARM64 by checking if `aarch64` is part of `uname -a` output
is_arm64=false
if uname -a | grep -q 'aarch64'; then
  is_arm64=true
fi

# Verify compatibility: Must be an OpenWrt device running on a 64-bit ARM CPU
if [ "$openwrt_exists" = false ] || [ "$is_arm64" = false ]; then
  echo "This program can only be executed on OpenWrt devices running on 64-bit ARM CPUs."
  exit 1
fi

API_URL="https://api.github.com/repos/tailscale/tailscale/releases/latest"

# Retrieve the currently installed Tailscale version
current_version=$(tailscale version | head -1)
echo "Current Tailscale version: $current_version"

# Fetch the latest available Tailscale version
latest_version=$(wget -q -O - "$API_URL" | sed -n 's/.*"tag_name":"v\([^"]*\)".*/\1/p')
echo "Latest Tailscale version: $latest_version"

# Compare versions and handle the update process
if [ "$current_version" = "$latest_version" ]; then
  echo "You are already using the latest Tailscale version ($latest_version)."
  exit 0
fi

package_name="tailscale_${latest_version}_${ARCH}"
package_url="https://pkgs.tailscale.com/stable/${package_name}.tgz"

# Check availability of the latest package
if wget --spider "$package_url" 2>/dev/null; then
  echo "An update to Tailscale $latest_version is available."
else
  echo "The latest version $latest_version is not available."
  exit 0
fi

# Prompt the user for an update confirmation
echo "Do you want to update? (y/n)"
read -r answer
case $answer in
  [nN])
    echo "Update canceled."
    exit 0
    ;;
  *)
    echo "Proceeding with the update."
    ;;
esac

# Uninstall current Tailscale
echo "Uninstalling current version of Tailscale..."
service tailscale stop
rm /usr/sbin/tailscale /usr/sbin/tailscaled
echo "Uninstall complete."

# Download the latest package
echo "Downloading Tailscale $latest_version..."
wget "$package_url" -O /tmp/tailscale.tgz

echo "Extracting package..."

# Install the new version
echo "Installing Tailscale $latest_version..."
tar zxvf /tmp/tailscale.tgz ${package_name}/tailscale -C /tmp
cp /tmp/${package_name}/tailscale /usr/sbin
rm -r /tmp/${package_name}

tar zxvf /tmp/tailscale.tgz ${package_name}/tailscaled -C /tmp
cp /tmp/${package_name}/tailscaled /usr/sbin
rm -r /tmp/${package_name}

rm /tmp/tailscale.tgz

echo "Installation complete."

# Start and configure Tailscale
service tailscale start
tailscale set --auto-update=false

echo
echo "Now you are using the latest Tailscale version ($latest_version)!"

👉 コードを /etc/config/ 内に保存する理由は、System > Backup で設定のバックアップ(archive)を作成する際、 /etc/config/ はバックアップファイルに含まれるためです。

ちなみに OpenAI o1 に書いてもらったコードはこちら。
  1. tgz ファイルを 1 回で解凍しているため、@hide_seki さんの改良部分が無効化されています。😱
  2. そのままでは動かなかったため、2 箇所修正しています。 ( CURRENT_VERSIONLATEST_VERSION の取得)
#!/bin/sh

# Script to update Tailscale on OpenWrt devices with 64-bit ARM CPUs

# Constants
ARCH="arm64"
API_URL="https://api.github.com/repos/tailscale/tailscale/releases/latest"
PACKAGE_BASE_URL="https://pkgs.tailscale.com/stable"

# Function to check system requirements
check_requirements() {
  # Ensure the script is running on OpenWrt
  if [ ! -f /etc/openwrt_release ]; then
    echo "Error: This script must be run on an OpenWrt device."
    exit 1
  fi

  # Ensure the CPU architecture is 64-bit ARM
  if [ "$(uname -m)" != "aarch64" ]; then
    echo "Error: This script can only be executed on devices with 64-bit ARM CPUs (aarch64)."
    exit 1
  fi
}

# Function to get the current Tailscale version
get_current_version() {
  CURRENT_VERSION=$(tailscale version | head -1)
  if [ -z "$CURRENT_VERSION" ]; then
    echo "Error: Could not determine the current Tailscale version."
    exit 1
  fi
  echo "Current Tailscale version: ${CURRENT_VERSION}"
}

# Function to get the latest Tailscale version from GitHub
get_latest_version() {
  LATEST_VERSION=$(wget -q -O - "$API_URL" | sed -n 's/.*"tag_name":"v\([^"]*\)".*/\1/p')
  if [ -z "$LATEST_VERSION" ]; then
    echo "Error: Unable to retrieve the latest Tailscale version."
    exit 1
  fi
  echo "Latest Tailscale version available: ${LATEST_VERSION}"
}

# Function to compare versions and decide if an update is needed
compare_versions() {
  if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ]; then
    echo "You are already using the latest Tailscale version (${LATEST_VERSION})."
    exit 0
  fi

  PACKAGE_NAME="tailscale_${LATEST_VERSION}_${ARCH}"
  PACKAGE_URL="${PACKAGE_BASE_URL}/${PACKAGE_NAME}.tgz"

  # Check if the package for the latest version is available
  if ! wget --spider "$PACKAGE_URL" 2>/dev/null; then
    echo "Error: Tailscale version ${LATEST_VERSION} is not available for architecture ${ARCH}."
    exit 1
  fi

  echo "An update to Tailscale ${LATEST_VERSION} is available."
}

# Function to prompt the user for an update
prompt_update() {
  echo -n "Do you want to update to Tailscale ${LATEST_VERSION}? (y/N): "
  read -r ANSWER
  case "$ANSWER" in
    [yY][eE][sS]|[yY])
      echo "Proceeding with the update..."
      ;;
    *)
      echo "Update canceled."
      exit 0
      ;;
  esac
}

# Function to uninstall the current Tailscale version
uninstall_tailscale() {
  echo "Uninstalling the current Tailscale version..."
  service tailscale stop
  rm -f /usr/sbin/tailscale /usr/sbin/tailscaled
  echo "Uninstallation complete."
}

# Function to install the new Tailscale version
install_tailscale() {
  echo "Downloading Tailscale ${LATEST_VERSION}..."
  TEMP_TGZ="/tmp/tailscale.tgz"
  PACKAGE_NAME="tailscale_${LATEST_VERSION}_${ARCH}"
  PACKAGE_URL="${PACKAGE_BASE_URL}/${PACKAGE_NAME}.tgz"

  if ! wget "$PACKAGE_URL" -O "$TEMP_TGZ"; then
    echo "Error: Failed to download Tailscale package."
    exit 1
  fi

  echo "Extracting package..."
  if ! tar -zxf "$TEMP_TGZ" -C /tmp; then
    echo "Error: Failed to extract Tailscale package."
    exit 1
  fi

  echo "Installing Tailscale binaries..."
  if ! cp "/tmp/${PACKAGE_NAME}/tailscale" "/usr/sbin/"; then
    echo "Error: Failed to install 'tailscale' binary."
    exit 1
  fi
  if ! cp "/tmp/${PACKAGE_NAME}/tailscaled" "/usr/sbin/"; then
    echo "Error: Failed to install 'tailscaled' binary."
    exit 1
  fi

  # Clean up temporary files
  rm -rf "/tmp/${PACKAGE_NAME}"
  rm -f "$TEMP_TGZ"

  echo "Installation of Tailscale ${LATEST_VERSION} complete."
}

# Function to start Tailscale service
start_tailscale() {
  echo "Starting Tailscale service..."
  service tailscale start
  tailscale set --auto-update=false
  echo "Tailscale is up and running."
}

# Main script execution
check_requirements
get_current_version
get_latest_version
compare_versions
prompt_update
uninstall_tailscale
install_tailscale
start_tailscale

Tailscale の設定の確認方法

方法 1. tailscale debug prefs

以下のコマンドで Tailscale の設定状況を確認できます。

tailscale debug prefs

方法 2. tailscale status --json | sed -n '/Self/,/}/p'

tailscale status --json を以下のように整形すると、現在のノードの設定状況が確認できます。

tailscale status --json | sed -n '/Self/,/}/p'

Tailscale が外部に対してどのポートを使用しているかは、 tailscale status --json | sed -n '/Self/,/}/p' | sed -n '/Addrs/,/]/p' で確認できます。

👉 Nested tailscale では、ポートが競合して通信が不能になってしまう場合があります。

Tailscale の設定方法

稼働中の Tailscale で設定の変更を行う場合は、 tailscale up ではなく tailscale set を使用する

実行例.

tailscale set --advertise-routes=10.0.0.0/8,192.168.0.0/24 --accept-routes --advertise-exit-node

# 以下のように一つずつ設定することもできます。
tailscale set --accept-routes
tailscale set --advertise-exit-node
tailscale set --advertise-routes=10.0.0.0/8,192.168.0.0/24

# 初めて `tailscale up` を実行する時は、以下のように実行して大丈夫です。
tailscale up --advertise-routes=10.0.0.0/8,192.168.0.0/24 --accept-routes --advertise-exit-node

tailscale set は 2022 年 12 月に 1.34.0 で導入されました。

全ての設定をデフォルト値に戻す場合は tailscale up --reset を使用する

--reset オプションは tailscale set にはなく、tailscale up にしかないため、全ての設定をデフォルト値に戻したい場合は tailscale up --reset を使用します。

Tailscale 導入後に OpenWrt で opkg update ができなくなった場合 (DNS 解決エラー)

私の場合は、 Network > Interfaceswan6 を停止したところ、
正常に opkg update が実行できるようになったため、 wan6 を削除しました。

OpenWrt Forum や Reddit でも、 Tailscale インストール後に DNS が使えなくなったというスレッドがあります。

OpenWrt の時刻がずれている場合も opkg update に失敗します

OpenWrt の時刻がずれていても opkg update に失敗するので、 ntpd -q -p 0.openwrt.pool.ntp.orgSystem > Startup > Local Startup に追記して、OpenWrt を再起動した後でも時刻がずれないように設定しましょう。

ntpd.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?