見出し画像

Windows・Mac・Linux全て。Kanataで作る「OS不問」のキー配列

​⚠️ 【重要】セキュリティに関する注意事項と更新履歴
2026年5月6日
​本記事で紹介している設定方法について、専門家の方より重要なご指摘をいただき、内容を一部更新しました。

​この記事では設定の簡便さを優先し、ユーザーを input グループに追加する方法を記載していますが、これには以下の技術的リスクが伴います。

​リスクの内容: input グループへの所属は、そのユーザーが実行するすべてのプログラムに対し、実質的なキー入力の読み取り権限(キーロガー級の権限)を与えることと同義です。

技術的なトレードオフを理解した上での設定をお願いいたします。

一般ユーザーをinputグループに追加する操作は非常にセキュリティリスクが高いです。反面教師として、コードをずっと載せていますがくれぐれも設定しないようにお願いします。(私の知識不足でこうしたコマンドを注意書きなしで掲載してしまったことをお詫び申し上げます。)

(ご指摘いただいた redyos-s さん、ありがとうございました!)

本記事の内容を実施する前にredyos-sのコメントを一読いただくようにお願いします。

5月7日
・NixOSのKanataモジュールでの制限説明を追加(Gemini君参照)

5月9日
・非NixOS設定推奨法を追加
・Home-manager非推奨の理由を追加

キーマップ変更プログラムの設定を間違えるとセキュリティに多大なリスクをもたらします。私はまだ未熟者ですので、セキュリティリスクがあるものについては指摘をお願いします。


前回の記事では、大学入学の記念に購入した Keychron B1 Pro をカスタマイズし、ホームポジションから一歩も動かない「快適な配列」を手に入れました。スマホとの組み合わせはもう、魔法のような快適さです。
……しかし、ここで一つの問題にぶつかります。

「この快適さを、ノートPC(Linux)でも再現したい!」

一度「極上の打鍵体験」を味わってしまうと、デフォルトの配列に戻るのが苦痛です。そこで今回は、マルチプラットフォーム対応のキーリマッパー 「Kanata」 を使い、Arch LinuxとNixOSのデュアルブート環境に配列を移植した記録をお届けします。


なぜ「Kanata」なのか? クロスプラットフォーム。

Macユーザーにはお馴染みの「Karabiner-Elements」という強力なツールがありますが、残念ながらmacOS専用です。WindowsやLinuxも併用する人にとって、「OSごとに設定を作り直す」のはとても大変です。

そこで登場するのが Kanata です。


  • クロスプラットフォーム対応: Windows、macOS、Linuxで動作。

  • 移植性が高い: 設定ファイルをコピーするだけで、どのOSでも同じ指の動きが使える。

  • 圧倒的な自由度: キーマップ変更可能なワイヤレスキーボードのできることはほぼできる。

  • 複数レイヤー対応: 最大25レイヤーを設定できる(多すぎるwww)

GitHubのドキュメントは驚くほど詳細ですが、初心者が一人で読み解くには少し骨が折れます。でも大丈夫。現代にはAIという強力な相棒がいます。ドキュメントを読み込ませて対話しながら、理想の設定を作り込んでいきましょう。


思考を止めない「kanata.kbd」の設計思想

今回、私が構築した配列のポイントは「親指の有効活用」「Vimライクな移動」です(この記事の最後に私が現在使っている設定ファイルを載せています)。

1. デフォルトレイヤー(基本の構え)

文字入力の要である「Enter」と「Backspace」を親指に割り当てることで、小指を無理に伸ばす必要がなくなります。

  • CapsLockキー: タップで Esc / 長押しで Ctrl

  • 変換キー: タップで Enter / 長押しで 全角半角

  • 無変換キー: タップで Backspace

  • Vキー: タップで v / 長押しされている間 は「ナビゲーションレイヤー」 にシフト

2. ナビゲーションレイヤー(Vキー長押しで発動)

Vキーを押し込んでいる間は、キーボードが強力な操作ツールに変貌します。

  • H / J / K / L: 左 / 下 / 上 / 右(Vim風のカーソル移動)

  • U / I / O / P: Home / End / スクロールアップ / スクロールダウン

  • N / M / , / .: マウスカーソルを縦横無尽に操作

  • Space / / : マウスの左クリック / 右クリック

これなら、文章を書きながらカーソルを移動させたり、ちょっとブラウザをスクロールしたりする際も、キーボードから手を離す必要が一切ありません。


実際に動かしてみる:デバッグと検証

設定(kanata.kbd)が書けたら、まずはでテスト走行です。
(kanataが/dev/input/event*を読み取れるように権限の設定をまず行うことが必要です。これより下のセクションに沿って、起動させてください。)

Bash

# この記事では、kanataという新たなサービスユーザーを作成し、このユーザーに権限を与えます。
# 一般ユーザーで以下のコマンドを実行しても、権限がなくて失敗します。
# 事前に設定が自分の思うように動いているのかを確かめるためにはsudo権限を与えて実行します。
# !!!--cfgのあとはあなたの設定ファイルのパスを指定して下さい!!!
kanata --cfg ~/.config/kanata/kanata.kbd

エラーが出ても焦らずに。出力されたメッセージをAIに投げれば、どこを直すべきか即座に教えてくれます。


⚠️非推奨:自動起動設定(非NixOS)

このセクションでは設定のやりやすさを最重要視して、一般ユーザーをinputグループに追加してしまう操作があります。この設定をすると一般ユーザーで実行しているすべてのアプリがあなたの入力した内容を監視することができてしまうため、絶対に設定をしないでください。反面教師として載せています(他のサイトでも同じようにセットアップしているものも見受けられますので、くれぐれも注意してください)

Kanataは低レイヤーで入力をフックするため、セキュリティへの配慮が不足すると大きなセキュリティ脆弱性になります。root権限(管理者権限)でぶん回すのではなく、必要な権限だけをユーザーに与えることでリスクを最小限に抑えることができます。


1. 権限の設定(udevルールの作成)

まずは、一般ユーザーがキーボード入力にアクセスできるようグループを作成し、ルールを適用します。

Bash

# uinputグループの作成とユーザー追加
sudo groupadd uinput
sudo usermod -aG input $USER #一般ユーザーをinputグループに追加するコードです。実行しないでください。
sudo usermod -aG uinput $USER

# udevルールの作成
sudo echo 'KERNEL=="uinput", MODE="0660", GROUP="uinput", OPTIONS+="static_node=uinput"' > /etc/udev/rules.d/99-input.rules

# ルールの反映とモジュールのロード
sudo udevadm control --reload && sudo udevadm trigger
sudo modprobe uinput

2. systemdによる自動化

PCを起動した瞬間に設定した配列が有効になるよう、ユーザーサービスとして登録します。

~/.config/systemd/user/kanata.service を作成:

[Unit]
Description=Kanata keyboard remapper
Documentation=https://github.com/jtroo/kanata

[Service]
Type=simple
ExecStart=%h/.local/share/bin/kanata --cfg %h/.config/kanata/kanata.kbd
Restart=always

[Install]
WantedBy=default.target

最後に、サービスを有効化すれば完了です!

Bash


# サービスの有効化と開始
systemctl --user enable kanata.service
systemctl --user start kanata.service

# 設定を変更した時の再読み込み
systemctl --user restart kanata.service

✅️推奨:自動起動設定(非NixOS)

以下のディスカッションでは、Kanataを一般ユーザーとは別のユーザーを作成して、systemdのオプションでKanataの権限をできるだけ狭めるセットアップをすることが推奨されています。この主張を踏まえながら、Geminiと相談した上でこのセクションを書いていることを念頭において参照してください。

このディスカッションにおいて、Yvan-Massonさんの設定がセキュリティ面において優れています。この設定では、kanataがローカルネットワーク、ホームディレクトリにすらアクセスできないように制限しています。なので、今回はこちらを引用させていただきます。

Kanataが現在使用しているディストロのリポジトリにある場合はそちらからインストールしてもかまいません。例えば、ArchLinuxではAURにもあるため、私はそちらからインストールしました。その場合は、実行バイナリファイルのパスが異なるためことがありますので、以下のコマンドを実行して、Yvan-Massonさんの設定のパスを自分の環境に合わせたものに変更してください。

which kanata
# 専用グループだけ、uinput カーネルモジュールの使用を許可する
sudo groupadd uinput
sudo echo 'KERNEL=="uinput", MODE="0660", GROUP="uinput", OPTIONS+="static_node=uinput"' | sudo tee /etc/udev/rules.d/50-kanata.rules > /dev/null
# kanataという名前のユーザーを作成する
sudo useradd --no-create-home --groups input,uinput --shell /bin/false --user-group kanata
# kanata をGithubからインストールする
# 現在の最新のリリースバージョンに変更しました。(最新のバージョンが出ている場合はそちらをご利用ください)
sudo wget -O /usr/local/bin/kanata https://github.com/jtroo/kanata/releases/download/1.11.0/kanata
sudo chown root:kanata /usr/local/bin/kanata  #Kanataのファイルの所有を管理者、グループをkanataに設定
sudo chmod 754 /usr/local/bin/kanata
# systemd ユニットを作成 
sudo echo "[Unit]
Description=Kanata keyboard remapper
Documentation=https://github.com/jtroo/kanata
Wants=modprobe@uinput.service
After=modprobe@uinput.service

[Service]
Type=simple
User=kanata
ExecStart=/usr/local/bin/kanata --quiet --cfg /my/kanata/config.kbd
Restart=no
# Security
CapabilityBoundingSet=
DeviceAllow=/dev/uinput rw
DeviceAllow=char-input
DeviceAllow=/dev/stdin
DevicePolicy=strict
PrivateDevices=true
BindPaths=/dev/uinput
BindReadOnlyPaths=/dev/stdin
BindReadOnlyPaths=/dev/input/
InaccessiblePaths=/dev/shm
LockPersonality=true
NoNewPrivileges=true
PrivateTmp=true
PrivateNetwork=true
PrivateUsers=true
# The following can not be enabled, otherwise Kanata can not open /dev/uinput.
# More hardening would require to explicitly list allowed system calls.
#ProtectClock=true
ProtectHome=true
ProtectHostname=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectSystem=strict
ProtectControlGroups=true
# Allow only on AddressFamily and then deny it to effectively deny everything
RestrictAddressFamilies=AF_AX25
RestrictAddressFamilies=~AF_AX25
RestrictNamespaces=true
SystemCallArchitectures=native
SystemCallErrorNumber=EPERM
SystemCallFilter=@system-service
SystemCallFilter=~@privileged
SystemCallFilter=~@resources
RemoveIPC=true
IPAddressDeny=any
RestrictSUIDSGID=true
RestrictRealtime=true
MemoryDenyWriteExecute=true
UMask=0077" | sudo tee /etc/systemd/system/kanata.service > /dev/null
sudo systemctl daemon-reload
sudo systemctl start kanata #kanataサービスを開始させる
sudo systemctl enable kanata #次回の起動から自動でスタートさせるようにする
systemctl status kanata.service #実際にkanataサービスが動作しているか確かめましょう。
                                #エラーも表示されるので確かめましょう。


こちらの設定で、systemd-analyze security kanata.serviceを実行すると、Overall exposure level for kanata.service: 0.4 SAFE 😀
という結果になりました。

表示された結果を参考にしてさらに強固な制約を課してもかまいません。(しかし、それによって動作されない場合もありますのでご注意ください。)


NixOSでの設定

Gemini君によると、以下のようにservice.kanataを有効化すると、自動的に裏側で安全な設定にしてくれるらいしい。このkanata.nixをconfiguration.nixでインポートして再ビルドしています。

{ ... }:

{
  services.kanata = {
    enable = true;
  # kanata.kbdを私はこのkanata.nixと同階層に配置しています
    keyboards.default.config = builtins.readFile ./kanata.kbd;
  };
}

このコードがどのように動作しているのかを確認するためのソースコードは以下にあります。

セキュリティを配慮して、Kanataの権限をガチガチに制限しています。
ソースコードでは「DynamicUser = true;」を指定していることによって、systemdを利用し、サービスが起動した瞬間にシステム上に一時的なユーザーを作成し、システムが終了したときに自動的にそのユーザーが削除されるような仕様になっています。また、この動的なユーザーは/homeにアクセスする権利を持ちません。「ProtectHome = true;」によってKanataはあなたのホームディレクトリにアクセスできません。#hardeningセクションではKanataがキーボード以外の入力デバイスにアクセスすることを禁じています。IPAddressDeny = [ "any" ]; によって、Kanataがネットワーク全体にアクセスできません。CapabilityBoundingSet = [ "" ];によって、KanataにRoot権限を一切与えないしようにしています。

私の環境(NixOS)でsystemd-analyze securityを実行して、「動作しているサービスがどれくらいサンドボックス化されているのか」の評価では以下のようになっています。0.4という数字はその制限の強固さを物語っています。もちろん、/dev/input/event*を読み取るので0.0にはなれません。

⚠️NixOSにおいて、Home-managerを使って、kanataをインストールして導入することは、一般ユーザーをinputグループに追加するような設定を必要とするため、やめましょう。必ず、NisOSのkanataモジュールを有効化させて使いましょう。


おわりに

キー配列をカスタマイズするプログラムはどうしても入力を記録するための権限を与える必要があります。だから結局は、そのプログラム(その制作者も含めて)を信頼できるか、という個人の判断に委ねられます。Kanataはオープンソースではありますが、信頼できない方は使用しないでください。

私はNixのモジュールの設定をある程度信用しているので、利便性をより重視して使っているだけです。

私が現在使用している kanata.kbd の中身については、以下のセクションにコードを掲載しておきます。皆さんのカスタマイズの参考になれば幸いです!

参考文献
https://github.com/jtroo/kanata/discussions/130#discussioncomment-10227272
https://github.com/jtroo/kanata/blob/main/docs/config.adoc
https://shom.dev/start/using-kanata-to-remap-any-keyboard/


私のkanata.kbd (JIS配列)

;; JIS配列の中のキーの名前をにそのまま使うと、エラーが出るので、レイアウトが見やすくなるように定義
;; ドキュメントではすでにUS配列を用いて説明しているので、US配列を使っている方はこの設定は不要かもしれない。
;; OSによってはキーを認識している番号が違う可能性があるので、いろんなOS間で使っている場合は別々に定義しよう
;; 参考: https://github.com/jtroo/kanata/blob/main/docs/config.adoc#deflocalkeys

(deflocalkeys-linux
  HZ 41  ;;半角全角
  MH 94  ;;無変換
  HN 92  ;;変換
  RM 93  ;;カタカナひらがなローマ字
  ^  13
  ¥  124
  @  26
  [  27
  :  40
  ]  43
  \  89
)

;; ファイル内でよく登場する値は変数として定義してあとから編集をしやすくする
(defvar
  mw-initial-v 1
  mw-maximum-v 1200
  mw-accel 1.15
  mw-decel 0.93
)

;;エイリアスを定義する
;;ここで定義されたものはdefsrcやdeflayerで先頭に@をつけることで使用可能

(defalias
  caps (tap-hold 200 200 esc lctl) ;;タップでEsc、長押しで左Ctl
  v    (tap-hold 200 200 v (layer-while-held nav))   ;;長押しで変更をリロード
  HN   (tap-hold 200 200 ret HZ)   ;;全角半角切り替え
  mwu (mwheel-accel-up   $mw-initial-v $mw-maximum-v $mw-accel $mw-decel)
  mwd (mwheel-accel-down $mw-initial-v $mw-maximum-v $mw-accel $mw-decel) 
  ms↑ (movemouse-accel-up 1 1000 1 5) 
  ms← (movemouse-accel-left 1 1000 1 5) 
  ms↓ (movemouse-accel-down 1 1000 1 5) 
  ms→ (movemouse-accel-right 1 1000 1 5) 
)

;;現在のキーボードレイアウト(JIS配列)を指定する
;;ここで定義されなかったキーをKanataは受け付けない。
;;ただし、defcfgにおいてprocess-unmapped-keys yesを定義したときにのみ、ここで定義されていなかったキーも出力の対象となる。
;;定義をすることで他の機能(Tap-holdなど)が正しく動作することが保証される
(defsrc
  esc  f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12  ins  del
  HZ   1    2    3    4    5    6    7    8    9    0    -    ^    ¥    bspc
  tab  q    w    e    r    t    y    u    i    o    p    @    [    ret
  caps a    s    d    f    g    h    j    k    l    ;    :    ]
  lsft z    x    c    v    b    n    m    ,    .    /    \    rsft
  lctl lmet lalt MH        spc       HN   RM   rctl
)

;;"default"レイヤー
;;@caps  @v   @HNを加えている
(deflayer default
  esc   f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12  ins  del
  HZ    1    2    3    4    5    6    7    8    9    0    -    ^    ¥    bspc
  tab   q    w    e    r    t    y    u    i    o    p    @    [    ret
  @caps a    s    d    f    g    h    j    k    l    ;    :    ]
  lsft  z    x    c    @v   b    n    m    ,    .    /    \    rsft
  lctl  lmet lalt bspc      spc       @HN  RM   rctl
)

;;"nav"レイヤー
;;"default"レイヤーの@vが押されている間このレイヤーがアクティブになる
;;Vim風にアレンジしてしている
(deflayer nav
  esc  f1   f2   f3   f4   f5   f6   f7   f8   f9   f10   f11  f12  ins  del
  HZ   1    2    3    4    5    6    7    8    9    0     -    ^    ¥    bspc
  tab  q    w    e    lrld t    y    home end  @mwu @mwd  @    [    ret
  caps a    s    d    f    g    lft  down up   rght ;     :    ]
  lsft z    x    c    v    b    @ms← @ms↓ @ms↑ @ms→ mrtp  \    rsft
  lctl lmet lalt bspc      mltp      ret  RM   rctl
)

いいなと思ったら応援しよう!