tech.guitarrapc.cóm

Technical updates

scoop の bucket を自動更新する

Scoop Bucket を作るのは避けたいものです。 しかし、Main や Extras に追加するのもアレだし、既存のパッケージ更新はメンテされてないし、など様々な理由で自分のバケットを作ることはあるでしょう。

自分のバケットを持った時に面倒なのが、バケットの更新追従です。 幸いにも Scoop には Excavate という自動更新する仕組みがあります。今回はこれを仕込んでみましょう。

目次

TL;DR

  • Bucket の manifest を記述した json に checkverautoupdate セクションを設定する
  • Excavate と更新スクリプトをバケットに配置する。
    • バケットフォルダで、bukcet/ などフォルダを掘っている場合はスクリプトで対応が必要
  • Excavate は docker-compose で動くので、動かしっぱなしにするか適当などこかで定期実行

実際に使用しているリポジトリ

この記事で使っている自動更新のためのスクリプトや仕組みは .github フォルダに一式が入っています。

github.com

動作環境

バケットの自動更新は以下の環境で動作します。

  • Linux コンテナ
  • PowerShell 7
  • 定期実行環境 (ローカルマシン、GitHub Actions、Kubernetes など)

Linux コンテナで動作するので、事実上実行環境に困らないでしょう。Windows でも実行できますが、私はLinuxのみで行っています。

Scoop App Manifest 自動更新の仕組み

3つやることがあります。

  1. 自動更新するバケットjsonを自動更新に対応させる
  2. 自動更新スクリプトをバケットのリポジトリにおく
  3. 自動更新を定期実行する

順番に見ていきましょう。

1. 自動更新するバケットjsonを自動更新に対応させる

Scoop App Manifest は、checkverautoupdate に適切な内容を記述することで自動更新対象のマニフェストとして認識されます。この辺りは公式の Wiki に書いてあります。

App Manifest Autoupdate · lukesampson/scoop Wiki · GitHub

といってもWikiの内容は複雑でよくわからん.... ということで実際に使っているシンプルなパターンで説明します。

GitHub のリリースページを見る

今回のパターンは GitHub Releases のパッケージ更新を見てバケットを構成している場合に利用できます。ただし、プレリリースではない && バージョン1.0.0 や v1.0.0 といったパターンでタグ公開されているの2点が前提です。

実際に利用しているctop を定義したマニフェストを用意しました。

{
    "description": "Top-like interface for container metrics",
    "homepage": "https://github.com/bcicen/ctop",
    "version": "0.7.5",
    "license": "MIT",
    "url": "https://github.com/bcicen/ctop/releases/download/v0.7.5/ctop-0.7.5-windows-amd64#/ctop.exe",
    "hash": "sha256:bffb1499d62c46b70dd25d557b653f812ccdc8b4bfb08473c063a6265faf78b3",
    "bin": "ctop.exe",
    "checkver": "github",
    "autoupdate": {
        "url": "https://github.com/bcicen/ctop/releases/download/v$version/ctop-$version-windows-amd64#/ctop.exe"
    }
}

自動バージョン更新に必要なのは、checkver と autoupdate のセクションです。

  • checkver"github" で問題ありません。これでリリースぺージのTagが \/releases\/tag\/(?:v|V)?([\d.]+) パターンで公開されていれば抽出されます。
  • autoupdate のセクションは、$version を使って実際のリリースページのダウンロードurl を表現します。url が https://github.com/bcicen/ctop/releases/download/v0.7.5/ctop-0.7.5-windows-amd64 なので、0.7.5 というバージョンが $version に置き換えられていることがわかります。

これでバケットのjsonは準備が整いました。

2. 自動更新スクリプトをバケットのリポジトリにおく

リポジトリ直下にバケットのjsonを配置しているか、bucketフォルダを掘ってそこにまとめているかで微妙に異なります。

bucket フォルダを掘っている場合は、lukesampson/scoop-extras の bin フォルダの中身を、そのまま自分のリポジトリの/binに持ってくるといいでしょう。

f:id:guitarrapc_tech:20201123222946p:plain
lukesampson/scoop-extras の bin フォルダの中身

もしもリポジトリ直下にバケットjson を置いている場合は、以下のように $dir = "$psscriptroot/.." とします。各スクリプトにこの変更がいるので面倒です。

# auto-pr.ps1
param(
    # overwrite upstream param
    [String]$upstream = "<user>/<repo>:master"
)
if(!$env:SCOOP_HOME) { $env:SCOOP_HOME = resolve-path (split-path (split-path (scoop which scoop))) }
$autopr = "$env:SCOOP_HOME/bin/auto-pr.ps1"
# $dir = "$psscriptroot/../bucket" # checks the parent dir
$dir = "$psscriptroot/.." # checks the parent dir
iex -command "$autopr -dir $dir -upstream $upstream $($args |% { "$_ " })"

これでバケットのスクリプト配置も完了です。

NOTE: 調べるとこのスクリプト名がbucket-updater.ps1 だったり auto-pr.ps1 だったりしますが、後述のExcavatorを使う場合どちらでも対応されているので大丈夫です。auto-pr.ps1 が公式でも使ってて新しいかな?

3. 自動更新を定期実行する

自動更新方法はWikiにもいくつかのっています。

App Manifest Autoupdate · lukesampson/scoop Wiki · GitHub

個人的には、ScoopInstaller/Excavatorを用いて docker-compose で実行するのがおすすめです。Linux で実行できるのと、docker-compose が利用できるので実行環境を選びません。あとこの方法なら Kubernetes で実行も簡単です。

github.com

docker-compose を実行すると ssh キーが生成されるので、公開鍵 id_rsa.pub をGitHub に登録して push できるようにしましょう。sshキーを再利用する場合は、id_rsa も取得しておいて、docker-compose 実行時にマウントさせればok です。

$ docker-compose up --build
$ docker-compose exec bucket cat /root/.ssh/id_rsa.pub
$ docker-compose exec bucket cat /root/.ssh/id_rsa

このコンテナイメージは定期的に呼び出して実行するには注意があります。/sbin/my_init を実行した上でないと scoop コマンドがコンテナ内部で見つからずエラーが出ます。

走らせっぱなしで定期実行する前提なイメージになっているので、自分のように定期的に呼び出し実行する場合は docker-compose で次のようなラッパーコマンドを用意して呼び出すといいでしょう。

#!/bin/bash
/sbin/my_init &
chmod 600 /root/.ssh/id_rsa
pwsh ./root/scoop/lib/install.ps1
bash -x /root/excavate.sh

これで コンテナを使っていい感じに更新されるようになります。

実行環境について

このような定期実行環境は、Kubernetes の cron job、後今日使えるようになった Amazon ECS のdocker-compose対応などが楽でしょう。

www.docker.com

GitHub Actions での使用は、使用条件のここに該当するかによりそうです。

any other activity unrelated to the production, testing, deployment, or publication of the software project associated with the repository where GitHub Actions are used.

バケットのデプロイ作業なので実行は許されそうですが、自前のクラスタで実行で行えるならそれがいいでしょう。 仮にリポジトリで実行していますが、自前Kubernetes クラスタでの実行に変更を予定しています。

以下に GitHub Actions で実行する場合の Workflow を示します。

name: auto update bucket

on:
  schedule:
    - cron: "0 * * * *"
  workflow_dispatch:

jobs:
  update:
    timeout-minutes: 10
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: openssl aes-256-cbc --pbkdf2 -d -in .github/.ssh/id_rsa.cipher -k ${{ secrets.CIPHER_KEY }} >> .github/.ssh/id_rsa
      - run: docker-compose up
        working-directory: .github

パッケージの更新ログの例です。

main_1  | 
main_1  | ScriptBlock ID: f43b73d1-2181-437c-9d72-8b0797e62035
main_1  | Path: /root/scoop/lib/install.ps1
main_1  | py: 1.0.1.6
main_1  | DejaVuSansMono-Bront: couldn't match '\/releases\/tag\/(?:v|V)?([\d.]+)' in https://github.com/chrismwendt/bront/releases/latest
main_1  | bombardier: 1.2.5 (scoop version is 1.2.4) autoupdate available
main_1  | Autoupdating bombardier
main_1  | Downloading bombardier-windows-386.exe to compute hashes!
main_1  | Downloading https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-windows-386.exe#/bombardier.exe (9.7 MB)...
main_1  | Computed hash: d2bfd99019ca590610c89ccf829bf4c84ed6652821fe55e7f9bcf342106fe496
main_1  | Downloading bombardier-windows-amd64.exe to compute hashes!
main_1  | Downloading https://github.com/codesenberg/bombardier/releases/download/v1.2.5/bombardier-windows-amd64.exe#/bombardier.exe (10.9 MB)...
main_1  | Computed hash: 52e0c22e3a10c06f7013bbb09d713ab52fae6fba5a86a5ffcfdd6546ed86b7cf
main_1  | Nov 22 12:17:39 3e2cb27a65fb powershell[86]: (7.0.2:9:80) [ScriptBlock_Compile_Detail:ExecuteCommand.Create.Warning] Creating Scriptblock text (1 of 1):
main_1  | {⏎⏎            $architecture = $_.Name⏎⏎            if ($json.architecture.$architecture.$prop -and $json.autoupdate.architecture.$architecture.$prop) {⏎⏎                $json.architecture.$architecture.$prop = substitute (arch_specific $prop $json.autoupdate $architecture) $substitutions⏎⏎            }⏎⏎        }
main_1  | 
main_1  | ScriptBlock ID: a1ca077d-4175-458e-9ad3-e0f9e4c68c86
main_1  | Path: /root/scoop/lib/autoupdate.ps1
main_1  | Writing updated bombardier manifest
main_1  | ctop: 0.7.5
main_1  | warning: LF will be replaced by CRLF in bucket/bombardier.json.
main_1  | The file will have its original line endings in your working directory.
main_1  | Creating update bombardier (1.2.5) ...
main_1  | hub add bucket/bombardier.json
main_1  | warning: LF will be replaced by CRLF in bucket/bombardier.json.
main_1  | The file will have its original line endings in your working directory.
main_1  | hub status --porcelain -uno
main_1  | hub commit -m 'bombardier: Update to version 1.2.5'
main_1  | [master 603a742] bombardier: Update to version 1.2.5
main_1  |  1 file changed, 5 insertions(+), 5 deletions(-)
main_1  | Pushing updates ...
main_1  | hub push origin master
main_1  | Warning: Permanently added the RSA host key for IP address '140.82.112.4' to the list of known hosts.
main_1  | To github.com:guitarrapc/scoop-bucket.git
main_1  |    c5e2c3f..603a742  master -> master
main_1  | hub reset --hard
main_1  | HEAD is now at 603a742 bombardier: Update to version 1.2.5
main_1  | + '[' -f /root/bucket/bin/bucket-updater.ps1 ']'
github_main_1 exited with code 0

まとめ

難しい記述をしなくても自動更新できるのはいいことです。 実行環境だけ面倒ですね。

参考

手の入れ方が好みじゃないので参考程度にしています。 こういう公式のやり方に乗っかる場合は、コンテナに手を入れないのがおすすめです。メンテしきれなくなるので。

Scoopを使ったWindows環境構築のススメ - Hyper!!! - Qiita

Unifi Dream Machine で MAP-E方式の IPv6 に対応する

IPv4 PPPoE からIPoE にしつつ、Unifi Dream Machine (UDM) で IPv4 over IPv6 環境でアクセスするまで組んだのでそのメモです。

Unifi Dream Machine はMAP-E に対応していないので、ちょっと小細工が必要だったのは学びでした。

私が欲しい内容の記事がなかったので自分で書いたいつものプレイ。

目次

TL;DR

特に複雑なことは行わず、必要なことを順にクリアするだけです。ポイントは3 つです。

  1. MAP-E 方式の IPoE (IPv4 over IPv6) で、DHCPv6 Prefix Delegate (DHCPv6-PD) を行うため「ひかり電話」の契約が必要 (HGWもこれで得られる)
  2. ホームゲートウェイ(HGW)によるIPoE接続 にすることで、UDMで DHCPv6-PD を受けられるようにする (ついでに速度も改善する)
  3. Unifi Dream Machine で、LAN/WAN ともに IPv6 対応を行う

構成は以下の通りです。

  • ぷらら光
  • 光配線方式
  • ひかり電話あり、HGW あり
  • Unifi Dream Machine

結果、UDM の出口速度でIPoE VDSL から IPoE光配線 で 約6-10倍に上がったのでいったんこれで。(満足できてない)

今後のメモ

  • HGW のLAN接続とUDMのWifi を比べたときに、アップロードは有線並みに出ている一方でダウンロードが遅い (要改善)
  • WIFI 6 対応した Unifi 製品はアメリカでアーリーアクセスで出ているので日本にも来てほしい (希望)
  • WAN回線を 2Gbps 程度にあげるか、10Gbps サービス試していきたいところ (まずはWifi速度の改善をしてから)

前説

いくつか事前情報を共有します。

記事の対象となる人

  • UDM (UDM Pro) を使いMAP-E 方式の IPoE を用いて、クライアントが IPv6 ネイティブアクセスを可能にしたい人
  • 海外ルーターなどMAP-E をサポートしてない自分の好みのルーターを使う場合、同様に該当するでしょう。

はたして国内に何人いるのでしょう、いない気がします。

記事の対象ではない人

  • UDM 配下のクライアントが IPv6 を持たなくていいなら不要です。IPoE を契約してUDM をつなぎ IPv4 のみにすればok です、この記事は IPv6 もクライアントに配布してつなぎたい場合に役立つでしょう。
  • 国内の IPoE 対応を謳うルータであれば不要です。多くの場合、MAP-E (あるいは DS-Lite) 方式のIPoE で契約して、プロバイダが提供する無線ルーターあたりでつなげばいいでしょう。自前のWifi にしても AP モードで適当につなげばok なはずです。
  • Nuro もIPv4/v6デュアル方式なので不要です。ほぼなにも考えずただつなぐだけでいいです。DHCP-PD で Prefix /56 が降ってきます。

LANネットワーク環境の前提

私の個人環境は8年前から完全にWifiで統一しています。 ケーブルが嫌いというのもあるのですが、配線や配置の自由さと、ネットワーク環境でやりたい放題やるを考えたときに、Wifiもまとめて制御することを自分に課しています。有線LANは好みではないし、Wifiの技術的進展が目覚ましいのでよい。

Wifi で統一するにあたり、当然メッシュ環境が欲しくなるので以前は Amplifi を使っていました。

tech.guitarrapc.com

しかし、メッシュを広げつつ、計測やIDS/IPSを展開しつつ、今後の変化にも追随することを考えるとUnifi にしたくなります。でも Cloud Keyはいや。ということで、Unifi Dream Machine は欲しかったマシンであり、日本Ubiquiti Store で販売されてすぐに切り替えました。

UniFi Dream Machinejp.store.ui.com

私の環境において「あらゆる機器は UDM配下からのアクセスになる」というのが構成上の大前提となります。

もしもUDMに興味がなくて、「さくっとIPoEでいい感じに組みたい」だけなら適当にIPoE 対応の国内ルーターでも使えばいいと思います、好きにするのが一番。Synology とかもMAP-E対応ありますしね。

www.synology.com

WAN ネットワーク環境の前提

私はISPに、ぷららを利用しています。

以前は住んでいたところが VDSL だったため、何をどうあがいても100Mbps が上限でした。

とはいえ、IPv4 PPPoE だと夜間の速度が不安定になることが多くなってきたので、回線速度を安定させるため IPoE にすることにします。

IPoE にするだけで、いったん回線速度は安定しますが、せっかくなので IPv6 への対応も考えたいものです。 しかし、ぷららが提供する MAP-E 方式の IPoE 環境とUDM は相性が悪いので「UDM配下のクライアントで IPv6 ネイティブでアクセスさせるためにどんな構成にするのか」、これがこの記事のポイントです。

ネットワーク環境

IPv4 で PPPoE でつないでいるときは次のような環境です。

ONU -- ルーター -- UDM -- 各Wifiクライアント

最終的に、MAP-E方式の IPv6 で次のような構成に持っていきます。

HGW -- UDM -- 各Wifiクライアント

PPPoE から IPoE までの変遷を見ていきます。

事前調査

IPoE と UDMをどう組めばいいのか考えます。

UDM は MAP-E にも DS-Lite にも対応していない。これは調べればすぐにわかります。

ではどうすれば組めそうでしょうか。

採用しなかった方法

まず採用しなかった方法を見てみます。

EdgeRouter の EdgeOS なら DS-Lite 構成組まれている方もいますが、UDM は UnifiOS でそういった構成は組めません。(そういえば MAP-E 組んでいる人はいませんね)

stop-the-world.hatenablog.com

こういう MAP-E に対応していない場合のよくある対処の一つは、IPv4 アクセスは IPv4 PPPoE 回線から、IPv6 アクセスは IPv6 プラスルーター経由でアクセスさせる方法です。PPPoE を残したくないですし、なんのための IPv4 over IPv6 なのかって話で好みではありません。(過渡期としてはやむを得ないですね。あと、ぷららの技術部門の人と話をしたときも、ぷららの人はこの構成で話していました、わかる。)

chitoku.jp

あるいは、ひかり電話なしでRAをLANにいきわたらせてしまうのも手でしょう。IPv6でクライアントがグローバルにさらされるのを避けるために、スマートスイッチでタグベースVLANを使ってIPv6を選択的に設定するのもありだと思います。(めんどくさすぎて好みじゃない)

yabe.jp

どれも単純ではない、自分が運用したくないと感じる構成です、こういうのは避けたい。

必要な条件が何かを考える

IPv4 over IPv6 でUDMを使ってどのように組めるか調査すると、「ひかり電話」の有無で前提が大きく変わるのがわかります。ひかり電話の有無で DHCPv6 が使えるかが決まり、同時にHGW を使えるかも決まります。

構成の単純さとDHCPv6 を考えるとひかり電話はいれるのが妥当だと思います。月500円で機器にお金をかけてもどうしようもない問題が解決するので。ひかり電話は使わないので、これだけのために入れるのは納得感はないですが!

もう一つが HGW です。UDM はMAP-Eをしゃべられないルーターなので、事前にMAP-E をしゃべらせておく必要があります。

  • HGWがない場合、MAP-E 認証をさせるため、HGWとUDMの間に対応ルータを置いた二重ルータが確定します。
    • HGWとUDM間にルーターを挟むため、DHCPv6-PD がスムーズにいかなくなります。
  • HGW がある場合、HGW でMAP-E認証が終わっているので、UDM を直接刺せます。
    • UDMで直接DHCPv6-PDを受け取ることができます。

HGWから直でなくても、MAP-E 対応ルーターが RA パススルーに対応していればワンチャンとふと思いましたが、私の借りた MAP-E対応ルーター WN-AX1167GR2 は RAパススルーがなかったです。

必要な条件

次の通りです。

  • ひかり電話を契約する
  • HGW を手に入れる

YAMAHA などでもよく組まれているほう方法ですね。

y2lab.org

NTT の方式でいうところの、光配線方式の接続パターンB が該当します。

4466.jp

では構成の変遷を見ていきましょう。

余談: UDM とMAP-E

UDM が MAP-E 対応すると、ひかり電話なしでもよくなるので対応されると嬉しいですね。対応されるかは期待はあまりできなさそうですが....

community.ui.com

1. PPPoE から IPoE への変更

ぷららの場合、ぷららv6エクスプレスで IPoEを提供しています。 プロフィールページから「ぷらら光」に契約を切り替えることでIPoE に変更できます。 なかなか手間がかかる作業で、事前にNTTから承諾番号を得る必要があり、ぷららの契約切り替え自体も概ね2週間見る必要があります。

www.plala.or.jp

この時点では、「HGW での IPoE 接続」はしません、まずは IPoE 接続を安定させます。ということで、IPoEへの切り替えを申し込むにあたり、MAP-E対応ルータとして「ぷららWi-Fiルーター」をレンタルします。

PPPoE から IPoE への切り替え時の申し込みは次の通りです、めんどくさい。

  • 切り替えに2週間程度は猶予時間を見る
  • 事前にNTT から承諾番号を得る
  • 「ぷらら光」への切り替え
  • 「ひかり電話」の契約
  • 「ぷららWi-Fiルーターレンタル」の申し込み

変更予定日前に、HGWとMAP-E 対応ルーターが届きます。変更予定前日夜にでもVDSLルータとUDM の間に入れましょう。AM8:00ぐらいに切り替えが走ったのが計測できました。

IPoEへの切り替えが無事に完了すると、ぷららv6エクスプレスが開通済み、IPoE対象接続先がIPv4+IPv6へと変わります。

f:id:guitarrapc_tech:20201017034334p:plain

接続状態はVDSL方式の接続パターンCになります。すごく面倒くさい。

VDSLルーター -- HGW -- MAP-E対応ルーター -- UDM -- 各Wifiクライアント

この時点では、UDM 配下には IPv6 が配布されず IPv4のみになります。MAP-E対応ルーターを抜いて IPv6 ネイティブ接続にすることはできますが、はっきり言ってどこも接続できないのでムリ。 (GitHub も Twitter もつながらないのは意外でしたが)

なので、IPoE + IPv6 もクライアントで使いたいなら、MAP-E 対応ルーターに直接接続すれば期待通り動きます。(私はUDM を使いたいのでやらない)

通信速度は、VDSL の上限によって 100Mbps できっちり止められます。PPPoE とは違い、IPoEでは速度はある程度安定し、100Mbps 程度ならずっと維持できるのでいいでしょう。

余談ですが、UDMの代わりに Amplifi HD をおいて Bridge 接続 + Router Steeling を仕掛けると、Wifi クライアントに IPv6 が配布されたりします。Amplifi をどうしても使いたい人はこれでもいいですね。

2. VDSL から 光ファイバー回線への切り替え

いろいろあって、住んでいるところがVDSL回線が光ファイバー回線に更新されることになりました。(下り/上り 1Gbps)

ということで、当然 VDSL ルーターは不要になり、光コンセントからHGWに直接回線がつながるようになります。 接続状態は光配線方式の接続パターンCに相当します、一般的な光回線が入っている場所ではこの構成が多いでしょう。

HGW -- MAP-E対応ルーター -- UDM -- 各Wifiクライアント

VDSL がなくなるだけですが、これで回線速度が 300Mbps に上がりました、遅いもののだいぶん改善しました。(LAN も Wifi も同じ速度がでている) 当然ですが、まだ UDM の配下には IPv6 は渡せず IPv4 のみです。

余談: MAP-E 対応ルータの下に UDM を置くと、なぜか速度が 60~70Mbps に落ちたのですが、どうやら LAN の DHCPv6 が残っているとゴミ設定で速度が落ちるバグがある気配があります。LAN の IPv6 対応を無効にして再起動すれば速度劣化なしに300Mbpsでます。(その後は同じ設定をいれても速度劣化がなくなりました)

3. ホームゲートウェイ(HGW)によるIPoE接続 への変更

これで、UDM で IPv6 を配布する準備が整います。IPoE の MAP-E 接続をHGW にゆだねましょう。

HGW にするには、HGW製品が型番が300番台以降でないとだめなのと、いくつか使えなくなるサービスがあるので注意です

faq.plala.or.jp

faq.plala.or.jp

まずは、ぷららのプロフィールから 「ホームゲートウェイ(HGW)によるIPoE接続」への切り替えを申し込みましょう。

www.plala.or.jp

次の日の夜ぐらいにいきなりスパッと切り替わります。HGW で PPPoE 接続を入れていない場合は回線が切れます、MAP-E対応ルーターは不要なので外します、やったー!

これで、光配線方式の接続パターンB に無事移行できました。

HGW -- UDM -- 各Wifiクライアント

余談: ちなみに、デフォルトのLANサブネットが HGW (192.168.1.1/24) と UDM (192.168.1.1/24) でかぶります。UDM のLANを 192.168.2.1/24 あたりにずらしておきましょう。(MAP-E 対応ルータが 192.168.0.1/24 なので放置していた)

HGWに特に設定は不要なので、HGW と UDM を再起動すればすべてが期待通りに動き出します。(PPPoE は不要ですし外しておきましょう)

4. UDM で IPv6 を受けてクライアントに配布する

さてようやく本題です。

ひかり電話を契約していれば、RA ではなくDHCPv6-PD (Prefix Delegate) 方式が利用できます。 早速UDM で IPv6 を HGW から受ける設定 (WAN) と、クライアントへのIPv6 配布の2点を行います。

WAN の設定

ひかり電話がある場合、IPv6は DHCPv6-PD 方式で60bitのPrefix再委任が行われます。(ひかり電話なしだと、RAが直でおりてきて 64bit しかこない)

ということで、IPv6の構成を行います。加えて、DNS の解決ができなくなるケースを防ぐため、DNSにGoogle DNS あたりを指定します。

  • IPv6 Connection Types: DHCPv6
  • Prefix Delegation Size: 60
  • DNS: 8.8.8.88.8.4.4

f:id:guitarrapc_tech:20201017042019p:plain

LAN の設定

LAN に IPv6 を配布する設定を行います。 IPv6 RA、IPv6 Priority、DHCP Range はデフォルトのままでok です。DHCPv6/RDNSS DNS は、Google DNS を指定します。

  • IPv6 Inteface type: Prefix Delegation
  • IPv6 RA: 有効
  • IPv6 Priority: High
  • DHCP Range: Start ::2、 Stop ::7d1
  • DHCPv6/RDNSS DNS Control: Manual
  • DNS Server1: 2001:4860:4860::8888
  • DNS Server2: 2001:4860:4860::8844

f:id:guitarrapc_tech:20201017042249p:plain

IPv6 の確認

ipv6 test を行います。 HGW - UDM 接続 + DHCPv6-PD の構成を組むことで、UDM のWifi クライアントもIPv6テストが通るようになります。長かった。

f:id:guitarrapc_tech:20201017042907p:plain

速度の確認

HGW と UDM を直接つなげたこと、ルーターが一つ減ります。ということで、速度も改善します。

UDM との LAN 接続で 610Mbps まで向上します。

UDM の 5GHz 160 VHT と 1.7 Gbpsのネットワークアダプタで接続すると、下りがLAN より劣化しているのが気になります。(調査中) アップロードは想定通り向上しているのだけれども...

まとめ

IPv6 IPoE で接続して、好きなルーターで良い感じに構成するなら、ひかり電話は契約しておくといいです。 DHCPv6-PD に持ち込めばどうとでもなれるので、ひかり電話なしで頑張るのは避けましょう。

なによりも、VDSLはところは絶対に避けて光配線の住居を選びましょう。自分で入れるのいろいろ面倒ですしね。

Windows開発環境をscoopで継続的に構築する

以前 Windows の開発環境を scoop で構築しているということを書きました。

tech.guitarrapc.com

その際に、scoopを継続的に使っていくためのツール ScoopPlaybook を書いたことに触れました。 今回はその ScoopPlaybook の紹介です。

目次

TL;DR

  • ScoopPlaybook という PowerShellモジュールを作った(2年近く使っている)
  • scoop で何をインストールするかをYAML定義して使える
  • Scoop-Playbook コマンドでYAML通りに実行される
  • 使い心地は、Ansible Playbook のYAML定義とコマンドにインスパイアされている

scoop 使っていて、YAMLでインストールするツールを定義したい方は使ってみてください。

目指す姿

私は普段からOS環境を壊すことをアリと考えています。 ただし壊すからには再構築にコストをなるべくかけたくないため、対象のマシン上で再構築がコマンド一つでできるようにしています。 macOS は Homebrew や defaultsをAnsible Playbookで構築し、Ubuntu は Ansible Playbook で構築しています。

Ansible Playbook を使うことで、ほどよく緩くいい感じの目指す姿が可能になります。

  • 利用する開発ツールをYAMLに定義して
  • 何度実行しても同じ結果に収束させる

例えば Homebrew でインストールする場合は次のように定義できます。

# roles/homebrew/tasks/main.yaml
- name: 'homebrew packages installation'
  homebrew:
    name: '{{ item.name }}'
    state: "{{ item.state|default('present') }}"
  with_items: "{{ homebrew_packages }}"

# roles/homebrew/vars/main.yaml
homebrew_packages:
  - name: autoconf
  - name: awscli
  - name: aws-iam-authenticator
  - name: azure-cli
  # and so on....

一度定義してしまえばツールを定義に追加したり、アンインストール ( state: "absent" ) を指定するだけとメンテナンスが非常に簡単です。

site.yml を置いたルートパスでいつも同じコマンドを実行するだけで、YAML定義通りに環境が構築されます、便利。

$ ansible-playbook -i hosts site.yml

sudo が必要な操作 (become) なら、実行時に入れるだけです。

ansible-playbook -i hosts site.yml --ask-become-pass

WSL との相性もよく、気軽に環境を壊してサクッと作り直すことがコストでなくなります。

自分の環境にどんなツールをいれているかを説明することがふとしたときにあるのですが、定義によって、いつでも確認したり継続的に変更をかけたり、場合によっては他人に共有できるのは個人的に好みです。

WindowsでAnsiblePlaybook のようなアプリケーションインストール基盤を作る

環境の再構築はWindowsでもたびたび行います。(OSいれなおしでなくてもリセットはやりますよね)

scoopを使っていくことに決めたときに、コマンドの羅列地獄になるのは嫌だと思いました。 しかしAnsible をWindows localhost に実行はサポートされていないので、Ansible Playbook のような定義とインストールを提供することにしました。(WSLからAnsible実行するというのはナシ派) その晩にザクっと書いたのが ScoopPlaybook という PowerShell Module です。

github.com

あんまり使い方とか書いていないので、どういう利用をするのか紹介します。

scoop の通常のインストール

例えば、scoop でgow、jq、time、unzipをインストールする場合、コマンドラインで次のように実行するでしょう。

scoop install gow jq time unzip

あるいは、次のようにコマンドを分けているかもしれません。

scoop install gow
scoop install jq
scoop install time
scoop install unzip

アンインストールもコマンドラインで制御できます。

scoop uninstall gow

入っているツールは scoop list で見えますが、ほかの環境や再構築、追加インストールをするときはいちいち考えるの嫌になります。

ScoopPlaybook で定義からインストールする

ScoopPlaybook はAnsible Playbook でやっていたのと同じ目指す姿を提供します。

  • 利用する開発ツールをYAMLに定義して
  • 何度実行しても同じ結果に収束させる

利用方法は Ansible Playbookに合わせています。

  • ルートパス/site.ymlに 利用する role のYAML定義し、
  • ルートパス/roles/バケット/tasks/main.yml にツールをYAML定義したら、
  • ルートパスで、Scoop-Playbook コマンドを実行すると、Scoopバケットやツールが定義通りにインストール/アンインストールされる。

YAMLで定義して、コマンド一つで定義を実行。ただそれだけです。 実際にどうやるのかイメージしにくいので利用例を見てみましょう。

利用例

先ほどのmainバケットのツールをScoopPlaybookでYAML定義してインストールしてみましょう。 ScoopPlaybook モジュールとYAM解析モジュールをインストールします。PowerShell 5.1 以降で動作します。

PS> Install-Module ScoopPlaybook -Scope CurrentUser
PS> Install-Module "PowerShell-Yaml" -Scope CurrentUser

適当にルートパスを切ります。

md ./begin
cd ./begin

まずは、インストールしたいアプリの定義YAMLを ルートパス/roles/main/tasks/main.yml に定義します。

PS> mkdir roles/main/tasks
PS> New-Item roles/main/tasks/main.yml
PS> vim roles/main/tasks/main.yml
- name: "Install main tools"
  scoop_install:
    state: present
    bucket: main
    name:
      - gow
      - jq
      - time
      - unzip

インストールするロールを指定したYAML定義 site.yml をルートパスにおきます。

PS> New-Item site.yml
PS> vim site.yml

今回のロールは main なのでこれを一つ指定します。

name: Windows Setup
roles:
  - main

早速定義をドライランしてみましょう、次のコマンドを site.yml のパスで実行します。

PS> Scoop-Playbook -Mode check

scoop のバケットを更新して (scoop update) 、ツールがインストールされるか実行計画を確認できます。

PRE [scoop : status] ***************************************************************
  [o] skip: [run with 'check' mode]
  [o] skip: [prerequisiting availability]
  [o] skip: [updating buckets]
  [o] check: [scoop-update: Updating Scoop...]
  [o] check: [scoop-update: Updating 'main' bucket...]
  [o] check: [scoop-update: Scoop was updated successfully!]
  [o] skip: [status checking]
  [o] skip: [scoop-status: Scoop is up to date.]
  [o] check: [scoop-status: Updates are available for:]
.... 省略
PLAY [Windows Setup] ***************************************************************

TASK [main : Install main tools] ***************************************************
  [!] check: [scoop_install: gow] => Installed: No
  [!] check: [scoop_install: jq] => Installed: No
  [!] check: [scoop_install: time] => Installed: No
  [!] check: [scoop_install: unzip] => Installed: No

問題なければインストールします。Mode パラメーターを省略するか、-Mode run を明示的に付けると実行します。

PS> Scoop-Playbook
PRE [scoop : status] ***************************************************************
.... 省略
PLAY [Windows Setup] ***************************************************************

TASK [main : Install main tools] ***************************************************
  [!] changed: [scoop_install: gow] => Installed: No
  Installing 'gow' (0.8.0) [64bit]
Loading Gow-0.8.0.exe from cache
Checking hash of Gow-0.8.0.exe ... ok.
Extracting dl.7z ... done.
Running pre-install script...
Linking ~\scoop\apps\gow\current => ~\scoop\apps\gow\0.8.0
.... 省略
'gow' (0.8.0) was installed successfully!
  [!] changed: [scoop_install: jq] => Installed: No
  Installing 'jq' (1.6) [64bit]
.... 省略
'jq' (1.6) was installed successfully!
  [!] changed: [scoop_install: time] => Installed: No
  Installing 'time' (0.2018.07.25) [64bit]
.... 省略
  [!] changed: [scoop_install: time] => Installed: No
  Installing 'time' (0.2018.07.25) [64bit]
.... 省略
'time' (0.2018.07.25) was installed successfully!
Notes
-----
Please use 'timecmd' instead of 'time' in cmd.exe.
  [!] changed: [scoop_install: unzip] => Installed: No
  Installing 'unzip' (6.00) [64bit]
.... 省略
'unzip' (6.00) was installed successfully!

再度実行しても同じ結果に収束します。 もし更新があれば更新してくれます。

PS> Scoop-Playbook
Scoop-Playbook
PRE [scoop : status] ***************************************************************
.... 省略
PLAY [Windows Setup] ***************************************************************

TASK [main : Install main tools] ***************************************************
  [o] skip: [scoop_install: gow] =>   gow  0.8.0
  [o] skip: [scoop_install: jq] =>   jq  1.6
  [o] skip: [scoop_install: time] =>   time  0.2018.07.25
  [o] skip: [scoop_install: unzip] =>   unzip  6.00

何かの理由でscoop コマンドで直接インストールすることもあるでしょう、そんな時は定義に一行足せばいいだけです。 もし scoop コマンドで誤ってアンインストールしても、Scoop-Playbook を実行すれば元通りです。

Scoop で管理したいツールを定義通りに実行する。それができます。

普段の利用例

私は ScoopPlaybook を使ってYAML定義をして GitHub においています。 参考に私が普段使っているリポジトリを置いておきます。ルートパスはこのリポジトリの ./envs/windows/ パスです。

local-provisioner/envs/windows at master · guitarrapc/local-provisioner · GitHub

そのため、環境構築するときは次のコマンドを実行しています。

git clone https://github.com/guitarrapc/local-provisioner.git
cd local-provisioner/envs/windows
. ./prerequisites.ps1
sudo Scoop-Playbook

ツールの追加や削除をしたいときは、定義のYAML を修正して git commit/push するだけです。 バッチファイルやスクリプトではないので、どのように動作するかは考えず、ツールをYAMLに並べるだけなのはメンテの面で作ってよかったと思っています。 実際これなしで scoop とかいやです。

できること

ScoopPlaybookは次の操作が可能です。これしかできないです。

  • scoop_bucket_install: バケットの追加、削除
  • scoop_install: ツールのインストール、アンインストール

バケットの追加、削除

scoop は任意のGitHubリポジトリなどをバケットにすることができます。scoop bucket add xxxx ScoopPlaybook も scoop_bucket_install でバケットの追加、削除をサポートしています。

例えば extras バケットを追加する場合、次のように書けます。

- name: "Install extras bucket"
  scoop_bucket_install:
    state: present
    bucket: extras

extras バケットは特別扱いされていますが、自分の GitHub URL を指定したい場合は次のようになります。

- name: "Install guitarrapc bucket"
  scoop_bucket_install:
    state: present
    bucket: guitarrapc
    source: https://github.com/guitarrapc/scoop-bucket.git

もしも追加したバケットを消したいならstate に absent を指定します。 (source は省略できます)

- name: "Uninstall guitarrapc bucket"
  scoop_bucket_install:
    state: absent
    bucket: guitarrapc

それぞれのキーは、scoop bucket コマンドに合わせてあります。

  • state: present か absent を指定。
  • bucket: 対象のバケット名を指定
  • source: GitHub などのバケットURLを指定

ツールのインストール、アンインストール

scoop はバケットからツールのインストール、アンインストールができます。scoop install xxxx ScoopPlaybook も scoop_install でツールのインストール、アンインストールをサポートしています。

- name: "Install main tools"
  scoop_install:
    state: present
    bucket: main
    name:
      - gow

先ほど追加した gow をアンインストールするなら次のように書けます。

- name: "Uninstall main tools"
  scoop_install:
    state: absent
    bucket: main
    name:
      - gow

それぞれのキーは、scoop install コマンドに合わせてあります。

  • state: present か absent を指定。
  • bucket: 対象のバケット名を指定
  • name: ツールを配列で指定

すでにインストールされているツールに更新がある場合は、Scoop-Playbook 実行時に更新してくれます。便利。

管理者権限で実行したい

scoop はユーザー権限が基本でーとか言いますが、ツールによってはFiddler のように管理者権限がないとインストールできないものもあります。 そんなときは sudo コマンドです。

sudo コマンドをインストールしておいて(scoop install sudo 相当)

- name: "Install main tools"
  scoop_install:
    state: present
    bucket: main
    name:
      - sudo

Scoop-Playbook を sudo つきで実行すればok です。

sudo Scoop-Playbook

まとめ

一人で使ってて満足していたんですが、WinGet が出てきて未来はどうなるかと楽しみにしています。 ただ、WinGet はこのままいくとこういう YAML 定義に関しては手を出さず、誰かが何か作るのでしょう。

アンインストールやUAC考慮がない、今のWinGet 触る気はありませんが、WinGetを触る将来が来たらこういうツール書くかもしれません。 ただ、その時はたぶん PowerShell では書かない気がするかもしれない。

WSL1 から WSL2 の対応

WSL1 を長い間使っていましたが、先日 Windows 10 Version2004 がリリースされて WSL2 に切り替えを行いました。

WSL2 いいのですが、WSL1 と同じように、あるいはちょっと欲張ろうと思うと少し困ったのでメモ。

目次

TL;DR

Windows 10 May 2020 Updateがリリースされてから2週間使ってますが、もう WSL1 に戻る気はないぐらいには気に入っています。おすすめです。 具体的には、

  • 👍: WSL2 にして apt/pip3 が爆速になってうれしい
  • 👍: WSL1 とおおむね使い勝手は変わらず、WSL2上のdockerでボリュームマウントが可能になってよかった(標準的なLinuxとみなせるようになった)
  • 🙅: WSL2 の Windowsボリュームのアクセスはとても遅くなった
  • 🙅: Windows のシステムボリュームは余計に食うようになったので 50GB 程度空きは欲しい (あるいはOSリセットすると減るはず)

kubernetes 周りに関しては、特段変化を感じません。

WSL1 で何をしていたのか

WSL1 では、Ubuntu 18.04 を動かして、中でアプリケーションやインフラにかかわるツールを動作させていました。 Docker でもいいのですが、普段使いのツールや、Windows でマウントしているファイルを(EOLを含めて) そのまま Linux で動作させたときの動作もサクッと確認できるのがいいのです。

  • dotnet core SDK
  • golang
  • cmake
  • Kubernetes (kubctl/helm/kubesec/sops...)
  • terraform
  • docker/docker-compose
  • aws cli/azure cli
  • jq/yq
  • sed 他

docker とWSL の使い分けはそのカジュアルさです。 WSLは、bash と入力するだけでほぼ Linux とみなせるインタラクティブな環境に行けるので、普段使いのUbuntu 環境に利用しています。多少無茶な使い方をしても、アンインストールして store から入れなおせばフレッシュになるので壊せる開発環境という感じです。 一方のdocker は、アプリ動作環境を閉じ込めるためや、特定のソフトウェアの挙動、壊れるだろうという操作やシステム設定の変更など戻すことがめんどくさいことをするときに使っています。

WSL2 で何をするのか

基本的な利用目的は変わりません。手軽にさくっと Linux 環境として Ubuntu を利用します。 WSL1 から WSL2 に変化することで期待したのは、ディスクIOです。 概ね事前にやっていた結果と Windows 10 Version 2004 における WSL2 に違いはなく、WSL1 に比べて ext4 上でのディスク書き込みの速度が上がりました。 具体的な変化は次の通りです。

  • apt update|instal が爆速になる
  • pip3 も爆速化
  • Windows マウントファイルへのアクセスは非常に低速に
  • WSL2上のDockerでボリュームマウントが可能になった

ディスクアクセスの改善は顕著です。具体的なシチュエーションだと、apt update/install に関しては、これまでUbuntu 18.04 を入れた後に実行すると10min 程度食うのを覚悟していたものが1min 程度になっています。pip3 も同様です、ansible 入れてみてください。 ただ、Windows のマウントディレクトリ ( /mnt/c など) でのファイル操作はけた違いに遅くなりました。(知ってた) そのため、例えばdocker-compose で Windows のフォルダを WSL2 からマウントするのはものを選びます。100MB を超えるdocker転送は永遠に終わらない気分になります。(node_modules とかつらい)

Windows のパス上からそのまま bash で WSL2 を起動する流れは変わらないものの、大き目なファイルサイズを伴う docker-compose に関しては Windows上で扱うか、ext4 上に git clone するのがいいでしょう。

しれっと書きましたが、WSL2ではWSL上のファイルをWSLのdockerにボリュームマウントできるようになっています。WSL1 では、WSL 上のファイルを WSL上で実行した docker にボリュームマウントすることができず、ふとしたdocker操作で挙動が違って無駄に時間を費やすことがありましたがなくなりました。最高です。

WSL2 への対応

WSL1 の環境を WSL2 にするにあたり、どのような対応をしたかメモしておきます。

Windows システムボリュームの利用が増えた

WSL1からWSL2にすると、Docker Desktop (35GB)、wsl (9GB)、Ubuntu 18.04(5GB) で 約50GB余計にシステムボリューム(C:) を利用するようになってしまいました。

f:id:guitarrapc_tech:20200609025451p:plain

デスクトップは長い間 256GB M.2 SSD (Samsung SSD 950 Pro) でやっていましたが、WSL2 にして残り 1.8MB になったためシステムボリュームを 1TB NVMe に差し替えました。 Crucial は 最近P2 が出ましたが、ちょっと試してみたかった P1 で。

www.crucial.jp

なお、Windows.old を含めてゴミを消しても容量はすぐに埋まりきりがなくなったので仕方ない。

qiita.com

なお、Windows 10も入れなおして開発環境、WSL2を組みなおしたところ利用容量が 76.1GB になったので、まぁそんなものです。知ってた。(だから 256GB で過ごせていた) Windowsの入れ直しは、Media Creation Tool で Windows 10 May 2020 Update で USBブートを作るのが今も安定でした。

f:id:guitarrapc_tech:20200609030003p:plain

Windows Features が不要に

幸いなことに、 Docker Desktop for Windows をインストールすると WSL2 周りは一通り入ります。(Kernel のぞく) そのため、これまで Enable-WindowsOptionalFeature でインストールしていた Microsoft-Windows-Subsystem-Linux、Hyper-V は不要になりました。

https://github.com/guitarrapc/local-provisioner/compare/wsl1...604c08d7313060c681fc2ecb91d9839df7056ccf#diff-500458443dc2514ec7bec4fde7ce776eL1-L25

脱Hyper-Vは、Windows 10 Home でも利用できるようになっていますし最高ですね。(Virtual Box とかも動くし)

tech.guitarrapc.com

WSL OS

WSL2 でも、現状は Ubuntu 18.04 を使っています。 折を見て Ubuntu 20.04 に切り替えていきますが、まずは変化を見たいので変えていません。

Provisioning

WSL1 と変わらず、WSL2 においても ansible を使って環境を構築しています。 私の場合は、Windows / macOS / Ubuntu を各種環境を利用するので、全環境に対してこのリポジトリの内容を当てています。

github.com

Ubuntu 18.04 においては、WSL1/WSL2であっても ansible で当てています。 Diff は次の通りです。

Comparing wsl1...724dad71fd0852173e10fbca4a961eec92db2710 · guitarrapc/local-provisioner · GitHub

いくつか初期化回りの変更をメモしておきます。

dockerの入れ直しをやめた

docker は、WSL1 においては docker.io の公式同様に入れなおしていましたが、WSL2 においてはデフォルトから変更していません。

-    - { role: "docker", tags: [docker] }
+    #- { role: "docker", tags: [docker] }

https://github.com/guitarrapc/local-provisioner/compare/wsl1...604c08d7313060c681fc2ecb91d9839df7056ccf#diff-b905abb381284c6c36b4ac2b6dc30641L24-L25

また、bashログイン時の起動も止めています。

- sudo -S cgroupfs-mount
- sudo usermod -aG docker $USER
- sudo service docker start
- # wsl1 using windows docker-compose. wsl2 don't need this line.
- # export DOCKER_HOST=tcp://localhost:2375 

https://github.com/guitarrapc/dotfiles-linux/commit/db47ddf5c1ba8400acb502b256c8a03bbcb5749b

WSL2でdocker の入れ直しをやめたのは、docker の入れ直しを行うことで Windows 上の Docker for Windows のイメージと WSL2 上のイメージ一覧が同期されなくなったためです。(Windows はWindows、WSL2 の UbuntuはUbuntu と個別にイメージを持つようになってしまった。)

# この結果を Windows と WSL で共有する
docker image ls

WSL2 を使うにあたって、Windows の状況がそのまま利用できるメリットを手放す理由は相応のものがない限り薄く、特に docker に関しては同じイメージが使えるのが最高なのでdocker の入れ直しはやめました。

systemd/snap

当初wsl2 なら snapも行けるしと思って試していた形跡があります。が、結局 snap使っていません。(また使えるようにファイルは残しています) 実際 systemd/snapd を動かして、snap 経由でのインストールも可能になりましたが、以下の理由で辞めています。

  • kubectl は意図通り snap のほうが楽だった
  • snap で差し替えたかった pip3 の snap ファイルが欲しいものではなかった
    • 具体的には ansible が公式がなく個人のパッケージは python2 版
  • Windows から bash や wsl で WSL2 を起動したときに、$HOME に移動するようになってしまう
    • WSL2 は、wsl や bash で Ubuntu に入ると Windows のパスのまま維持しますが、snap 対応を入れたスクリプトでのログインしなおしでパスが $HOME になってしまう。

snapを使うことでバージョニングを楽にインストールをしたいと思ったのですが、なかなか難しいようです。 現状あんまり snap に頑張る気もないので、やめました、はい。

Windows パスの分離

WSL2 は WSL1 同様に、標準では Windows のPATH が $PATH に入ってきます。 これにより、WSL2 上で code . とすることで Remote WSL がVS Code で使えたりします。(~/docker.cfg も Windows の docker cred のパスが入っています)

Windows PATHがWSLで使えるのはすごく便利なのですが、WSL1 で Windows のパスとWSLのパスが競合してWSLでアプリ動作がおかしくなった経験があります。 そのため、 /etc/wsl.conf でPATH を停止しています。

[interop]
appendWindowsPath = False

wsl.conf をおいて、 wsl --shutdown を実行することでWSL上で Windows のパスが入らなくなります。

$ echo $PATH
/home/guitarrapc/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/guitarrapc/.dotnet/tools

まとめ

おおむねWSL2 にして幸せになります。 ディスク容量は明らかに食うようになるので、私は割り切ってシステムボリュームを1TB まで増やしてわずらわしさを感じないようにしました。 ただ、ラップトップでなくても、PCのシステムドライブはそれほど大きくないことも多いので要注意な感じがあります。