気を散らすノート

色々と散った気をまとめておくところ.論文読んだり自分で遊んだりする.たぶん.

LLM agents を安全に走らせるために,podman での隔離を試してみる

LLM,つかってますか.

Codex や Claude Code など, cli で動くよ,色んなことを自律的にやるよ,というツールを試してみたいところだが,ローカルのファイルに任意にアクセスされるの,怖すぎる.

うまく読み書きできる対象を絞ることについては,

などあるが,この信頼性を評価したり,更新に追従したりするのに時間を使いたくはない.前者は明示的に β で,みんな一体どこまでは許容するつもりで codex とか走らせてるんだろう……と思ったりする.

というわけで,

  • agent はある程度好きに動いてほしいが,なにかした時(インストールした,誤って削除した, etc. )の自分の環境へのダメージを最小化したい
  • agent に見えてもらっては困るファイルというのもあるので,「明示的に見ていいよ」と渡したファイル以外には一切アクセスができない状況にしたい
  • 設定がある程度簡便で,今どのファイルにどうアクセスできてるのかがわかりやすい状態であること

…を目標に,色々わからんなりに検討して作ってみたのでメモ.

注意書きとしては,

  • linux は長く使っているが docker も podman も使ったことがなく, SELinux もある環境になって1ヶ月の非情報系の人間が,LLM に聞いたりしながらやったことです
  • 後述するが,やってみるとこれがベストではなさそう…? という部分があります
  • まだ作っただけで使い込んでないので,評価が未です

なので,全体に評価はご自身で行っていただき,あくまで参考として使ってください.

環境は Fedora 44,SELinux も enforcing.

今回の構成

色々考えて,以下の通りにした.

  • agents というユーザを作る(これはあとから考えるとむしろ burden かも)
  • agents の下にあるフォルダは,自分 (kagcc とします)から見られる設定にしておく
  • podman でコンテナを作って, agents ユーザ から起動する
  • claude とか codex はこのコンテナの中で起動する.
  • データの共有・保持のためには, /home/agents/shared/ みたいなディレクトリを作って,これを コンテナに bind mount しておいて,そこでやり取りする

これで,「見せてないディレクトリはそもそも見えない」「見せたディレクトリへの変更は外から見える」「 dnf install みたいなシステムへの変更も外部に影響を及ぼさず可能」が両立する

他の選択肢

  • bubblewrap がどちらかというと LLM agent の構成ではよく使われているようで,これはざっくり /usr/bin/ とかそのへん + 見せたいやつ を渡す…という感じ. …なんですけど,なんか ~/.local/bin/ とかに置いてあるツールの共有とかミスりそうとか,LLM がほしいツールを自分のシステムにインストールするのもな……とか,agent がファイルを消し飛ばした時に,自分の環境を復旧するのに手間を掛けたくないな,と思って,完全に別途の環境として podman にすることにした.
  • codex とかも bubblewrap をベースにした隔離の仕組みを作り始めているようだが,β だったりで今後の更新への追従が面倒そうでやめた

ユーザの設計

agents というユーザを作って,例えば podman はこれから動かすことにした.イメージは

ユーザ名と役割
自分 kagcc からもコンテナに共有するファイルの確認・編集は できるようにする
agent 用のユーザ agents.コンテナの管理とかそれを動かしたり
コンテナ内 root で Codex とか Claude Code が動く.コンテナ外部からみると agents が動かしている (rootless podman)

別ユーザを作ったのは,単に「エージェントが一から作ったファイルの owner は自分じゃないほうが気分的に良い」という程度で,別に要らなかったかも.

permission の壁がもう一つ安全性を担保してくれる可能性はあるのだが(例えば,git で管理されてるディレクトリで agent が owner のところで,自分が git を動かすと大丈夫かというチェックが入る), あとから思うと設定の煩雑さと隣合わせではあり,例えば kagcc のまま rootless Podman を使えば,コンテナが作る共有ファイルの owner も kagcc となるし, 自分が owner のファイルも podman のコンテナにマウントさえすれば見てもらえることができるようになる.ユーザを分けていると,コンテナが作る共有ファイルは agents に所有されてるし, agents は owner が kagcc のファイルは読めない…といった煩雑さが発生するわけですね.

ディレクトリ構成と,何がどこから見えるか

具体的には,今回はこういう感じのディレクトリ構成にしてみた. /home/agents/host-only には,コンテナのセットアップに関するものをおく.名前が変だけど container-shared はコンテナ内から見えるという設定. online としてるのは,今回のコンテナにネットワークアクセスを許可してるので,そのことをディレクトリ切って明確にしたもの.

~agents/ 内容 コンテナ内からどう見えるか
host-only/setup/ Containerfile とか,そこで COPY とかされるべきファイル群とか コンテナからは見えない,agents ユーザから使う
container-shared/online/ ここをまるっとコンテナに bind mount /workspace,読み取り専用
container-shared/online/repos/ 既存リポジトリの clone /workspace/repos,読み書き可能
container-shared/online/projects/ agents が新たに一から作る系 /workspace/projects,読み書き可能
container-shared/online/reference/ 参考資料で触ってほしくないもの (PDFとか) /workspace/reference,読み取り専用
container-secrets/online/ 認証情報とかは分けてみた /agent-secrets/
container-secrets/online/codex/ auth.json(認証)とかを残す用 /agent-secrets/codex,読み書き可能
container-secrets/online/claude/ .credentials.jsonとかを残す用 /agent-secrets/claude,読み書き可能

container-secrets/online については,:コンテナ作り直した時に codex 再認証したくないし,認証情報はマウントしたコンテナ外部に置くことにしたという経緯.例えば codex ならその認証情報とかキャッシュとかそのへんが入る.

GitHub の personal access token は別途 podman secret で管理し,コンテナから読める /run/secrets/github-readonly に配置する…ことになったが,これがベストかは微妙.

手順

ユーザ作る!

まず, agents ユーザをつくる.これは上記のとおり自分 (kagcc)としてやるほうがシンプルかもしれないので読み飛ばせば良いかもしれない.

1. btrfs subvolume

Fedora のデフォルトでは, / と /home/ がそれぞれ sibling な btrfs subvolume になっている.気分で /home/agents もその兄弟にあたる subvolume にすることにした. こだわりがなければ useradd に --btrfs-subvolume-home というオプションがあるので,普通に子の subcolume にしてこれ使っとけば良かったと思う.

気を取り直して,まず現状の確認

findmnt -t btrfs
sudo btrfs subvolume list -p /
findmnt --fstab -t btrfs

subvolid=5 でファイルシステムのトップレベルを一時的にマウントし,その直下 (= / とか /home の兄弟) に agents を作る.arch wiki に書いてある手順に近いはず.

sudo mkdir -p /mnt/btrfs-top  # マウントする場所を作っとく.名前は何でもいい
sudo mount -o subvolid=5,compress=zstd:1 UUID=$(findmnt -no UUID /) /mnt/btrfs-top # マウントする
sudo btrfs subvolume create /mnt/btrfs-top/agents # subvolume を作る
sudo umount /mnt/btrfs-top  # 後片付け
sudo rmdir /mnt/btrfs-top

agents は Btrfs 上では / や /home と同格,ディレクトリの場所としては /home/agents と言う感じ.

さて,これをいちいち手動でマウントするのは大変なので, /home/agents を作ったうえで fstab を設定する

sudo cp -a /etc/fstab /etc/fstab.bak
printf 'UUID=%s /home/agents btrfs subvol=agents,compress=zstd:1,x-systemd.device-timeout=0 0 0\n' \
  $(findmnt -no UUID /) | sudo tee -a /etc/fstab
sudo mkdir -p /home/agents
sudo findmnt --verify --verbose

…んだけどここのことはよく分かってない.systemctl とか 再起動とかしたらいけてるはずで, $ findmnt -no SOURCE,FSTYPE,OPTIONS /home/agents とかすると良いと思われる.

2. ユーザとグループの設定

agents というユーザを作りましょう.すでに /home/agents/ があるのでそんな感じだ.

sudo useradd  --home-dir /home/agents  --comment "LLM agents" --no-create-home agents
sudo cp -a /etc/skel/. /home/agents/
sudo chown -R agents:agents /home/agents
sudo restorecon -RFv /home/agents  # SELinux

で,覗き見用に agents-work というグループを作っておく

sudo groupadd -r agents-work
sudo usermod -aG agents-work kagcc
sudo chown agents:agents-work /home/agents
sudo chmod 0750 /home/agents

コンテナを作っていくぜ!

sudo -iu agents でも良さそうだが,こっちで agents として入るこどができる.

sudo machinectl shell agents@.host /bin/bash -l

3. ディレクトリと権限

ここは kagcc から

sudo install -d -o agents -g agents-work -m 2770 \
  ~agents/container-shared \
  ~agents/container-shared/online \
  ~agents/container-shared/online/{repos,projects,reference}

sudo install -d -o agents -g agents -m 0700 \
  ~agents/container-secrets \
  ~agents/container-secrets/online \
  ~agents/container-secrets/online/{codex,claude}

※ install は今回初めて知ったが,こういうふうに cp (あるいは mkdir) と chmod をまとめてできる感じで便利らしいです.How is install different from cp? [unix.stackexchange.com]

共有フォルダの permission を 2770 にしていて,これは setgid をディレクトリにつけて,新規ファイルも agents-work のグループになるようにしているはず.

ここから先は agents として作業する.

4. Github の設定

  • LLM に github の private repository にあるコードを渡したい
  • 例えば 「"claude/feat-A" というブランチは好きにしてくれていいが main はだめ」みたいな設定は難しそう (protected branch を作るくらい).要するに agent を自分と区別するにはアカウント分けるしかないけど,あまりそういう手段は想定されてなさそうなのだ.
  • というわけで,とりあえず fine-grained personal access token を使ってみることにした.
  • Contents と Metadata に読み取り権限,ついでに issue も読めるようにして設定してみた.PAT を作ると一度だけ github 上で表示してくれるので,これを podman-secret に覚えさせてみる.

LLM が推奨してきたこれで入力してみる(不用意に履歴とかに残らないようにということだと思う).

(
    set +x
    IFS= read -r -s -p 'GitHub read-only PAT: ' agent_github_pat || exit
    printf '\n'
    [[ -n "$agent_github_pat" ]] || exit
    printf '%s' "$agent_github_pat" |
        podman secret create github-readonly -
)

で,コンテナの中で使う gitconfig がこれを含むようにする (Containerfile のなかでこれを適切にコピーする).

[credential "https://github.com"]
    helper = "!f() { test \"$1\" = get || return 0; token=$(cat /run/secrets/github-readonly) || return 1; printf '%s\\n' 'username=x-access-token' \"password=$token\"; }; f"

追記 20260927: 一旦

  • コンテナ内: Personal Access Token で概ね read-only
  • コンテナ外の, agents ユーザから見えるところに一個 ssh key は作っておく
  • gitconfig でどっちも name にそれっぽい設定をしておく

という形で運用してみている.

5. Containerfile をつくる

いよいよコンテナの中身を作ります.ここでは ~agents/host-only/setup/default/Containerfile に置いてみてるけど,別にどこでもいい.同じディレクトリに,使いたい bashrc とかさっきの gitconfig とか COPY する対象のものは置いておく.今回はシステムと揃えて Fedora をベースにします.再現性よりは「いい感じの最新版」でいいことにしているが,ここは適宜 :44 とかをつけると良いと思われる.

FROM quay.io/fedora/fedora

RUN dnf install -y texlive-scheme-full \
    google-noto-sans-cjk-fonts google-noto-serif-cjk-fonts google-noto-sans-jp-fonts \
    mrsw-biz-udgothic-fonts-all mrsw-biz-udpgothic-fonts \
    mrsw-biz-udmincho-fonts-all mrsw-biz-udpmincho-fonts \
    pandoc-cli \
    && dnf clean all

RUN dnf install -y \
    git ssh vim make cmake gcc clang gettext curl perl nkf \
    gmp gmp-devel ncurses ncurses-compat-libs xz nodejs \
    qpdf mupdf mupdf-libs openssl openssl-devel ninja-build \
    htop opencv inkscape yt-dlp ripgrep fd-find git-delta \
    && dnf clean all

# これでいいのかよくわからないゾーン
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
COPY --chown=0:0 uv.toml /etc/uv/uv.toml
RUN uv tool install ruff
RUN uv tool install pyright

ENV PATH="/root/.cargo/bin:/root/.local/bin:${PATH}"
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup.sh \
    && sh /tmp/rustup.sh -y --default-toolchain nightly --profile default \
    --component rustfmt,clippy \
    && rm /tmp/rustup.sh
RUN cargo install --locked typst-cli

RUN curl -fsSL https://claude.ai/install.sh  -o /tmp/claude.sh \
    && bash /tmp/claude.sh

RUN npm install --global @openai/codex@latest \
    && npm cache clean --force

COPY --chown=0:0 gitconfig /root/.gitconfig
# コンテナ内で人が作業することがあるので最低限で
COPY --chown=0:0 basic_bashrc.sh /root/.bashrc 
COPY --chown=0:0 editorconfig /root/.editorconfig

CMD ["/bin/bash"]

ビルドしておく

podman build -t localhost/agent-base:fedora44 ~/host-only/setup/default  # 上の Containerfile の置いたディレクトリ

6. いざ起動

~/host-only/setup/default/create-agents-online.sh など便利な場所に置いておいて,こんな感じで起動する.

#!/usr/bin/env bash
set -euo pipefail

podman create -it \
  --name agents-online \
  --user=0:0 \
  --security-opt=no-new-privileges \
  --umask=0007 \
  --memory=16g --memory-swap=16g --cpus=6 --pids-limit=1024 \
  --secret github-readonly,type=mount,mode=0400 \
  --volume "$HOME/container-shared/online:/workspace:ro,Z" \
  --volume "$HOME/container-shared/online/repos:/workspace/repos:rw,Z" \
  --volume "$HOME/container-shared/online/projects:/workspace/projects:rw,Z" \
  --volume "$HOME/container-shared/online/reference:/workspace/reference:ro,Z" \
  --volume "$HOME/container-secrets/online:/agent-secrets:rw,Z" \
  --env CODEX_HOME=/agent-secrets/codex \
  --env CLAUDE_CONFIG_DIR=/agent-secrets/claude \
  --workdir /workspace \
  localhost/agent-base:fedora44 /bin/bash

ro と rw でコンテナ内から書けるかどうかの設定をしていて,例えば見てくれたらいい reference は ro にしている.

bash "$HOME/host-only/setup/default/create-agents-online.sh"

で起動したら,あとは

$ podman start -ai agents-online でOK.

コンテナ内!

あとはコンテナ内で,たとえば codex とか claude でOK. Codex は今のところ device code での認証ができるように (openai の設定で)変更してそれを使う感じになるみたい.

認証状態は コンテナ外部に保存して,コンテナを作り直しても再利用できる設計にしている(まだ環境作りたてでそういう機会が多そうだったので).

Git clone も(PAT で許容した repository については)コンテナ内から普通にできるはず.

その後

Containerfile の変更に際してはまずイメージをビルド→コンテナ停止→作り直し,で OK.

podman build -t localhost/agent-base:fedora44 ~/host-only/setup/default/
podman stop agents-online
podman rm agents-online
bash ~/host-only/setup/default/create-agents-online.sh
podman start -ai agents-online

まとめ

  • podman など,コンテナ技術を agent の隔離に使うのは結構ありっぽい気がする
  • コンテナを起動するユーザを分けてみたが,果たして有意義かは微妙(コンテナによる隔離一層でいい気もする,ただ agents というユーザでログインして色々作業をすると,LLM の生成した何らかのスクリプトが有害であった場合に一定のダメージコントロールができる.コンテナ内でそれもやればいい話だが).ユーザ分けずにやる方向にシフトするかもしれない.
  • 実際に使ってみての評価などはまだなので,また使って感想と余力があれば別途投稿します.

Panasonic Let's note CF-SC6 レビュー (Linux で使うことも含めて)

あまりこういうの書くことはないのだがメモがてら書いておく

先行レビュー

news.mynavi.jp

www.itmedia.co.jp

sandambara.com

本体

薄いが頑丈感があってよい.カメラは物理で覆いをつけられる

キーボード

割と打ちやすくて打つ心地もよい.別レビューで言及のある Enter の狭さも気にならない.表面にちょっとざらっとした加工がしてあって気持ちいいが,半年くらい使うとよく触るところはつるつるになっていく感じ. Ctrl-Fn の変更はまだ慣れないが,まあこれは選択の問題.設定での変更もできる.

ディスプレイ

やや縦長で,結局文章を読むときも左右に分割するときもこの縦幅はつかいやすい.解像度の割にサイズが小さい(=ドット密度が高い)ディスプレイで,ノングレアのが好きなので,ちょうど好み.

タッチパッド

以前のより広くなって使いやすくなった. 丸いの好きです.

スピーカー

そもそもあまり期待してないが,わりといい音する気がする. Linux で音が出ない問題については後述.

端子

  • 左側 奥から
    • HDMI, USB-A, USB-C, USB-C, LAN, イヤホン
  • 手前 なし
  • 右側
    • USB-A

というわけで, (1) 右側に端子が少なすぎる (2) Type-A が2つしかない (3) SD をさせない …のにはたまに不自由を感じている.HDMI が省略されてないのはまあありがたいとしても,キーボードとマウスを繋いだ時に他に何もさせないとか,外付け SSD/HDD とか2 つで移行する時に使える type-A がなくなるとか,右側につなぎたいものを繋げないとか,そういう不自由さがある.

また,細かいところでは, type-A が若干垂直方向で下よりについてるので,実害が生じた経験はないけど,フラッシュメモリみたいに長くて硬いのを差す時に若干差しにくく感じる.

まあ USB-C とか bluetooth への移行は全体には進んでるし,このご時世 USB-C が一口というのも…というのも大きいのだろうし,モバイル性ということもあるのだが,「パワフルで頑健なモバイル機」としてはディスプレイに繋いで母艦みたいな使い方も生じるわけで,その時にはちょっと不自由することがある. あとSD カードスロットがなくなったのは謎.

Linux

  • ファンの問題を panafanpwr で解決すると(以前の記事),問題なく稼働する.Fedora 44 入れて機嫌よく使っている
    • 起動から OS が起きるまでは,Win でもどちらでもファンがガっと回る
    • Windows で使ってたときから,スリープ時とかにファンが妙にめっちゃ回ることがあったようにおもって,ファンの速さの管理にはちょっと謎が多い.
  • 本体からの音声については,以前から噂のある,「Windows 側でミュートにした状態で Linux を入れると,本体スピーカーから音が出ない」が生じている気がする. Windows 側で音が出る状態にしてからインストールすると(Windows は上書きして),現在問題なく音が出せている. Windows の復元ドライブで,再インストールまではせずに起動して音設定する方向での復帰があり得るのかは確認してない
  • タッチパッド,ウェブカメラ,それぞれ問題なく動作する. 指紋センサは多分まだ対応
  • バッテリの持ちも悪くない (Windows 11 より延長する感触).

Fedora 44 で fcitx5-mozc と mozc-utを利用する

  • Fedota 44 で mozc-ut 辞書を使いたい…というのを,色々 generative AI にも尋ねたりしながらやってどうやらうまく動作しているので,そのメモ.
  • Mozc UT dictionaries は,mozc に組み込む追加辞書で,arch wiki で Use of the UT dictionary is optional but highly recommended. と言及されている.
  • 一旦公開が停止された後 (cf: Mozcdic-UT (Mozc-UT)が終わった話と、代替品を開発してる話),各種辞書をバンドルするツール merge-ut-dictionaries の形を取って,それを各自が実行する前提での配布に切り替わって継続されているようだ.ありがたいかぎりである.みなさんありがたいとおもったら Star つけましょうね
    • 上記記事をかいた方は reasonset/mozcdict-ext として「 現在はMozc-UTとは異なるアプローチによって、より快適な変換環境を構築することを目指している」とのことで,ウェブサイト上にも関連記事がアップされているが,今回はとりあえず UT を使ってみることにする.
  • merge-ut-dictionaries の README を読む限りは,git clone して src/merge/make.sh を編集して使いたい辞書を決め, sh make.sh でビルドした結果物を,mozc-master/src/data/dictionary_oss/dictionary00.txt に append して mozc をビルドすればいい…という感じ.
  • しかし,fcitx と一緒に動かすときに設定要るのか…?みたいなのを含め,なるべく RPM の仕組みに乗っかる方向になった.
  • 方針は,Fedora の fcitx5-mozc のパッケージのソースを取ってきて,ビルド時に上記の merge-ut-dictionaries を追記する処理を足して,新たなバージョンとして RPM パッケージを作り,これをインストールしたうえで, dnf でバージョンを固定するというもの.これがベストかはわからないが,やっていることはまあまあわかりやすい.

前座

mozc の辞書の構造

パッケージとしては fcitx5-mozc があれば mozc は不要

  • Fedora の fcitx5-mozc は自称 mozc の wrapper ではあるが,じつは mozcには別に依存していない
  • fcitx5, fcitx5-data, fcitx5-libs, glibc, hicolor-icon-theme, libgcc, libstdc++, qt5-qtbase, qt5-qtbase-gui が依存
  • なので,システム辞書を追加したい場合は,mozc を無視して fcitx5-mozc をいじることでなんとかなりそうだ
  • 実際,/usr/libexec/fcitx5-mozc/mozc_server はこいつ由来で,普通に mozc が動いているときに稼働しているのもこいつだ ($ ps aux | grep mozc).

工程

普段使わない必要パッケージは, fedora で rpm をいじる系統のパッケージで,多分 fedpkg と mock で入る.

辞書ファイルの生成

以下2つのディレクトリで主に作業をする

export UT_DIR=~/src/mozc-ut/merge-ut-dictionaries
export MOZC_DIR=~/src/rpms/fcitx5-mozc

UT 辞書の準備はほぼ READMEにある下記の説明通り.https://github.com/utuhiro78/merge-ut-dictionaries を clone して上記の場所に置いて,

cd src/merge/
sh make.sh # 必要なら編集して有効化したい辞書を選ぶ
# これは別のステップでやる
# cat mozcdic-ut.txt >> ../../../mozc-master/src/data/dictionary_oss/dictionary00.txt

mozcdic-ut.txt が生成されるのを確認して,mozc 側の準備に移る.

mozc のビルドの準備

rpm のパッケージとしての fcitx5-mozc のソースは https://src.fedoraproject.org/rpms/fcitx5-mozc.git からclone でき, git checkout f44 で Fedora 44 のブランチになる.

今回は改変するので,ut/f44 みたいなブランチを切っておくとよいと思われる.

これで clone されるのはこんなディレクトリだ.このあとの作業は全部ここでやる

$ tree $MOZC_DIR
/home/me/src/rpms/fcitx5-mozc/
├── 0001-use-system-absl.patch
├── changelog
├── fcitx5-mozc.spec
├── mozc-abseil-cpp-20240116-includes.patch
├── mozc-build-new-abseil.patch
├── mozc-build-verbosely.patch
├── README.md
└── sources

大事なのは fcitx5-mozc.spec で,例えば以下のような行がある

# main source
Source0:        %{forgesource0} 
Source1:        %{forgesource1} 

%if %{with bundle_protobuf}
# protobuf
Source2:        %{forgesource2} 
%endif

# 中略...

# Public Domain
Source5:        http://www.post.japanpost.jp/zipcode/dl/kogaki/zip/ken_all.zip
Source6:        http://www.post.japanpost.jp/zipcode/dl/jigyosyo/zip/jigyosyo.zip

# add -v to ninja command, to make verbose output during building
Patch0:         mozc-build-verbosely.patch
# only applied if the bundle_abslcpp bcond is false
Patch1:         0001-use-system-absl.patch

BuildRequires:  python3-devel
BuildRequires:  gettext 
BuildRequires:  gtk2-devel
# ...

以下が %prep というソースの準備を司るところの抜粋で,辞書への追記がこんな感じで行われていそうと読める

%prep
%setup -q -n %{archivename0} -a 5 -a 6
rm -rf src/third_party/*

# (...)

(cd src/data/dictionary_oss;
PYTHONPATH="${PYTHONPATH}:../../" python3 ../../dictionary/gen_zip_code_seed.py \
    --zip_code=../../../KEN_ALL.CSV --jigyosyo=../../../JIGYOSYO.CSV >> dictionary09.txt;
)

というわけで,以下のように編集をする.

1. 辞書ファイルのコピーと,それを source として追加

さっき作った mozcdic-ut.txt を,.spec のあるディレクトリにコピーして,fcitx5-mozc.spec に Source として追記する.Source6の記載のあるところの下に

# fcitx5-mozc.spec
Source7:        mozcdic-ut.txt

なお,このあたりのファイル(git status していらなさそうなやつ)は .git/info/exclude に追記しながらやると後々楽です.

2. それを dictionary_oss/dictionary00.txt に追記する処理を追記

上で dictionary09.txt に追記しているのの前後くらい, %prep の中に

# mozc-ut
cat %{SOURCE7} >> src/data/dictionary_oss/dictionary00.txt

3. 管理のためバージョン番号を変更

Release: %autorelease という行があるが,これに extravarというフィールドを足して ut1 という文字がバージョンに追記されるようにする(後述).

Release:        %autorelease -e ut1
sudo dnf5 install \
    git bzip2 unzip python3 python-unversioned-command \
    fedpkg mock mock-core-configs

sudo usermod --append --groups mock "$USER"

差分のイメージ

diff --git a/fcitx5-mozc.spec b/fcitx5-mozc.spec
index f5796b1..c0be128 100644
--- a/fcitx5-mozc.spec
+++ b/fcitx5-mozc.spec
@@ -74,7 +74,7 @@ Name:           fcitx5-mozc
 # git snapshot should have snapshot date will be taken care
 # of by forgemeta after importing to dist-git
 Version:        %{forgeversion}
-Release:        %autorelease
+Release:        %autorelease -e ut1
 Summary:        A wrapper of mozc for fcitx5
 License:        BSD and UCD and Public Domain and mecab-ipadic and LGPLv2+ and MS-PL%{?with_bundle_abslcpp: and ASL-2.0}
 URL:            %{forgeurl}
@@ -102,6 +102,10 @@ Source4:        %{forgesource4}
 Source5:        http://www.post.japanpost.jp/zipcode/dl/kogaki/zip/ken_all.zip
 Source6:        http://www.post.japanpost.jp/zipcode/dl/jigyosyo/zip/jigyosyo.zip
 
+# mozc-ut, built locally and copied
+Source7:        mozcdic-ut.txt
+
+
 # add -v to ninja command, to make verbose output during building
 Patch0:         mozc-build-verbosely.patch
 # only applied if the bundle_abslcpp bcond is false
@@ -183,6 +187,9 @@ mv %{archivename4} src/third_party/abseil-cpp
 %patch 1 -p1
 %endif
 
+# ut dictionary
+cat %{SOURCE7} >> src/data/dictionary_oss/dictionary00.txt
+
 (cd src/data/dictionary_oss;
 PYTHONPATH="${PYTHONPATH}:../../" python3 ../../dictionary/gen_zip_code_seed.py \
     --zip_code=../../../KEN_ALL.CSV --jigyosyo=../../../JIGYOSYO.CSV >> dictionary09.txt;

fcitx5-mozcのビルド

  • まず fedpkg --release f44 prep を試す(--release f44 の F は Fedora, prep より前で指定).辞書をダウンロードし,追記し,までやってくれるはず.
    • find . -name 'dictionary00.txt' とかで確認してみよう.
    • .git/info/exclude に入れると安心.
  • うまく行っていれば, ut/f44 ブランチで commit しとくといいかも.
  • なお,id.def の互換性については末尾を参照

source rpm を作る

引き続き fcitx5-mozc のディレクトリでk

fedpkg --release f44 srpm

いい感じのバージョン名になってるか,我々の UT辞書が同梱されてるかを確認

rpm -qp --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' ./*.src.rpm
rpm -qpl ./*.src.rpm | grep mozcdic-ut

出力は例えば

fcitx5-mozc-2.30.5618.102^20250124gitc0ed34e-7.ut1.fc44.x86_64
mozcdic-ut.txt

さっき ut1 としたのはこのバージョンに UT 入れた(そして入れ方の version 1)というのを入れ込むためでした.

ビルドして RPM にする

ここで mock という,多分綺麗な Fedora 環境を仮想的に作ってその中で依存先だけでパッケージをビルドする,をやってくれる的なものを使う. 使用時には mock というグループへの所属が必要 (doc). リンク先の指示に従って追加して,ログイン・ログアウトして $ id -nG とかで確認.たんに mock と打ってみても良い.

準備ができたら,同じディレクトリで引き続き

fedpkg --release f44 mockbuild

find -name 'fcitx5-mozc*.rpm' でいい感じのファイルができているはずだ.*x86_64.rpm が我々の目的.

軽くチェックするならこういう感じで出力を確認していくといいらしい

PKG="$(
    find results_fcitx5-mozc -type f \
        -name 'fcitx5-mozc-[0-9]*.x86_64.rpm' \
        -print -quit
)"

printf '%s\n' "$PKG"

rpm -K "$PKG"

rpm -qp --qf \
'Name: %{NAME}\nVersion: %{VERSION}\nRelease: %{RELEASE}\nArchitecture: %{ARCH}\nInstalled size: %{SIZE} bytes\n' \
    "$PKG"

rpm -qpl "$PKG"

インストール

上の $PKG を使って

sudo dnf install "$PKG"

想定通り fcitx5-mozc が入れ替わることを確認して進めよう. Warning: skipped OpenPGP checks for 1 package from repository: @commandline と言われたりするが,まあこれは,それはそう.

再起動すれば我々のビルドした fcitx5-mozc が走って,UT辞書を含む変換候補が表示されているはず!!

バージョンロック

せっかくビルドした我々の fcitx5-mozc を,Fedora側のアップデートがいちいち上書きしないようにしたい.

sudo dnf versionlock add fcitx5-mozc

いつでも dnf versionlock list で確認できる

Package name: fcitx5-mozc
evr = 2.30.5618.102^20250124gitc0ed34e-7.ut1.fc44

これで全部行けているはず.お疲れ様でした.

アップデートについて

多分,上記の rpm の操作をしたディレクトリで,時々 fetch したり rebase あるいは cherry-pick していく感じになるのだと思う.

id.def の互換性

詳細確認していないが,一応使ったLLMは以下のチェックを推している(Fedora の fcitx5-mozc が想定する id.def のバージョンと, merge-ut-dictionaries の使ってるバージョンの合致を確認するため).

prep までしたあとで,(名詞,一般)のIDを比較している

FEDORA_ID="$(
    find "$MOZC_DIR" -type f \
        -path '*/src/data/dictionary_oss/id.def' \
        ! -path '*/src/data/test/*' \
        -print -quit
)"

MOZC_ZIP="$(
    find "$UT_DIR/src/merge" -maxdepth 1 -type f -name 'mozc-*.zip' \
        -printf '%T@ %p\n' |
    sort -nr | head -n 1 | cut -d' ' -f2-
)"

diff -u \
    <(grep -F ' 名詞,一般,' "$FEDORA_ID") \
    <(unzip -p "$MOZC_ZIP" \
        mozc-master/src/data/dictionary_oss/id.def |
      grep -F ' 名詞,一般,')

差分がなければスルーで.


というわけで,上記でより快適な日本語入力が可能になった. rpm とかパッケージングとかのことが分かってないと戸惑う部分が多く,独力ではたどりにくそうだが,それぞれのステップ自体はあまり大きくないように思う.どなたかの参考になれば幸いです.

tag: - mozc, fcitx

Panasonic Let's note CF-SC6 に linux をいれるとファンが回り続ける件の解決 (panafanpwr)

Panasonic 製,2026年の CF-SC6 の Windows を消して Linux に入れ替えると,ほぼアイドル状態でも冷却ファンがめちゃくちゃ回る…問題が解決したのでメモ.  今回は Fedora. 3月に随分苦しんで結果諦めたのが,いつの間にか解決していた.

概要

  • https://sr.ht/~szern/panafanpwr/ というユーティリティを使う.
  • panafanpwr はどこかの個人の開発したものだが,以下でまあ大丈夫かという感じ
    • 実質的には 2 つの python ファイルで,読んだ限りやってることは信頼できそう
    • 「Let's note で linux を使いたくて困ってる人」は狙うにはニッチすぎる
  • 開発は arch で行われていて, aur: https://aur.archlinux.org/packages/panafanpwr も開発者によるもの.
  • CF-SC6 以外の最近の端末もサポートがあり,また報告を上げればサポートを入れてくれそう
  • 依存は現時点では以下
    • Linux with systemd
    • acpi_call kernel module
    • A org.freedesktop.UPower.PowerProfiles DBus provider (power-profiles-daemon, tuned-ppd, or tlp-pd)
    • Python 3.11+ with jeepney (the AUR package pulls this in automatically; if installing via make install, install it separately: pacman -S python-jeepney or your distro's equivalent)
  • このうち,acpi_call は, kernel module を用意するということになるのだが,
    • Arch 系では普通に入るが,その他のディストリビューションではビルドが必要なこともあるかも
    • panafanpwr の README にも記載のある https://github.com/nix-community/acpi_call が upstream としては信頼できそう.dkms.conf.in があり, Makefile を読むと make dev が結構ちょうどよくやってくれそうに見える(試してない).
    • kernel module を自分でビルドする…が不慣れな場合は, 第791回 自作のカーネルモジュールをDKMS対応にする | gihyo.jp とかが参考になりそうに思う.
    • Fedora においては,copr (という多分 arch でいう aur 的な立ち位置のレポジトリ群)に https://copr.fedorainfracloud.org/coprs/rhea/acpi_call/ というのがある.
      • この rhea さん,調べると Fedora 界隈で結構著名・大事なことやっている人のようだったので,今回はもうこれを信頼することにした.
  • というわけで,Fedora 44 からだと, rhea/acpi_call (sudo dnf copr enable rhea/acpi_call して sudo dnf install acpi_call-dkms) をいれ, python3-jeepney を入れたら依存が揃う (tuned-ppd はもともと入っていた).
  • あとは, panafanpwr を clone して sudo make install, そして readme にしたがって有効化すれば OK. echo acpi_call | sudo tee /etc/modules-load.d/acpi_call.conf は不要だった

雑談

結局, panasonic がファンのコントロールに凝ったことをするんだけどそれを linux から見えるようにしてくれないって感じ…とめっちゃふわっと理解している.2026年3月時点ではまだ上記の解決策が存在せず,fancontrol や acpi_call はうまく効かなかったはず(そのあたりの適切な magic number を調べる…ところまでにはたどり着けなかった).コントリビューションのしどころとも思ったけど,ハードウェア寄りのことでどう手を付けていいかわからなかったんですよね……. ありがたいことだ.

Let's note CF-SC については別途書くかもしれないけれど,そもそも Windows で動かしてるときも,スリープする手前とか,起動直後とか妙にファンがうるさく感じられることがあり,なんかよくわからんなーと思っていた.

Zotero のファイル同期を linked files 運用から WebDAV (InifiniCLOUD) に切り替える

文献管理ソフトとしては Zotero を使っている.不満もなくはないが普通に使いやすく,またローカルにデータを持っておけること(とオープンソースなこと)を踏まえてかれこれ10年弱使っている.

集めた文献とともにその実体 (概ね PDF ファイル) を同期しておくことができるが,

  • Zotero のストレージへの同期 (300MB まで無料,2GB まで $20 / 年,6GB まで $60/年,無制限は $120/年)
  • Linked files (Zotero では同期を行わず,端末ごとに設定できる特定のディレクトリからの相対パスとして記録して,そのディレクトリは別途同期する)
  • WebDAV を使って外部のストレージに Zotero 自身が同期をする

という選択肢がある.これまで,お布施がてら 2GB 分購入しつつも,全く容量が足りずに,実態としては主に Linked files で運用していた(イメージとしては, ~/Documents/shelf/ を base directory として, ~/Documents/shelf/Zotero の下にファイルを置き, Zotero は $ZOTERO_DIR/Zotero/path/to.pdf としてそのファイルを覚えておく. ~/Documents/shelf/Zotero は他の手法で同期しておく,という感じ). ただ,二重管理状態になってること,PDF ファイルを所定のディレクトリに置く際に一手必要なこと,Zotfile でここをやっていたが Zotero 7 になって動かなくなり, zotmoov とか使ってたけどプラグインの選択含めて色々面倒になってきたこと,Zotero の起動と別途同期を行わなければならないこと,等色々運用上引っかかるところがあり,まとめて WebDAV に切り替えることとした.InfiniCLOUD の無料枠で十分戦えている.

(ちなみに,最初から適切に運用を設計できていれば Linked files 運用も悪くないと思います.PDF ファイルのディレクトリ構成の自由が利き,zotmoov などのプラグインでそこは自動化できる.このディレクトリ,僕で言うと ~/Documents/shelf/Zotero, の同期に webdav を使うのもアリ).

WebDAV での同期

基本的には, (1) Linked Files じゃなくて直接ファイル添付する形に切り替わる, (2) なので,ファイルの実態は Zotero の Data Directory (Edit > Settings > Advanced > Data Directory Location で確認できる, zotero.sqlite とかのあるディレクトリ) の下の storage/2HTV567Y/filename.pdf みたいなところに行く, (3) この storage/ の同期を,zotero のストレージの代わりに WebDAV 経由で外部ストレージに(Zotero が自動で)行う, という形になる. 切り替えてもファイル実体はローカルに保存されるから安心(同期の際に全部ダウンロードするのと,開こうとするときにダウンロードするのは選べるようだ).また,文献情報の方は引き続き Zotero 側で(ストレージに加算されずに)同期される.

なので,実作業は以下の流れになる

  • バックアップ (上記 data directory 全体と,一応 linked files を置いているところ)
  • Edit > Settings > General > File Renaming で,ファイル名の変更の設定 (好みに応じて)
  • Tools > Manage Attachments > Convert Linked Files to Stored Files で,linked files を WebDAV 経由で同期される stored file に変更
  • Edit > Settings > Sync > File Syncing > 'Sync attachment files in My Library using' を Zotero から WebDAV に切り替え
  • 待つ!

クラウドストレージの選択

最終的には NAS とかでやる選択肢もあるみたいだが,今回は InfiniCLOUD を使うことにした.無料で 20GB, 年9700円で 300GB (+今のところ30日継続ごとに 10GB ずつ,1500 GB まで増える長期増サービス),14600円で 3000GB 等のプラン があって,写真のバックアップにも検討しているサービスだ. 今回は,クラウドストレージ系のなかで WebDAV 対応を謳っているのはそんなに多くはないっぽいなか, Zotero との使い方についてわざわざ解説していたり, 国内だったり,無料で十分な容量があったり,を踏まえてこちらにした.

紹介コード 7PCBJ よければどうぞ.

InfiniCLOUD 準備

ZoteroでWebDAV接続する|InfiniCLOUD に沿えば OK.

  • 登録,お好みのディレクトリを適宜設定・作成 (Zotero 側で最終的なディレクトリ名は zotero に固定されている.自分は普通にストレージ直下に zotero/ を作った)
  • InfiniCLOUD マイページから「外部アプリ接続を許可する」にチェック.このとき「アプリパスワード」はこの時一度しか表示されないので,特に複数端末で使う場合はメモする
  • マイページ > 外部アプリ接続 > WebDAV接続URL に記載のある URL, 接続 ID (-> Username), 先ほどのアプリパスワード (password) で,Zotero の Edit > Settings > File Syncing を設定
    • https://infini-cloud.net/ の「ファイルブラウザー」上部に address と書いてあるの (自分の環境では https://****.infini-cloud.net/v2/dav/ みたいな) ではないので注意 (400 BAD REQUEST が返ってくる).
    • Documents/shelf/zotero みたいにサブディレクトリにするなら, URL のところの末尾は dav/Documents/shelf/ まで記入, zotero/ は後ろに勝手につくはず.
  • Verify Server で成功したら後は待つ.容量にもよるが割と時間がかかります.

Zotero settings &gt; Sync &gt; File Syncing の部分
zotero側の設定画面

これで,全添付ファイルが上記の Data Directory の下の storage/ ディレクトリに保存され,その同期は InfiniCLOUD を使って行われる…という状態になっているはず.

InfiniCLOUD 側はこういう感じになっている.

InfiniCLOUD 側では, Zotero の storage の下にあるディレクトリを反映したファイル群がアップロードされている.

Zotero のストレージ開放

上記で PDF ファイル類は全部クラウドストレージ上に移ったので, Zotero 側に「これもう忘れていいよ」と伝えるフェーズが必要になる(自動では消えないみたい,それはそうか).

ウェブサイトからログイン, settings > storage の最下部に Purge Storage in My Library というボタンがあり,説明として "Use this to free up space for group libraries you own after disabling file syncing for My Library or switching to WebDAV storage. " と書かれているので,これを押すと少なくとも容量は解放され,ローカルのファイルはそのまま保持される.

Zotero のウェブサイトにログイン, Settings の Storage, 最下部に Purge Storage in My Library がある
最下部に Purge Storage in My Library

なお,Group Library の方は WebDAV にするオプションがないようなので,これは linked files にするか,普通に Zotero の storage を使うか,になりそうです.

2025年聴いた音楽

結論としては,昨年と同様,インナージャーニー を聴いてください.

インナージャーニー

メンバーの脱退とかいろいろありそうだがめちゃくちゃ好きなのでひきつづき歌を歌っていてほしい.年末には(もう解散したけど僕が以前から好きだった) SUNNY CAR WASH というバンドの岩崎優也さんというひとと共演とかいう激アツ事象もあったらしい.


帝国喫茶

音楽の形容の語彙が本当に乏しくてアレなんだけど,キャッチーなポップさ,温かさ,華やかさ,ちょっとした郷愁みたいなのの同居が好みポイントなのかなと思う.

橋本泰河

川端四条の交差点で歌っておられてあまりに好みでそのまま聴いて,帰ってから検索した,という珍しいパターン.交差点で歌ってはったのは配信されてないように思う.

一番好きなのは雨都という曲だが,本人の youtube channel にはライブのしかない

そのほか

PK Shampoo

blog 振り返ると 2020年には聴いてたっぽいが,なんというか一層歌うまくなってるよね

ブランデー戦記

  • 赤いワインに涙が・・・

なんか自分は演歌も好きになるんじゃないかって瞬間もある

  • Musica

きのこ帝国

Skinny Lister

毎年推していくぜ

番外: パペットスンスン

友人の姉が真似が上手いというどうでも情報から知ったパペットスンスン


なんかじわじわと変調を感じる.良いお年を.

LaTeX + beamer (beamerposter) で発表ポスターを作る覚書

思ったよりはシンプルに,満足のいく綺麗さのものができたので(作ったのは英文ポスター),メモとして残しておく.

概要

  • beamer に乗っかった beamerposter を使うのが安心感があり(…というか,すでに beamer はよく使うので覚えることが少ないかと思って),今回はこちらを使った.
  • 基本的には,全体は一つの frame となっている.columns 環境で縦方向の列を作って,その中に block 環境で長方形のエリア(Introduction とか Method とか,以下「箱」と言います)を詰めていく形,と理解すればよさそう.列と列の間にちょっと隙間をあけたりするのも,空の column を作って実現している.
  • gemini という theme が,作例もついていて見栄えもよい.今回は repository を clone して,poster.tex にそのまま手を入れて自分のスライドに作り変えていったところ,かなりやりやすかった.結構お勧めかも.
  • ほかどんなのが作りうるかを見たい場合は,Overleaf の templates and examples を眺めてみよう.

他のパッケージについて

How to create posters using LaTeX - TeX - LaTeX stack exchange が見本付きで詳しくてよい.

  • tikzposter - 細かい調整とか凝ったレイアウトができそう,またパッケージのドキュメントがまだしもちゃんとしている.
  • 情報が少ないが a0poster や baposter (これ かな?CTAN には xebaposter) も時々勧められている

書き方

自分のポスターを参考に載せようと思ったが,載せられる形に改変するのがかなり面倒なのと,gemini についてるサンプル (poster.tex) が仕上がりもきれいでわかりやすくコメントも入ってる,のでそれでよいことにします.

冒頭はこんな感じ……

\documentclass{beamer}

% ====================
% Packages
% ====================


\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[orientation=portrait,size=a0paper,scale=1.4]{beamerposter}
\usetheme{gemini}
\usecolortheme{gemini}

例えば,左右2列に均等に割り付けるとすると,こんな↓感じの準備をする. \midcolumn は元のテンプレートになかったもので,縦線を引くようにしたものだ(が,一旦無視して良い).

\newlength{\sepwidth}
\newlength{\colwidth}
\setlength{\sepwidth}{0.02\paperwidth}
\setlength{\colwidth}{0.47\paperwidth}

\newcommand{\separatorcolumn}{\begin{column}{\sepwidth}\end{column}}%
\newcommand{\midcolumn}{\begin{column}{0.5\sepwidth}\end{column}\vrule\begin{column}{0.5\sepwidth}\end{column}}

タイトルとかを飛ばすと,本文のところは結局こういう作りになっている

\begin{document}
\begin{frame}[t]
\begin{columns}[t]
% 小さいサイズの空の column で,左側にちょっと隙間を作る
\separatorcolumn

\begin{column}{\colwidth}
  % 左側の列

  \begin{block}{Method}
    text.....
  \end{block}

  \begin{block}{Participants}
    text ....
  \end{block}
\end{column}

% 左右の列の間にちょっとスペースを作る
\midcolumn

\begin{column}{\colwidth}
  % 右側の列

  \begin{block}{Result}
    text.....
  \end{block}

  \begin{block}{Future}
    text ....
  \end{block}
\end{column}

\end{columns}
\end{frame}
\end{document}

左右ぶち抜いたり,一部だけ3列にしたかったりするときは,そこに別の columns 環境を入れれば良い,というわけだ(columns>separatorcolumn+column+separatorcolumn のあとに columns>separatorcolumn+column+separatorcolumn+column+separatorcolumn みたいな構造になる).

タイトル部分は,gemini であれば \title, \institute, 必要なら \logoright とかを組み合わせるといい感じに仕上がる(ところどころいじって縦の空白を減らしたりはした).ロゴを複数縦に積みたいときは,

\logoright{%
    \begin{minipage}[t]{7cm}%
        \vspace*{-1.3cm}%
        \centering%
        \includegraphics[height=5cm,width=7cm,keepaspectratio]{./assets/logo1.png}\\%
        \includegraphics[height=5cm]{./assets/logo2.png}%
    \end{minipage}%
}

みたいにしたらとりあえず機能してくれていた.

Configuration

スタイルファイルがいじりやすく書かれているように思うので,結構雰囲気でやりやすい.

  • フォント→ beamerthemegemini.sty で定義されているので,見様見真似で変更を入れたらいい感じになる.自分は本文を Fira Sans にしたくて
\newfontfamily\FiraSans[Ligatures=TeX]{FiraSans} %要らんかも?
\setsansfont{FiraSans}
% .....
\setbeamerfont{heading}{family=\FiraSans,series=\bfseries}

のようにしていた.

  • いろんなスペース→これも beamerthemegemini.sty を見ながら
\newcommand\heading[1]
{%
  \par%\bigskip
  {\usebeamerfont{heading}\usebeamercolor[fg]{heading}#1}\par%\smallskip
}

みたいにコメントアウトしてスペース減らしたり.

  • 色 → beamercolorthemegemini.sty たとえば
\definecolor{MyUnivColour}{RGB}{0,0,0}

みたいにしとけば

% Headline
\setbeamercolor{headline}{fg=lightgray,bg=MyUnivColour}

で好きな色をヘッダにできる.

うれしさ

  • LaTeX は使い慣れているが,powerpoint 全く触ることがないので難しすぎる.
  • 他のポスターも見て回ったがやっぱり組版は綺麗(リガチャとかも含めて).
  • 差分とかバージョン管理がしやすい.
  • 参考文献とかの管理がらく.
  • 主義と嗜好のこと

よかったですね.(かれこれ 10年以上いわゆる office 系をなるべく回避して暮らし続けているので,この調子でがんばりたい.)

参考資料