Apache Ossie を実際に動かしてみた — 仕様と実装のあいだで何が起きているか

Apache Ossie を実際に動かしてみた — 仕様と実装のあいだで何が起きているか

はじめに

以前、Open Semantic Interchange(OSI)のスコープと概要を別記事で整理した。今回はその続きで、実際に動かして仕様と実装の差を測った記録である。

対象は Apache Ossie(旧 OSI)。セマンティック層のベンダー中立標準で、2026年6月22日に Apache Incubator 入りし、OSI から改名した。「Write Once, Query Anywhere」を掲げている。

見出しだけを追うと標準化が着々と進んでいるように見える。実際に触ってみると、まだ整いきっていない部分にも出会う。どのバージョンを見ればいいのか、公式サンプルはなぜ動かないのか、参加企業のうち何社が実装しているのか。公開情報を追うだけでは答えが出ない。そこで仕様を一次読解したうえで dbt を相手に取り込ませ、いま実際にどこまで使えるのかを確かめた。

Ossie は発足して日が浅い。2025年9月に始まり、Apache Incubator 入りは4週間前(2026年6月22日)である。以下で挙げるつまずきには、仕様の設計に根ざすものと、バージョン管理や出力形式といった運用規約がまだ揃っていないものが混在する。両者は解け方が違うので、区別して記録する。

長い調査レポートは別途 Quarto で公開している。本記事はその要約で、根拠・出典・再現手順はレポート側に置いた。

以下はいずれも 2026-07-19 時点のスナップショットで、動きの速い領域を扱っている。数日で状況が変わりうる。

まず状況が分裂している

技術の中身に入る前に、名前・バージョン・ワーキンググループのいずれもが分裂していて、どれを見ればいいのか分からない。

最も混乱するのがバージョンだ。

  • 0.1.1 — 唯一のリリース版(正確にはタグ osi-0.1.1-rc1 で、正式リリースではない)。出荷版 dbt が受理するのはこちら。しかし公式サンプルもコンバータも存在しない
  • 0.2.0.dev0main の開発版。仕様本文に「本番で依存するな」と明記されている。しかし公式サンプル2本もリポジトリ内のコンバータ8本も、すべてこちらを対象にしている

つまり「動く実装がある方」には手本がなく、「手本がある方」には動く実装がない。リリース版と開発版の主役が入れ替わっている過渡期で、この非対称が以下の検証でのつまずきにつながる。裏を返せば、両者の足並みが揃えば解消する種類でもある。

なお ASF としての正式リリースはまだ1本も出ていない。署名鍵も未登録で、Apache Release を出す準備はこれからという段階だ。

動かして分かったこと

0.1.1 と 0.2.0.dev0 は揃っているツールチェーンが異なるため、2トラックに分けて検証した。すべて docker 内で完結させ、再現性のため実行中は外部ネットワークから切り離している。

1. dbt を挟んだ往復が、この構成では成立しない

リポジトリ同梱の公式コンバータで dbt プロジェクトから OSI 文書を生成し、同じ dbt に戻せるかを試した。成立しなかった。 しかも別々の層で3つの要因が重なっており、どれか1つを直しても残りで止まる。

  1. 公式コンバータの出力が、同一コミットの公式バリデータで落ちる。ルート構造は 0.1.1 のまま、version 文字列だけ 0.2.0.dev0 になっている
  2. dbt 側がそのバージョン文字列(0.2.0.dev0)を受理集合(0.1.0 / 0.1.1)から外して拒否する
  3. コンバータが source の識別子をクォート付きで出力し、dbt のモデル突き合わせ(クォートなし)と一致しない

3つはいずれも、バージョン管理・出力形式・識別子表記といった取り決めの層にある。メトリクスの意味をどう表現するかという設計上の難問とは別の種類で、取り決めを揃えれば解消しうる。ただしこれは本検証の固定コミット・dbt-core 1.12.0・特定入力での観測であり、製品やアダプタを横断する一般命題ではない。

2. 取り込み時に情報が落ちる

一方、手書きの 0.1.1 準拠文書は、公式バリデータを通り、dbt に取り込まれ、dbt run まで到達した。経路そのものは存在する。ただし取り込みの過程で2種類の情報が落ちる。

型情報が運ばれない。 OSI の dimension は「時間軸かどうか」の真偽値しか持たず、数値か文字列かを示す欄がない。結果として、数値の amount と文字列の status がどちらも同じ categorical(カテゴリ軸)として取り込まれた。合計したい金額が「値ごとに行を切り分ける軸」として扱われることになる。

集約関数が脱落する。 SUM(orders.amount)COUNT(orders.order_id) を書いたメトリクスを取り込むと、SUMCOUNT が消え、残ったのは対象列だけだった。OSI が集約をメトリクスの式として持つのに対し、dbt/MetricFlow は「measure への参照」を前提とするため、指すべき部品が存在せず、集約の指示が写像で落ちる。これは取り込み後の manifest 上での観測で、実行時にどう出るかは確認できていない。取り込んだメトリクスをローカルでクエリする手段が、出荷版ツールチェーンにないためだ(対応する dbt-metricflow が dbt-core 1.12 を除外している)。

3. 仕様に書かれていない前提が要る

OSI に適合しているだけでは dbt の取り込みは通らない。仕様の外に、走査対象は .json のみ・time spine モデルが要る・source が dbt 管理下のモデルと一致する必要がある、といった消費側の事情がある。

つまずきは3種類に分かれる

観測されたつまずきは、解けやすさの異なる3つに整理できる。

  • (1) 運用規約の未整備 — バージョン文字列の排他、コンバータの追随遅れ、識別子表記の未規定。仕様の設計を変えずに、取り決めを揃えれば解消する層である
  • (2) 仕様そのものの設計上の制約 — 型情報を運ばないこと、フィールドレベルの measure を持たない設計が消費側と噛み合わないこと。仕様を変えなければ解けず、どう変えるべきかも定まっていない。既存のセマンティック層が別々の答えを出してきた領域で、自明な正解がない
  • (3) 実装の数 — 製品として動く実装は現状2件(dbt Core 1.12、Honeydew。後者は有償・要問い合わせ)。実装が増えるほど (1)(2) も表面化し、修正の対象になる

運営も立ち上がり途中

技術面と重ねて運営面も見ておくと、ASF 移管から4週間の時点で、Apache Release はなく、署名鍵も未登録、仕様変更の [VOTE] が実行された記録もない。中核的な意味論の一部は Google Docs と Slack にある。

これらは移管から日が浅いことを踏まえて読む必要がある。ASF 流の運営が定着するには通常それなりの期間を要し、incubation 初期の podling が同様の状態にあることは珍しくない。mentor から是正が入る典型的な段階でもある。

そのうえで、ワーキンググループ一覧が公式内で3系統に食い違うことや、バージョン管理の食い違いは、何を正とするかが定まりきっていないことの表れに見える。技術的な難問ではなく、決める場の整備が追いついていない、という順序で理解するのが妥当だろう。

導入判断

現時点では、本番採用の条件は揃っていない。動く実装は2件で、リリース版 0.1.1 には公式サンプルもコンバータもなく、取り込み時に型情報と集約関数が落ち、その結果をローカルで検証する手段もない。

一方で、状況は速く動いている。直近数週間で実質的な変化が続いている(移管後4週間で merged PR 32本、expression_language.md の追加、dbt Core 1.12 での import + export の GA など)。本記事の結論も短期間で覆りうる。

現実的には、こう向き合うのがよい。

  • 今すぐ乗るのではなく、自社のセマンティックモデルを Ossie で表現できる形に保っておく。仕様の構造は素直で、dbt / Cube / LookML などから機械的に写像できる範囲にある
  • 特定ベンダーの固有機能に深く依存しない。依存する場合は custom_extensions(他ベンダーには解釈されない退避先)に落ちる部分がどこかを把握しておく
  • 中立性を取れば速度は落ちる。今必要な機能があるなら、単一ベンダーの実装を選ぶのは合理的でありうる

何を見ていれば状況が分かるか

公開情報から判定できる指標をいくつか挙げておく。

  • 初回の Apache Release が出るか(PGP 署名鍵の登録が前段階)
  • 仕様変更が ML の [VOTE] を通るようになるか。所属に関係なく反対意見が検討され、理由付きの合意が記録されるか
  • 0.1.1 と 0.2.0.dev0 の分裂が解消されるか(公式サンプルとコンバータがリリース版を向くか、あるいは 0.2.0 が正式リリースされるか)
  • 公式コンバータの出力が公式バリデータを通るようになるか(現状は通らない)
  • dbt と Honeydew 以外の3例目の実装が出るか

まとめ

指標定義の断片化という課題そのものは、現実に存在する。AI エージェントが指標を参照して判断を下すようになれば、定義の不一致は気づかれないまま下流へ伝播する。共通の記述形式を持つ意義は、今後さらに問われる。

2026年7月時点では、標準として本番に依拠する段階には至っていない。残る論点は、技術的な難しさ・運営の成熟・実装数の3つで、互いに絡んでいる。決める場が整うほど難しい判断が進み、実装が増える、という関係にある。

ASF 移管は運営面に働く変更で、移管からまだ4週間である。判断の材料が揃うのは、8月以降の月次 podling report と初回 Apache Release の頃になる。

根拠・出典・再現手順は調査レポート(https://dobachi.github.io/ossie-playground/)に置いた。動作確認は docker だけで追試できる。

参考

更新履歴

  • 2026-07-21: 初版
共有

Apache Iceberg と REST Catalog の仕組み — 調べて、動かして確かめた

Apache Iceberg と REST Catalog の仕組み — 調べて、動かして確かめた

概要

Apache Iceberg とその REST Catalog について、一次情報の裏取りを前提に調べ、あわせてローカル環境で実際に動かして確かめた。結果は2つのサイトに公開している。

本記事はその要点で、Iceberg の中核であるメタデータ構造とコミットの仕組みを中心にまとめる。どちらも個人的な調査メモであり、本番環境での利用を想定したものではない。

調べていて繰り返し出てきたのは、仕様と実装の距離である。仕様が定めていることと、ある実装が実際にできることは一致しない。この記事でも、仕様の記述と、手元で観測した挙動を分けて書く。

検証環境は Apache Iceberg 1.11.0 / PyIceberg 0.11.1 / Apache Polaris 1.6.0、検証基準日は 2026-07-17 である。

詳細

Iceberg とは何か(そして何でないか)

Iceberg はデータの保存形式ではない。データ本体は Parquet や ORC、Avro のままで、Iceberg が定めるのは、そのファイル群を1つのテーブルとして扱うための取り決め、つまりテーブル仕様である3

実体はオブジェクトストレージ上のファイル群だ。データも、スキーマも、スナップショットの履歴も、すべて S3 上に置かれる。ではカタログは何を持っているのかというと、「このテーブルの最新の metadata.json はどれか」というポインタ1本だけである。

この一点を押さえると、後の仕組みがつながる。Iceberg のコミットとは、カタログが持つポインタを新しい metadata.json に差し替えることに他ならない。

三層のメタデータ構造

ポインタの先は次のように連なる。

1
catalog → metadata.json → manifest list → manifest → data file

なぜ間に2層も挟むのか。クエリプランニングで段階的に枝刈りするためである。

第1段では manifest list に記録された各 manifest のパーティション要約統計だけを見て、manifest ファイル自体を開かずにスキップを判定する。第2段で残った manifest を開き、第3段で data file ごとの列統計(lower_bound / upper_bound)を使ってファイル単位で除外する。述語に合致しないファイルは、開かれることなく落ちる。

裏を返すと、統計が効かない条件ではこの枝刈りが働かない。既定値には注意が要る。

  • write.metadata.metrics.default = truncate(16) — 文字列の境界値は16文字で切り詰められる。URL のように共通プレフィックスが長い列では、https://example. までしか記録されず、ファイル間で境界値が同一になる。どの述語を投げても1ファイルも枝刈りできない
  • write.metadata.metrics.max-inferred-column-defaults = 100 — 101列目以降には既定でメトリクスが収集されない。ワイドテーブルで後方の列に述語をかけると全ファイル読みになる

どちらも「遅い」という形でしか表面化せず、原因にたどり着きにくい。

メタデータの肥大も構造上の帰結だ。手元の実験では、5行のデータを3回に分けて書いただけで、manifest ファイル(4434〜4438バイト)のほうが、それが記述する data file(1746〜1753バイト)より大きくなった。append 1回がスナップショット1個と metadata JSON 1個を生むためで、これは最適化の余地ではなく原子性のための要件である。高頻度コミットがメタデータを膨らませるのはこのためだ。

コミットは「ポインタの差し替え」

REST Catalog のコミットは POST /v1/{prefix}/namespaces/{namespace}/tables/{table} で行う。ボディは2つの配列でできている4

  • requirements — コミット前に成り立っていなければならない条件の表明(assert-table-uuidassert-ref-snapshot-id など)
  • updates — 適用したい変更(set-propertiesadd-snapshotset-snapshot-ref など)

サーバは requirements を現在の状態と突き合わせ、すべて満たされる場合にだけ updates を適用する。requirements は「自分が読んだ版はこれだ」という宣言であり、その版が変わっていればコミットは拒否される。

これが compare-and-swap による楽観的並行制御である。ロックを取らずに書きに行き、書く瞬間に「読んだときから変わっていないこと」を条件として付ける。衝突がまれであれば、ロックの管理コストを払わずに済む。

実際に古いスナップショット ID を表明して投げると、次のように拒否された。

1
2
3
4
5
6
7
{
"error": {
"message": "Requirement failed: branch main has changed: expected id 1234567890123456789 != 1472481652836649450",
"type": "CommitFailedException",
"code": 409
}
}

エラーメッセージが期待値と実際の値の両方を含んでいる。同時に送った set-properties は適用されていなかった。requirements が1つでも失敗すれば updates は一切適用されず、中途半端な状態が残ることはない。

requirements を正しい値に直して再送すると成功し、metadata-location00001-... から 00002-... へ移った。これがコミットの実体である。

なお仕様は、未知の requirement や update を受け取ったサーバは 400 で失敗しなければならないと定めている5。黙って読み飛ばす実装があると、クライアントは検証されたつもりでコミットが通ってしまうためだ。

409 と 500 を分ける理由

コミットの失敗には、意味の異なる2種類がある。

ステータス 意味 リトライ
409 CommitFailedException requirements が満たされなかった。確実に適用されていない 安全。読み直して再送
500 CommitStateUnknownException サーバが結果を確定できなかった。適用されたか不明 危険。そのまま再送してはいけない

500 の場合は、成功している可能性が残る。ポインタを書き換えたあと応答を返す前に落ちた場合がこれにあたる。単純にリトライすると、同じスナップショットをもう一度追加してしまう。

これを解消するのが Idempotency-Key ヘッダで、同じ鍵のリクエストをサーバが2回目以降は処理せず1回目の結果を返す。ただし対応は必須ではない。仕様は GET /v1/config のレスポンスに idempotency-key-lifetime が無ければ非対応とみなせと定めており6、フィールドの有無そのものが対応可否の宣言になっている。手元の Polaris 1.6.0 はこのフィールドを返さなかったため、500 を受けたらクライアント側でテーブルを読み直し、自分のコミットが入っているか確認する経路が要る。

同じ 409 が別の意味でも使われる点にも注意が要る。namespace 作成時の 409 は「すでに存在する」で、何度リトライしても結果は変わらない。ステータスコードだけで分岐すると無限にリトライする実装になるので、エラーボディの type を見る必要がある。

credential vending

クライアントが S3 上のデータを読むには、S3 の資格情報が要る。しかしそれを全クライアントに配ると、テーブル単位の権限管理が成立しない。カタログ側で「このユーザはこのテーブルだけ」と決めても、鍵を持っていればバケット全体を直接触れてしまうからだ。

credential vending はこの矛盾を解く。クライアントは S3 の鍵を持たず、カタログにテーブルを要求する。カタログは権限を確認したうえで、そのテーブルのパスにだけ有効な期限付きの鍵を発行する。

手元で loadTable を叩いたところ、実際に払い出された。

1
2
3
4
5
6
storage-credentials が 1 個返りました:
prefix: s3://warehouse/lab_catalog/lab/rest_demo
s3.access-key-id = ***
s3.secret-access-key = ***
s3.session-token = ***
expiration-time = 1784386178000

prefix がテーブル1つ分のパスになっている。カタログ全体でも namespace 単位でもない。s3.session-token が付いていることから、静的な鍵ではなく一時的な資格情報だと分かる。

ただし仕様上、これは要求であって保証ではない。クライアントが X-Iceberg-Access-Delegation ヘッダで要求しても、サーバは応じない選択ができる7

テーブル仕様のバージョンと、実装との距離

テーブル仕様は版で管理されている。v1 が基本形、v2 で position delete / equality delete による merge-on-read が入り、v3 で deletion vector と row lineage が加わった8

ここで冒頭の「仕様と実装の距離」が関わる。新規テーブルの既定は今も v2 である。v3 が定義されていることと、v3 が使えることは別だ。

PyIceberg 0.11.1 では v3 テーブルを作れない。試すと ValueError: Unsupported table format version: 3 になる。ソースを追うと二重にガードされていて、手前の upgrade_table_versionformat_version not in {1, 2} で弾いている9。その奥には「Writing V3 is not yet supported」という NotImplementedError もあるが10、手前で止まるため通常は到達しない。追跡 issue は 2026年7月時点で Open のままである11

紛らわしいのは型定義で、typedef.pyTableVersion = Literal[1, 2, 3] は v3 を許容しているように読める12。しかし実際に書けるのは v2 までである。型定義だけを見て対応状況を判断すると誤る。

さらに v4 は仕様として未採択でありながら、Java 実装は 1.10.0 以降 format-version=4 を設定できる。つまり「仕様が定めている」と「実装ができる」がどちらの方向にもずれる。

実装の制約は他にもある。PyIceberg で確認したものを挙げる。

できないこと 実態
format-version 3 の書き込み 上記のとおり。deletion vector も row lineage も使えない
equality delete の読み取り 書けないだけでなく読めない。Flink の UPSERT は equality delete ベースなので、その組み合わせは実害が出る
merge-on-read での書き込み プロパティを設定しても警告を出して copy-on-write に落ちる
compaction / orphan file 削除 MaintenanceTableexpire_snapshots のみ

「Python だけで Iceberg を運用する」は現時点で成立しない。読み取りと軽い書き込みは PyIceberg、メンテナンスと重い DML は Spark、という分担が現実的である。

カタログ実装を選ぶときに見るもの

REST Catalog は「サーバが仕様どおりの HTTP を話しさえすれば、クライアントは実装を知らずに済む」という差し替え可能性のために生まれた。実装は増えており、選定の観点も整理が要る。

開発の活発さを見るときは、コミット数に依存更新ボットの分が含まれる点に注意した。ある実装は直近365日で1,652コミットあったが、うち85.2%が renovate ボットで、人間のコミットは245件だった。リリース頻度が高いのも、依存更新を自動リリースしているためである。

ストレージ側にも変化があった。ローカル検証で使われてきた MinIO は、2026-04-25 にリポジトリがアーカイブされている13。入手可能な最新の公開イメージは、2025年10月の権限昇格の修正を含まない。Apache Polaris 公式も MinIO ガイドに maintenance mode の警告を出し、RustFS の例を追加している14。ここで流通している「ライセンスを AGPLv3 に変更したのが理由」という説明は誤りで、ライセンスは AGPLv3 のまま変わっていない。変わったのは保守方針と配布形態である。

認証は、そもそも使う経路に注意が要る。ラボでは便宜上 POST /v1/oauth/tokens でトークンを取得したが、このエンドポイントは仕様上 DEPRECATED for REMOVAL である15

The oauth/tokens endpoint is DEPRECATED for REMOVAL. It is not recommended to implement this endpoint, unless you are fully aware of the potential security implications.

Iceberg (Java) 1.6.0 で非推奨となり、2.0 で仕様から削除される予定と明記されている16。推奨されるのは、クライアントに oauth2-server-uri を設定して外部の IdP を使う構成である。学習用途で使う分には差し支えないが、本番構成の出発点にはならない。

この非推奨の経路では、OAuth2 の scope(Polaris では「どの principal role を有効化するか」の指定)に存在しないロール名を渡し、有効ロールが空になったトークンでも、テーブルを新規作成できた。ロール名自体は解釈されており、ログには roles=[] と警告が出る17。書き込みが通る理由までは追えていない。削除予定の経路での観測なので、外部 IdP を使う構成での挙動は別途確認が要る。

まとめ

Iceberg の中核設計は、確かめた範囲では一貫していた。field ID による列の解決、manifest を書いた時点の spec で解釈する規則、ポインタ差し替えによるコミット。これらは互いに噛み合っており、スキーマ進化とパーティション進化が既存データを書き換えずに成立する理由になっている。

一方で、「Iceberg が対応している」という表現は、どの仕様バージョンの、どの実装の話かを伴わなければ意味を持たない。仕様は v3 で deletion vector を定義し v4 が議論されているが、PyIceberg は v3 を書けず、Java 実装は未採択の v4 を既に受け付ける。仕様・実装・記事の3つは一致しないという前提で読む必要がある。

判断に使う数値やバージョンは、この記事も含めて一次情報で確認してほしい。調べた範囲と、確かめられなかったことは公開したサイト1819に明記してある。

参考文献

更新履歴

  • 2026-07-19: 初版

  1. dobachi, "Apache Iceberg 調査報告書", アクセス日 2026-07-19↩︎

  2. dobachi, "Iceberg REST Lab", アクセス日 2026-07-19↩︎

  3. Apache Iceberg, "Iceberg Table Spec", アクセス日 2026-07-19↩︎

  4. Apache Iceberg, "Iceberg REST Catalog OpenAPI 仕様", アクセス日 2026-07-19↩︎

  5. Apache Iceberg, "Iceberg REST Catalog OpenAPI 仕様", アクセス日 2026-07-19↩︎

  6. Apache Iceberg, "Iceberg REST Catalog OpenAPI 仕様", アクセス日 2026-07-19↩︎

  7. Apache Iceberg, "Iceberg REST Catalog OpenAPI 仕様", アクセス日 2026-07-19↩︎

  8. Apache Iceberg, "Iceberg Table Spec", アクセス日 2026-07-19↩︎

  9. PyIceberg, "table/init.py L338(upgrade_table_version のバージョン検証)", アクセス日 2026-07-19↩︎

  10. PyIceberg, "table/metadata.py L578(Writing V3 is not yet supported)", アクセス日 2026-07-19↩︎

  11. apache/iceberg-python, "Issue #1551: Support writing V3 metadata", アクセス日 2026-07-19↩︎

  12. PyIceberg, "typedef.py L212(TableVersion の定義)", アクセス日 2026-07-19↩︎

  13. MinIO, "minio/minio リポジトリ(アーカイブ済み)", アクセス日 2026-07-19↩︎

  14. apache/polaris, "PR #3482: RustFS の例を追加", アクセス日 2026-07-19↩︎

  15. Apache Iceberg, "Iceberg REST Catalog OpenAPI 仕様", アクセス日 2026-07-19↩︎

  16. Apache Iceberg, "Iceberg REST Catalog OpenAPI 仕様", アクセス日 2026-07-19↩︎

  17. Apache Polaris, "DefaultAuthenticator.java(principal role の解決)", アクセス日 2026-07-19↩︎

  18. dobachi, "Apache Iceberg 調査報告書", アクセス日 2026-07-19↩︎

  19. dobachi, "Iceberg REST Lab", アクセス日 2026-07-19↩︎

共有

Keychron Nape Pro の設定をバックアップ・復元する(非公式ツール NapeProConfiguration)

はじめに

Keychron Nape Pro は、専用のブラウザアプリ「Keychron Launcher」からキーマップやエンコーダ、DPI などを設定できるキーボードである。 ただし現時点の Launcher には、設定内容をファイルとして書き出す「エクスポート」や、書き戻す「インポート」の機能が用意されていない。

このため、次のような場面で困ることがある。

  • 設定をリセットしてしまい、また一から手作業でやり直す羽目になった
  • 別の Nape Pro でも同じ設定を再現したいが、手で写すしかない
  • 気に入った配列を「プロファイル」として残しておきたい

この課題を補うために、非公式のツール群として NapeProConfiguration を用意した。設定を JSON としてバックアップし、必要なときに復元するための手順をまとめる。

免責事項 本記事で紹介するツールは Keychron 公式の機能ではなく、ブラウザの WebHID API を通じてキーボードを直接操作する非公式のものである。 公式サポートの対象外であり、利用はすべて自己責任で行っていただきたい。

背景:なぜ設定のバックアップが難しいのか

Nape Pro の設定は、Launcher と キーボードの間で HID(Human Interface Device)というプロトコルを通じてやり取りされている。 キーボードによっては設定を JSON として書き出し・読み込みできるものもあるが、Nape Pro の Launcher にはその入口がなく、また通信仕様も公開されていない。

そこで NapeProConfiguration では、ブラウザ標準の WebHID API を通じて Launcher と同じようにキーボードと通信し、設定内容を JSON ファイルとして取り出す・書き戻すという方法を採っている。

NapeProConfiguration の概要

リポジトリは大きく次の3つで構成されている。

ディレクトリ 内容
tools/ エクスポート/インポートを行うスクリプト(ユーザースクリプト・ブックマークレット・コンソール貼り付け用)
docs/ HID プロトコルのリファレンスや調査データ
configs/ テーマ別の設定プロファイル(テンプレート)

利用者としてまず触れるのは tools/ で、実行方法として次の3通りが用意されている。

  1. ユーザースクリプト(Tampermonkey 等)— Launcher に Export/Import ボタンを常時表示する。おすすめ
  2. ブックマークレット — 拡張機能のインストール不要で使える
  3. コンソール手動貼り付け — スクリプトを開発者ツールに貼って実行する

動作確認環境

以下の環境で動作を確認している。バージョンが異なると、内部の設定構造が変わっていて動かないことがある。

  • Keychron Launcher: V1.3.8
  • Nape Pro ファームウェア: v1.2.3-ZK / v1.2.5-ZK

WebHID API に対応したブラウザ(Google Chrome や Microsoft Edge など Chromium 系)が必要である。

仕組み(概要)

NapeProConfiguration の動作イメージは以下の通りである。

NapeProConfiguration 仕組み概要
  • Launcher のページ上で動くスクリプトが、WebHID API 経由でキーボードに接続する
  • エクスポート時は、キーマップ・エンコーダ・DPI などの現在値を読み出し、バージョン情報を添えて JSON ファイルとしてダウンロードする
  • インポート時は、JSON を読み込み、その内容をキーボードへ書き戻す

HID プロトコルの詳細は docs/ にリファレンスとしてまとめてある。

なお、WebHID のデバイス権限は Launcher のページに紐づく。そのため、どの実行方法であっても、スクリプトは launcher.keychron.com を開いたそのページ上で動かす必要がある。別タブやローカルの HTML ファイルからはデバイスにアクセスできない。

使い方1:ユーザースクリプト(おすすめ)

Launcher を開くたびに Export/Import ボタンが表示されるため、日常的に使うならこの方法が最も手軽である。

  1. ブラウザに Tampermonkey(または Violentmonkey)拡張をインストールする
  2. 拡張のメニューから「新規スクリプト」を選び、tools/nape-pro-export.user.js の内容を貼り付けて保存する
  3. Keychron Launcher のページを開き、Nape Pro を接続する
  4. 画面右下に表示される 「⬇ Export / ⬆ Import」 ボタンを使う
    • エクスポート: ボタンをクリックすると JSON が自動的にダウンロードされる
    • インポート: ボタンをクリックし、ファイル選択ダイアログで JSON を指定する

使い方2:ブックマークレット(インストール不要)

拡張機能を入れたくない場合は、ブックマークレットが使える。

  1. ブラウザに2つのブックマークを登録する
    • 名前「Nape Pro Export」/ URL に tools/export-bookmarklet.txt の内容を貼り付ける
    • 名前「Nape Pro Import」/ URL に tools/import-bookmarklet.txt の内容を貼り付ける
  2. Launcher を開き、Nape Pro を接続する
  3. 目的に応じてブックマークをクリックする
    • エクスポート: nape-pro-settings-YYYY-MM-DD.json が自動的にダウンロードされる
    • インポート: ファイル選択ダイアログで JSON を選ぶと、デバイスに書き込まれる

使い方3:コンソール手動貼り付け

一度きりの作業なら、スクリプトを開発者ツールに貼り付けて実行する方法もある。

エクスポート

  1. Launcher を開き、Nape Pro を接続する
  2. 開発者ツールを開き(F12 または Ctrl+Shift+I)、Console タブを選ぶ
  3. 初回のみ、貼り付けに関するセキュリティ警告が出るので、指示に従って allow pasting と入力する
  4. tools/export-nape-pro-settings.js の内容を貼り付けて Enter を押す
  5. JSON が自動的にダウンロードされる

インポート

  1. Console に tools/import-nape-pro-settings.js の内容を貼り付けて Enter を押す
  2. ファイル選択ダイアログで JSON を選ぶ
  3. キーマップ・エンコーダ・DPI などがデバイスに書き込まれる
  4. Launcher の画面をリロードすると反映が確認できる

出力される JSON と設定プロファイル

エクスポートで得られるのは JSON ファイルで、キーマップ・エンコーダ・DPI などの設定値に加えて、ファームウェアや Launcher のバージョン情報も記録される。 バージョンが記録されているため、後から「どの環境で取ったバックアップか」を判断しやすい。

また configs/ には、あらかじめ用意された設定プロファイル(例: main-side-and-presentation)が置かれている。 一から作らず、こうしたテンプレートを取り込んで出発点にすることもできる。

注意点

  • バージョン差異: 動作確認環境と Launcher/ファームウェアのバージョンが違う場合、設定構造の変更により正しく動作しないことがある。まずは自分の環境のバージョンを確認しておきたい。なおインポート時には、書き込み前にデバイスの現在のバージョンとファイルに記録されたバージョンを照合し、食い違えば確認ダイアログが出て続行するかどうかを選べる(Launcher バージョンは取得できないと照合をスキップすることがある)。
  • バックアップを先に取る: インポートは設定を上書きする操作である。試す前に、現在の設定をエクスポートして手元に残しておく。
  • 非公式・自己責任: 公式サポートの対象外である。うまくいかない場合は、Launcher からの手動設定に切り替える判断も必要になる。

まとめ

Keychron Nape Pro の Launcher には設定の書き出し・読み込み機能がないが、WebHID を利用した非公式ツール NapeProConfiguration を使えば、設定を JSON としてバックアップし、必要なときに復元できる。日常的に使うならボタンが常時出るユーザースクリプト方式が手軽で、インストールを避けたいならブックマークレット、一度きりならコンソール貼り付けを選ぶとよい。

参考リンク

共有

IDSA Connector Report 2026 — DSP 2025-1 と DCP 1.0 でコネクタエコシステムが成熟段階へ

IDSA Connector Report 2026 — DSP 2025-1 と DCP 1.0 でコネクタエコシステムが成熟段階へ

概要

IDSA(International Data Spaces Association)が2026年6月30日付で「Connector Report」を更新した。今回は DSP 2025-1 と DCP 1.0 のリリースが主軸であり、テスト(TCK)合格コネクタ数が8件に達するなど、データスペースのインフラが実装・拡張フェーズへ移行したことを示している。また、自動車業界主導だった Tractus-X も他産業へ展開する「multi-industry」戦略へ舵を切った。

詳細

プロトコル標準の確立: DSP 2025-1 と後方互換性

主要コネクタが共通標準として DSP 2025-1 を採択した。旧バージョン(DSP 0.8)との後方互換性も維持されており、既存のコネクタ資産を段階的に移行できる1

DSPとDCPによるコネクタエコシステム

DCP 1.0 と TCK 合格エコシステム

TCK合格コネクタは8件。EDCフレームワークをベースに、DCP 1.0およびDSP 2025-1のサポートが実装されている2。特にDCP 1.0による分散クレーム認証(Decentralized Claims)が実用レベルに達したことで、データスペースにおけるアイデンティティ管理とコネクタ接続の統合が現実的になった。

DSP 2025-1 と DCP 1.0 の役割分担

DSP と DCP は、いずれも Eclipse Dataspace Working Group(EDWG)が管理する別々の仕様だが、レイヤーが異なり互いを補完する。

仕様 担うレイヤー 標準化する範囲
DSP 2025-1 データ取引の制御 カタログ(アセットとODRLポリシーの公開・発見)、契約交渉のステートマシン、データ転送プロセスの制御
DCP 1.0 アイデンティティと信頼 Verifiable Presentation の提示・検証、クレデンシャル発行、自己署名アイデンティティトークンの形式

DSP は認証方式に対して中立で、HTTPSリクエストは Authorization ヘッダにトークンを載せる(SHOULD)とだけ定め、「トークンの意味づけは本仕様の対象外」としている。中身が OAuth2 か OIDC か分散IDかは問わない3。DCP はそこに載せるトークンとして、W3C の Verifiable Credential / Presentation や自己署名アイデンティティトークンの生成・検証手順を定める4

EDCベースのコネクタでは、両者は次のように組み合わさる。消費者コネクタが Credential Service(Identity Hub)で DCP 準拠のトークンを生成し、DSP の各メッセージ(カタログ取得・契約交渉・転送要求)の Authorization ヘッダに載せて送る。受け取ったプロバイダは DCP の手順でトークンとクレデンシャルを検証し、相手がデータスペースの正規メンバーか、契約を結ぶ属性を満たすかを判定してから、DSP のカタログ・交渉・転送処理を実行する5。検証は特定の一点ではなく、カタログ要求・契約交渉・データ転送の各段階で行われる。

なお DSP 2025-1 は DCP を規範的に必須とはしていない。OAuth2 や OIDC といった集中型・フェデレーション型の認証と組み合わせることも仕様上は可能である6。ただし分散・主権型のデータスペースを構築する EDC や Catena-X の実装では、DSP と DCP をペアで導入する構成が事実上の標準になっている7

EDC の本番導入障壁の低下(単一ソース情報)

EDCの本番運用に向けた改善として、EDR(Endpoint Data Reference)トークンのリフレッシュ機能追加や、Kubernetes用Helm Chartの整備が挙げられている8。これによりコンテナ環境での運用が標準化され、導入のハードルが下がった。

Tractus-X の multi-industry 転換と EDWG 提携

Tractus-Xはこれまでの自動車業界(Catena-X)特化から、複数産業や異なるデータスペースを繋ぐ「multi-dataspace / multi-industry」戦略へシフトした。2026年2月にマドリードで開催されたData Spaces Symposiumにおいて、EDWGとの公式連携が合意されている9。アーキテクチャは製造業、半導体、建設、化学などの他セクターへの横展開を見据えた設計に変更された10。あわせて、IDS認証(Level 1〜2)の段階的な認定スキームも整備された11

考察

DSP 2025-1とDCP 1.0の同時リリースは、データスペースの技術レイヤーが仕様策定から実用フェーズへ入ったことを意味する。これまで各プロジェクトで個別実装されがちだったアイデンティティ連携がDCP 1.0として規格化され、異なるデータスペース間でも共通の信頼基盤を構築しやすくなった点は大きい。

Tractus-Xの他産業展開も、この技術的標準化が背景にある。Catena-Xで培った仕組みをポータブルな基盤として化学や半導体といった他業界に水平展開することで、IDSAやGaia-Xが描く「欧州データスペース of 共通インフラ」という構想の実効性が高まる。

ただし、TCK合格コネクタがまだ8件に留まっている点は課題だ。実運用を広げるには、認定プロセスの効率化はもちろん、EDC以外の独自実装コネクタ(例えば国産コネクタや他ベンダーの軽量コネクタなど)の合格例が増える必要がある。

参考文献

更新履歴

  • 2026-07-11: 初版
  • 2026-07-12: 「DSP 2025-1 と DCP 1.0 の役割分担」章を追加

  1. IDSA, "IDSA Data Space Connector Report", アクセス日 2026-07-11↩︎

  2. IDSA, "IDSA Data Space Connector Report", アクセス日 2026-07-11↩︎

  3. Eclipse Dataspace Working Group, "Dataspace Protocol", アクセス日 2026-07-12↩︎

  4. Eclipse Dataspace Working Group, "Decentralized Claims Protocol", アクセス日 2026-07-12↩︎

  5. Eclipse Dataspace Working Group, "Decentralized Claims Protocol", アクセス日 2026-07-12↩︎

  6. Eclipse Dataspace Working Group, "Dataspace Protocol", アクセス日 2026-07-12↩︎

  7. Eclipse Dataspace Working Group, "Decentralized Claims Protocol", アクセス日 2026-07-12↩︎

  8. IDSA, "IDSA Data Space Connector Report", アクセス日 2026-07-11↩︎

  9. Eclipse Tractus-X, "Tractus-X Blog", アクセス日 2026-07-11↩︎

  10. Eclipse Tractus-X, "Tractus-X Blog", アクセス日 2026-07-11↩︎

  11. IDSA, "IDSA Data Space Connector Report", アクセス日 2026-07-11↩︎

共有

Open Semantic Interchange (OSI) 技術深掘り — スコープと利用実例

Open Semantic Interchange (OSI) 技術深掘り — スコープと利用実例

概要

Open Semantic Interchange(OSI)は、セマンティック層の構成要素(データセット・メトリクス・ディメンション・関係・コンテキスト)をベンダー中立かつ拡張可能な形式で表現するオープン標準だ。Snowflake が主導し、Salesforce・dbt Labs・BlackRock らと2025年9月23日に発足、2026年1月27日に初版仕様(v0.1系)を GitHub 上で公開した12。「Write Once, Query Anywhere」の原則で、メトリクス定義を一度書けば BI・AI・分析ツール間で一貫して解釈できるようにする。2026年6月には Apache Software Foundation の Incubator に受け入れられ、「Apache Ossie (incubating)」として開発が続いている3

詳細

仕様概要とライセンス

OSI は YAML/JSON で宣言的にセマンティックモデルを定義する Apache 2.0 ライセンスのオープン標準である45。ベンダー中立な形式で構成要素を定義し、BI・AI・分析ツール間で一貫した解釈を可能にする6。公開された初版はバージョン v0.1 系で、dbt の実装も document version 0.1.0 / 0.1.1 を対象としている7。「v1.0」という表記が流通することがあるが、正式なバージョンタグではない点に注意したい。

OSIのスコープ

OSI は「論理的なセマンティック層」に範囲を絞り、物理層や実行層には踏み込まない。何を対象とし、何を対象外とするかは明確に線引きされている8

区分 内容
スコープ内 Semantic Model(データセット・関係・メトリクスを束ねる最上位コンテナ)、Datasets(ファクト/ディメンションの論理エンティティ、主キー・一意キー)、Fields(グルーピング・フィルタ・式に使う行レベル属性)、Relationships(データセット間の外部キー、単純/複合キー)、Metrics(複数データセットにまたがる集計指標)、Custom Extensions(ベンダー固有メタデータ)、AI Context(指示・同義語・サンプルクエリ等の注釈)
スコープ外 物理データ形式(Parquet・Arrow)、クエリ/アクセスインターフェース(ODBC・JDBC)、カタログメタデータ(Hive Metastore 等)、クエリの実行そのもの

OSI はこれらの既存標準を置き換えるものではなく、補完する位置づけを明言している9。オーサリングツールを置き換えるのではなく、その出力を相互運用可能にすることが狙いだ。Custom Extensions は互換性保証の対象外だが、仕様を理解しないツールを経由しても往復変換で保持されるため、ベンダー間の変換で情報が失われない10

技術的イメージと利用実例

構造はハブ&スポークだ。各ツールが OSI という単一の交換フォーマットを介するため、ツール同士を N×N で個別接続する必要がなくなる。定義側(dbt/MetricFlow、Snowflake、Cube など)が OSI を出力し、利用側(Tableau・Sigma・ThoughtSpot などの BI、AI エージェント、分析ツール)が OSI を読む。

OSIによるWrite Once, Query Anywhereのハブ&スポーク構造

技術的な特徴のひとつが、フィールドやメトリクスの式を SQL 方言ごとに持てることだ。同じ論理定義に対して、実行先の方言に応じた式を並記する11

1
2
3
4
5
6
7
8
expression:
dialects:
- dialect: ANSI_SQL
expression: LOWER(email)
- dialect: SNOWFLAKE
expression: LOWER(email)::VARCHAR
- dialect: DATABRICKS
expression: lower(email)

実装例として、dbt Core は v1.12 以降で OSI をサポートする。プロジェクト直下の OSI/ ディレクトリ(または dbt_project.ymlosi-paths で指定した場所)に OSI ドキュメントを置き、dbt compile または dbt run で解析させると、target/ 配下に osi_document.jsonmanifest.jsonsemantic_manifest.json が生成される12。OSI 由来の定義と dbt ネイティブのセマンティックモデルは同一プロジェクトで共存できる13

1
2
3
4
5
6
7
8
9
10
11
{
"version": "0.1.1",
"semantic_model": [
{
"name": "orders",
"datasets": [
{ "name": "orders", "source": "my_database.my_schema.fct_orders" }
]
}
]
}

source はウェアハウス上の完全修飾名(database.schema.table)で、dbt は各データセットを既存の dbt モデルに突き合わせる14。エクスポート側では、データカタログの Dawiso がデータプロダクトを OSI 形式へ書き出す機能を提供している。コア開発は Snowflake・dbt Labs・Dremio が担う15

参加組織とワーキンググループ

参加組織は50を超える。Snowflake・Databricks・Salesforce・Oracle・Alation・BlackRock・ServiceNow・Mistral AI などが名を連ねる1617

ワーキンググループの一覧については、公式情報の中に三系統が並存している点に注意が要る。

実態に最も近いのはリポジトリ内の docs/working_groups.md である。各グループにリード担当者と Slack チャンネルが割り当てられており、実際に会合が回っているのはこの単位だ18

ワーキンググループ リード
Metric Language and Relationships Will Pugh
Composability Dianne Wood(AtScale)
Catalog Shubham Bhargav(Atlan)
Ontology Kurt(RelationalAI)
Sync API Francois Lopitaux(ThoughtSpot)

一方、公式サイトのトップページも5つを掲げるが、名称が一致しない19。「Sync API」に対応する項目がなく、代わりに「Model Converters & Developer Tools」が入る。

  • Advanced Metrics & Expression Language(高度なメトリクスと式言語)
  • Composability(合成可能性)
  • Catalog Integration(カタログ統合)
  • Ontology Representation(オントロジー表現)
  • Model Converters & Developer Tools(モデル変換と開発者ツール)

さらに ROADMAP は「Current Efforts / Working Groups」として3つに絞る20

  • Metric Semantics & Core Semantic Model(メトリクス意味論とコアモデル)
  • Catalog Integration & Semantic Services(カタログ統合とセマンティックサービス)
  • Ontology & Semantic Interoperability(オントロジーと意味的相互運用)

さらに ROADMAP には「Future Efforts」として7項目が並ぶ。これらは着手前の構想であり、現行のワークストリームではない21

  • Dataset Abstraction & Logical Modeling(データセット抽象化と論理モデリング)
  • Semantic Query Language & Reference Engine(セマンティッククエリ言語と参照エンジン)
  • SQL Dialect, Expressions, and Execution Boundaries(SQL方言・式・実行境界)
  • Dimensions, Hierarchies, and Time Semantics(ディメンション・階層・時間意味論)
  • AI-Native Semantic Layer(AIネイティブなセマンティック層)
  • Governance, Identity, and Validation(ガバナンス・アイデンティティ・検証)
  • Industry / Domain-Specific Semantic Models(業界・ドメイン特化モデル)

粒度も名称も揃っておらず、2026年7月時点でこの不整合は解消されていない。ASF移管のアナウンスは ROADMAP 側の3つを採っている22。実際に動いているワークストリームを知りたければ、ROADMAP の Current Efforts を見るのが確実だ。

初回のワーキンググループ会合は2025年10月に開かれた23。業界特化の動きとして、2026年には金融サービス向けのセマンティック WG が立ち上がり、Net Asset Value のような定義の統一を進めている24

AI統合対応

OSI は AI エージェントにセマンティックコンテキストを渡すことを設計に組み込んでいる。AI Context として、指示・同義語・サンプルクエリといった注釈をモデルに付与できる25。すべてのツールとエージェントが同一の定義から動くことで、チーム間の定義不一致や重複作業を避けられる26

異なるセマンティックモデルをまたぐ連携

押さえるべき線引きは、OSI が与えるのは「フォーマット(構造)の相互運用」であって「意味の自動突き合わせ」ではない、という点だ。

OSIはフォーマットを統一するが、意味の整合はマッピングと共通語彙層が担う

A社とB社が別々のセマンティックモデルを持つ場合、OSI は両社のモデルを同じ文法(YAML/JSON)で表現させる。相手のメトリクス定義(式・ディメンション・関係・方言別の式)が機械可読で明示的になり、プロプライエタリなサイロや専用コネクタから解放される。ただし A社の「churn」と B社の「churn」を自動で同一視することはしない。定義が食い違えば OSI はその差分を正確に可視化するが、対応づけ(マッピングや統一定義の合意)は当事者のガバナンスに委ねられる。コア仕様にモデル間クロスウォークの仕組みはまだなく、ロードマップ上の目標にとどまる27

この線引きは Apache Ossie の ROADMAP でも明言されている。「現状は構造的相互運用は解けている(どのツールも共通フォーマットでモデルを読み書きできる)が、概念的相互運用(conceptual interoperability)はまだ解けていない」という認識だ28。差分を可視化した先を担う取り組みも進む。「Dataset Abstraction & Logical Modeling」はモデルをまたいだデータセット・関係の再利用(composability)を、「Ontology & Semantic Interoperability」は業務概念を物理レイアウトから切り離し、オントロジーベースのモデルとモデル間の概念的アラインメントを可能にすることを目標に掲げる29

業界横断では「業界が OSI の上に共通ドメイン語彙を作る」パターンになる。金融サービス向けのセマンティック WG は、Net Asset Value のような定義を業界で揃えようとする例だ30。異なる業界どうしなら、双方が参照する共通リファレンス・オントロジー(金融の FIBO など)へのマッピングが鍵になるが、これは現時点ではロードマップであり、完成したスキーマ機能ではない31

要するに、OSI は共通の文法・ファイル形式であって共通の意味辞書ではない。「同じ単語で違う意味」を自動解決はしないが、各自の意味を交渉可能なほど明示化し、Composability や Ontology 層で整合を積み上げる土台を与える。

考察

OSI が解くのは「セマンティック層の断片化」という古くて新しい問題だ。BI 時代にはメトリクス定義の不統一がダッシュボード間の数字の食い違いを生んでいた。AI エージェントが普及した今、定義の不統一はエージェントの判断誤りに直結するため、共通の定義基盤の価値は質的に高まる。

一方で普及の速度は、WG が実装ガイドと相互運用テストをどれだけ早く整備できるかに依存する。ここで効いてくるのが Apache Incubator への移管だ。特定ベンダーのイニシアチブから中立な財団のガバナンス下に移ったことで、参加ベンダーが安心して実装へ投資しやすくなる。dbt Core のように import が実際に動く実装が出てきた段階であり、今後は Snowflake・Cube・BI 各社の export/import がどこまで揃うかが分岐点になる。

参考文献

更新履歴

  • 2026-07-10: 初版
  • 2026-07-13: ワーキンググループの記述を最新の Apache Ossie ROADMAP に合わせて修正し、WG関連の出典(ROADMAP・初回WG会合・金融WG)を追加。仕様リポジトリのURLを Apache Ossie に更新
  • 2026-07-19: ワーキンググループの記述を訂正。ROADMAP の「Current Efforts」3件と「Future Efforts」7件を一列に並べ、計10件すべてを現行WGとして記載していた誤りを修正し、両者を区別した。あわせて、リポジトリの docs/working_groups.md・公式サイトのトップページ・ROADMAP の三者で一覧が食い違っている実態を追記し、リード担当者と Slack チャンネルを伴う docs/working_groups.md を実態に最も近いものとして本文に加えた

  1. Open Semantic Interchange, "Open Semantic Interchange", アクセス日 2026-07-10↩︎

  2. Snowflake, "Open Semantic Interchange (OSI) Specification Finalized", アクセス日 2026-07-10↩︎

  3. Apache Incubator, "Apache Ossie (incubating)", アクセス日 2026-07-12↩︎

  4. Open Semantic Interchange, "Open Semantic Interchange", アクセス日 2026-07-10↩︎

  5. Snowflake, "Open Semantic Interchange (OSI) Specification Finalized", アクセス日 2026-07-10↩︎

  6. Open Semantic Interchange, "Open Semantic Interchange", アクセス日 2026-07-10↩︎

  7. dbt Labs, "OSI semantic layer documents", アクセス日 2026-07-12↩︎

  8. Apache Ossie, "Apache Ossie (旧 OSI) 仕様リポジトリ", アクセス日 2026-07-13↩︎

  9. Apache Ossie, "Apache Ossie (旧 OSI) 仕様リポジトリ", アクセス日 2026-07-13↩︎

  10. Apache Ossie, "Apache Ossie (旧 OSI) 仕様リポジトリ", アクセス日 2026-07-13↩︎

  11. Apache Ossie, "Apache Ossie (旧 OSI) 仕様リポジトリ", アクセス日 2026-07-13↩︎

  12. dbt Labs, "OSI semantic layer documents", アクセス日 2026-07-12↩︎

  13. dbt Labs, "OSI semantic layer documents", アクセス日 2026-07-12↩︎

  14. dbt Labs, "OSI semantic layer documents", アクセス日 2026-07-12↩︎

  15. Apache Incubator, "Apache Ossie (incubating)", アクセス日 2026-07-12↩︎

  16. Open Semantic Interchange, "Open Semantic Interchange", アクセス日 2026-07-10↩︎

  17. Snowflake, "Open Semantic Interchange (OSI) Specification Finalized", アクセス日 2026-07-10↩︎

  18. Apache Ossie, "docs/working_groups.md", アクセス日 2026-07-19↩︎

  19. Open Semantic Interchange, "Open Semantic Interchange", アクセス日 2026-07-10↩︎

  20. Apache Ossie, "ROADMAP.md — Current Efforts / Working Groups", アクセス日 2026-07-13↩︎

  21. Apache Ossie, "ROADMAP.md — Current Efforts / Working Groups", アクセス日 2026-07-13↩︎

  22. Apache Ossie, "Apache Ossie (Incubating): The New Name for Open Semantic Interchange", アクセス日 2026-07-19↩︎

  23. Snowflake, "OSI Further Expands Partner Ecosystem and Holds First Working Group Meeting", アクセス日 2026-07-13↩︎

  24. Open Semantic Interchange, "Updates(金融サービス向けWG ほか)", アクセス日 2026-07-13↩︎

  25. Apache Ossie, "Apache Ossie (旧 OSI) 仕様リポジトリ", アクセス日 2026-07-13↩︎

  26. Snowflake, "Open Semantic Interchange (OSI) Specification Finalized", アクセス日 2026-07-10↩︎

  27. Apache Ossie, "Apache Ossie (旧 OSI) 仕様リポジトリ", アクセス日 2026-07-13↩︎

  28. Apache Ossie, "ROADMAP.md — Current Efforts / Working Groups", アクセス日 2026-07-13↩︎

  29. Apache Ossie, "ROADMAP.md — Current Efforts / Working Groups", アクセス日 2026-07-13↩︎

  30. Open Semantic Interchange, "Updates(金融サービス向けWG ほか)", アクセス日 2026-07-13↩︎

  31. Apache Ossie, "ROADMAP.md — Current Efforts / Working Groups", アクセス日 2026-07-13↩︎

共有

EU Data Act B2B by design 2026 — 日本の電気・機械メーカーへの具体的影響

EU Data Act B2B by design 2026 — 日本の電気・機械メーカーへの具体的影響

概要

EU Data Act(EU規則2023/2854)は、コネクテッド製品のデータアクセス権を段階的に義務化する規則だ。2025年9月12日のPhase 1施行に続き、2026年9月12日にはアクセス機能を製品設計段階で組み込む「access-by-design」義務が発効する。EU市場で製品を販売する日本の電気・機械メーカーは、設立地を問わず規制対象となる。対応すべき実務は、製品再設計・契約対応・法的代理人の選任の3点に整理できる。

詳細

Phase 1 → Phase 2 の段階的義務化

EU Data Act の施行は二段階に分かれている。2025年9月12日のPhase 1では、EU向けコネクテッド製品のメーカーに対し、B2B・B2Cを問わずユーザーへのデータアクセス権の付与が義務付けられた12。データは「遅延なく、無償で、継続的かつリアルタイムに」提供しなければならない。ただし規則本文(第4条)では、継続的・リアルタイムの提供は「関連性があり技術的に可能な場合」に限られる3

2026年9月12日からのPhase 2では、この日以降にEU市場へ新規投入するコネクテッド製品に「access-by-design」義務が課される。データアクセス機能を、デフォルトで容易・安全・直接に利用できる形で製品設計段階から実装する必要がある(第3条、「関連性があり技術的に可能な場合」の限定付き)4。過去に上市済みの製品を遡及的に再設計する義務ではないが、同一モデルでも2026年9月12日以降に初めて出荷する個体は本義務の対象となる。

なお「Phase 1 / Phase 2」は施行スケジュールを説明するための呼称で、規則本文が用いる法令用語ではない。

EU Data Act の段階的義務化と日本メーカーへの適用

日本メーカーへの適用範囲

日本に法人を置くメーカーでも、EU市場でコネクテッド製品を販売する場合は規制対象となる56。Data Act は特定業界に限定しない水平規則で、データ収集・通信機能を持つ産業機器・農業機械・医療機器が対象に含まれる7。IoT機能を搭載した工場設備や農業用機械も対象になりうる。

B2B・B2C 双方への適用とFRAND条件

データアクセス権はビジネスユーザー(B2B)にも消費者(B2C)にも等しく適用される89。B2Bのデータ共有には、FRAND(公正・合理的・非差別的)条件が義務付けられる10。中小企業(SME)向けのデータ提供対価は、データ提供にかかる直接コストを上限とし、利益マージンを上乗せできない(第9条2項)11

考察

2026年9月の「access-by-design」義務は、要求仕様を後付けで満たす「パッチ型」対応では費用対効果が悪い。製品ロードマップへ前倒しで統合する方が合理的だ。特に影響が大きいのは、「データはメーカーが保有・活用する」という前提のまま開発されてきたIoT機器群で、アーキテクチャ全体の見直しを迫られる。

FRAND条件の実装では、データ仲介レイヤーや標準API仕様の活用が実務的な選択肢になる。あわせて、EU域外企業に課される法的代理人の選任要件は、日本企業が見落としやすい実務コストであり、早めの手当てが要る。

参考文献

更新履歴

  • 2026-07-10: 初版

  1. Wilson Sonsini, "EU Data Act September 2026 Deadline: What Businesses Need to Know", アクセス日 2026-07-10↩︎

  2. Faegre Drinker, "The EU Data Act: Impact on Connected Products and Device Manufacturers", アクセス日 2026-07-10↩︎

  3. Faegre Drinker, "The EU Data Act: Impact on Connected Products and Device Manufacturers", アクセス日 2026-07-10↩︎

  4. Wilson Sonsini, "EU Data Act September 2026 Deadline: What Businesses Need to Know", アクセス日 2026-07-10↩︎

  5. Wilson Sonsini, "EU Data Act September 2026 Deadline: What Businesses Need to Know", アクセス日 2026-07-10↩︎

  6. Faegre Drinker, "The EU Data Act: Impact on Connected Products and Device Manufacturers", アクセス日 2026-07-10↩︎

  7. Faegre Drinker, "The EU Data Act: Impact on Connected Products and Device Manufacturers", アクセス日 2026-07-10↩︎

  8. Wilson Sonsini, "EU Data Act September 2026 Deadline: What Businesses Need to Know", アクセス日 2026-07-10↩︎

  9. Faegre Drinker, "The EU Data Act: Impact on Connected Products and Device Manufacturers", アクセス日 2026-07-10↩︎

  10. Faegre Drinker, "The EU Data Act: Impact on Connected Products and Device Manufacturers", アクセス日 2026-07-10↩︎

  11. Faegre Drinker, "The EU Data Act: Impact on Connected Products and Device Manufacturers", アクセス日 2026-07-10↩︎

共有

Tailscale 使用時にインターネットが遅くなるときの切り分け(Exit Node / DNS / Direct 接続)

メモ

Tailscale をオンにしてからインターネットが遅い、と感じたときに最初に確認したい3点をまとめる。
原因の大半は次のいずれかに収まる。

  1. Exit Node(出口ノード)が有効になっている — すべての通信が他ノード経由になり、当然遅くなる
  2. Tailscale の DNS 設定が悪さをしている — DNS 解決でつまずく
  3. P2P の直接接続が確立できておらず DERP リレー経由になっている — 中継サーバ経由なので遅い

関連: [Headscale を自宅サーバまたは AWS EC2 で運用する]

環境

  • クライアント: Windows / macOS / Linux / iOS / Android いずれも考え方は同じ
  • 確認に使うコマンド: tailscale status, tailscale netcheck

1. Exit Node を無効化する

Tailscale の Exit Node 機能を有効にしていると、Web 閲覧を含むすべてのインターネット通信が指定ノード経由でルーティングされる。出口ノードの回線品質や物理的距離に律速されるため、通常は明確に遅くなる。

確認と解除:

  • GUI クライアント: トレイ/メニューバーの Tailscale アイコンから Exit node → None
  • CLI:
1
2
3
4
5
# 現在の Exit Node を解除
tailscale up --exit-node=

# 状態確認("exit node" の行が消えていればOK)
tailscale status

ローカル LAN のリソースに Tailscale でアクセスしたいだけなら、Exit Node はオフのままで良い。

2. Tailscale の DNS 設定を見直す

MagicDNS や Admin Console の Nameservers 設定により、OS の DNS が Tailscale 管理下に置き換わっていることがある。
社内 DNS や ISP の DNS との解決順序がずれて、名前解決でタイムアウト気味になっているケースが多い。

切り分け手順:

  1. クライアント設定で Use Tailscale DNS settings(または Override local DNS)をいったんオフにする
  2. それでも遅い場合は OS 側の DNS を 8.8.8.8 / 1.1.1.1 などのパブリック DNS に固定して比較
  3. 改善するなら、Admin Console の DNS 設定(カスタム Nameserver、Split DNS、Search Domains)を見直す

CLI でも確認できる:

1
tailscale dns status

恒久対策としては、社内 DNS が必要なドメインだけ Split DNS で個別に解決させ、それ以外は OS デフォルトに任せる構成が扱いやすい。

3. Direct 接続になっているかを確認する

Tailscale は本来 WireGuard ベースで P2P 直接接続するが、NAT 越えに失敗すると DERP リレー(Tailscale が運用する中継サーバ)経由にフォールバックする。リレー経由は帯域・レイテンシの両面で不利になる。

確認:

1
tailscale status

各ピアの行末に direct <peer-ip>:<port> と表示されれば直接接続。relay "xxx" と表示されているとリレー経由。

ネットワーク側の事情を見たい場合:

1
tailscale netcheck

UPnP / PMP / PCP の可否、最寄り DERP までの RTT、IPv4/IPv6 の到達性などが出る。

DERP リレーから抜け出すための対処

ルーター側で次のいずれかを行う。

  • UPnP / NAT-PMP / PCP を有効にする — クライアント側でポートを自動的に開ける
  • UDP 41641 を手動で開放(ポートフォワード)する — Tailscale クライアントが直接接続要求を受けるための既定ポート
  • CGNAT 配下を疑う — モバイル回線や一部 ISP では、どう設定しても直接接続できないことがある。この場合は割り切るか、片側をグローバル IP のある拠点に置く

両側のクライアントがどちらも対称 NAT 配下にいると、UPnP を入れても直接接続できないことがある。netcheckNAT mapping 行で hard NAT と出ているなら、ルーター買い替えやネットワーク構成見直しが必要になる。

切り分けのまとめ

症状 まず疑うもの 確認コマンド
Web 全体が遅い Exit Node が有効 tailscale statusexit node
ページ表示が引っかかる、名前解決が遅い DNS 設定の競合 tailscale dns status
Tailscale 内通信だけ遅い/不安定 DERP リレー経由 tailscale status / tailscale netcheck

最初の一手は tailscale statustailscale netcheck を見ること。これだけで上記3つのうちどれが効いているかはほぼ判別できる。

参考

  • Tailscale 公式ドキュメント (KB): Exit Nodes / DNS / Connection Types / Firewall Ports
  • tailscale --help, tailscale status --help, tailscale netcheck --help
共有

Ubuntu 26でキーボードをカスタマイズ(Caps Lock⇔Ctrl入れ替えとCtrl+SpaceでIME切替)

メモ

Ubuntu 26.04 LTS (Resolute Raccoon) でキーボードを2点カスタマイズするメモ。

  1. Caps LockキーとCtrlキーを入れ替える
  2. Ctrl + Space で日本語入力(Mozc)と直接入力を切り替える

Ubuntu 26.04 LTSはGNOME 50を採用しており、GNOME-on-X11セッションが廃止され、デスクトップはWaylandのみで動作する点に注意(XWaylandは引き続き利用可能)。これに伴い、xmodmapsetxkbmap といったX11時代の小技は使えない(XWaylandアプリにしか効かない)ため、GNOME本体の設定や低レイヤなツールを使う必要がある。

環境

  • Ubuntu 26.04 LTS (Resolute Raccoon)
  • GNOME 50 / Wayland セッション
  • USキーボード(JISでも考え方は同じ)

Caps LockとCtrlの入れ替え

方法1: GNOME Tweaks(GUI)

一番手軽なGUI手順。Tweaksを入れていない場合は先にインストールする。

1
$ sudo apt install gnome-tweaks

Tweaksを起動して以下を辿る。

  1. 左メニューの「Keyboard」(キーボードとマウス)を開く
  2. 「Additional Layout Options」をクリック
  3. 「Ctrl position」を展開
  4. 「Swap Ctrl and Caps Lock」を選択

設定は即時反映され、再ログインしても保持される。

方法2: gsettingsコマンド(CLI / Wayland対応)

Tweaksを入れたくない場合や、dotfilesで管理したい場合は gsettings を直接叩く。Waylandでもそのまま効く。

現状確認:

1
$ gsettings get org.gnome.desktop.input-sources xkb-options

入れ替え:

1
$ gsettings set org.gnome.desktop.input-sources xkb-options "['ctrl:swapcaps']"

代表的なオプション:

オプション 動作
ctrl:swapcaps Caps LockとCtrlを入れ替え
ctrl:nocaps Caps LockをCtrlに置き換え(Caps Lockは使えなくなる)
caps:ctrl_modifier Caps Lockを「もう一つのCtrl」として扱う(Caps Lockも残る)

元に戻す:

1
$ gsettings reset org.gnome.desktop.input-sources xkb-options

なお、gsettings の値はGNOMEセッションに対する設定なので、コンソール(TTY)には効かない。コンソールでも入れ替えたい場合は /etc/default/keyboardXKBOPTIONSctrl:swapcaps を追加し、sudo dpkg-reconfigure keyboard-configuration を実行する。

方法3(補足): keyd によるカーネルレベルの入れ替え

GNOMEに依存せず、ログイン画面・コンソール・任意のWaylandコンポジタで一様に動かしたい場合は keyd を使う。evdev / uinput を経由してカーネルレベルでリマップするため、X11/Waylandを問わず動作する。

1
2
$ sudo apt install keyd
$ sudo systemctl enable --now keyd

/etc/keyd/default.conf を以下のように作成する。

1
2
3
4
5
6
[ids]
*

[main]
capslock = control
control = capslock

設定を反映:

1
$ sudo keyd reload

「Caps Lockをホールド時はCtrl、タップ時はEsc」のような複合動作が欲しい場合もkeydで書ける(Vim使いには定番)。

Ctrl + Space で日本語/英語切り替え

Ubuntu 26.04 では IME フレームワークとして IBus(従来のデフォルト)と fcitx5(近年推奨されつつある)の二択になる。WaylandやAnki等のElectronアプリとの相性ではfcitx5の方が安定しているケースが多い。

どちらを使うかで設定箇所が変わるので、それぞれ書く。

注意: Super + Space との競合

GNOME 50のシステム既定は Super + Space で入力ソースを切り替える挙動。Ctrl + Space を IME 側に割り当てる場合、システム側のショートカットを変更する必要はないが、Ctrl + Space を別アプリ(Emacs の set-mark-command、tmuxのprefix等)で使っている場合は競合するため要注意。

パターンA: IBus + Mozc の場合

Ubuntu の伝統的な構成。IBus の「入力ソースの切り替え」ではなく、Mozc側のキー設定でトグルを定義するのが素直。理由は、IBusのレイヤだと「直接入力 → Mozc」の片方向しか拾わないことがあり、トグルとして機能させるには Mozc 内のモード遷移を直接書く必要があるため。

  1. 画面右上の入力ソースアイコンをクリック → 「ツール」 → 「プロパティ」を開く
  2. 「キー設定」の項目で「キー設定の選択」を「カスタム」にし、「編集」をクリック
  3. キーマップエディタで「編集」 → 「エントリーを追加」を選び、以下の2エントリを追加する
モード キー コマンド
直接入力 Ctrl + Space IMEを有効化
入力文字なし Ctrl + Space IMEを無効化

ポイントは、IMEを有効化する側のモードを「入力なし」ではなく「直接入力」にすること(先に紹介した UbuntuでJISとUSの両キーボードを使う の記事と同じパターン)。

合わせて、デフォルトで Ctrl + Space に「全角スペースを挿入」が割り当てられているエントリがある場合は削除しておく。重複していると意図しない挙動になる。

設定後はログアウト/ログインで反映。反映が怪しい時は以下で再起動できる。

1
$ ibus-daemon -drx

パターンB: fcitx5 + Mozc の場合

fcitx5 はそもそも デフォルトのトリガキーが Ctrl + Space だが、Ubuntu 26 + GNOME 50(Wayland)の組み合わせでは「インストールしただけでは動かない」要素が複数ある。順に潰す必要がある。

B-1. パッケージのインストール(フロントエンド込み)

1
2
3
4
5
$ sudo apt install fcitx5 fcitx5-mozc fcitx5-config-qt \
fcitx5-frontend-gtk3 fcitx5-frontend-gtk4 \
fcitx5-frontend-qt5 fcitx5-frontend-qt6 \
mozc-utils-gui
$ im-config -n fcitx5

フロントエンドパッケージ(gtk3/4, qt5/6)を入れ忘れると、fcitx5は起動するけれど対象アプリで Ctrl + Space を押しても無反応、という症状になる。最初は環境変数だけ確認しがちだが、フロントエンドが無いとそもそもアプリ側にIMモジュールが注入されない。

B-2. ~/.config/fcitx5/profilekeyboard-usmozc を並べる

これが特に分かりにくい。fcitx5のトリガキーは「IMをon/off」ではなく「グループ内の入力メソッドをトグル」。グループに mozc しか居ないと、Ctrl + Space を押しても見かけ上の挙動が「mozc ⇄ inactive」となり、英語直接入力には戻らないか、fcitx5自体がオフになって入力レイアウト依存になる。

profile の最小例(USキーボード):

1
2
3
4
5
6
7
8
9
10
11
12
13
[Groups/0]
Name=Default
Default Layout=us
DefaultIM=mozc

[Groups/0/Items/0]
Name=keyboard-us

[Groups/0/Items/1]
Name=mozc

[GroupOrder]
0=Default

JISキーボードなら keyboard-uskeyboard-jpDefault Layout=usDefault Layout=jp に変える。

GUIで入れたい場合は fcitx5-configtool を起動 → 左の「Input Method」タブで Keyboard - English (US)Mozcこの順で リストに登録する。

B-3. ~/.config/fcitx5/config の TriggerKeys は サブセクション形式 で書く

地味だが重大なハマり所。以下は動かない書き方:

1
2
3
4
# NG: TriggerKeys と 0= が同じ [Hotkey] セクション内
[Hotkey]
TriggerKeys=
0=Control+space

正しい書き方は、Hotkey/TriggerKeys という独立したサブセクション:

1
2
3
4
5
[Hotkey/TriggerKeys]
0=Control+space

[Hotkey/AltTriggerKeys]
0=Shift_L

前者はfcitx5に「TriggerKeysが空のリスト」と解釈され、Ctrl + Space を押しても沈黙する。設定後は fcitx5 -r で再起動。

B-4. fcitx5の自動起動を仕込む

Ubuntu 26 + GNOME 50 では、im-config -n fcitx5 だけでは fcitx5 デーモンはログイン時に起動しない。/etc/xdg/autostart/ にfcitx5のdesktopファイルが配られるパッケージ構成にもなっていないので、自分で入れる:

1
2
3
4
5
6
7
8
9
$ mkdir -p ~/.config/autostart
$ cat > ~/.config/autostart/fcitx5.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Fcitx 5
Exec=fcitx5 -d
X-GNOME-Autostart-enabled=true
NoDisplay=false
EOF

B-5. 既存の ibus 系 autostart をユーザ側でマスクする

これも踏みやすい罠。apt purge ibus-mozc をしていない場合、/etc/xdg/autostart/ には ibus-mozc-gnome-initial-setup.desktopibus-mozc-launch-xwayland.desktop などが残り、毎回ログイン時に ibus-daemon が起動する。fcitx5と並走して、フォーカスや起動順次第でキー入力を奪い合う。

ユーザ側の ~/.config/autostart/ に同名ファイルを置けば、システム側はシャドウされる。

1
2
3
4
5
$ for f in /etc/xdg/autostart/ibus-*.desktop; do
name=$(basename "$f")
cp "$f" ~/.config/autostart/"$name"
echo 'Hidden=true' >> ~/.config/autostart/"$name"
done

B-6. GNOME側の入力ソース切替ショートカットを潰す

Ubuntu 26のGNOMEは入力ソースをデフォルトで Super + Space に割り当てているが、設定経路によっては Ctrl + Space も拾うことがある。さらに org.gnome.desktop.input-sources sources に複数登録があると、GNOME自体がキー入力を横取りしてfcitx5に届かなくなる。

1
2
3
4
5
6
# 入力ソースを単一に固定(fcitx5に任せる)
$ gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us')]"

# WMキーバインドの切替系を空に
$ gsettings set org.gnome.desktop.wm.keybindings switch-input-source "[]"
$ gsettings set org.gnome.desktop.wm.keybindings switch-input-source-backward "[]"

B-7. 反映と確認

ここまでやってログアウト/再ログイン(または再起動)。確認:

1
2
3
4
$ env | grep -E 'IM_MODULE|XMODIFIERS'   # fcitx を指しているか
$ pgrep -a fcitx5 # fcitx5 が起動しているか
$ pgrep -x ibus-daemon # 何も出ないことを確認(出るならB-5を見直し)
$ fcitx5-remote -t && fcitx5-remote -n # CLIでトグル → mozc / keyboard-us

もし端末で env に出ないが gnome-shell 本体には入っている、というケースもある。これはGUIアプリには効いている状態なので、入力テスト本体(テキストエディタで Ctrl + Space)が成功するならOK。

動作確認

テキストエディタや端末で Ctrl + Space を叩き、画面右上のIMEインジケータが「あ」と「A」(または相当の表示)で切り替わるかを確認する。切り替わらない場合は、以下を順に確認する。

  • システムショートカット(Settings → Keyboard → View and Customize Shortcuts)でCtrl+Spaceに別の機能が割り当たっていないか(B-6)
  • Mozc側のキー設定が 直接入力入力文字なし の両方に入っているか(IBusの場合)
  • fcitx5の場合は fcitx5-diagnose を実行して環境変数(GTK_IM_MODULEQT_IM_MODULEXMODIFIERS)が fcitx を指しているか
  • fcitx5の ~/.config/fcitx5/config の TriggerKeys がサブセクション形式で書かれているか(B-3)
  • fcitx5の ~/.config/fcitx5/profilekeyboard-*mozc両方が登録されているか(B-2)

Ansibleで自動化する

複数台に同じ設定を繰り返し入れる場合は、手元のAnsibleコレクション [ansible-miscs] に2つのroleと1つのplaybookを追加した。

追加したrole

roles/keyboard_swapcaps_gnome

CapsとCtrlの入れ替えをUbuntu desktop(GNOME 50 / Wayland)と仮想コンソールの両方に適用する。系統が2層あるため両方を面倒見るのが要点。

  • GUIセッション側: /etc/dconf/db/local.d/00-keyboard-swapcaps をテンプレートで配置し、dconf update でシステム全体のGNOMEデフォルトとして反映。ユーザは次回ログイン時から有効
  • コンソール側: /etc/default/keyboardXKBOPTIONSctrl:swapcaps を入れ、setupcon --force を発火

keyboard_swapcaps_xkb_optionctrl:nocapscaps:ctrl_modifier に切り替えれば挙動を変えられる。

gsettings set ... をユーザDBus越しに叩く方式は、SSH越しのAnsible実行ではセッションが取れないので意図的に避けた(dconfシステムoverrideなら無人で確実に効く)。

roles/fcitx5_mozc

fcitx5 + fcitx5-mozc 一式を入れて、~/.config/fcitx5/config をテンプレートで上書きし Control+space をトリガキーに固定する。im-config -n fcitx5 をユーザコンテキストで実行し、/etc/environmentGTK_IM_MODULE=fcitx などを書き込む。

既存IM環境との競合に対する安全弁

Ubuntu標準は伝統的にIBus + ibus-mozcで、ユーザがすでに辞書登録やキーマップカスタマイズをしている可能性が高い。雑にfcitx5に上書きすると ユーザのIBus側Mozcデータが孤児になる ため、role冒頭で以下を検出する。

  • im-config -m(現在の選択)
  • dpkg -l で既存IMフレームワークの一覧
  • pgrep -x ibus-daemon

別系統のIMが検出されたら assert失敗させる。明示的に -e fcitx5_mozc_force_switch=true を渡したときだけ進む。-e fcitx5_mozc_purge_ibus_mozc=true を併用するとibus側Mozcもpurgeされる(データ喪失を伴うので別フラグに分離)。

追加したplaybook

playbooks/conf/linux/ubu26_desktop.yml

1
2
3
4
5
6
7
8
9
- hosts: "{{ server | default('localhost') }}"
become: yes
vars:
fcitx5_mozc_user: "{{ lookup('env', 'SUDO_USER') | default(lookup('env', 'USER'), true) }}"
fcitx5_mozc_user_home: "/home/{{ fcitx5_mozc_user }}"
roles:
- register_home
- keyboard_swapcaps_gnome
- fcitx5_mozc

実行例:

1
2
3
4
$ cd ~/Sources/ansible-miscs
$ ansible-playbook -i hosts playbooks/conf/linux/ubu26_desktop.yml \
-e server=localhost \
-K

事前検出だけ走らせたい場合(実機を変更しない):

1
2
$ ansible-playbook -i hosts playbooks/conf/linux/ubu26_desktop.yml \
-e server=localhost --tags fcitx5_mozc_check -K

既存roleとの整理

Role 用途 採用すべきケース
keyboard_nocaps(既存) /usr/share/X11/xkb/symbols/{jp,us} を直接編集してCaps→Ctrl片方向 Raspberry Pi OSなどX11時代の構成。dist-upgradeで戻る点は注意
keyboard_swapcaps_gnome(新規) dconf override + /etc/default/keyboard でCaps↔︎Ctrl入れ替え Ubuntu 26.04などGNOME/Wayland desktop
japanese(既存) locale設定 + fcitx4 + fcitx-mozc + WSL用GTKスケール WSL上で日本語が要るケース
fcitx5_mozc(新規) fcitx5 + fcitx5-mozc + Ctrl+Spaceトリガ + 既存IM検出 Ubuntu 26.04 desktopのIME

ロールバック

うまく動かなかった場合や、元の構成に戻したい場合の手順。手で当てた設定とAnsibleで当てた設定で復旧の経路が違うので、それぞれ書く。

Caps↔︎Ctrl入れ替えを戻す

方法1(GNOME Tweaks)で当てた場合

GNOME Tweaks の Keyboard → Additional Layout Options → Ctrl positionDefault に戻す。

方法2(gsettings)で当てた場合

1
$ gsettings reset org.gnome.desktop.input-sources xkb-options

方法3(keyd)で当てた場合

1
2
$ sudo systemctl disable --now keyd
$ sudo rm /etc/keyd/default.conf # 設定ごと消す場合

サービスを残したまま個別マシンで一時無効化したいだけなら disable --now のみで十分。

Ansibleで当てた場合(keyboard_swapcaps_gnome role)

dconfシステムoverrideと /etc/default/keyboard の両方を戻す必要がある。

1
2
3
4
5
6
7
# GUIセッション側(dconfシステムoverride)
$ sudo rm /etc/dconf/db/local.d/00-keyboard-swapcaps
$ sudo dconf update

# コンソール側(/etc/default/keyboard)
$ sudo sed -i 's/^XKBOPTIONS=.*/XKBOPTIONS=""/' /etc/default/keyboard
$ sudo setupcon --force

各ユーザがログイン中の場合、GNOMEセッションには即時反映されない。一度ログアウト/ログインする。なお、ユーザ側で個別に gsettings set ... xkb-options "['ctrl:swapcaps']" を後から叩いている場合はそちらが優先されるので、gsettings reset も併せて実行する。

IME(Ctrl+Space切替)を戻す

IBus + Mozc を変更した場合

Mozcのプロパティ → キー設定 → 「カスタム」のエントリから、追加した Ctrl + Space の2エントリ(直接入力時:IMEを有効化/入力文字なし時:IMEを無効化)を削除する。デフォルトの「全角スペース挿入」を消していた場合は元に戻す。

設定後:

1
$ ibus-daemon -drx

fcitx5 を変更した場合

~/.config/fcitx5/config[Hotkey/TriggerKeys] を編集して元に戻すか、ファイル自体を消して再起動するとfcitx5デフォルト(Ctrl+Space)に戻る。

1
2
$ rm ~/.config/fcitx5/config
$ fcitx5 -r & # restart

IBusに完全に戻したい(fcitx5を入れた後)

1
2
$ im-config -n ibus
$ sudo systemctl reboot # 環境変数の再読込のため再ログイン or 再起動

Ansibleで当てた場合(fcitx5_mozc role)

/etc/environment への追記をブロックマーカーで囲んでいるので、マーカーごと削除する。

1
2
3
4
5
6
7
8
9
10
11
12
# /etc/environment に追記したIM環境変数を削除
$ sudo sed -i '/# BEGIN ANSIBLE MANAGED: fcitx5/,/# END ANSIBLE MANAGED: fcitx5/d' /etc/environment

# fcitx5パッケージを完全に外す場合
$ sudo apt purge fcitx5 fcitx5-mozc fcitx5-config-qt mozc-utils-gui
$ sudo apt autoremove

# IBusに戻す
$ im-config -n ibus

# 再ログイン or 再起動
$ systemctl reboot

fcitx5_mozc_purge_ibus_mozc=trueibus-mozc をpurgeしていた場合、ユーザの個人辞書(~/.config/mozc/ 以下)はパッケージ削除では消えていないので、再インストール後にそのまま使える。ただしibus-mozcとfcitx5-mozcで個人辞書のパスは共有なので、移行時にデータ重複や上書きが起きていないかは要確認。

まとめてロールバックしたい場合

Ansibleでまとめて当てた構成を一気に戻すワンライナー的な手順は用意していない(破壊的すぎるため)。上記の「Caps↔︎Ctrl」と「IME」を順に手で実行する。安全に戻したい場合は、playbook適用前に該当設定ファイルのバックアップを取っておくのが確実。

1
2
3
4
5
6
7
$ sudo tar czf ~/keyboard_backup_$(date +%F).tgz \
/etc/default/keyboard \
/etc/dconf/db/local.d/ \
/etc/environment \
~/.config/fcitx5/ \
~/.config/mozc/ \
~/.xinputrc 2>/dev/null

参考

共有

Headscale を自宅サーバまたは AWS EC2 で運用する

はじめに

Tailscale は WireGuard をベースとしたメッシュ型 VPN サービスで、複数のデバイスを安全に相互接続できます。 普段はマネージドサービスとして利用すれば十分ですが、

  • 制御サーバ(コーディネーションサーバ)を自分の管理下に置きたい
  • ベンダーロックインを避け、構成情報を自身で持ちたい
  • WireGuard と Tailscale の仕組みを学びたい

といった動機がある場合、Headscale を使ってセルフホスト構成を組むという選択肢があります。 本稿では、個人利用を想定して、Headscale を AWS EC2 単体 または 自宅 Linux サーバ で運用する手順を整理します。 あわせて、設定の自動化のための Terraform と Ansible の構成例も紹介します。

Headscale の概要

Headscale は Tailscale 制御サーバの OSS 互換実装です。 データプレーン(実際のトラフィック)は Tailscale 公式と同じく WireGuard で構成され、 クライアントは公式の Tailscale クライアント(macOS / Windows / Linux / iOS / Android)をそのまま利用します。 Headscale が代替するのは、ノード登録、鍵管理、ACL 配布、DNS、DERP リレーの調整といった「制御プレーン」の部分のみです。

Headscale 制御プレーンとデータプレーン

公式によれば「単一 tailnet を対象とした、個人や小規模 OSS 組織向けの実装」とされています 1。 本稿の執筆時点における最新版は v0.28.0(2025-02-04 リリース)です 2

構成パターンの選択

ホストする場所は、大きく次の 2 通りがあります。

構成 長所 短所
AWS EC2 単体 公衆 IP・DNS・帯域が安定。ポート開放を気にしなくてよい。 月額のランニングコストが発生する。
自宅 Linux サーバ 既存サーバを活用できる。電気代以外の月額コストはほぼゼロ。 グローバル IP の確保や、ISP の制約(CGNAT 等)に応じた工夫が必要。

リバースプロキシは Caddy を推奨します。Tailscale プロトコルは WebSocket POST を必要とするため、 Cloudflare(および Cloudflare Tunnel)は使えない 点に注意してください。 公式のリバースプロキシリファレンス 3 でも明記されています。

事前準備(AWS アカウントとローカル環境)

実際に試す前に整えておくと、以降の手順がスムーズになります。 AWS で構築する場合と、自宅サーバ構成のどちらでも共通する項目を先に列挙します。

AWS を使う場合

1. AWS アカウントと IAM ユーザー

ルートアカウントは使わず、Terraform 用の IAM ユーザーを作成します。

  1. AWS マネジメントコンソール → IAM → 「ユーザーの作成」
  2. 必要な権限ポリシー(個人利用なら以下のマネージドポリシーで十分):
    • AmazonEC2FullAccess(VPC・EIP も含む)
    • AmazonRoute53FullAccess(Route 53 を使う場合のみ)
  3. 作成後、対象ユーザー → 「セキュリティ認証情報」 → 「アクセスキーを作成」 → 用途「コマンドラインインターフェイス(CLI)」
  4. アクセスキー ID とシークレットアクセスキーを控えておきます(一度しか表示されない

2. AWS CLI のプロファイル設定

ローカル PC(WSL2 や Linux)に AWS CLI をインストールして、プロファイルを設定します。

1
2
3
4
5
6
7
sudo apt install -y awscli   # 未インストールなら

aws configure --profile headscale
# AWS Access Key ID: <控えたアクセスキー>
# AWS Secret Access Key: <控えたシークレット>
# Default region name: ap-northeast-1
# Default output format: json

以降のコマンドではプロファイルを環境変数で固定すると楽です。

1
2
3
4
5
export AWS_PROFILE=headscale
export AWS_REGION=ap-northeast-1

# 認証確認
aws sts get-caller-identity

3. SSH 鍵と EC2 キーペア

EC2 にログインするための鍵です(IAM のアクセスキーとは別物)。

1
2
3
4
5
6
7
# ローカルの SSH 鍵が無ければ生成
[ -f ~/.ssh/id_ed25519.pub ] || ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""

# AWS にキーペアを import
aws ec2 import-key-pair \
--key-name headscale-key \
--public-key-material fileb://~/.ssh/id_ed25519.pub

ここで指定した --key-name の値(例: headscale-key)を、後で Terraform の key_name 変数に渡します。両者の名前が一致していないと EC2 起動時に InvalidKeyPair.NotFound で失敗するので注意してください。

4. 利用可能な AZ の確認

新規 AWS アカウントには 特定の AZ(例: ap-northeast-1a)が割り当てられないことがあります。 事前に利用可能な AZ を確認してください。

1
2
3
aws ec2 describe-availability-zones \
--query "AvailabilityZones[?State=='available'].[ZoneName,ZoneId]" \
--output table

返ってきた中から 1 つを Terraform の availability_zone に指定します。 割り当てられていない AZ を指定すると、サブネット作成時に unexpected state 'unavailable' エラーが出ます。

5. ドメイン

hs.example.com のように、Headscale サーバを公開するドメイン(あるいはサブドメイン)が必要です。 お名前.com、Cloudflare、Route 53 など好みの DNS で構いません(後述の「DNS レコードの設定」で具体例を示します)。

自宅サーバを使う場合

  • Ubuntu 24.04 LTS(ARM64 / AMD64 どちらでも)が動作するマシン
  • ローカルから SSH 接続できる状態
  • 以降の DNS / グローバル IP 関連は「案B: 自宅 Linux サーバでの構成」で扱います

ローカル PC のツール

ツール 用途 備考
Terraform >= 1.6 AWS リソース構築 自宅サーバ構成の場合は不要
Ansible >= 2.16(ansible-core) サーバへのソフトウェアインストール 後述の通り apt 版は古い場合があるので注意
AWS CLI v2 AWS との対話 AWS 構成の場合のみ
ssh / dig / curl 動作確認 通常入っている

想定コスト(AWS 構成、東京リージョン)

項目 月額目安
EC2 t4g.micro(24h 稼働) $7.78
EBS gp3 16 GiB $1.54
Public IPv4(EIP)※ $3.60
合計 約 $13 / 月(≒ ¥2,000)

※ 2024 年 2 月以降、AWS は接続中・未接続を問わずすべての Public IPv4 アドレスに対して $0.005/h の課金を行います。 試用後はすみやかに terraform destroy で削除すれば、それ以降の課金は止まります。

案A: AWS EC2 単体構成

先に前提条件が単純な EC2 構成から扱います。 本稿では Ubuntu 24.04 LTS(ARM64、t4g.small)を 1 台立ち上げ、Caddy で TLS 終端し、Headscale 本体はバックエンドに置く構成とします。

1. インスタンスの準備

  • インスタンスタイプ: t4g.micro(2 vCPU / 1 GiB、ARM64)で個人利用には十分(クライアント数が増える / ACL を凝るなら t4g.small 推奨)
  • AMI: 最新の Ubuntu 24.04(Canonical 公式)
  • ストレージ: gp3 16 GiB(暗号化)
  • パブリック IP: Elastic IP を付与(再起動でも IP を維持するため)
  • AZ と キーペアは「事前準備」で確認した値を使用

セキュリティグループの受信ルールは次の通りです。

  • 22/tcp: 管理用、自宅 IP の /32 のみ許可
  • 80/tcp443/tcp: Caddy(自動 TLS 取得と HTTPS 公開)
  • 3478/udp: 組み込み DERP を使う場合のみ。本稿の構成では Tailscale 公式 DERP を利用するので 不要

EIP を確保したら、後述の「DNS レコードの設定」に従って、利用するドメイン(例: hs.example.com)の A レコードを EIP に向けます。

2. Headscale のインストール

DEB パッケージでのインストールが公式推奨です 4HEADSCALE_VERSION は最新リリースに合わせて更新してください。

1
2
3
4
5
6
HEADSCALE_VERSION="0.28.0"
HEADSCALE_ARCH="arm64" # x86_64 の場合は amd64

wget --output-document=headscale.deb \
"https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb"
sudo apt install ./headscale.deb

DEB パッケージなら、headscale ユーザー、systemd サービス、/etc/headscale/ 以下のディレクトリ、/var/lib/headscale/ のデータ領域などが一式整備されます。

3. 設定ファイル

/etc/headscale/config.yaml を編集します。最小構成は次のようなものです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
server_url: https://hs.example.com
listen_addr: 127.0.0.1:8080 # Caddy 経由なのでローカル限定
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
grpc_allow_insecure: false

tls_cert_path: "" # TLS は Caddy で終端
tls_key_path: ""

noise:
private_key_path: /var/lib/headscale/noise_private.key

prefixes:
v4: 100.64.0.0/10
v6: fd7a:115c:a1e0::/48
allocation: sequential

derp:
server:
enabled: false
urls:
- https://controlplane.tailscale.com/derpmap/default

database:
type: sqlite
sqlite:
path: /var/lib/headscale/db.sqlite
write_ahead_log: true

dns:
magic_dns: true
base_domain: hs-net.example.com # server_url のドメインとは別にする
nameservers:
global:
- 1.1.1.1
- 9.9.9.9

policy:
mode: file
path: /etc/headscale/acl.hujson

unix_socket: /var/run/headscale/headscale.sock
unix_socket_permission: "0770"

要点は次の通りです。

  • server_url はクライアントが接続する URL。後述の Caddy が公開するドメインに合わせます。
  • tls_cert_path / tls_key_path を空にして、TLS 終端は Caddy に任せます。
  • dns.base_domainserver_url のドメインと 別の ドメインを指定する必要があります(重複していると起動に失敗します)。
  • 個人利用ではデータベースは SQLite で十分です。Postgres はレガシー扱いとされています 5
  • 設定の検証は sudo headscale configtest で行えます。

4. Caddy で自動 HTTPS

Caddy は自動 HTTPS と WebSocket 対応をデフォルトで備えており、Headscale との相性が良いです。

1
2
3
4
5
6
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -fsSL https://dl.cloudsmith.io/public/caddy/stable/gpg.key \
| sudo tee /usr/share/keyrings/caddy-stable.asc > /dev/null
echo "deb [signed-by=/usr/share/keyrings/caddy-stable.asc] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main" \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install -y caddy

/etc/caddy/Caddyfile を以下のように書き換えます。

1
2
3
4
5
6
7
{
email you@example.com
}

hs.example.com {
reverse_proxy 127.0.0.1:8080
}

設定を反映します。

1
2
sudo systemctl reload caddy
sudo systemctl enable --now headscale

https://hs.example.com/health にアクセスして pass が返ってくれば疎通できています。

案B: 自宅 Linux サーバでの構成

自宅サーバで運用する場合、最大の論点は インターネットからの到達性 です。 ISP の契約によって状況が異なるため、まずは前提を整理します。

1. グローバル IP まわりの整理

確認すべき項目は次の 3 点です。

  1. 公衆 IPv4 アドレスを持っているか
    • 固定 IP か、動的 IP か
    • ルータの WAN 側 IP と、curl ifconfig.me で取得できる IP が一致していれば公衆 IP を直接持っています
    • 一致しない場合は ISP 側で NAT されており、おそらく CGNAT 環境です
  2. ポート 80 / 443 を外向けに開けられるか
    • ルータでポートフォワードができるか
    • ISP が 80 / 443 をブロックしていないか
  3. IPv6 が利用できるか
    • 利用できる場合でも、接続するクライアント側で必ず IPv6 が使えるとは限らないため、IPv6 単独は実用上の冗長系として捉えるのが無難です

これらの結果に応じて、以下のパターンに分かれます。

パターンA: 公衆 IP + ポート開放可

最も素直な構成です。

  • 動的 IP の場合は DDNS で名前を固定します。 Cloudflare の DNS(普通の DNS のみ。Cloudflare Tunnel ではない)を使う場合、API トークンと簡単なスクリプト(ddclient や自前の cron スクリプト)でレコードを更新できます。
  • 自宅ルータで 80/tcp443/tcp をサーバへフォワードします。
  • サーバ側のセットアップは前述の AWS EC2 構成と同じです。Caddy が Let's Encrypt から自動で証明書を取得します。

パターンB: CGNAT / ポート開放不可

外側からの着信が物理的に通せないため、外部に「踏み台」が必要になります。

  • 解1: 安価な VPS に Headscale を直接置く 実質的に AWS EC2 と同じ構成になります。Hetzner や Vultr、Oracle Cloud の Always Free 枠などが選択肢です。
  • 解2: VPS をリバースプロキシにし、自宅サーバへ WireGuard 等で逆トンネル Headscale 本体は自宅サーバに置きつつ、外部に対する HTTPS エンドポイントは VPS が担う構成です。 自宅サーバから VPS に向けて WireGuard を張り、VPS の Caddy が自宅側へ reverse_proxy します。 自宅サーバの計算資源を活用したい場合に有用ですが、構成要素が増えるため 解1 のほうがおすすめです。
CGNAT 配下の自宅サーバを VPS 経由で公開する構成

Cloudflare Tunnel が使えない理由(補足)

外部公開の手段として人気のある Cloudflare Tunnel ですが、Headscale では使えません。 公式リバースプロキシリファレンス 6 にも明記されている通り、Tailscale プロトコルは WebSocket の POST を必要とし、これを Cloudflare はサポートしていないためです。 Cloudflare 経由の HTTPS 化には魅力がありますが、Headscale に関しては別の方法を検討してください。

2. ソフトウェアのセットアップ

ここから先(Headscale + Caddy のインストール、config.yamlCaddyfile の内容)は AWS EC2 構成と共通です。

DNS レコードの設定

Headscale サーバには、server_url で指定したドメイン(例: hs.example.com)の A レコード を、サーバの公開 IP に向ける設定が必須です。 EC2 構成の場合は Elastic IP、自宅サーバ構成の場合は自宅ルータの公衆 IP(または踏み台 VPS の IP)が対象になります。 ドメインを管理している DNS 提供元ごとに、設定の入り口が異なります。

お名前.com で運用する場合

お名前.com には紛らわしい点があり、初期状態ではドメインのネームサーバが「お名前.com DNS(実際にレコード管理ができるサービス)」に向いていない ことが多いです。 ドメイン購入直後は dns1.onamae.com / dns2.onamae.com(パーキング用 NS)が設定されており、A レコードを追加しようとしても画面が出てきません。

切り替えの最短手順は次の通りです。

1. 「DNS レコード設定を利用する」を選んでネームサーバごと切替

  1. お名前.com Navi にログイン
  2. 上部メニューの「ドメイン」 → 対象ドメインの行で「DNS」または「ドメインの DNS 関連機能の設定」をクリック
  3. 表示された選択肢から 「DNS レコード設定を利用する」 → 「設定する」
    • この操作で、ネームサーバが自動的に 01.dnsv.jp04.dnsv.jp に切り替わります
  4. レコード追加フォームで以下を設定して「追加」:
    • ホスト名: hs(フルで hs.example.com の場合)
    • TYPE: A
    • TTL: 3600(初期検証中は 300 でも可)
    • VALUE: サーバの公開 IP(EIP など)
    • 状態: 有効
  5. 画面下の「確認画面へ進む」 → 「設定する」で確定

2. NS 切替の反映を確認

ネームサーバの変更は反映に時間がかかります(最長 24 時間、通常は数分〜1 時間)。

1
2
3
4
5
6
7
8
9
# 権威 NS が切り替わったか
dig +short NS example.com
# 期待値: 01.dnsv.jp. 〜 04.dnsv.jp.

# A レコードが返るか(権威 DNS に直接問い合わせ)
dig +short hs.example.com @01.dnsv.jp

# 通常解決でも見えるか
dig +short hs.example.com

NS が dns1.onamae.com のままだと、A レコードを設定しても応答に反映されない、あるいは パーキング用の IP(150.95.x.x 等)が返ってきてしまう ので、まず NS の切替を完了させてください。

動的 IP の自宅サーバの場合(補足)

お名前.com DNS は API 経由の自動更新(DDNS)に対応していません。 公衆 IP が動的に変わる環境では、ドメインはお名前.com で管理したまま、ネームサーバを Cloudflare DNS(無料プラン)に変更 する構成がよく使われます。 Cloudflare の API トークンと ddclient などのスクリプトがあれば、IP 変更時に A レコードを自動更新できます。 本稿で除外している「Cloudflare Tunnel」は WebSocket 制約により使えませんが、DNS としての Cloudflare 利用は問題ありません。

Route 53 で運用する場合

DNS を AWS Route 53 でホスティングしているなら、Terraform で A レコードまで一括管理できます。 本稿の Terraform に次のリソースを追加するだけです。

1
2
3
4
5
6
7
8
9
10
11
data "aws_route53_zone" "this" {
name = "example.com."
}

resource "aws_route53_record" "headscale" {
zone_id = data.aws_route53_zone.this.zone_id
name = "hs.example.com"
type = "A"
ttl = 300
records = [aws_eip.headscale.public_ip]
}

クライアントの接続

クライアントを Tailnet に参加させる手順は、大きく次の流れになります。

  1. サーバ側でユーザーと(必要なら)事前認証鍵を発行する
  2. クライアント側で公式 Tailscale を起動し、--login-server で Headscale を指定する
  3. 必要に応じてサーバ側でノードを承認する

サーバ側: ユーザーと事前認証鍵の発行

v0.28.0 から preauthkeys コマンドはユーザー名ではなく ユーザー ID を引数に取る仕様に変わっているため、先に users list で ID を確認します。

1
2
3
4
5
6
sudo headscale users create alice
sudo headscale users list
# 表示された ID(例: 1)を控える

sudo headscale preauthkeys create --user 1 --reusable --expiration 24h
# 出力された tskey-auth-xxxxxxxxxxxxxxxxxxxxx を控える

preauthkeys create の主なフラグは次の通りです。

  • --reusable: 同じ鍵を複数台に使い回す(IaC との併用で便利)
  • --ephemeral: 切断時にノード登録を自動削除(CI ランナーや一時的なサーバ向け)
  • --expiration <duration>: 有効期限(例: 24h30d

方法 A: 事前認証鍵で自動登録(推奨)

クライアント側で --login-server--authkey を渡すだけで完了します。スクリプトや cloud-init から無人で投入できるため、複数台を一気に追加する場合や、サーバ系のノードを登録する場面に向いています。

1
2
3
4
# Linux クライアント
sudo tailscale up \
--login-server https://hs.example.com \
--authkey tskey-auth-xxxxxxxxxxxxxxxxxxxxx

実行後、サーバ側で sudo headscale nodes list を打つと、登録済みノードとして表示されます。

方法 B: インタラクティブ登録(事前認証鍵を使わない)

--authkey を渡さずに tailscale up を実行すると、クライアント側に登録用 URL が表示されます。Headscale ではその URL を踏むだけでは登録が完了せず、URL に含まれる ノードキー(nodekey:...)をサーバ側で承認 する流れになります。

1
2
3
4
5
# クライアント側
sudo tailscale up --login-server https://hs.example.com
# 出力例:
# To authenticate, visit:
# https://hs.example.com/register/nodekey:abcdef0123...

URL の末尾にあるノードキーをサーバ側に渡して承認します。

1
2
3
4
5
# サーバ側(Headscale)
sudo headscale users list # 対象ユーザー ID を確認
sudo headscale nodes register \
--user 1 \
--key nodekey:abcdef0123...

事前認証鍵の発行・配布が不要な代わりに、サーバ側で 1 台ずつ手動承認する手間が増えます。少数のノードを慎重に管理したいケースや、認証鍵をクライアント側に置きたくない運用ポリシーで有効です。

公式アプリ(macOS / iOS / Windows / Android)

GUI クライアントでも Headscale に接続できます。共通する流れは次の通りです 7

  1. アプリの設定で「カスタムコーディネーションサーバ(Custom coordination server / Alternate server URL)」に https://hs.example.com を指定
  2. ログイン操作を行うと、ブラウザで Headscale の登録ページが開く
  3. 表示されたコマンド(headscale nodes register --user <id> --key <nodekey>)をサーバ側で実行して承認

事前認証鍵を使わせたい場合は、各アプリの「authkey でサインイン」相当のメニューに鍵を貼り付けます。 UI の文言や設定階層は OS とアプリ版によって変わりやすいため、本稿では公式ドキュメントへのリンクに留めます。

起動時に指定できる代表的なフラグ

tailscale up には接続時に指定できる便利なフラグがあります。よく使うものを用途別にまとめます。

フラグ 用途
--hostname=<name> Tailnet 上での表示名・MagicDNS 名を上書き
--reset 過去のフラグを破棄して指定したフラグだけで再構成
--ssh Tailscale SSH を有効化(ACL で ssh ルール定義が必要)
--accept-routes 他ノードが広告したサブネット経路を取り込む
--accept-dns=false MagicDNS を使わず既存の DNS 設定を保つ
--advertise-routes=<cidr> 自ノードをサブネットルータとして広告(要 ip_forward
--advertise-exit-node Exit Node として広告
--exit-node=<peer> 通信を peer 経由でインターネットに出す

サブネットルータや Exit Node として広告する場合は、サーバ側でも経路の承認が必要です(headscale nodes list-routes で一覧、headscale nodes approve-routes で承認)。 ACL や経路まわりの細かい挙動は公式リファレンス 8 に委ね、本稿では「クライアントを Tailnet に参加させる」ところまでをカバーします。

接続後の動作確認(クライアント側)

Headscale 構成でも、クライアント側のサブコマンド体系は公式 Tailscale と同一です 9。 接続が完了したら、まず以下の順で状態を確認します。

1. ノードの状態とピア一覧

1
2
3
tailscale ip          # 自ノードの Tailnet IP(既定では 100.64.0.0/10 から払い出し)
tailscale status # ピア一覧と各ノードの状態(idle / active / offline 等)
tailscale version

tailscale status の各行末に idleoffline が並んだ状態のままになる場合、クライアント自身がコーディネーションサーバへ到達できていない可能性が高いため、次の netcheck とログで切り分けます。

2. 接続性とリレー判定

1
2
tailscale netcheck            # NAT 種別と各 DERP リレーまでの遅延を計測
tailscale ping <peer> # 特定ピアまでの経路を確認(DERP 経由 / 直接 P2P を判別)

tailscale ping は ICMP ではなく Tailscale プロトコル上での到達性を測るため、経路途中で ICMP がブロックされていても結果が得られます。 出力に via DERP と表示されればリレー経由、via direct であれば P2P で接続できています。

3. デーモンの状態とログ

Linux クライアントでは tailscaled の状態と journald のログから原因を絞り込めます。

1
2
systemctl status tailscaled
sudo journalctl -u tailscaled -n 100 --no-pager

Unable to connect to the Tailscale coordination server のような出力がある場合は、

  • server_url(例: hs.example.com)の DNS が公開 IP を指しているか
  • Caddy が稼働しており https://hs.example.com/healthpass を返すか
  • クライアントの --login-serverserver_url と完全一致しているか(末尾スラッシュやスキームの差にも注意)

の順で見直すとスムーズです。

4. 再ログインと切断

ログインサーバを変更したり、状態をリセットしたい場合は次のコマンドを使います。

1
2
3
sudo tailscale up --login-server https://hs.example.com --reset
sudo tailscale down # トンネルだけ切断(設定は維持)
sudo tailscale logout # ノード登録を破棄

--reset を付けると過去に渡したフラグを引き継がず、指定したフラグのみで再構成できるため、設定変更時の事故を避けられます。

複数ノード間で SSH するまで

ここまでで 1 台のクライアントを Tailnet に参加させる手順を整理しました。 実用上は 複数のノード(ノート PC、サーバ、自宅マシンなど)を相互につなぎ、Tailnet 経由で SSH や各種サービスへ到達できる ところまでを確認したいはずです。 本節では、2 台のクライアント(仮に client-aclient-b と呼びます)を登録した直後から、SSH 接続が通るまでの流れを順に追います。

1. ノードがサーバに登録されているかを確認

サーバ側で headscale nodes list を打ち、両ノードが並んで表示されることを確認します。

1
sudo headscale nodes list
列の見方 意味
ID Headscale 内部のノード ID
Hostname クライアント側の OS ホスト名(変更したい場合は tailscale up --hostname で上書き可能)
IP addresses 払い出された Tailnet IP(既定では 100.64.0.0/10 内)
Online コーディネーションサーバとの接続状態
Expired ノードキーの有効期限切れ

Online: true で両方が並べば、登録は完了です。クライアント側でも同様に状態を確認します。

1
2
3
# client-a で
tailscale status
# 自ノードの行に続いて、ピアとして client-b が表示される想定

2. ピア間の疎通確認

Tailscale プロトコル経由で相手ノードに到達できるかを tailscale ping で確認します。 このコマンドは ICMP ではなく Tailscale 内部の到達性を測るため、経路上で ICMP がブロックされていても結果が出ます。

1
2
3
4
5
# client-a から client-b へ
tailscale ping client-b

# IP 指定でも可
tailscale ping 100.64.0.x

出力に注目するのは経路の種別です。

  • pong from client-b ... via DERP(tok) in 12ms → DERP リレー経由(NAT 越えに失敗した場合の自動フォールバック)
  • pong from client-b ... via 198.51.100.20:41641 in 5ms → 直接 P2P 接続

最初は DERP 経由でも、しばらくすると P2P に切り替わることがあります。 NAT が厳しい環境では DERP のままになることもありますが、通信は成立します。

通常の ping も合わせて確認しておくと、ICMP まで通るかを把握できます。

1
ping -c 3 100.64.0.x

3. MagicDNS による名前解決

config.yamldns.magic_dns: true にしている場合、<hostname>.<base_domain> 形式でノード名を引けます。 たとえば base_domainhs-net.example.com に設定していれば、client-b.hs-net.example.comclient-b の Tailnet IP に解決されます。

1
2
3
4
5
6
7
# 名前解決を確認
tailscale status # 各ノードの完全名(FQDN)を表示
ping -c 1 client-b.hs-net.example.com

# どうしても解決できない場合の切り分け
tailscale debug prefs | grep -i corpdns # MagicDNS が有効か
resolvectl status # systemd-resolved 環境

tailscale up 時に --accept-dns=false を付けていると MagicDNS は無効になります。 その場合は IP 直打ち、または OS の /etc/hosts などで明示的に名前解決の経路を作る必要があります。

4. 通常の SSH で接続する

ここまで来れば、Tailnet 内であれば通常の OpenSSH で接続できます。 クライアント側に tailscaled が動いていて IP が振られていれば、SSH デーモン側は特別な設定なしで Tailnet からの接続を受け付けます。

1
2
3
4
5
# Tailnet IP で接続
ssh user@100.64.0.x

# MagicDNS 名で接続(推奨。IP が変わっても影響しない)
ssh user@client-b.hs-net.example.com

接続できない場合のチェック順は次の通りです。

  1. ピア側で sshd が稼働しているか(systemctl status ssh
  2. ピア側のファイアウォール(ufw status など)が tailscale0 インターフェイスからの 22/tcp を許可しているか
  3. ACL(/etc/headscale/acl.hujson)で dst 側の 22/tcp が許可されているか
  4. Tailnet IP / MagicDNS 名のどちらでも tailscale ping で疎通できているか

ACL を初期状態(全許可)から絞り込んだ場合、SSH のために次のような最小ルールを残しておくと運用しやすいです。

1
2
3
4
5
6
7
8
9
{
"acls": [
{
"action": "accept",
"src": ["alice"],
"dst": ["alice:22"]
}
]
}

alice の部分は、Headscale 上で users create したユーザー名に置き換えます。 ユーザー単位で許可することで、後から別ユーザーを追加しても影響範囲を分離できます。

5. (任意)Tailscale SSH を有効化する

各ノードに OpenSSH を立てて鍵を配るのが面倒な場合、tailscaled 経由で SSH を提供する Tailscale SSH が便利です 10。 鍵管理が不要になり、ACL でアクセス可否を一元的に制御できます。

クライアント側で SSH サーバ機能を有効化します。

1
2
3
4
sudo tailscale up \
--login-server https://hs.example.com \
--ssh \
--reset

ACL には ssh ルールを追加します。

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"acls": [
{ "action": "accept", "src": ["*"], "dst": ["*:*"] }
],
"ssh": [
{
"action": "accept",
"src": ["alice"],
"dst": ["alice"],
"users": ["autogroup:nonroot"]
}
]
}

利用側からは通常の ssh コマンドで接続できます。

1
2
ssh alice@client-b.hs-net.example.com
# OpenSSH の鍵ではなく、Tailscale ACL で認可される

autogroup:nonroot は root 以外のすべてのユーザーを意味します。 特定ユーザーだけに絞りたい場合は ["alice", "bob"] のように列挙します。 ポリシー編集後は sudo headscale policy check --file /etc/headscale/acl.hujson で構文を確認してから反映してください。

構築の自動化(Terraform / Ansible)

ここまでの手順を自動化するための Terraform と Ansible の最小構成を用意しています。 記事と対応するソースは GitHub の dobachi/headscale-iac-sample リポジトリに置いてあるので、git clone してそのまま試せます。

Terraform: AWS 側のリソース構築

新規 VPC、パブリックサブネット、セキュリティグループ、Ubuntu 24.04 ARM64 の EC2、Elastic IP を一括で作成します。

1
2
3
4
5
cd iac/terraform
cp terraform.tfvars.example terraform.tfvars
# key_name と allowed_ssh_cidr を編集
terraform init
terraform apply

主な変数(variables.tf)は次の通りです。

  • region / availability_zone: デフォルトは東京リージョン
  • vpc_cidr / public_subnet_cidr: VPC とサブネットの CIDR
  • instance_type: 既定 t4g.small(個人利用なら t4g.micro でも十分。コストを優先したいときに切り替え)
  • key_name: 事前に作成済みの EC2 キーペア名
  • allowed_ssh_cidr: 自宅の /32 を指定
  • enable_stun: 組み込み DERP を使う場合に true

apply 後、terraform output public_ip で Elastic IP を確認し、DNS の A レコード(例: hs.example.com)をその IP へ向けます。

Ansible: Headscale + Caddy のセットアップ

EC2 でも自宅サーバでも同じ Playbook が使えます。Ubuntu 24.04 を前提とし、

  • Headscale の DEB をダウンロード・インストール
  • /etc/headscale/config.yaml をテンプレートから配置
  • 初期 ACL ファイル(全許可、後で絞り込み)を配置
  • headscale configtest で構文検証
  • Caddy をインストールし、Caddyfile を配置
  • 初期ユーザーを作成

までを行います。

Ansible のインストール

Ubuntu の apt で入る ansible 2.10 系は古く、Python 3.12 が動くターゲット(Ubuntu 24.04)では No module named 'ansible.module_utils.six.moves' のような互換性エラーが出ます。 pipx で最新の ansible-core を入れる のが確実です。

1
2
3
4
5
6
7
8
9
sudo apt remove --purge -y ansible ansible-core 2>/dev/null || true
sudo apt install -y pipx python3-venv
pipx ensurepath
source ~/.bashrc

pipx install --include-deps ansible

ansible --version
# ansible [core 2.16.x] 以上 が表示されることを確認

実行

1
2
3
4
5
6
7
8
9
cd iac/ansible
cp inventory.example.ini inventory.ini
cp group_vars/all.yml.example group_vars/all.yml
# inventory.ini と group_vars/all.yml を編集

# 接続テスト(pong が返ればOK)
ansible -i inventory.ini headscale -m ping

ansible-playbook -i inventory.ini playbook.yml

group_vars/all.yml で設定する主な変数は次の通りです。

  • headscale_server_url: クライアントが接続する URL(例: https://hs.example.com
  • headscale_base_domain: MagicDNS のベースドメイン(server_url のドメインとは別にする)
  • caddy_admin_email: Let's Encrypt の連絡先
  • headscale_users: 初期作成するユーザー名のリスト
  • headscale_arch: arm64(AWS t4g.* や Raspberry Pi)または amd64

運用

ACL ポリシー

policy.mode: file の場合、/etc/headscale/acl.hujson を編集することでアクセス制御を行います。 最小構成として「同一ユーザーのデバイス間のみ通信可」とする例です。

1
2
3
4
5
{
"acls": [
{ "action": "accept", "src": ["alice"], "dst": ["alice:*"] }
]
}

ACL 構文は Tailscale の ACL とほぼ互換で、グループ・タグ・ユーザー単位で細かく制御できます 11。 編集後は sudo headscale policy check --file /etc/headscale/acl.hujson で検証してから、サービスを再読み込みします。

バックアップ

最低限バックアップすべき対象は次の 3 つです。

  • /var/lib/headscale/db.sqlite: ノード・ユーザー・鍵などの実体
  • /var/lib/headscale/noise_private.key: ノイズプロトコルの秘密鍵(紛失すると全クライアントの再登録が必要
  • /etc/headscale/: 設定一式と ACL

cron で日次に固める例です。

1
2
sudo tar czf /var/backups/headscale-$(date +%F).tgz \
/etc/headscale /var/lib/headscale

S3 や別ホストへ rsync する仕組みと併用するとより安全です。

アップデート

DEB パッケージを上書きインストールするだけで完了します。

1
2
3
4
sudo systemctl stop headscale
sudo apt install ./headscale_<NEW_VERSION>_linux_arm64.deb
sudo headscale configtest
sudo systemctl start headscale

マイナーバージョンを跨ぐ場合は、必ず CHANGELOG を確認してください。 v0.28.0 のように、PreAuthKey の保存形式変更(bcrypt 化)など破壊的変更が入ることがあります 12

ログとトラブルシュート

サーバ側のログは journald で確認します。

1
2
sudo journalctl -u headscale -f
sudo journalctl -u caddy -f

つながらないときの典型的なチェックリストは次の通りです。

  • DNS が EIP / 自宅の IP を正しく指しているか
  • セキュリティグループ(あるいはルータ)で 443/tcp が開いているか
  • Caddy が証明書を取得できているか(80/tcp が空いているかどうかが ACME 取得に効きます)
  • headscale nodes list でノードが登録されているか
  • クライアント側の tailscale status でコントロールプレーンへの接続状況を確認

つまずきポイント集

実際に手順をなぞる過程で発生しやすいエラーをまとめておきます。

Terraform: unexpected state 'unavailable'(サブネット作成)

1
2
Error: waiting for EC2 Subnet (subnet-xxxx) create:
unexpected state 'unavailable', wanted target 'available'.

原因: terraform.tfvarsavailability_zone が、AWS アカウントに割り当てられていない AZ を指している。 新規 AWS アカウントは ap-northeast-1a などが使えないことがあります。

対応: 「事前準備」の AZ 確認コマンドで使える AZ に書き換えて terraform apply。 すでに失敗したサブネットが残っている場合は terraform state rm aws_subnet.public で状態をクリアしてから再実行します。

Terraform: InvalidKeyPair.NotFound

1
Error: ... api error InvalidKeyPair.NotFound: The key pair 'xxx' does not exist

原因: key_name の値が AWS に登録済みのキーペア名と一致していない。

対応: aws ec2 describe-key-pairs --query "KeyPairs[].KeyName" で確認し、terraform.tfvarskey_name を実在する名前に修正。

DNS: パーキング用 IP(150.95.x.x)が返る

原因: お名前.com の場合、NS が dns1/dns2.onamae.com(パーキング用)のままになっている。

対応: 上述の「お名前.com で運用する場合」の手順で、NS を 01.dnsv.jp04.dnsv.jp に切り替え、A レコードを再設定。

Ansible: No module named 'ansible.module_utils.six.moves'

原因: ローカル Ansible のバージョンが古く(2.10 系等)、ターゲット側の Python 3.12 と互換性がない。

対応: 上述の「Ansible のインストール」に従って pipx で最新版を入れ替え。

Ansible: headscale configtestacl.hujson 不在で失敗

原因: 設定で policy.mode: file を有効にしているが、ACL ファイル本体を配置していない。

対応: 本稿の Ansible ロールには ACL テンプレート(templates/acl.hujson.j2)を含めてあるので、ロールを最新化してから再実行してください。手動セットアップの場合は次のようなファイルを /etc/headscale/acl.hujson に置きます。

1
2
3
4
5
{
"acls": [
{ "action": "accept", "src": ["*"], "dst": ["*:*"] }
]
}

v0.28.0 以降: preauthkeys create -u <ユーザー名> が失敗

1
2
Error: invalid argument "alice" for "-u, --user" flag:
strconv.ParseUint: parsing "alice": invalid syntax

原因: v0.28.0 で preauthkeys コマンドの --user がユーザー名から ユーザー ID 指定 に変わった。

対応: headscale users list で ID を確認してから渡す。

1
2
sudo headscale users list           # ID を確認
sudo headscale preauthkeys create --user 1 --reusable --expiration 24h

おわりに

本稿では、個人利用を想定して Headscale を AWS EC2 と自宅 Linux サーバの 2 通りで運用するための具体的な手順をまとめ、Terraform と Ansible による自動化の足場も用意しました。 EC2 構成は前提が単純で t4g.small でも快適に動きます。 自宅サーバ構成は ISP 環境次第で構成が分かれますが、CGNAT 配下でも安価な VPS を踏み台として使えば現実的に運用できます。 セルフホスト Tailscale を起点に、自宅とクラウド、外出先の端末をひとつの仮想ネットワークでつなぐ運用は、個人の学習用途としても実用上もよい題材だと感じます。

参考


  1. Headscale 公式ドキュメント, Headscale↩︎

  2. Headscale v0.28.0 リリースノート, https://github.com/juanfont/headscale/releases↩︎

  3. 公式リバースプロキシリファレンス, https://headscale.net/stable/ref/integration/reverse-proxy/↩︎

  4. 公式インストールガイド, https://headscale.net/stable/setup/install/official/↩︎

  5. 公式設定リファレンス, https://headscale.net/stable/ref/configuration/↩︎

  6. 公式リバースプロキシリファレンス, https://headscale.net/stable/ref/integration/reverse-proxy/↩︎

  7. クライアント接続ガイド, https://headscale.net/stable/usage/↩︎

  8. ACL 構文の解説, https://tailscale.com/kb/1018/acls↩︎

  9. Tailscale CLI リファレンス, https://tailscale.com/kb/1080/cli↩︎

  10. ACL 構文の解説, https://tailscale.com/kb/1018/acls↩︎

  11. ACL 構文の解説, https://tailscale.com/kb/1018/acls↩︎

  12. Headscale v0.28.0 リリースノート, https://github.com/juanfont/headscale/releases↩︎

共有

論文解説:Data-centric Artificial Intelligence: A Survey

論文解説:Data-centric Artificial Intelligence: A Survey

論文情報

  • タイトル:Data-centric Artificial Intelligence: A Survey
  • 著者:Daochen Zha, Zaid Pervaiz Bhat, Kwei-Herng Lai, Fan Yang, Zhimeng Jiang, Shaochen Zhong, Xia Hu
  • 所属:Rice University / Texas A&M University(DATA Lab)
  • 掲載誌:ACM Computing Surveys, Vol. 57, No. 5
  • DOI:10.1145/3711118
  • arXiv:2303.10158 (初版 2023年3月、ACM掲載 2025年1月)
  • 付随リソース:data-centric-AI GitHub

動機と位置づけ

従来のAI研究は「model-centric」なパラダイム、すなわち固定されたデータセットを前提にモデル設計・ハイパーパラメータ最適化を繰り返すアプローチを中心としてきた。しかしこのアプローチにはいくつかの本質的な限界がある。

  • 固定データセットへの過度な依存は、実世界応用における汎化性能の低下を招く
  • モデルが特定の問題・データに高度に特化するため、転移が困難
  • データに潜む質的問題(欠損値・不正確なラベル・異常値)を看過しがちであり、データカスケード(上流の品質問題が下流に連鎖的に波及する現象)を引き起こす

Andrew Ng が提唱した Data-centric AI(DCAI) の概念は、この状況への応答として登場した。本論文はその概念を体系的に整理し、156本以上の文献を横断的に調査・分類した初の包括的サーベイである。

なお、「data-centric」と「data-driven」は根本的に異なる概念である。data-drivenはデータをAI開発の指針として使うことを強調するだけで、依然としてモデル開発が主体となる。これに対してdata-centricはデータそのものをエンジニアリングの主対象と置く。

著者について

全著者がRice大学とTexas A&M大学に所属し、Xia Hu 教授(Rice大)が率いる DATA Lab を中心とするグループである。筆頭著者のDaochen Zhaは本サーベイのリードを担い、NeurIPS・ICMLなどのトップ会議への掲載多数。グループはサーベイだけでなく、KDD 2023でのチュートリアル開催、関連ベンチマーク整備、GitHubでのリソースリスト継続更新など、コミュニティ形成にも積極的に関与している。

リサーチクエスチョン

本論文が明示的に設定した4つの問いは以下の通り。

  • RQ1:AIをdata-centricにするために必要なタスクは何か?
  • RQ2:データの開発・維持においてなぜ自動化が重要か?
  • RQ3:どの場面でなぜ人間の参加が不可欠か?
  • RQ4:Data-centric AIの現在の進捗はどこまで来ているか?

フレームワーク:3つの目標(Goal-driven Taxonomy)

論文の中核は、データライフサイクル全体を3つの目標で整理したgoal-driven taxonomyである。

Goal-driven Taxonomy
  • Training Data Development:学習データの収集から前処理・拡張までのパイプライン
  • Inference Data Development:モデルに入力するデータの設計・評価
  • Data Maintenance:データの継続的なメンテナンス

以下、それぞれの目標について詳述する。

Training Data Development

学習データの収集から前処理・拡張までのパイプラインを扱う。モデルの性能はデータの質と量に強く依存するため、このフェーズへの投資がAIシステム全体の基盤となる。

Data Collection

学習に必要な生データを様々なソースから収集・統合する。収集戦略がデータ品質・量の出発点を決定づける。論文は「データ収集プロセスは重要なインフラとツールのサポートを必要とする」と指摘する。

代表的なタスク・手法:Dataset discovery、Data integration、Raw data synthesis

Data Labeling

収集した生データに教師信号(ラベル)を付与し、教師あり学習を可能にする。「ラベリングはモデルが意図した予測を行えるようにするうえで不可欠であり、適切なラベルなしにはモデルは与えられたデータ以上の性能を発揮できない」と論文は述べる。従来は人手に依存していたが、近年は効率化手法が多数提案されている。

代表的なタスク・手法:Crowdsourced labeling、Semi-supervised labeling、Active learning、Data programming(Snorkel)、Distant supervision

Data Preparation

収集・ラベリング済みデータを学習に適した形式に変換・整備する。欠損値処理・外れ値除去・特徴量抽出・変換など、モデルへの入力品質を直接左右する工程である。

代表的なタスク・手法:Data cleaning、Feature extraction、Feature transformation

Data Reduction

データの次元や量を削減しつつ、モデル性能を維持または向上させる。不要な特徴量を除去することで計算コストを下げ、過学習を抑制する。「特徴選択は数十年前から研究されてきた古典的テーマ」と論文は位置づけている。

代表的なタスク・手法:Feature selection、Dimensionality reduction、Instance selection

Data Augmentation

手元のデータセットに対して変換・合成を施し、データの多様性と量を拡大する。追加収集なしにデータ分布を豊かにし、モデルの汎化性能を高める。クラス不均衡への対応(SMOTE・ADASYN)も含む。

代表的なタスク・手法:Basic manipulation(回転・フリップ等)、GAN・拡散モデルによる合成、Upsampling

Pipeline Search

前処理・削減・拡張など複数工程を横断的に統合し、エンドツーエンドで最適な構成を探索する。個別工程の局所最適ではなく全体最適を目指す。AutoSklearnを先駆けとし、DARPAのD3Mプログラムがインフラ整備を牽引してきた。

代表的なタスク・手法:AutoSklearn、DARPA D3M、End-to-end AutoML

Inference Data Development

モデルに入力するデータの設計・評価を扱う。model-centricパラダイムではほぼ看過されていた領域だが、大規模言語モデルの台頭によりその重要性が急上昇している。

In-distribution Evaluation

学習データ分布の範囲内で、モデルの挙動を細粒度に把握・診断する。特定のデータスライス(属性の組み合わせ等)でモデルが弱い箇所を特定したり、モデル判断の「反事実的な境界」(Algorithmic recourse)を可視化する。潜在的なバイアスの検出にも有効である。

代表的なタスク・手法:Data slicing(Slice Finder)、Algorithmic recourse(反事実的説明)

Out-of-distribution Evaluation

学習分布から外れた入力に対するモデルの脆弱性・頑健性を評価する。敵対的サンプルを用いたAIセキュリティ研究の基盤であり、実世界展開時のリスク把握に直結する。

代表的なタスク・手法:Adversarial samples生成、Distribution shiftのシミュレーション

Prompt Engineering

学習済みの大規模モデルをパラメータ更新なしに活用するため、入力データ(プロンプト)を最適化する。「モデルが十分に強力な場合、推論データ(プロンプト)を調整するだけで目的を達成できる」と論文は示す。手動設計から自動探索(Automated Prompt Search)まで幅広い手法が対象である。

代表的なタスク・手法:Manual prompt design、Automated prompt search

Data Maintenance

実世界ではデータは一度作成して終わりではなく、継続的なメンテナンスが必要である。このフェーズはトレーニング・推論データの正確性と信頼性を動的環境の中で保証するための役割を担う。

Data Understanding

複雑なデータセットを人間が洞察を得やすい形に可視化・要約する。また Data valuation(各データポイントがモデルに対してどれだけ貢献しているかの定量評価)により、取捨選択や改善優先度の判断を支援する。

代表的なタスク・手法:Visual summarization、Clustering for visualization、Visualization recommendation、Data valuation

Data Quality Assurance

データの品質を定量的に評価し、問題箇所を検出・修復する。動的環境でのデータドリフト検知や継続的な品質モニタリングを含む。データカスケード(品質問題の連鎖的伝播)を防ぐ最重要プロセスである。

代表的なタスク・手法:Quality assessment、Quality improvement

Data Storage & Retrieval

必要なデータを効率的に供給するためのインフラ最適化。クエリ性能の向上・インデックス自動選択・DBの自律チューニングなど、大規模データを実用速度で扱うための基盤技術である。機械学習を用いてDB管理システム自体を自律化する方向性(Self-driving DB)も含まれる。

代表的なタスク・手法:Query index selection、Query rewriting、Resource allocation、DB自律チューニング

なお、各サブゴールのうち、Data Preparation・Data Reduction・Data Storage & Retrieval の説明については、論文のフレームワーク定義とTable 1の分類を根拠として補足している。論文ではこれらの項目は手法列挙が主であり、目的の散文的説明は省略されているため、論文のコンテキストから解釈・補完した部分がある。

横断的な分析視点:自動化 vs. 人間協働

各タスクを「自動化の程度」と「人間の関与度」という2軸でさらに分類している点が本論文の独自性の一つである。2軸はそれぞれ独立したスペクトラムであり、論文内の各手法はいずれかに分類される。

自動化 vs. 人間協働の2軸

自動化の3レベル

自動化軸はコスト・複雑さが低い方から高い方に向かって以下の3レベルに分かれる。

  • Programmatic(人間コスト:低):ヒューリスティクスや統計的ルールでデータを自動処理する。設計が単純で高速だが、柔軟性は低い。
  • Learning-based(人間コスト:中):目的関数を最適化することで自動化戦略自体を学習する。より柔軟・適応的だが、学習コストが発生する。
  • Pipeline(人間コスト:高):前処理〜拡張など複数工程を横断して最適構成を一括探索する。全体最適を狙えるが、探索コストが大幅に増大する。

人間協働の3段階

人間協働軸は人間の関与度が低い方から高い方に向かって以下の3段階に分かれる。

  • Minimum participation(人間コスト:低):手法がプロセス全体を制御し、必要なときのみ人間に判断を求める。
  • Partial participation(人間コスト:中):手法が主導しつつ、人間が継続的にフィードバックを提供し続ける。
  • Full participation(人間コスト:高):人間がプロセスを完全制御し、手法は補助ツールに徹する。

自動化・人間協働のどちらのレベルも「高い方が優れている」わけではない。効率(人間労力の削減)と有効性(人間の意図との整合)はトレードオフであり、ドメイン・ステークホルダーのニーズに応じた使い分けが前提となる。たとえば Pipeline automation はシナリオによっては過複雑となり、単純な Programmatic 手法の方が実用的なケースも多い。

調査対象論文の範囲と時代的分布

本サーベイが対象とする文献は、古典的な研究から最新の動向まで幅広い時代にわたる。

  • 古典的・確立領域:Feature selection、Data augmentation(基本的手法)、Active learning
  • 2010年代後半:Crowdsourcing(MTurk系)、AutoML(AutoSklearn等)、GAN系データ拡張
  • 2020年代前半:Data programming(Snorkel)、Prompt engineering、RLHF、Adversarial robustness
  • 最新動向(2023年時点):Foundation models活用、Automated prompt search、Algorithmic recourse

個別テーマに絞った既存サーベイ(データ拡張、ラベリング、特徴選択等)はすでに存在していたが、データライフサイクル全体を横断するgoal-driven taxonomyによる統合的整理は本論文が初である。

主要な考察結果

Data-centric と Model-centric は対立しない

model-centricの価値を否定するのではなく、相互補完的なパラダイムとして捉える。GANや拡散モデル等のモデル技術がデータ拡張を支援し、逆に拡充されたデータがモデル設計の進化を促す。本番環境ではデータとモデルは絶えず変化する環境の中で交互に進化していく。

データカスケード問題の深刻さ

データ品質を軽視すると、上流の問題が下流に連鎖的に波及し、精度低下・持続的バイアスなどを引き起こす。高リスク領域(医療・金融等)ではこの影響が特に甚大である。

大規模言語モデルの成功はData-centric AIの証左

GPT-2からGPT-3への進化はアーキテクチャの変更ではなく、高品質・大規模なデータの収集によって達成された。ChatGPTもGPT-3と同等アーキテクチャのまま、RLHFによる高品質ラベルデータの活用が成功の鍵となっている。

評価フェーズの再定義

Data-centric AIパラダイムにおける評価は、精度指標だけでなく、データの動的な性質・攻撃者の存在・説明可能性(right of explanation)など多面的な側面を考慮すべきである。

将来の研究課題(Future Directions)

  • Foundation Models との統合:大規模事前学習モデルがラベリング・拡張・品質保証などのData-centric AIタスクをどう変革するか
  • プライバシー保護との両立:連合学習・差分プライバシー等を組み合わせた、データ品質向上とプライバシー保護の共立
  • 統一ベンチマーク整備:個別タスクに偏った既存ベンチマーク(DataPerf等)を超える、データライフサイクル全体を評価できる指標の構築
  • 高リスクドメインへの展開:医療・金融・法律等における体系的なデータエンジニアリングの適用と検証
  • データカスケードの予防:上流品質管理の自動化・定量化手法の確立

総評

本論文の最大の貢献は、従来は独立して議論されていた多数のデータ関連タスクを、データライフサイクルという統一的な視座のもとに再配置し、自動化と人間協働という実践的な軸を加えて整理した点にある。単なるサーベイにとどまらず、コミュニティへの方向付けを意図した「教科書的」な役割を担う論文として位置づけられる。

ただし、本論文が主に扱うのはアルゴリズム・手法レベルの分類であり、システムアーキテクチャ(データスペース設計・分散インフラ等)については対象外である点は留意が必要である。データエコシステムや主権保護的なデータ流通の文脈でこの論文を読む際は、Data Maintenanceのサブゴール(品質保証・データ理解)との接続点を中心に参照するのが実用的である。

参考情報

共有