テクニカルプア

備忘録と若干の補足

mkosi で実行される処理に AUR パッケージのビルドとインストールを含める

の続編。件の記事で挫折した内容が達成できたので書く。

mkosi によるイメージのビルド時に AUR パッケージのビルドとインストールもあわせてやる方法が実現できた。 これによって先の内容は無用となった。哀しい。

TL; DR

をみてもらうのが手っ取り早い。

解説

上の通りなのだがそれではブログに書く意味がないので言葉で説明する。

ビルド中のコンテナから外に出れない

mkosi.default[Packages] 内で WithNetwork=yes を与えるか mkosi 自体に --with-network を与える。 こうすることで mkosi.build スクリプトが実行される段階(mkosi の man 内容でいう development image)でコンテナから外に出れる。 man に書いてあったのを見落としていた。man はちゃんと読むべきだった。

ちなみに WithNetwork=yes をすると mkosi を実行しているホストのネットワークがそのまま使用され、そうでない場合は systemd-nspawn コマンドに --private-network が付与されるようだった。 ホストとコンテナとでネットワークまわりの namespace が共有されてしまうのはちょっと気持ち悪いが、まあいいか……。

ビルド対象が依存するパッケージをいれる

上の WithNetwork=yes でインターネットに出れるようになる為、 pacman -U する際の依存関係解決も pacman 側で任せられるようになる。 よって mkosi.default[Packages] 内に依存パッケージをズラズラ書いておく必要がなくなる。単に pacman -U --noconfirm とかすればよい。 ただデフォルトでは /etc/pacman.d/mirrorlist の内容が全部コメントアウトされているので、 mkosi.postinst あたりで適当なミラーをアンコメントするなり適当なファイルで書き換えるなりする処理がが必要。 私は後者を選んだ。

PKGBUILD をコンテナ内に持ち込む

あらかじめ AUR 上のパッケージを手元に git clone しておく。以下では git clone してできたディレクトリを aurpkg/ とする。 mkosi.default[Package] 内で以下のようにしてやればよい:

  • BuildSources=aurpkg を指定
  • SourceFileTransfer=mount を指定

こうすると mkosi するディレクトリの中にある aurpkg/ というディレクトリがビルド用コンテナ内から $SRCDIR (/root/src) で参照できる。

makepkg コマンドを叩く

makepkg コマンドは root では実行できない。しかし mkosi.build は root として実行される。どうするか。nobody ユーザとして makepkg を実行してやればよさそう。 具体的には sudo -u nobody -- bash -c "makepkg -sr" などとやればよい。

ただしこれを実行すると AUR パッケージが必要とするパッケージをインストールする段階にうつり、nobody ユーザが sudo で root になる為のパスワードをきかれてしまい悲しいことになる。 なので事前に PKGBUILD の dependsmakedepends に書かれてるものを pacman -S --noconfirm しておくのがよい。

以上を踏まえて私は以下のようにした:

source $SRCDIR/PKGBUILD
[[ -n "$depends" ]] && pacman -Sy --noconfirm "${depends[@]}"
[[ -n "$makedepends" ]] && pacman -Sy --noconfirm "${makedepends[@]}"

また makepkg は自身が使うディレクトリを一旦 mkdir -p してみる実装になっているようで 1$SRCDIR (/root/src/) や $BUILDDIR (/root/build/) を nobody ユーザで mkdir -p できるようになっていないとエラーを吐いてコケてしまう。これには /root/ で nobody ユーザが実行権限をもっている必要がある。 加えて $BUILDDIR$SRCDIR および後述する $DESTDIR (/root/dest/) それ自体も nobody ユーザから読み書きができるようになっていないと必要なファイルを参照したり作成できなくなってしまうので、これまたコケてしまう。 よって setfacl で以下のようにしてやる:

for DIR in $BUILDDIR $SRCDIR $DESTDIR; do
        setfacl -m u:nobody:rwx $DIR
        setfacl -d --set u:nobody:rwx,o::- $DIR
done
setfacl -m u:nobody:rwx /root
setfacl -d --set u:nobody:rwx,o::- /root

makepkg の結果をどうインストールするか

mkosi.build が実行される development image の段階で生成物を pacman -U しても最終的に得られるイメージには反映されない。development image はあくまで中間イメージであり、最終成果物を得る為の過程にすぎない為だ。 また mkosi.build を実行することで作成された内容は $DESTDIR(通常はコンテナ内 /root/dest/)に移しておかないと mkosi.build 終了時に中間イメージごと消滅してしまう。

mkosi.postinst は中間イメージ作成時と最終イメージ作成時の双方で実行されるので、 pacman -Umkosi.postinst で実行してあげればよい。 また mkosi.buildmakepkg -sr した結果作成されたパッケージを $DESTDIR 下に移すには makepkg する際に PKGDEST という環境変数$DESTDIR にしてやればよい。こうすることで作成されたパッケージは $DESTDIR 以下に出力される。 $DESTDIR に移された成果物は最終イメージ内 / 直下に配置されるので、 mkosi.postinst では / 下にあるパッケージを pacman -U してやればよい。

# mkosi.build
# mkosi.build は $SRCDIR (/root/src/) で実行されるので makepkg する前にディレクトリを移動する必要はない
# PKGEXT を変えているのは生成物を xz で圧縮させないようにさせるため
sudo -u nobody -- bash -c "PKGDEST=$DESTDIR PKGEXT='.pkg.tar' makepkg -sr"
# mkosi.postinst
for CANDIDATE in /*.pkg.tar; do
        if [ -e "$CANDIDATE" ]; then
                pacman -U --noconfirm "$CANDIDATE"
                rm -f "$CANDIDATE"
        fi
done

まとめ

とりあえずやりたいことはできるようになったのでよかった。なんかもっとシンプルにできそうな気もするが、今はこれが限界。

参考

mkosi でつくる nspawn 用イメージに AUR パッケージをインストールしたい

2019-10-05 追記: この内容は古くなった。もっと確実な方法を以下で書いている。 ただし単純さでいえば本項目のほうが優れているかも。


90日以上放置すると出るアレが出ていたのでくだらん内容で凌ぐ。 それと mkosi はとくに systemd-nspawn 専用のツールというわけでもなく qemu などで起動する VM 用のイメージも作れるようだが、まあ、うん、いいじゃないですか。

最初に書いておくと mkosi する過程で AUR パッケージをビルドしてイメージにインストールするという方法は扱っていない。 それをやろうとして2ヶ月ほど苦悩し、結局挫折して今に至る。

TL; DR

devtools いれて事前にホスト側でパッケージつくる。 作ったパッケージを mkosi.extra 内に置いた上で mkosi.postinstpacman -U するようにして mkosi する。

動機

https://aur.archlinux.org/packages/tor-browser/ を使いたかったのだが Firefox が動くことになるので GTK が必要だった。 一方で現在 KDE を使っていて GTK なしでなんとかなっているので GTK をインストールしたくないという気持ちがあった。 既に Chromium が動くようになっている systemd-nspawn 用イメージがあるので、そこから起動してくるコンテナに件のパッケージをインストールしてやれば万事解決するのではと考えた。

方針

AUR パッケージをビルドする際に必要となると思しきパッケージをインストールすることでホストを汚したくないという向きの為に https://www.archlinux.org/packages/extra/any/devtools/ というものがある。 どうやらこれは Arch Linux 開発者向けのものらしいが、Arch 用パッケージを作るだけという用途でも充分に効果を発揮する。

https://wiki.archlinux.org/index.php/DeveloperWiki:Building_in_a_clean_chroot が詳しいが、 devtools に同梱される各種スクリプトを使用することで chroot で隔離された環境で makepkg に類することができる。

今回の用途としては AUR から git clone してできたディレクトリ内で extra-x86_64-build してやれば事足りる。 こうすると extra-x86_64-build を実行したときに居たディレクトリ内に pacman で処理できるパッケージができる。こいつを mkosi で処理できる場所に置いてやればよい。

mkosi はこれを実行したディレクトリ内にある mkosi.extra/ というディレクトリの中身をビルド対象イメージ内に全部コピーするので、先のパッケージをこのディレクトリに置いてやればイメージ内にパッケージが持ち込まれる。

これをどうインストールしてやるかについては mkosi.postinst というビルド処理完了時にイメージ内で実行されるスクリプトがあるので、この中で対象のパッケージを pacman -U してやるようにすればよい。 なお AUR パッケージの依存関係解決が走る場合、 mkosi.postinst が実行される段階ではネットワークがうまく疎通できなくなる 1 ので、ビルド内容を定義する mkosi.default なファイルで事前に AUR パッケージが依存するパッケージを全部列記してインストールしておくようにしたほうがよい。

実例

  1. https://github.com/nosada/mkosi-files/blob/41302ee69b925ee9b65693122eab59b48d5f456b/guispawn/Makefile#L13-L20 のようにする
  2. https://github.com/nosada/mkosi-files/blob/41302ee69b925ee9b65693122eab59b48d5f456b/guispawn/mkosi.postinst#L12-L14 のようにする
  3. https://github.com/nosada/mkosi-files/blob/41302ee69b925ee9b65693122eab59b48d5f456b/guispawn/mkosi.default.tmpl#L11-L40 のように必要なパッケージを書いておく
  4. こうすると make で AUR パッケージ入りのイメージが生成される

  1. mkosi 中に AUR パッケージをビルドできず挫折したのもこれが原因。ただこれ systemd-nspawn の問題というよりは veth に対しての iptables ルールが原因な気もしている。

nspawn コンテナの中で nginx を動かそうとすると /dev/null が open() できずコケる件が解消された

GitHub のプルリクやらイシューの観察日記なのでこの項目を読む価値はないです。

mastodon.sngsk.info が死んだ / 潰れたとき用兼 TL; DR

mastodon.sngsk.info が動いてる時だけ用を成す本文

sngsk.info の現在 - テクニカルプア でも言及していた下記が修正されていた:

以下これに気付いたときの記録:

Docker から逃れるために nspawn 使ってたのに nspawn が使えなくなって Docker に逃げるというアベコベな状況がなんとかなってよかった。

sngsk.info の現在

そろそろ三ヶ月以上更新されていない表示がされそうな雰囲気があるので書く。 だいぶ前に書いた下記の続編: nosada.hatenablog.com

現在 https://sngsk.infohttps://mastodon.sngsk.info もしょぼいリソースしかない1台のサーバで動いている:

# ユーザ名やホスト名は適当に変えています
[user@remote-host ~]$ nproc
1
[user@remote-host ~]$ free -h
              total        used        free      shared  buff/cache   available
Mem:          1.9Gi       1.0Gi        76Mi       168Mi       890Mi       653Mi
Swap:            0B          0B          0B
[user@remote-host ~]$ uname -a
Linux remote-host 4.19.7.a-1-hardened #1 SMP PREEMPT Thu Dec 6 03:19:15 CET 2018 x86_64 GNU/Linux

sngsk.info で動かしているアプリケーションは先の記事では nspawn で動いていると書いたが、現在は Docker コンテナを docker-compose で動かすように改めている。これは下記によって nspawn 内で Nginx がうまく動かない為だ:

mastodon.sngsk.info については現在も nspawn コンテナで稼動している。 以前はもうちょっと潤沢なリソースが使えるサーバで動かしていたが、お金の節約のため前述のリソースしか使えないサーバに引っ越している。 その際にリソース不足ですぐアップアップになってしまったので下記を参考に PgBouncer やら puma / sidekiq のチューニングなどしてなんとか宥めることに成功した: docs.joinmastodon.org

sngsk.info やら mastodon.sngsk.info についての愚痴はだいたい toot として集約している: mastodon.sngsk.info

これは mastodon.sngsk.info がいつかフッ飛べば不浄な記録も全部消滅するだろうということを企図したためだ。自分が運用しているアプリケーションが今後も安定して動作しつづけるとは全く思っていないため、sngsk.info も mastodon.sngsk.info も基本的にはいつ消滅しても諦められるような気持ちで過ごしている。

Essential Phone PH-1 買った

f:id:aaodsn:20180917151032j:plain Nexus5X 使うようになってからけっこう経ったしそろそろ買い替えるかあと思い、Essential Phone なんかいいんじゃないかなといろいろ調べてフームとなっていたところでIIJmio で Essential Phone が買えるようになったようでまあそれなら買ってしまうかとなり、サクっと買ってしまった。買ってから色々調べるともっと安く買えた時期があったようでちょっと哀しかった。

そして Nexus5X 使うようになってからけっこう経ったと書いたものの Nexus 5X 買った - テクニカルプア を見るとまだ2年も経っていなかったのだった。

これまでずっと Nexus 系統の携帯電話を使っていたのでほんとうは Pixel あたりを狙ったほうがよかったのだろうが、買いたいときに買いたいものを買ってしまって思い患いをなくしたほうが色々便利なのでそうした。どうやらPixel シリーズの新しいやつが日本で発売されるみたいな情報もあるらしい(信憑性は知らん)事を買ってから知ったので僻みも入っているかもしれない。

いまのところ stock の Android 9.0 で運用している。飽きたらカスタム ROM なりなんなりを調べ出すと思う。

ところで余談だが PH-1 を買ってから下記に突き当たってしまった。音声回線の維持に余計なコストを掛けたくないのでどうしようか思い悩んでいる。

systemd 239.0 で machinectl list-images の標準出力をパイプやリダイレクトで処理させようとすると assert して止まる

という事象がある。 これについては github.com で issue をつくった。 内容を追っていると assert() している箇所を消せば終わりな気がしたので github.com でプルリクもつくった。

先程プルリクを master にマージして頂いたのを記念して記事を書いている。 なお本件のワークアラウンドとしては /var/lib/machines/ 下をみてよしなにする以外の方法を思いついていない。

プルリクの中で

  • 英語がずさんすぎる
  • テスト書いてない
  • レビュアーさんを急かす

ということをしていてだいぶひどいことになってしまった事をここで謝罪致します。

systemd 239.0 で machinectl import-(raw|tar) を使うと結果が返ってこない事象の迂回策

TL; DR

systemd-importを使うとよい。 /usr/lib/systemd/ 下にあるのでパスが通っていない場合は絶対パスで頑張る。

systemd のバージョン

Arch Linux を使っています:

$ systemctl --version
systemd 239
+PAM -AUDIT -SELINUX -IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN +PCRE2 default-hierarchy=hybrid

$ machinectl --version
systemd 239
+PAM -AUDIT -SELINUX -IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN +PCRE2 default-hierarchy=hybrid

$ pacman -Qs systemd
local/libsystemd 239.0-2
    systemd client libraries
local/systemd 239.0-2 (base-devel)
    system and service manager

内容

systemd 239.0 になってから machinectl のサブコマンドである import-rawimport-tar とで nspawn 用イメージのインポートができなくなった様子。

具体的にはインポートしたいイメージをこしらえてから machinectl import-rawmachinectl import-tar を実行しても transfer を enqueue したというメッセージ以降でコマンドが応答しなくなる(以下 import-raw を取りあげるが import-tar でも同じだった):

# machinectl import-raw RAW_IMAGE
Enqueued transfer job 1. Press C-c to continue download in background.

コマンドとしては何も返さないが、machinectl list-transfers をみるとイメージのインポートについての進捗が得られる:

$ machinectl list-transfers
ID PERCENT TYPE       LOCAL    REMOTE
 1     31% import-raw RAW_IMAGE

1 transfers listed.

しかし list-transfers が下記のようになり、machinectl list-images でインポートしたイメージが見れるようになっても import-raw はプロンプトを戻してくれず、ダンマリを決めこんでしまう。

$ machinectl list-transfers
No transfers.

いろいろあって

https://www.freedesktop.org/software/systemd/man/systemd-importd.service.html によれば machinectlimport-(raw|tar) は systemd-importd の実装を借りているとのこと。

これを踏まえて import-raw 中に systemctl status systemd-importd を眺めていてみつけた /usr/lib/systemd/systemd-import を使ってみたところ、インポートの進捗がコマンドの応答として得られ、インポート完了後もプロンプトを返してくれた:

# /usr/lib/systemd/systemd-import raw RAW_IMAGE
Importing 'RAW_IMAGE', saving as 'RAW_IMAGE'.
Imported 0%.
Imported 1%.
Imported 2%.
Imported 3%.
Imported 4%.
...
Imported 99%.
Operation completed successfully.
Exiting.
#

いまのところ systemd-import を使うので特に問題なさそうなので、しばらくはこれでいこうと思う。

追記

issue あげた。勘違いとかでないとよいのだが。コメント欄の通り修正された。ご対応ありがとうございます。

machinectl: import-raw and import-tar not show progress / not respond · Issue #9527 · systemd/systemd · GitHub