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 の depends
や makedepends
に書かれてるものを 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 -U
を mkosi.postinst
で実行してあげればよい。
また mkosi.build
で makepkg -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.postinst
で pacman -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 パッケージが依存するパッケージを全部列記してインストールしておくようにしたほうがよい。
実例
- https://github.com/nosada/mkosi-files/blob/41302ee69b925ee9b65693122eab59b48d5f456b/guispawn/Makefile#L13-L20 のようにする
- https://github.com/nosada/mkosi-files/blob/41302ee69b925ee9b65693122eab59b48d5f456b/guispawn/mkosi.postinst#L12-L14 のようにする
- https://github.com/nosada/mkosi-files/blob/41302ee69b925ee9b65693122eab59b48d5f456b/guispawn/mkosi.default.tmpl#L11-L40 のように必要なパッケージを書いておく
- こうすると
make
で AUR パッケージ入りのイメージが生成される
nspawn コンテナの中で nginx を動かそうとすると /dev/null が open() できずコケる件が解消された
GitHub のプルリクやらイシューの観察日記なのでこの項目を読む価値はないです。
mastodon.sngsk.info が死んだ / 潰れたとき用兼 TL; DR
- [Arch|AUR] After upgrading to 3.4 nginx won't start on container because it can't open /dev/null · Issue #4950 · lxc/lxd · GitHub というものがあった
- [RFC] core: adapt PrivateDevices= to changed behavior on 4.18 kernels by brauner · Pull Request #9483 · systemd/systemd · GitHub というプルリクが systemd に対して存在していて、これはマージこそされなかったが事象は解消された的なメッセージが添えられて閉じられている
- あとは掲題通り
mastodon.sngsk.info が動いてる時だけ用を成す本文
sngsk.info の現在 - テクニカルプア でも言及していた下記が修正されていた:
以下これに気付いたときの記録:
Docker から逃れるために nspawn 使ってたのに nspawn が使えなくなって Docker に逃げるというアベコベな状況がなんとかなってよかった。
sngsk.info の現在
そろそろ三ヶ月以上更新されていない表示がされそうな雰囲気があるので書く。 だいぶ前に書いた下記の続編: nosada.hatenablog.com
現在 https://sngsk.info も https://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 買った
Nexus5X 使うようになってからけっこう経ったしそろそろ買い替えるかあと思い、Essential Phone なんかいいんじゃないかなといろいろ調べてフームとなっていたところでIIJmio で Essential Phone が買えるようになったようでまあそれなら買ってしまうかとなり、サクっと買ってしまった。買ってから色々調べるともっと安く買えた時期があったようでちょっと哀しかった。
そして Nexus5X 使うようになってからけっこう経ったと書いたものの Nexus 5X 買った - テクニカルプア を見るとまだ2年も経っていなかったのだった。
これまでずっと Nexus 系統の携帯電話を使っていたのでほんとうは Pixel あたりを狙ったほうがよかったのだろうが、買いたいときに買いたいものを買ってしまって思い患いをなくしたほうが色々便利なのでそうした。どうやらPixel シリーズの新しいやつが日本で発売されるみたいな情報もあるらしい(信憑性は知らん)事を買ってから知ったので僻みも入っているかもしれない。
いまのところ stock の Android 9.0 で運用している。飽きたらカスタム ROM なりなんなりを調べ出すと思う。
ところで余談だが PH-1 を買ってから下記に突き当たってしまった。音声回線の維持に余計なコストを掛けたくないのでどうしようか思い悩んでいる。
FOMA 契約な SIM を刺してる Nexus4 を退役させ Nexus5X をその用途にあてて IIJmio な SIM を PH-1 に充てようと思っていたのだが Nexus5X で FOMA な SIM が使えないことを今日知ってこの始末をどうにかつける必要がでてきた結果とばっちりで PH-1 触る気力が失われてきた
— 之貞 (@ngsksdt) 2018年9月16日
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-raw
と import-tar
とで nspawn 用イメージのインポートができなくなった様子。
具体的にはインポートしたいイメージをこしらえてから machinectl import-raw
や machinectl 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 によれば machinectl
の import-(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 あげた。勘違いとかでないとよいのだが。コメント欄の通り修正された。ご対応ありがとうございます。