Ports jail
From FBSD_tips
Back to "Admin building blocks"
DRAFT DRAFT DRAFT
Contents |
[edit] Rationale
Sometimes you want to be able to isolate certain jobs away from the main host environment. Compiling ports with huge dependency lists is a candidate for this. Many times the dependencies involve important foundational packages and effect the proper operation of the host environment. Updating KDE is a good example of this. A full KDE build can take quite some time, even on fast machines, and having a portion of the dependencies updated and a portion outdated can render the desktop partially or fully inoperative. Add to this the possibility of an error (either in the options or a port issue) and you could have to start again in part or full. This is an unacceptable downside for a machine that you want to be operational for continuous use, e.g. your primary desktop. Compiling whole dependency trees in a jail is one solution for this situation (and several other use cases).
[edit] Optional prerequisites
(or is "Optional prerequisites" an oxymoron?)
Related articles
- jail_building
- Ports building options
This article is meant as a follow on to Jail building although I have kept it as applicable to generic jails as possible. Where I use some feature of the Jail building I will note it.
[edit] Setup
Now we will create and start up a jail with the script from the article Here.
make_jail.sh -D /usr/jails/ports
You will want this jail OS version to match the OS version of your target install machine(s). Additionally, the point of a port builder jail is isolation, this isolation is twofold :
- isolate the host from build issues
- create pristine packages.
Towards these ends, you should NOT reuse the jail for any other purposes.
Then, get into the jail by finding it's jail ID and jexec-ing yourself a shell.
Host # jls JID IP Address Hostname Path 1 YOUR_JAIL_IP_ADDRESS jail1.example.com /usr/jails/jail1.example.com/root/ Host # jexec 1 sh
Update your ports tree like this.
Make the directory that ports will put your buil;t packages in.
Jail1 # mkdir /usr/ports/packages/All
Finally, link the jailed ports tree to the host's environment(1st moving or deleting the old ports tree that was there).
Deleting the old tree :
Host # rm -rf /usr/ports
Moving the old tree :
Host # mv /usr/ports /usr/ports.old
Then link :
Host # ln -s /usr/jails/jail1.example.com/root/usr/ports /usr/ports
[edit] Testing
Now you can build ports in isolation, installing the resulting packages in the host's environment, in other jails or on other machines. As an example test it out like this :
Host # jexec 1 sh Jail1 # cd /usr/ports/shells/bash Jail1 # make package-recursive
You should now have these files in your /usr/ports/packages/All/ (or slightly different version numbers).
Jail1 # pkg_info bash-3.2.17_2.tbz libiconv-1.9.2_2.tbz gettext-0.16.1_3.tbz
These are ready to install with pkg_add.
[edit] A real world example
Building something like KDE can take a day (or more) even on a fast machine. While the build process is installing new packages you will have mismatched versions of libs and package for nearly the duration of this process. Here is a simple method to make sure that you have a complete package set built BEFORE you start wholesale upgrading on a machine you may well depend on.
In the host environment, make a text file with all the origins of your packages in it.
Host # pkg_info -o -a -q > /path/to/ports/builder/jail/host_package_list.txt
Next, for each origin, build a new package in the builder jail.
Host # jexec 1 sh
Jail1 # cat host_package_list.txt | \
Jail1 # while read ORGN
Jail1 # do
Jail1 # (cd /usr/ports/$ORGN/ 2> /dev/null && make -DBATCH package || echo "error on ${ORGN}" >> error.log )
Jail1 # done
This process is not bullet proof, if ports move or are restructured massively it has no intelligence built into it to handle it (e.g. the X11 6.X to 7.X "explosion). For work-a-day updates to ports/packages it is however quite effective.
Now in the host environment run pkg_replace (from ports) first setting PKGREPOSITORY and unsetting PACKAGEROOT (to prevent downloading packages)
Host # export PKGREPOSITORY /path/to/ports/builder/jail/usr/ports/packages/All/ Host # export PACKAGEROOT "" Host # pkg_replace -a -P
If the process missed building a package you can go build it individually and return to the pkg_replace phase again.
[edit] Keeping the environment clean
Portupgrade has a useful utility in it, portsclean. Build the package and all dependencies with the target package-recursive for quick addition later via package_add :
Jail1 # cd /usr/ports/ports-mgmt/portupgrade Jail1 # make package-recursive
The next time all you need to do is (substitute your version number) :
Jail1 # pkg_add /usr/ports/packages/All/portupgrade-2.3.1,2.tbz
Now, to start from a clean ports building environment do this :
Jail1 # portsclean --workclean --distclean Jail1 # pkg_delete -a
[edit] Discussion
You may want to do a read only nullfs mount into the jails from the port builder like this :
Add this to /etc/fstab :
/usr/jails/ports/live/usr/ports /usr/jails/[DIRECTORY]/live/usr/ports nullfs ro 0 0
Then
mkdir /usr/jails/[DIRECTORY]/live/usr/ports mount /usr/jails/[DIRECTORY]/live/usr/ports
Gongo 20:36, 26 September 2007 (UTC)
