[RFC] Skeleton jail (rc.d feature proposal)

From: Xin LI <delphij_at_delphij.net>
Date: Tue, 10 Feb 2009 19:24:22 -0800
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

Ok, some local users has prodded me in committing the "skeleton jail"
feature, I find it useful myself but not sure if it's appropriate to
commit it against -HEAD, so I'd like to explain it, try to present it in
a better way, and request for comments.  I'd like to have some native
English speakers to proof read the manual page changes if this is found
useful for general consumption.

Some descriptions:

=====

What is it?

Basically, a "skeleton" jail is a jail which has part of its
directories, typically directories containing the base system, say the
binaries, libraries, mount_nullfs'ed from a template, usually /.  What I
did implemented is some helper scripts as well as some Makefile changes
to make the task easier.

A NULLFS mount, typically, read-only, from either a template (an
installed world located in some directory, or the host system, say, /
itself), would reduce the time that is taken upon system upgrade; on the
other hand, it makes it possible to switch the base system libraries
on-the-fly.  The read-only nature of these NULLFS mounts also helps
development environments that don't want programmers to make
unauthorized changes to the base system itself, we actually have used it
in our development environment and found this as an useful side effect.

=====

How to use it?

One make(1) target, "installskel" has been added to top-level (/usr/src)
Makefile.  This can be used to populate a skeleton where only a minimal
set of files and directories are installed that will support the startup
of a skeleton jail.  "installskel" is actually a shortcut of "make
hierarchy" and "cd etc; make distribution".

So, to create a skeleton:

	cd /usr/src
	make installskel DESTDIR=$D

Where "D" is the directory where you want the skeleton to be placed at,
say, /vhost/myjail in this example; then, set up rc.conf(5) parameters
like this:

	jail_myjail_rootdir="/vhost/myjail/"
	jail_myjail_devfs_enable="YES"
	jail_myjail_skel_enable="YES"

The rc.d infrastructure would automatically mount the following
directories from the template (when not specified, /) as read-only:

	bin
	lib
	libexec
	sbin
	usr/bin
	usr/include
	usr/lib
	usr/libdata
	usr/libexec
	usr/sbin
	usr/share
	usr/src
	usr/obj

Cheers,
- --
Xin LI <delphij_at_delphij.net>	http://www.delphij.net/
FreeBSD - The Power to Serve!
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (FreeBSD)

iEYEARECAAYFAkmSROUACgkQi+vbBBjt66DncwCguU5YAytGEhvwMGbLzk0uFqkI
lKEAn3RhVNxIF4XROQj0ijWyEsZgP+IJ
=Sd9e
-----END PGP SIGNATURE-----

Index: Makefile
===================================================================
--- Makefile	(版本 188424)
+++ Makefile	(工作副本)
_at__at_ -84,6 +84,7 _at__at_
 	depend distribute distributeworld distrib-dirs distribution doxygen \
 	everything hierarchy install installcheck installkernel \
 	installkernel.debug reinstallkernel reinstallkernel.debug \
+	installskel \
 	installworld kernel-toolchain libraries lint maninstall \
 	obj objlink regress rerelease showconfig tags toolchain update \
 	_worldtmp _legacy _bootstrap-tools _cleanobj _obj \
_at__at_ -98,6 +99,7 _at__at_
 .ORDER: buildworld installworld
 .ORDER: buildworld distributeworld
 .ORDER: buildworld buildkernel
+.ORDER: buildworld installskel
 .ORDER: buildkernel installkernel
 .ORDER: buildkernel installkernel.debug
 .ORDER: buildkernel reinstallkernel
Index: Makefile.inc1
===================================================================
--- Makefile.inc1	(版本 188424)
+++ Makefile.inc1	(工作副本)
_at__at_ -651,6 +651,18 _at__at_
 	    ${IMAKEENV} rm -rf ${INSTALLTMP}
 
 #
+# installskel
+#
+# Installs a minimum set of files that can support a mini-jail
+#
+installskel:
+	_at_echo "--------------------------------------------------------------"
+	_at_echo ">>> Making installskel"
+	_at_echo "--------------------------------------------------------------"
+	${_+_}cd ${.CURDIR}; ${MAKE} hierarchy
+	${_+_}cd ${.CURDIR}/etc; ${MAKE} distribution
+
+#
 # reinstall
 #
 # If you have a build server, you can NFS mount the source and obj directories
Index: etc/defaults/rc.conf
===================================================================
--- etc/defaults/rc.conf	(版本 188424)
+++ etc/defaults/rc.conf	(工作副本)
_at__at_ -611,6 +611,11 _at__at_
 jail_set_hostname_allow="YES" # Allow root user in a jail to change its hostname
 jail_socket_unixiproute_only="YES" # Route only TCP/IP within a jail
 jail_sysvipc_allow="NO"	# Allow SystemV IPC use from within a jail
+jail_skel_enable="NO"	# Whether to globally enable "skel" jail
+jail_skel_root="/"	# The root directory for skel template
+jail_skel_romounts="bin lib libexec sbin usr/bin usr/include usr/lib usr/libdata usr/libexec usr/sbin usr/share usr/src usr/obj"
+			# Read-only nullfs mounts from the template
+jail_skel_rwmounts=""	# Read-write nullfs mounts from the template
 
 #
 # To use rc's built-in jail infrastructure create entries for
_at__at_ -640,6 +645,11 _at__at_
 #jail_example_mount_enable="NO"			# mount/umount jail's fs
 #jail_example_fstab=""				# fstab(5) for mount/umount
 #jail_example_flags="-l -U root"		# flags for jail(8)
+#jail_example_skel_enable="NO"			# Whether to enable "skel" jail
+#jail_example_skel_root="/"			# The root directory for skel template
+#jail_example_skel_romounts="bin lib libexec sbin usr/bin usr/include usr/lib usr/libdata usr/libexec usr/sbin usr/share usr/src usr/obj usr/ports"
+						# Read-only nullfs mounts from the template
+#jail_example_skel_rwmounts=""			# Read-write nullfs mounts from the template
 
 ##############################################################
 ### Define source_rc_confs, the mechanism used by /etc/rc.* ##
Index: etc/rc.d/jail
===================================================================
--- etc/rc.d/jail	(版本 188424)
+++ etc/rc.d/jail	(工作副本)
_at__at_ -85,6 +85,16 _at__at_
 	[ -z "${_consolelog}" ] && _consolelog="/var/log/jail_${_j}_console.log"
 	eval _fib=\"\${jail_${_j}_fib:-${jail_fib}}\"
 
+	# Default settings for skel jail
+	eval _skel_enable=\"\${jail_${_j}_skel_enable:-${jail_skel_enable}}\"
+	[ -z "${_skel_enable}" ] && _skel_enable="NO"
+	eval _skel_root=\"\${jail_${_j}_skel_root:-${jail_skel_root}}\"
+	[ -z "${_skel_root}" ] && _skel_root="/"
+	eval _skel_romounts=\"\${jail_${_j}_skel_romounts:-${jail_skel_romounts}}\"
+	[ -z "${_skel_romounts}" ] && _skel_romounts="bin lib libexec sbin usr/bin usr/include usr/lib usr/libdata usr/libexec usr/sbin usr/share usr/src usr/obj"
+	eval _skel_rwmounts=\"\${jail_${_j}_skel_rwmounts:-${jail_skel_rwmounts}}\"
+	[ -z "${_skel_rwmounts}" ] && _skel_rwmounts=""
+
 	# Debugging aid
 	#
 	debug "$_j devfs enable: $_devfs"
_at__at_ -120,6 +130,10 _at__at_
 	debug "$_j exec stop: $_exec_stop"
 	debug "$_j flags: $_flags"
 	debug "$_j consolelog: $_consolelog"
+	debug "$_j skel enable: $_skel_enable"
+	debug "$_j skel mount-readonly: $_skel_romounts"
+	debug "$_j skel mount-readwrite: $_skel_rwmounts"
+	debug "$_j skel mount skeleton from: $_skel_root"
 
 	if [ -z "${_hostname}" ]; then
 		err 3 "$name: No hostname has been defined for ${_j}"
_at__at_ -241,6 +255,14 _at__at_
 			secure_umount ${_mountpt}
 		done
 	fi
+	if checkyesno _skel_enable; then
+		for _mntpt in ${_skel_romounts} ${_skel_rwmounts}
+		do
+			if [ -d "${_rootdir}/${_mntpt}" ] ; then
+				umount -f ${_rootdir}/${_mntpt} > /dev/null 2>&1
+			fi
+		done
+	fi
 }
 
 # jail_mount_fstab()
_at__at_ -509,6 +531,17 _at__at_
 			fi
 			jail_mount_fstab
 		fi
+		if checkyesno _skel_enable; then
+			info "Mounting skeleton for jail ${_jail} from ${_skel_root}"
+			for _mntpt in $_skel_rwmounts
+			do
+				mount_nullfs ${_skel_root}/${_mntpt} ${_rootdir}/${_mntpt} > /dev/null 2>&1
+			done
+			for _mntpt in $_skel_romounts
+			do
+				mount_nullfs -ordonly ${_skel_root}/${_mntpt} ${_rootdir}/${_mntpt} > /dev/null 2>&1
+			done
+		fi
 		if checkyesno _devfs; then
 			# If devfs is already mounted here, skip it.
 			df -t devfs "${_devdir}" >/dev/null
Index: share/man/man5/rc.conf.5
===================================================================
--- share/man/man5/rc.conf.5	(版本 188424)
+++ share/man/man5/rc.conf.5	(工作副本)
_at__at_ -24,7 +24,7 _at__at_
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 27, 2009
+.Dd February 10, 2009
 .Dt RC.CONF 5
 .Os
 .Sh NAME
_at__at_ -3413,6 +3413,46 _at__at_
 .Va jail_ Ns Ao Ar jname Ac Ns Va _exec_stop
 for every jail in
 .Va jail_list .
+.It Va jail_skel_enable
+.Pq Vt bool
+Set to
+.Dq Li NO
+by default.
+When set to
+.Dq Li YES ,
+sets
+.Va jail_ Ns Ao Ar jname Ac Ns Va _skel_enable
+to
+.Dq Li YES
+by default for every jail in
+.Va jail_list .
+.It Va jail_skel_root
+.Pq Vt str
+Set to
+.Dq Li /
+by default.
+When set, use as default value for
+.Va jail_ Ns Ao Ar jname Ac Ns Va _skel_root
+for every jail in
+.Va jail_list .
+.It Va jail_skel_romount
+.Pq Vt str
+Set to
+.Dq Li bin lib libexec sbin usr/bin usr/include usr/lib usr/libdata usr/libexec usr/sbin usr/share usr/src usr/obj
+by default.
+When set, use as default value for
+.Va jail_ Ns Ao Ar jname Ac Ns Va _skel_romount
+for every jail in
+.Va jail_list .
+.It Va jail_skel_rwmount
+.Pq Vt str
+Set to empty by default.
+When set, use as default value for
+.Va jail_ Ns Ao Ar jname Ac Ns Va _skel_rwmount
+for every jail in
+.Va jail_list .
 .It Va jail_ Ns Ao Ar jname Ac Ns Va _rootdir
 .Pq Vt str
 Unset by default.
_at__at_ -3549,6 +3589,38 _at__at_
 .Dq Li /bin/sh /etc/rc.shutdown
 by default.
 This is the command executed at jail shutdown.
+.It Va jail_ Ns Ao Ar jname Ac Ns Va _skel_enable
+.Pq Vt bool
+Set to
+.Dq Li NO
+by default.
+When set to
+.Dq Li YES ,
+enable the skeleton jail, which
+.Xr mount_nullfs 8
+two lists of filesystems, one of which lists read-only,
+another lists read-write as specified by the administrator,
+relative to the template root, into inside jail
+.Ar jname
+respectively, at jail startup.
+.It Va jail_ Ns Ao Ar jname Ac Ns Va _skel_root
+.Pq Vt str
+Set to
+.Dq Li /
+by default.
+Specifies the root directory that a skeleton template is based on.
+.It Va jail_ Ns Ao Ar jname Ac Ns Va _skel_romounts
+.Pq Vt str
+Specifies a list of directories that is expected to be mounted from
+the skeleton template, into inside jail
+.Ar jname ,
+as read-only.
+.It Va jail_ Ns Ao Ar jname Ac Ns Va _skel_rwmounts
+.Pq Vt str
+Specifies a list of directories that is expected to be mounted from
+the skeleton template, into inside jail
+.Ar jname ,
+as read-write.
 .It Va jail_set_hostname_allow
 .Pq Vt bool
 If set to
Index: usr.sbin/jail/jail.8
===================================================================
--- usr.sbin/jail/jail.8	(版本 188424)
+++ usr.sbin/jail/jail.8	(工作副本)
_at__at_ -412,6 +412,46 _at__at_
 /etc/rc.d/jail start myjail
 /etc/rc.d/jail stop myjail
 .Ed
+.Ss "Setting up a Jail from a template directory"
+A so-called skeleton jail, is an environment where part of its
+directories comes from
+.Xr mount_nullfs 8
+from a template directory.
+.Pp
+Such setup can save the time for the administrator because it makes
+it possible to share certain binaries and libraries between several
+jails, as well as easy experimenting different releases of the
+operating system libraries by switching template directories.
+Also, this type of setup would save certain amount of disk space.
+.Pp
+A template directory can be populated with
+.Dq "make world" ,
+or, the host system environment
+.Aq Dq "/" ,
+can be used as well.
+.Pp
+To set up a jail directory tree containing the jail, one can use
+the following
+.Xr sh 1
+command script:
+.Bd -literal
+D=/here/is/the/jail
+cd /usr/src
+mkdir -p $D
+make installskel DESTDIR=$D
+.Ed
+.Pp
+One should explicitly specify that the jail is skeleton jail, by
+either enabling the global flag
+.Dq jail_skel_enable ,
+or the per-jail flag
+.Dq Va jail_ Ns Ao Ar jname Ac Ns Va _skel_enable
+in 
+.Xr rc.conf 5
+configuration.  The system supplied a set of defaults that is
+useful for typical setup, and is tweakable through several variables
+as described in
+.Xr rc.conf 5 .
 .Ss "Managing the Jail"
 Normal machine shutdown commands, such as
 .Xr halt 8 ,
Received on Wed Feb 11 2009 - 02:24:40 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:42 UTC