jailを利用すると、FreeBSDの中で、もう一つ(あるいは複数)のFreeBSDを動かすことが出来ます。厳密に言うと、ディレクトリツリーやプロセスを封じ込めて、各種サービスやアプリケーションを実行することができます。ですから、見かけ上、FreeBSDの中で別のFreeBSDが動いているように見えます。
これと似たようなものに[[jman 8:chroot][chroot(8)]]があります。これは、特定のコマンドを実行する際、ルートディレクトリの位置を変更することにより、そのコマンド以下のプロセスが、許可されているディレクトリより上位の部分にあるコマンドの実行やファイルの閲覧を防止する、というものです。
ただ、chrootでは、上位ディレクトリは隠せてもプロセスまでは隠せません。丸見えです。これでは万が一、root等の高い権限が乗っ取られた場合、chroot環境下以外の全く別のプロセスを停止させられたり、そのプロセス自体が乗っ取られる危険性があります。
それに対して、jailではjail外のプロセスは参照できません。何か不都合が生じたとしても、それはそのjail内だけの話です。ですから、jailはchrootよりも、安全であると言えます。外部に公開するサービスなどはjail内に置いた方が良い場合もあるかも知れません。
これは、FreeBSD 5.4におけるjail環境の構築と運用についての覚え書きです。
まず、構築の準備として、jailの親となるホスト側の/etc/make.confを適切に設定して、不要なものをビルドしないようにしておきます。
さて、ソースツリーに入り、jailを構築します{{fn:ホスト側を[[FreeBSD/makeworld][makeworld]]で構築し直した際、それの使いまわしでもOK}}。DESTDIRには、jailがインストールされるPATHを示します。ここでは、便宜上、環境変数JAIL_ROOTに、jailがインストールされるPATHを予めセットしておきます{{fn:jail環境をどこに置かなければならないかということは決まっておらず、当然、各自の都合の良い場所に設けてもらって構わない。この例では、/usr/homeにマウント(/home自体は/usr/homeへの[[jman 7:symlink][symlink(7)]])されているパーティション以下に${JAIL_ROOT}を置いて説明している。やや話が逸れるが、例えば、ホスト側の/usrを後で触れるmount_nullfsを利用して、jail側の/usrに使い回そうとした場合、これだと/usrと/usr/home/jail/www/usrのPATHは直系の関係(そのまま${JAIL_ROOT}から上に登っていけば/usrにたどり着く)になってしまい、「not distinct paths」とか言われて、nullfsではマウントすることができない。ホスト側の====/usr/ports====、/usr/bin、/bin等は、ここでの${JAIL_ROOT}とは枝分かれした傍系の関係(上に遡っても、どの時点かで一旦、下に降りなければ該当する場所にたどり着けない)になるので問題なくマウントできる。したがって、もし、ここで例示したような/home以下に${JAIL_ROOT}を設定するケースにおいて、nullfsを介してホスト側の/usr以下を一括してjail側に使いまわしたいような場合には、事前に、/usr/homeにマウントしているパーティションのマウント先を/homeに変更し、既存の/usr/homeはそれへのsymlinkに置き換えるなどと工夫が必要になる。もっとも、jail専用のパーティションを設けるなりして、/jailなどとマウントし、他と重複しないような場所に${JAIL_ROOT}を最初から設定していれば、このような問題はそもそも発生しないが。}}。
# setenv JAIL_ROOT /home/jail/www # mkdir -p ${JAIL_ROOT} # cd /usr/src # make buildworld # make installworld DESTDIR=${JAIL_ROOT}
次に、/usr/src/etcに入り、jail側の/etcに展開される設定ファイルをインストールします。
# cd /usr/src/etc # make distribution DESTDIR=${JAIL_ROOT}
ビルドが終了したら、jailが正常に動作するための基本設定をします。
タイムゾーンをJST(日本標準時)にします。
# cp -p /usr/share/zoneinfo/Asia/Tokyo ${JAIL_ROOT}/etc/localtime
jailの起動時にエラーが表示されないよう、kernelと/etc/fstabのダミーファイルを作成。
# cd ${JAIL_ROOT} # ln -sf dev/null kernel # touch etc/fstab
jail内の/etc/rc.confを次のように作成。
network_interface="" syslogd_flags="-ss" sendmail_enable="NONE"
任意で、各jailごとにセキュリティレベルを設定することができます([[jman 8:init][init(8)]]参照)。
#kern_securelevel_enable="YES" #kern_securelevel="3"
必要に応じて、sshdを起動するように以下を追加しても良いでしょう{{fn:ただし、その場合は、jail内の/etc/ssh/sshd_configファイル内の====ListenAddress====の項目で、jailに割り当てる予定のIPアドレスを明示すること。}}。
#sshd_enable="YES"
加えて、jail側の/etc/resolv.confも設定し、jail内で名前解決が解消できるようにしておきます。
# echo 'nameserver 123.123.123.123' > etc/resolv.conf
あと、jail側の/homeは、ホスト側から覗く頻度も多いと思います。しかし、そのシンボリックリンクが、絶対PATHで指定されていると混同して紛らわしいので、予め相対PATHで作成しておくと便利です。
# mkdir usr/home # ln -sf usr/home .
としておきます。
ここまでで大体出来上がり。後で使いまわせるように、バックアップを取っておきます。
# cd ${JAIL_ROOT} # tar zcf /var/tmp/jail.tar.gz .
事前に、ホスト自体に、IPアドレスを明示せずにlistenしているサービスがあるかどうかを確かめます。
# sockstat | grep "\*:[0-9]"
ここで、もし、jman:sockstat][sockstat(1)を実行した際、「LOCAL ADDRESS」に該当する項目で、IPアドレスが明示されていないもの{{fn:「 *: 」のように表示されるもの。jman:jail][jail(8)にマニュアルに具体例が書かれています。その他、メジャーなサービスについては、http://www.section6.net/wiki/index.php/Creating_a_FreeBSD_Jail#Getting_services_to_not_listen_to_.2A][Creating a FreeBSD Jail - Section6wikiに解かり易く記載されていました。}}があれば、そのポートの使用に関しては、jail側と競合することになります。この問題を回避するため、予めホストに割り当ててあるIPアドレスを明示してlistenさせるように、該当するサービスの設定を見直しましょう。
さて、実際に構築したjailが起動するかどうか確かめましょう。まず、jailに割り当てるIPアドレスを確保するため、doc-ja:books/handbook/configtuning-virtual-hosts.html][ネットワークインターフェースにエイリアスをつけます。
# ifconfig fxp0 alias 192.168.0.20/32
次に、devfsがjailからも見えるように、jail側の/devにもマウントします。
# mount -t devfs dev ${JAIL_ROOT}/dev
念のため、jail用のdevfsルールセット{{fn:通常、====/etc/defaults/devfs.rule====で定義されているjail用のルールセットを適用。数値で指定。[[man 8:devfs][devfs(8)]]参照。}}を適用し、不要なデバイスファイルを隠します。
# devfs -m ${JAIL_ROOT}/dev rule -s 4 applyset
これで起動できると思います{{fn:JAIL_ROOTをjailのルートディレクトリとして、www.somedomain.comというhostnameを与え、192.168.0.20というIPアドレスをバインドして、jail内の/bin/shを起動すると言う意味です。}}。
# jail ${JAIL_ROOT} www.somedomain.com 192.168.0.20 /bin/sh
システム起動時、自動的に====/etc/rc.d/jail====スクリプトを実行して、jailを起動するようにするためには、ホスト側の/etc/rc.confに次を加えます{{fn:コメントにしてあるものは任意。また、====FreeBSD 6.1-RELEASE====からは、「jail_www_interface="fxp0"」のように、各jail環境ごとに、(IPアドレスを割り当てるための)インターフェースを指定することができるようになりました。jail環境で用いるIPアドレスは、/etc/rc.d/jailの起動時、指定したインターフェース上に、エイリアスとして、割り当ててくれます。したがって、jail環境で用いるIPアドレスを確保するため、上記「ifconfig_fxp0_alias0」のような記述を事前にしておく必要はなくなりました(http://www.xdelta.net/blog/FreeBSD/2006/05/07/p184][FreeBSD Notes - FreeBSD 6.1-RELEASEにアップグレードを参照)。}}。
ifconfig_fxp0_alias0="inet 192.168.0.20 netmask 255.255.255.255 broadcast 192.168.0.255" jail_enable="YES" jail_list="www" # 起動したいjailを列挙。複数ある場合は、"www www2"の様に、スペースで区切る ### 全jail共通の設定 ### #jail_set_hostname_allow="YES" # jail内のrootユーザが、そのjailに割り当ててある # hostnameを変更しようとしても、許可しないのならNO #jail_socket_unixiproute_only="YES" # jail内から、UNIXドメインソケット・IPv4アドレス・ # ルーティングソケット以外へのアクセス(例えば、 # 他のドメイン、IPX等へのアクセス)を許可するのならNO #jail_sysvipc_allow="NO" # jail内でSystemVの共有メモリの使用を許可するならYES ### 各jail固有の設定 ### jail_www_rootdir="/home/jail/www" jail_www_hostname="www.somedomain.com" jail_www_ip="192.168.0.20" jail_www_devfs_enable="YES" #jail_www_exec_start="/bin/sh /etc/rc" # jail起動スクリプトの既定値 #jail_www_exec_shutdown="/bin/sh /etc/rc.shutdown" # jail終了スクリプトの既定値 #jail_www_fdescfs_enable="NO" # jail内でfdescfs(5)を使用するならYES #jail_www_procfs_enable="NO" # jail内でprocfs(5)を使用するならYES #jail_www_mount_enable="NO" # 当該jail起動/終了時、特別にmount/umountを実行するかどうか #jail_www_devfs_ruleset="ruleset_name" # jail用の/devに適用するルールセットが特別にあれば指定 # # 既定では/etc/defaults/devfs.rulesで定義されている # # "devfsrulesets_jail"になる #jail_www_fstab="" # 上記jail_www_mountをYESとした場合、参照されるfstabの名前 # # 通常、マウントポイントはjail_www_rootdir以下のディレクトリを指定 ### その他に、jail_listに列挙したjailがあれば、上記を参考に設定 ### #ifconfig_fxp0_alias1="inet 192.168.0.21 netmask 255.255.255.255 broadcast 192.168.0.255" # #jail_www2_hostname="www2.somedomain.com" #jail_www2_ip="192.168.0.21" #jail_www2_rootdir="/home/jail/www2" #jail_www2_devfs_enable="YES"
これにより、システム起動時、====/etc/rc.d/jail====スクリプトから、上記設定{{fn:なお、上記「全jail共通の設定」に関しては、これ以外にも[[jman 8:sysctl][sysctl(8)]]でカーネルのMIB変数を操作することで、細かな設定が可能です。それらについては、man:jail][jailの最新のオンラインマニュアル、「Sysctl MIB Entries」の項を参照してください。}}が読み込まれ、jailが開始します。
直接、このjailスクリプトから開始したい場合は、
# /etc/rc.d/jail start
とします。
必要な設定を済ませているjail環境であれば、たとえ、上記====/etc/rc.conf====内の「====jail_list====」に列記していなくても、
# /etc/rc.d/jail start www2
といったように、直接、jail名を指定することでも実行できます。
jailを任意に停止する場合は、停止させたいjail内にrootでログインし、
# kill -TERM -1
# kill -KILL -1
のいずれかのように、すべてのプロセス{{fn:jman:kill][kill(1)で、プロセス番号「-1」を指定すると、rootの場合、それは、全プロセスを意味する。一般ユーザが用いた場合は、そのユーザに属する全てのプロセスを意味する。}}に対して、目的に応じたシグナルを送るか、もしくは、ホスト側で、
# killall -TERM -j JID
の様に、jman:killall][killall(1)に、-jオプションを付けて、JID{{fn:このJIDとは、コマンド====/usr/sbin/jls====を実行して得られる、jailを識別するための番号の事である。}}を指定してシグナルを送ることにより、該当jailを停止する事が出来ます。
====/etc/rc.conf====に前述のjailに関する設定をしてあれば、単に、
# /etc/rc.d/jail stop
とコマンドスクリプトを実行する事により、jailは停止します。また、
# /etc/rc.d/jail restart
とすることにより、jailを再起動することも出来ます{{fn:一旦、停止させた後、jls等を使って完全に停止したのを確認してから、起動し直した方が確実なようです。}}。
ただし、これらの方法では、====/etc/rc.conf====内の「====jail_list====」に列挙されている全てのjailが対象となるので、注意して下さい。任意のものを指定したい場合には、
/etc/rc.d/jail stop www2
等とjail名を指定します。
もし、構築したjailが不要になり、削除したい場合は、まず、完全にjailを停止し、JAIL_ROOT以下にマウントされたものを全てマウント====解除====します。
特定のファイルには、schgフラグ{{fn:rootのみが設定できる変更不可フラグ。jman:chflags][chflags(1)参照。}}が設定されているので、実際にJAIL_ROOT以下を削除する前、
# chflags -R noschg ${JAIL_ROOT}
を実行して、フラグを取り除きます。これで、通常のようにして削除できると思います。
まず、第一に、rootのパスワードを設定します。初期の状態では、設定されていないので大変危険です。jail内でpasswd等のコマンドを実行して任意のパスワードを設定するか、あるいは、jman:vipw][vipw(8)を実行してjail内のrootのパスワードの箇所を「*」のように書き換えましょう。
# vipw -d ${JAIL_ROOT}/etc/ root:*:0:0::0:0:Charlie &:/root:/bin/csh
この方法では、rootでは通常、入れなくなります。しかし、root権限が必要な場合もあるので、そういった場合は、ホスト側からjman:jexec][jexec(8)というコマンドを使用するという風にします。
ホスト側で、[[FreeBSD/jls][jls]]とコマンドを打ち込むと、
JID IP Address Hostname Path 1 192.168.0.20 www.somedomain.com /home/jail/www
のように表示されるので、このJID{{fn:なお、特定のjailを停止・起動した時、新たに割り振られるJIDは停止前と同じではない。固定ではないということに注意。}}に該当するjailで操作が行いたければ、
# jexec 1 /bin/csh
とすれば、該当jail内のcshを起動して、root権限で作業が行えます。
ただし、この場合、ホスト側の環境変数が引き継がれてしまうので、引き継ぎたくなければ、csh起動後、
# su -
を実行するか、最初から、
# jexec 1 /usr/bin/su -
等と、ログインすると、うまくいくようです。
jail内に追加するユーザのUID/GIDは、ホスト側と重複しないものに設定した方が無難。例えば、ホスト側に1001のUIDを持つ「kou」とユーザが存在する時、jail内に同じUIDを持つ「ostu」というユーザを追加すると、ホスト側から見た場合、ユーザ「kou」とjail内のユーザ「otsu」の区別が付きにくく、紛らわしいからである。
導入するアプリケーションは、[[FreeBSD/packages][packages]]や[[FreeBSD/ports][ports]]を利用した方が管理が容易です。
ホスト側のportsツリーを同期した後、jail側に既にインストールされているものも更新されてないかを知りたい時には、
env PKG_DBDIR=${JAIL_ROOT}/var/db/pkg pkg_version -l '<'
とすることにより、チェックできます。
また、各jail内に[[FreeBSD/portaudit][portaudit]]の導入を考えている場合、ports:security/jailaudit][security/jailauditというものもあるので、検討してみるのも良いでしょう。これを使うと、個々のjailにportauditを導入する手間が省け、ホスト側から一元して、各jail内にインストールされているportsの脆弱性のチェックを行うことができるので便利です。
しかし、jail側でportsを利用する場合、一番問題となるのは、膨大な量の====/usr/ports====以下のファイルをjail側にも展開しなければならないことです。jail環境にまでportsツリーを展開するのは資源の無駄{{fn:http://bird.zero.ad.jp/~zau60806/FreeBSD/sono41_.html][初心者もOK! FreeBSD質問スレッド その41++のログ内、795,797-798,801,810,835番の書き込み参照。}}なので、ここでは、[[jman 8:mount_nullfs][mount_nullfs(8)]]を利用{{fn:なお、もし、このケース以外にnullfsを活用する場合でも、書き込みが可能でマウントした時には、nullfsを介してアクセスできる箇所(この場合だと====/usr/ports====以下にあるファイル群)が、jail側から不本意に書き換えられるかも知れないという危険性に留意しておく必要がある(/usr等のホスト環境の安全性に関わる部分を、書き込み可能でマウントしたnullfsを介して、jail側に使い回そうとするのは危険)。}}{{fn:それに加え、通常のファイル・ディレクトリ以外(要するにスペシャルファイル)には、nullfsを介してアクセスしないよう注意。そういう場合は、前述したホスト側の/etc/rc.confの設定などで各${JAIL_ROOT}以下に専用のものを用意する。}}して、ホスト側のportsツリーを借用することにします。
# mkdir ${JAIL_ROOT}/usr/ports # mount_nullfs /usr/ports ${JAIL_ROOT}/usr/ports
これでhost側の====/usr/ports====が、jail側の====/usr/ports====にマウントされることになります。
導入するportによっては、/usr/srcのファイルを必要とするものもあるので、適宜、
# mount_nullfs /usr/src ${JAIL_ROOT}/usr/src
としておきます。これで、
# jexec JID /bin/csh www# cd /usr/ports/someports www# make install && make clean www# exit
の様にすれば、jail側のportsツリーからアプリケーションを導入する事が出来ます。
もし、nullfsでマウントした====/usr/ports====に、portsをビルドする際、書き込みされるのが不都合{{fn:現在のところ、nullfsは公式にはサポートされておらず、万が一の場合はデータ破壊の恐れもあり得る。通常、書き込み可能モードよりも、読み込み専用モードの方が安全性が高いと考えるのが妥当であって、全く書き込みされるのを避けたいのであれば、http://www.otsune.com/bsd/jail/fulljail.html][otsune's FreeBSD memo :: jailの作り方にも記載されているように、最初から====「mount_nullfs -o ro /usr/ports ${JAIL_ROOT}/usr/ports」====などと読み込み専用の状態でマウントする方針で、上記make.confの設定をした方が良い(ただし、4.10以前ではPR:kern/63662][問題があったので注意。なお、====FreeBSD==== 6.0以降でのnullfsは、実用に耐え得るものに改善されているようです)。}}であれば、jail側の/etc/make.confに、
DISTDIR=/home/data/distfiles PACKAGES=/home/data/packages WRKDIRPREFIX=/var/tmp
等と、予め適当な作業ディレクトリを環境変数に指定{{fn:各環境変数の役割についてはjman:ports][ports(7)を参照。これらを指定しておかないと、jail側の作業であるにも拘らず、nullfsを介して、ホスト側の====/usr/ports====内でビルドに関連した作業が行われてしまう。それに、もし、同時にホスト側や他のjail環境でも、====/usr/ports====を共有してビルドしたような場合、それだと、作業が競合してトラブルが発生する可能性もあるので、特に理由がなければ、上記設定を各jail内の/etc/make.confに明示して作業用のディレクトリは、それぞれ固有のものに別けておいた方が良い。}}しておくと良いでしょう。
アプリケーションの導入が完了し、先ほどマウントしたportsツリー等の必要がなくなれば、ホスト側で以下のようにします。
# umount /usr/ports # umount /usr/src
これでアンマウントされます{{fn:定時に/etc/crontabから呼び出される[[jman 8:periodic][periodic(8)]]等で、重複してjman:find][find(1)されたりしても無駄なので、こまめに[[jman 8:umount][umount(8)]]するよう習慣づけておいた方が何かと無難(もっとも、FreeBSD 6.0以降、nullfsは安定していると言われているので、ports:sysutils/ezjail/][sysutils/ezjailというportのように、nullfsを常時利用することを前提にしたものもある。各jail環境ごとにmakeworld等で個別のベースシステムを用意するのではなく、予めjail環境専用のベースシステムを一つ用意しておき、それをnullfsを介し、複数のjail環境と共有することで、ディスク領域を節約しようという試みである)。}}。
マニュアルを読むと、現在のところnullfsは完全にサポートされていない{{fn:====FreeBSD==== 6.1のマニュアルでは、このような記述は消えました(実質、6.0でも実用に耐え得るものです)。}}とのことなので、そのようなリスクを侵してまで使用したくない、しかし、一つのシステム内にportsツリーを多重に展開するのは明らかに無駄だと考える方にとって、====/usr/ports====以下を別パーティション、あるいは、doc-ja:books/handbook/disks-virtual.html#DISKS-MDCONFIG][ファイルベースのファイルシステムに移行{{fn:====/usr/ports====以下にソースファイルを置いたり、ビルド等を行わない方針であれば、確保するディスク容量は、400MB弱ぐらいあれば(現時点で)十分足りると思うが、ファイル数が多いので、問題となるのは[[jman 8:newfs][newfs(8)]]時のinodeの密度。通常、全体のファイルサイズの平均値辺りが目安といわれている。}}して、必要に応じてホスト側とjail側とで切替え、便宜上、portsビルドの際に使い回すというのも一つの選択肢です。
既に====/usr/ports====を別パーティション等に設けてあれば問題はありませんが、設けてない場合、新規に物理的なディスクを用意したり、既存の領域を見直したりするよりも、通常、ファイルベースの仮想ディスクを作成する方が容易です。
以下は、[[man 8:mdconfig][mdconfig(8)]]を利用して、ファイルベースの仮想ディスクを作成し、====/usr/ports====以下{{fn:作成時で、総ファイル数 94,953(内ディレクトリ数 20,343)、合計 158,262,103bytes(なお、この内、man:portsdb][portsdb(1)によって作成されたINDEX.dbの14,385,152bytesが含まれる)、平均値 1,666.7bytes、標準偏差 53,408.9(?)でした。}}をそれに移行させて、ホスト側とjail側でportsツリーを使い回すことにしようという一例です{{fn:portsツリーの更新はホスト側で行うこととし、jail側にマウントする際は、不用意な書き換えを防ぐため、読み込み専用にしてマウントすることを指向しています。多少、容量に余裕を持たせていますが、====/usr/ports====(仮想ディスク)内に、ソースファイルを置いたり、ビルド作業を行う等は、この例では考慮していません。それらはホスト及び各jail内に個別に設けたディレクトリで行います。したがって、各/etc/make.conf内に、href:#nullfsを用いた事例][nullfsを用いた事例で触れたDISTDIR、WRKDIRPREFIX等の環境変数を設定しておくことが前提です。もし、distfilesやpackagesも仮想ディスク内に置きたい場合は、もっと容量をとった方が良いでしょう。なお、mdconfigを用いて既存のディスクイメージをマウントすることになるので、通常のファイルシステムのように/etc/fstabに記述して、起動時、自動的にマウントさせるといったことはできません。別途、設定が必要になります。}}。
# date Fri Sep 23 21:03:06 JST 2005 # dd if=/dev/zero of=/var/tmp/ports.image bs=1k count=500k # mdconfig -a -t vnode -f /var/tmp/ports.image md0 # bsdlabel -w md0 # bsdlabel md0 # /dev/md0: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 1023984 16 unused 0 0 c: 1024000 0 unused 0 0 # "raw" part, don't edit # newfs -i 2048 md0a # bsdlabel md0 # /dev/md0: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 1023984 16 4.2BSD 2048 16384 60864 c: 1024000 0 unused 0 0 # "raw" part, don't edit # ;; # mount /dev/md0a /mnt # ( cd /usr/ports/ && tar cf - . ) | ( cd /mnt/ && tar xfp - ) # df -i /mnt Filesystem 1K-blocks Used Avail Capacity iused ifree %iused Mounted on /dev/md0a 435670 294292 106526 73% 94954 209364 31% /mnt # ls -l /var/tmp/ports.image -rw-r--r-- 1 root wheel 524288000 Sep 23 21:39 /var/tmp/ports.image # umount /mnt # ;; # cd /usr # mv ports ports.bak # mkdir ports # ;; # mount /dev/md0a /usr/ports # mount | grep md0a /dev/md0a on /usr/ports (ufs, local) # ls -l /usr/ports/INDEX.* -rw-r--r-- 1 root wheel 14385152 9 23 14:06 /usr/ports/INDEX.db # umount /usr/ports # ;; # mount -o ro /dev/md0a /home/jail/www/usr/ports # mount | grep md0a /dev/md0a on /usr/home/jail/www/usr/ports (ufs, local, read-only) # jls JID IP Address Hostname Path 1 192.168.0.20 www.somedomain.com /home/jail/www # jexec 1 su - www# cd /usr/ports www# touch test touch: test: Read-only file system www# logout # umount /home/jail/www/usr/ports # ;; # mdconfig -d -u md0
その2{{fn:異なるリソースを割り当てて、同じイメージをする同時に使用したいような場合は、全て読み込み専用の状態でマウントした方が無難(書き込み可能であれば、事前に、読み込み専用にマウント状態を変更。なお、この例ではホスト側と同時にビルドを行うことを想定していましたが、煩瑣になるので割愛しました)。}}
# mdconfig -a -t vnode -f /home/data/disks/ports.image -u 0 # mount /dev/md0a /usr/ports/ # mount | grep md0 /dev/md0a on /usr/ports (ufs, local) # ;; # cd /usr/ports/ && make update && portsdb -Uu # ;; # mount -u -r /usr/ports # mdconfig -a -t vnode -f /home/data/disks/ports.image -u 1 # mount -o ro /dev/md1a ${JAIL_ROOT}/usr/ports # mdconfig -l md1 md0 # mount | grep "md[0-1]" /dev/md0a on /usr/ports (ufs, local, read-only) /dev/md1a on /usr/home/jail/www/usr/ports (ufs, local, read-only) # ;; # umount /dev/md[0-1]a # mdconfig -d -u 0 # mdconfig -d -u 1