diff --git a/README.md b/README.md
index f07ecf1..dbaf75c 100644
--- a/README.md
+++ b/README.md
@@ -5,17 +5,156 @@ used to build, update, manage and run jails in a versioned environment.
Every jail consists of layers of directories mounted on top of each
other using nullfs mounts. Some of them can be shared among jails,
-some are versioned.
+some are versioned. By using shared and versioned layers of mounts it
+is easy to update jails in a new version while the current version is
+still running, you can switch back to an older version of a jail.
+
+Most of the layers are mounted read-only for security reasons.
+
+Let's take a look at the layers of a typical running jail built with `jaildk`:
+```
+ 1 /jail/base/12.1-RELEASE-p10 /jail/run/db read-only
+ 2 /dev/md12 /jail/run/db/tmp
+ 3 devfs /jail/run/db/dev
+ 4 /jail/log/db-20201026 /jail/run/db/var/log
+ 5 /jail/appl/db-20201026 /jail/run/db/usr/local read-only
+ 6 /jail/etc/db/etc-20201026 /jail/run/db/etc read-only
+ 7 /jail/etc/db/local-etc-20201026 /jail/run/db/usr/local/etc read-only
+ 8 /jail/etc/db/cron-20201026 /jail/run/db/var/cron
+ 9 /jail/home/db/root-20201026 /jail/run/db/root
+ 10 /jail/data/db/mysql-20201026 /jail/run/db/usr/local/data/mysql
+ 11 /backup/db /jail/run/db/var/backups
+ |
+ +--- root of the jail
+```
+
+As can be easily deduced this is a database jail with the following layers:
+
+1. **base layer**: This is basically the same as a FreeBSD base, which
+ contains all biinaries, libraries and other files required to boot
+ up a FreeBSD system. Our base doesn't contain a kernel by default,
+ but you could add one, required if you want to use the ports
+ collection and compile `lsof` yourself.
+ This particular base is based on 12.1-RELEASE-p10, that is, I
+ created it while I had this release installed and running on the
+ host system.
+2. **tmp layer**: Just a ramdisk for `/tmp`, the size can be tuned.
+3. **dev layer**: Contains /dev/null and friends, required by every jail.
+4. **log layer**: Here we have our first versioned layer for
+ `/var/log`. Notice how all other layers are using the same version,
+ this is done by purpose (but can be changed if you like). The
+ version is a jail variable (see below) which is being used for all
+ layers.
+5. **application layer**: As you know if you're using FreeBSD, any
+ additional software, wether installed from a port or as package,
+ will be installed to `/usr/local`. In our case it contains the
+ mysql server software, bash and a couple of supporting
+ utilities. It is being mounted read-only, so no new software can be
+ installed in the running jail. This might sound annoying at first,
+ because you can't just install stuff inside the jail anytime you
+ like. But it forces you to work more disciplined. Once a jail has
+ been completely built you can be sure, all components match with
+ each other. Read below how to install or update software in a jail.
+6. **/etc layer**: this just contains the normal etc, it is basically
+ a stripped copy of the host `/etc`. We do not use it at all inside
+ a jail, but it's required nontheless. There are some exceptions
+ however, like `/etc/resolv.conf`.
+7. **/usr/local/etc layer**: This is the place we configure all
+ aspects of the jail, all configs reside here (like in our case the
+ mysql config). It is also being mounted read-only, just like
+ the etc layer.
+8. **cron layer**: A writable mount for the crontabs of users inside
+ the jail. That way one can modify crontabs with `crontab
+ -e`. However, if you don't want or need this, just remove the layer
+ and add cronjobs to `/etc/crontab`.
+9. **/root layer**: most of the administrative work inside a jail must
+ be done as the root user and it would be a pity not to have a
+ writable history. So, `/root` is mounted writable to add more
+ comfort.
+10. **a data layer**: A versioned data layer which contains the binary
+ data of our mysql server. This is very jail specific and you have
+ to add such layers yourself. Variants of such a layer include the
+ document root of a webserver or the repositories of a git server.
+11. **backup layer**: Another custom layer, here we've mounted a
+ global backup directory of our host which contains all backups.
+
+All layers are configured in a `mount.conf` file specific for each
+jail. The one for this jail looks like this:
+```
+base/$base $name nullfs ro
+md $name/tmp mfs rw,nosuid,async 500m 1777
+dev $name/dev devfs
+log/$name-$version $name/var/log nullfs rw
+appl/db-$version $name/usr/local nullfs ro
+etc/$name/etc-$version $name/etc nullfs ro
+etc/$name/local-etc-$version $name/usr/local/etc nullfs ro
+etc/$name/cron-$version $name/var/cron nullfs rw
+home/$name/root-$version $name/root nullfs rw
+data/$name/mysql-$version $name/usr/local/data/mysql nullfs rw
+/backup/db $name/var/backups nullfs rw
+```
+
+Now, as you can see, we're using variables here. Those are defined in
+the `jail.conf` (not to be confused with `/etc/jail.conf` on the
+host!):
+```
+name=db
+version=20201026
+base=12.1-RELEASE-p10
+```
+
+You might wonder how the other aspects of a jail are configured like
+ip addresses, routing, jail parameters, sysctls etc. Well, that's
+beyond the purpose of `jaildk`. You just use the standard FreeBSD
+mechanism for these things, that is `/ect/rc.conf`, `/etc/jail.conf`,
+`service jail ...`, `jexec`, etc. However, `jaildk` provides some
+handy wrappers to make live easier.
+
+For an overview of the provided commands, here's the usage screen:
+```
+Usage: /usr/local/bin/jaildk
+
+Building Jails:
+base -b [-w] - build a new base
+build [-b ] [-v ] - install a build chroot of a jail
+create - create a new jail from a template
+clone -s -d [-o ] [-n ] - clone an existing jail or jail version
+fetch - fetch current port collection
+
+Installing Jails:
+install [-r function] - install a jail (prepare mounts, devfs etc)
+uninstall [-w] - uninstall a jail
+remove - remove a jail or a jail version
+reinstall - stop, remove, install and start a jail
+
+Maintaining Jails:
+start - start a jail
+stop - stop a jail
+restart - restart a jail
+status [] - display a jail's status
+rc [-r ] - execute an rc-script inside a jail
+
+Managing Jails:
+login [] - login into a jail
+blogin - chroot into a build jail
+
+Transferring Jails:
+freeze [-a -b -v ] - freeze (build an image of) a jail
+thaw - thaw (install) an image of a jail
+
+Getting help:
+help - request help on
+```
## Installation
-Execute the following command:
+Download the file `jaildk` or clone this repository to your FreeBSD server and execute the following command:
```
./jaildk setup
```
-This will create the directory structure required for the tool install
-the tool itself, create a template jail and build a base directory.
+This will create the directory structure required for the tool itself,
+create a template jail and build a base directory.
## Basic usage
@@ -37,7 +176,7 @@ Create the file `/etc/jail.conf` with the following innitial contents:
sysvshm = "new";
host.hostname = $name;
path = "/jail/run/$name";
- exec.prestart = "/jail/bin/jaildk install $name all start";
+ exec.prestart = "/jail/bin/jaildk install $name start";
exec.clean = "true";
}
@@ -52,12 +191,12 @@ Refer to [jail(8)](https://www.freebsd.org/cgi/man.cgi?query=jail&sektion=8) for
Next add the following lines to your `/etc/rc.conf`:
```
-ifconfig_em0_alias0="inet 144.76.67.168/32"
+ifconfig_em0_alias0="inet 172.16.1.1/32"
jail_enable="YES"
```
You may need to replace the interface name `em0` with the one in use on your system.
-
+You might need to restart the interface to apply the alias: `/etc/rc.d/netif restart`.
### Create the jail
```
@@ -135,7 +274,7 @@ A normal base directory cannot be used with the ports collection
because jaildk removes libraries and binaries for security reasons
from normal bases. To create a build base, execute:
-`jaildk base 12-RELEASE-build rw`
+`jaildk base -b 12-RELEASE-build -w`
Next, add the following entry to the configuration of you jail. To
stay with our example, edit `/jail/etc/myjail/jail.conf` and add:
@@ -197,7 +336,7 @@ fcgiwrap is running as pid 37682.
### Login into the running jail for administration
```
-# jaildk jlogin myjail
+# jaildk login myjail
```
You can use this to login into a database or execute commands inside the jail.
@@ -209,22 +348,22 @@ The very first thing to do is to update the host system using `freebsd-update`.
Next create a new base version:
```
-jaildk base `uname -r`
+jaildk base -b `uname -r`
```
Now you can create clone of your jail with a new version:
```
-jaildk clone myjail myjail 20201106 20210422
+jaildk clone -s myjail -d myjail -o 20201106 -n 20210422
```
Mount the build chroot for the new version:
```
-jaildk build myjail start `uname -r` 20210422
+jaildk build myjail start -b `uname -r` -v 20210422
```
And finally chroot into the new jail and update it:
```
-blogin myjail
+jaildk blogin myjail
pkg update
...
```
@@ -233,6 +372,178 @@ The last step is to remove the current running jail, change the version in `etc/
If there's anything wrong you can always go back to the previous version using the above steps.
+## Advanced Features
+
+Jaildk also offers some advanced features like automatically setting
+up and deleting ipfw rules or freezing and thawing a jail (to make it
+easily portable).
+
+### Using the IPFW
+
+To use the IPFW on your host you first have to enable ipfw in your
+hosts rc.conf `firewall_enable="YES"`. You probably want to set the
+default firewalling-type there aswell, check out the
+[FreeBSD handbook](https://www.freebsd.org/doc/handbook/firewalls-ipfw.html)
+for further information.
+
+Once enabled you also need to start ipfw by executing the rc script:
+
+`/etc/rc.d/ipfw start`.
+
+Be aware that inter-jail communication is transfered via the loopback
+interface (normally lo0) for which there is a high priority allow any
+to any rule by default:
+
+`allow ip from any to any via lo`
+
+In order to control the inter-jail communication you have to delete
+this rule first.
+
+If an ipfw.conf exists for a jail (e.g. /jail/etc/myjail/ipfw.conf)
+the rules inside that config file are added when starting, and deleted
+when stopping the jail. E.g. allowing HTTP/HTTPS traffic for that
+jail (webserver):
+
+`allow tcp from any to $ip setup keep-state`
+
+As demonstrated in the previous rule `$ip` is reserved and
+automatically replaced with the jails own ip (as reported by
+`jls`). The same applies to the ipv6 address which will be available
+as variable `$ip6`. Also, all variables in the jails `jail.conf` can
+be used.
+
+In order to make these ipfw rules available on boot, you need to add
+the following line to `/etc/jail.conf` in the section of the jail
+which uses custom ipfw rules:
+
+`exec.prestart = "/jail/bin/jaildk ipfw $name"`
+
+Be aware, that the ipfw module will only be executed if the jail is
+running so that we can properly determine the ip addresses of the
+running jail. **Note**: this might change in the future.
+
+### Using pf
+
+Beside ipfw, Free supports
+[pf](https://www.freebsd.org/doc/de_DE.ISO8859-1/books/handbook/firewalls-pf.html)
+as well. You can use pf with `jaildk`. Unlike the ipfw module (see
+above) it is a normal `install` module. That is it can be installed or
+reloaded before the jail is running (i.e. like the mount module).
+
+In order to use `pf` with a jail, enable and configure it according to
+the FreeBSD handbook linked above. It is recommended to include
+general block, scrup, state rules, communication to and fro localhost
+etc and just leave everything which is related to your jail.
+
+Just so that you know how such a global `/etc/pf.conf` file might look
+like, here's a simple one:
+```shell
+# variables
+ext = "em0"
+me = "your ipv4 address here"
+me5 = "your ipv6 address here/64"
+loginports = "{ 22, 5222, 443 }"
+icmp_types = "echoreq"
+
+# tables. look at the contents of a table:
+# pfctl -t bad_hosts -T show
+# remove an entry from a table:
+# pfctl -t bad_hosts -T delete $ip
+table persist
+
+# default policy
+set block-policy drop
+
+# optimize according to rfc's
+set optimization aggressive
+
+# normalisation
+scrub in all
+antispoof for $ext
+
+# allow localhost
+pass quick on $local
+
+# additional default block rules w/ logging. to view the log:
+# tcpdump -n -e -ttt -r /var/log/pflog
+# to view live log:
+# tcpdump -n -e -ttt -i pflog0
+block in log on $ext
+block in log on $ext inet6
+
+# whoever makes it into those tables: you loose
+block quick from
+
+# allow outgoing established sessions
+pass out keep state
+pass out inet6 keep state
+
+# allow troubleshooting
+pass in on $ext inet proto icmp all icmp-type $icmp_types keep state
+pass in on $ext inet proto udp from any to any port 33433 >< 33626 keep state
+
+# allow all icmpv6
+pass in quick inet6 proto icmp6 all keep state
+
+# allow login but punish offenders
+block quick from
+pass in quick on $ext inet proto tcp from any to $me port $loginports \
+ flags S/SAFR keep state \
+ (max-src-conn-rate 10/60, \
+ overload flush global) label ServicesTCP
+pass in quick on $ext inet6 proto tcp from any to $me6 port $loginports \
+ flags S/SAFR keep state \
+ (max-src-conn-rate 10/60, \
+ overload flush global) label ServicesTCP
+```
+
+Install the ruleset with `service pf start`.
+
+Now that everything is prepared you can create a `/jail/etc/myjail/pf.conf` file for your
+jail. Here's an example I use for a webserver jail, which includes a
+git server:
+```shell
+ip = "jail ip4 addr"
+ip6 = "jail ip6 addr"
+loginports = "{ 22 }"
+prodports = "{ 80, 443 }"
+ext = "em0"
+
+# dynamic block list
+table
+
+# restrict foreigners
+block quick from
+pass in quick on $ext inet proto tcp from any to $ip port $loginports \
+ flags S/SAFR keep state \
+ (max-src-conn-rate 10/60, \
+ overload flush global) label ServicesTCP
+
+# allow production traffic v4
+pass in quick on $ext proto tcp from any to $ip port $prodports keep state
+
+# allow production traffic v6
+pass in quick inet6 proto tcp from any to $ip6 port $prodports keep state
+```
+
+That's it already. Now install the jail as usual. You can also install
+the pf ruleset for the jail separately:
+
+`jaildk install myjail start -r pf`
+
+To take look at the rules, execute:
+
+`jaildk install myjail status -r pf`
+
+You can of course manipulate the ruleset manually. `jaildk` installs
+rulesets into a jail specific anchor using the following naming
+scheme: `/jail/`. So, for example to view the rules, execute:
+
+`pfctl -a /jail/myjail -s rules`
+
+Manipulate a jail specific table:
+
+`pfctl -a /jail/myjail -t blocked -T show`
## Getting help
@@ -251,6 +562,8 @@ This software is licensed under the BSD license.
T.v.Dein
+F.Sass (Culsu)
+
## Project homepage
https://github.com/TLINDEN/jaildk
diff --git a/jaildk b/jaildk
old mode 100644
new mode 100755
index 971bedf..9e2c928
--- a/jaildk
+++ b/jaildk
@@ -1,6 +1,6 @@
#!/bin/sh
-version=1.07
+version=1.09
usage_jaildk() {
beg=`tput -T ${TERM:-cons25} md`
@@ -11,39 +11,52 @@ This is jaildk version $version, a jail management toolkit.
Usage: $0
${beg}Building Jails:${end}
-base - build a new base
-build - install a build chroot of a jail
-create - create a new jail from a template
-clone - clone an existing jail or jail version
-fetch - fetch current port collection
+base -b [-w] - build a new base
+build [-b ] [-v ] - install a build chroot of a jail
+create - create a new jail from a template
+clone -s -d [-o ] [-n ] - clone an existing jail or jail version
+fetch - fetch current port collection
${beg}Installing Jails:${end}
-install - install a jail (prepare mounts, devfs etc)
-uninstall - uninstall a jail
-remove - remove a jail or a jail version
-reinstall - stop, remove, install and start a jail
+install [-r function] - install a jail (prepare mounts, devfs etc)
+uninstall [-w] - uninstall a jail
+remove - remove a jail or a jail version
+reinstall - stop, remove, install and start a jail
${beg}Maintaining Jails:${end}
-start - start a jail
-stop - stop a jail
-restart - restart a jail
-status - display a jail's status
-rc - execute an rc-script inside a jail
+start - start a jail
+stop - stop a jail
+restart - restart a jail
+status [] - display a jail's status
+rc [-r ] - execute an rc-script inside a jail
+ipfw - add or remove ipfw rules
${beg}Managing Jails:${end}
-login - login into a jail (also available as separate command)
-blogin - chroot into a build jail (dito)
+login [] - login into a jail
+blogin - chroot into a build jail
${beg}Transferring Jails:${end}
-freeze - freeze (build an image of) a jail
-thaw - thaw (install) an image of a jail somewhere else
+freeze [-a -b -v ] - freeze (build an image of) a jail
+thaw - thaw (install) an image of a jail
-Run the without arguments to get usage help about the command.
+${beg}Getting help:${end}
+help - request help on
EOF
)
- echo "$usage"
- exit 1
+ echo "$usage"
+ exit 1
+}
+
+usage_help() {
+ command=$1
+
+ usage="usage_${command}"
+ if ! type "$usage" > /dev/null 2>&1; then
+ die "Unknown command $command!"
+ else
+ $usage
+ fi
}
ex() {
@@ -67,6 +80,11 @@ bold() {
echo -n "$BOLD_OFF"
}
+fin() {
+ echo "$*" >&2
+ exit
+}
+
die() {
bold "$*" >&2
exit 1
@@ -101,28 +119,100 @@ die_if_not_exist() {
fi
}
+parse_jail_conf() {
+ #
+ # just in case we want or have to fetch variables out of
+ # /etc/jail.conf, this is the way to go. Call it like this:
+ #
+ # ip=`parse_jail_conf $jail ip4.addr`
+ #
+ # Output may be empty, so check before using. Multiple variables
+ # of the same type (like multiple ip addresses) will be returned
+ # comma separated.
+ jail=$1
+ search=$2
+ JAIL=''
+ list=''
+
+ # fetch 20 lines after "^$jail {", ignore comments
+ egrep -A20 "^$jail" jail.conf | egrep -v "^ *#" | \
+ # turn each line into an evaluable shell expression \
+ sed -e 's/ *{//g' -e 's/}//g' -e 's/ *= */=/g' -e 's/;$//' | \
+ # ignore empty lines \
+ egrep -v '^$' | while read LINE; do
+ if echo "$LINE" | egrep -q "="; then
+ case $JAIL in
+ $jail)
+ var=`echo "$LINE" | cut -d= -f1`
+ opt=`echo "$LINE" | cut -d= -f2 | sed -e 's/^"//' -e 's/"$//'`
+ case $var in
+ $search)
+ if test -z "$list"; then
+ list="$opt"
+ else
+ list="$list,$opt"
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ echo $list
+ return
+ ;;
+ esac
+ else
+ case $LINE in
+ \*) JAIL=any;;
+ *) JAIL="$LINE";;
+ esac
+ fi
+ done
+}
+
+
+
+usage_build() {
+ fin "Usage: $0 build [] [-b ] [-v ]
+Mount to $j/build read-writable for maintenance. Options:
+-b Use specified . default: use configured base.
+-v Mount of .
+ One of start, stop or status. default: start."
+}
+
jaildk_build() {
jail=$1
mode=$2
- base=$3
- version=$4
+ shift
+ shift
+
+ base=''
+ version=''
- load-jail-config $jail
+ while getopts "b:v:" arg; do
+ case $arg in
+ b) base=${OPTARG};;
+ v) version=${OPTARG};;
+ *) usage_build;;
+ esac
+ done
if test -z "$mode"; then
- echo "Usage: $0 build [] []"
- exit 1
+ mode=start
fi
+ die_if_not_exist $jail $version
+
+ load-jail-config $jail
+
if test -n "$buildbase"; then
base="$buildbase"
elif test -z "$base"; then
- # not configured, use default: latest
+ # nothing configured, use default: latest
base=`ls $j/base | tail -1`
fi
# install the jail to build/
- jaildk_install $jail all $mode rw $base $version
+ jaildk_install $jail $mode -r all -w -b $base -v $version
case $mode in
start)
@@ -133,12 +223,40 @@ jaildk_build() {
esac
}
+jaildk_rc_pf() {
+ jail=$1
+ mode=$2
+ conf=$j/etc/$jail/pf.conf
+
+ # FIXME: maybe we use parse_jail_conf() to fetch ip addresses,
+ # generate a config file containing pf macros, which the user
+ # needs to include in the jails pf.conf? On the other hand,
+ # there's not that much duplication in the config. So, maybe not.
+ if test -f $conf; then
+ case $mode in
+ start)
+ bold "Installing PF rules for jail $jail:"
+ pfctl -a /jail/$jail -f $conf -v
+ ;;
+ status)
+ bold "PF rules for jail $jail:"
+ pfctl -a /jail/$jail -s rules -v
+ ;;
+ stop)
+ bold "Removing PF rules for jail $jail:"
+ pfctl -a /jail/$jail -f $conf -v -F all
+ ;;
+ esac
+ fi
+}
+
jaildk_rc_mtree() {
jail=$1
mode=$2
base=$3
version=$4
rw=$5
+ rcscript=mtree
if [ $mode = "start" ]; then
if test -n "$rw"; then
@@ -342,46 +460,57 @@ jaildk_rc_mount() {
done
}
-jaildk_install_usage() {
- err "Usage: $0 install [[] ]"
- err "If is 'all' every script will be executed in rc-order."
- err "If is not specified, just execute all scripts with ."
- err "Available rc.d-scripts: $RCSCRIPTS_START"
- exit 1
+
+
+usage_install() {
+ fin "Usage: $0 install [] [-r rc-function]
+Install according to its config. Options:
+ Mode can either be start, stop or status. default: start
+-r Only execute function with parameter. default: all.
+
+Available rc.d-scripts: $RCSCRIPTS_START"
}
jaildk_install() {
jail=$1
- rcd=$2
- mode=$3
+ mode=$2
+ shift
+ shift
+ rcd=''
- # used by jaildk_build() only
- rw=$4
- base=$5
- version=$6
+ # options -b -w -v are undocumented, used by jaildk_build() only
+ rw=''
+ base=''
+ version=''
+
+ while getopts "r:b:v:w" arg; do
+ case $arg in
+ w) rw=1;;
+ b) base=${OPTARG};;
+ v) version=${OPTARG};;
+ r) rcd=${OPTARG};;
+ *) usage_install;;
+ esac
+ done
if test -z "$jail"; then
- jaildk_install_usage
- fi
-
- if test -z "$rcd"; then
- # default just install all
- mode=start
- rcd=all
- else
- case $rcd in
- start|stop|restart|status)
- # shift args
- mode=$rcd
- rcd=all
- ;;
- esac
+ usage_install
fi
if test -z "$mode"; then
- jaildk_install_usage
+ mode=start
fi
+ if test -z "$rcd"; then
+ # default just install everything
+ rcd=all
+ fi
+
+ case $mode in
+ start|stop|restart|status) :;;
+ *) usage_install;;
+ esac
+
die_if_not_exist $jail
if test "$rcd" = "all"; then
@@ -410,14 +539,27 @@ jaildk_install() {
done
}
+usage_uninstall() {
+ fin "Usage: $0 uninstall [-w]
+Uninstall . Options:
+-w Uninstall writable build chroot."
+}
+
jaildk_uninstall() {
# wrapper around _install
jail=$1
- rw=$2
+ shift
+ rw=''
+
+ while getopts "w" arg; do
+ case $arg in
+ w) rw=1;;
+ *) usage_uninstall;;
+ esac
+ done
if test -z "$jail"; then
- err "Usage: $0 uninstall []"
- exit 1
+ usage_uninstall
fi
die_if_not_exist $jail
@@ -426,18 +568,34 @@ jaildk_uninstall() {
die "Jail $jail($version) is still running, stop it before removing!"
fi
- jaildk_install $jail all stop $rw
+ jaildk_install $jail stop -r all -w
+}
+
+
+usage_base() {
+ fin "Usage: $0 base -b [-w]
+Build a base directory from bsd install media. Options:
+-b can be the name of a base (e.g. 12.2-RELEASE)
+ or a directory where it shall be created
+-w Create a writable base, including compiler and other
+ build stuff. Use this if you want to use the ports
+ collection."
}
jaildk_base() {
- base=$1
- rw=$2
+ base=""
+ rw=""
+
+ while getopts "b:w" arg; do
+ case $arg in
+ w) rw=1;;
+ b) base=${OPTARG};;
+ *) usage_base;;
+ esac
+ done
if test -z "$base"; then
- err "Usage: $0 base []"
- err "If the has been set, the base will not cleaned up"
- err "and will contain compilers and other build stuff. Use"
- err "this if you want to use the ports collection."
+ usage_base
fi
removelist="tests
@@ -515,7 +673,7 @@ var/tmp"
exit 1
else
ex mkdir -p $basedir
- bsdinstall jail $basedir
+ bsdinstall jail $basedir || exit 1
if test -z "$rw"; then
# run base
@@ -565,21 +723,40 @@ clone() {
fi
}
+usage_clone() {
+ fin "Usage: $0 clone -s -d [-o ] [-n ]
+-s Source jail to clone from
+-d Destionation jail to create from source
+-o Old version
+-n New version
+
+Hints:
+- if no source version has been given, tha latest version will be used.
+- if no new version has been given, source version will be used.
+- if source and new jail are the same, both versions must be given
+ and a new version of the same jail will be created (update)"
+}
+
jaildk_clone() {
- src=$1
- new=$2
- srcversion=$3
- newversion=$4
- update=""
+ src=''
+ new=''
+ srcversion=''
+ newversion=''
+ update=''
+
+ while getopts "s:d:o:n:" arg; do
+ case $arg in
+ o) srcversion=${OPTARG};;
+ n) newversion=${OPTARG};;
+ s) src=${OPTARG};;
+ d) new=${OPTARG};;
+ *) usage_clone;;
+ esac
+ done
+
if test -z "$new"; then
- echo "Usage: $0 clone [ []]"
- echo "Hints:"
- echo "- if no source version has been given, tha latest version will be used."
- echo "- if no new version has been given, source version will be used."
- echo "- if source and new jail are the same, both versions must be given"
- echo " and a new version of the same jail will be created (update)"
- exit 1
+ usage_clone
fi
if test "$src" = "$new"; then
@@ -620,7 +797,7 @@ jaildk_clone() {
clone $j/data/$src/www $j/data/$new/www
clone $j/data/$src/spool $j/data/$new/spool
- ex cp -pRp $j/etc/$src/mount.conf $j/etc/$src/ports.conf $j/etc/$src/mtree.conf $j/etc/$new/
+ ex cp -pRp $j/etc/$src/mount.conf $j/etc/$src/ports.conf $j/etc/$src/mtree.conf $j/etc/$src/ipfw.conf $j/etc/$new/
echo "Creating $j/etc/$src/jail.conf"
cat $j/etc/$src/jail.conf | egrep -v "^(name|version)=" > $j/etc/$new/jail.conf
@@ -656,17 +833,26 @@ jaildk_clone() {
echo
else
. $j/etc/$src/jail.conf
+ jail=$new
bold "To mount the build chroot of the new jail, execute:"
echo "jaildk build $new start $base $newversion"
fi
}
+usage_create() {
+ fin "Usage: $0 create
+Create a new jail from template."
+}
+
jaildk_create() {
jail=$1
+ # $jail gets overwritten in jaildk_clone or some subcall to .template :-( ...
+ newjail=$jail
+
src=.template
if test -z "$jail"; then
- die "Usage: $0 create "
+ usage_create
fi
. $j/etc/$src/jail.conf
@@ -674,8 +860,15 @@ jaildk_create() {
newversion=`date +%Y%m%d`
mkdir -p $j/etc/$jail
-
- jaildk_clone $src $jail $srcversion $newversion
+
+ jaildk_clone -s $src -d $jail -o $srcversion -n $newversion
+ # some perl magic to extract the hostname (if any) from /etc/jail.conf - and write it into the jails rc.conf
+ jailhostname=$(cat /etc/jail.conf | tr -d '\t\r\n ' | perl -ne '$_ =~ /.*'"$newjail"'(\{(?:\{.*\}|[^{])*\})|\w+/; print $1;' | grep -oE 'hostname=[^;]+' | cut -d= -f2)
+ if [ -n "$jailhostname" ]; then
+ echo "new name: $jailhostname"
+ echo "in path $j/etc/$jail/local-etc-$newversion/rc.conf"
+ sed -iE 's/^hostname.*$/hostname="'"$jailhostname"'"/' $j/etc/$newjail/local-etc-$newversion/rc.conf
+ fi
}
remove() {
@@ -688,12 +881,25 @@ remove() {
fi
}
+usage_remove() {
+ fin "Usage: $0 remove [-v ]
+Remove from disk."
+}
+
jaildk_remove() {
jail=$1
- version=$2
+ shift
+ version=''
+
+ while getopts "v:" arg; do
+ case $arg in
+ v) version=${OPTARG};;
+ *) usage_remove;;
+ esac
+ done
if test -z "$jail"; then
- die "Usage: $0 remove []"
+ usage_remove
fi
if jls | egrep -q "${jail}"; then
@@ -726,19 +932,37 @@ jaildk_remove() {
}
jaildk_jail_usage() {
- die "Usage: $0 | status"
+ fin "Usage: $0 | status"
+}
+
+usage_start() {
+ fin "Usage $0 start
+Start ."
+}
+
+usage_stop() {
+ fin "Usage $0 stop
+Stop ."
+}
+
+usage_restart() {
+ fin "Usage $0 restart
+Restart ."
+}
+
+usage_status() {
+ fin "Usage $0 status []
+Show status of . Without , show status of all jails."
}
jaildk_jail() {
- mode=$1
jail=$2
+ mode=$1
- if test -z "$mode"; then
- jaildk_jail_usage
- fi
-
- if test -z "$jail" -a $mode = "status"; then
+ if test -z "$jail"; then
+ usage_$mode
+ elif test -z "$jail" -a $mode = "status"; then
bold "Running jails:"
bold " JID IP Address Hostname Path"
jls | grep -v JID
@@ -754,8 +978,6 @@ jaildk_jail() {
jls | grep -v JID | awk '{print $3}' | while read J; do
jaildk_rc $J status
done
- elif test -z "$jail"; then
- jaildk_jail_usage
else
bold "Jail $jail $mode:"
case $mode in
@@ -765,6 +987,7 @@ jaildk_jail() {
;;
*)
service jail $mode $jail
+ jaildk_ipfw $jail $mode
;;
esac
fi
@@ -783,35 +1006,33 @@ get_rc_scripts() {
done
}
-jaildk_rc_usage() {
- err "Usage: $0 rc { [] | }"
- err "If is all, execute for every rc script"
- err " must be a parameter of "
- err "if only has been given, execute all scripts"
- exit 1
+usage_rc() {
+ fin "Usage: $0 rc [] [-r with parameter . Options:
+-r Execute . default: execute all enabled scripts."
}
jaildk_rc() {
jail=$1
- rc=$2
- mode=$3
+ mode=$1
+ shift
+ shift
+
+ rc=''
+
+ while getopts "r:" arg; do
+ case $arg in
+ r) rcd=${OPTARG};;
+ *) usage_rc;;
+ esac
+ done
if test -z "$rc"; then
- jaildk_rc_usage
+ rc='all'
fi
- if test -z "$mode"; then
- # shift args
- case $rc in
- start|stop|restart|status)
- # shift args
- mode=$rc
- rc=all
- ;;
- *)
- jaildk_rc_usage
- ;;
- esac
+ if test -z "$jail" -o -z "$mode"; then
+ usage_rc
fi
if ! jls | egrep -q "${jail}"; then
@@ -840,6 +1061,14 @@ jaildk_rc() {
fi
}
+usage_blogin() {
+ err "Usage: $file
+Chroot into a build jail.
+
+Mounted build chroot's:"
+ mount|egrep "base.*build" | awk '{print $3}' | cut -d/ -f 4
+ exit 1
+}
jaildk_blogin() {
jail=$1
@@ -851,10 +1080,7 @@ jaildk_blogin() {
else
file="$0"
fi
- echo "Usage: $file []"
- echo "mounted build jails:"
- mount|egrep "base.*build" | awk '{print $3}' | cut -d/ -f 4
- exit
+ usage_blogin
fi
chroot="$j/build/$jail"
@@ -878,6 +1104,16 @@ jaildk_blogin() {
env - HOME=$home TERM=$term SHELL=$shell PATH=$path chroot $chroot $shell
}
+usage_login() {
+ err "Usage: $file []
+Login into a jail by name, ip or domain. If has not been
+specified, login as root.
+
+Available jails:"
+ jls
+ exit 1
+}
+
jaildk_login() {
jail=$1
user=$2
@@ -891,10 +1127,7 @@ jaildk_login() {
else
file="$0"
fi
- echo "Usage: $file []"
- echo "available jails:"
- jls
- exit
+ usage_login
fi
jid=""
@@ -932,10 +1165,19 @@ jaildk_login() {
env - JAIL=$jail HOME=$home TERM=$term SHELL=$shell PATH=$path $jexec -U $user $jid $shell
}
+usage_reinstall() {
+ fin "Usage: $0 reinstall
+Stop, uninstall, install and start .
+"
+}
jaildk_reinstall() {
jail=$1
+ if test -z "$jail"; then
+ usage_reinstall
+ fi
+
die_if_not_exist $jail
if jls | egrep -q "${jail}"; then
@@ -960,7 +1202,7 @@ jaildk_setup() {
j=$1
if test -z "$j"; then
- die "Usage: $0 setup "
+ fin "Usage: $0 setup "
fi
bold "preparing directories"
@@ -1005,8 +1247,10 @@ home/$name/root-$version $name/root nullfs rw' >
bold "creating template config $j/etc/.template/ports.conf"
(echo bash; echo ca_root_nss) > $j/etc/.template/ports.conf
+ bold "creating template config $j/etc/.template/ipfw.conf"
+ touch $j/etc/.template/ipfw.conf
+
bold "creating template config $j/etc/.template/mtree.conf"
-# touch $j/etc/.template/mtree.conf
echo '/set type=dir uid=0 gid=0 mode=01777
. type=dir mode=0755
tmp
@@ -1063,7 +1307,7 @@ endif
read yesno
case $yesno in
y|Y|yes|YES)
- jaildk_base $j/base/$os
+ jaildk_base -b $j/base/$os
;;
esac
}
@@ -1092,7 +1336,7 @@ jaildk_fetch_ports() {
ex rm -rf $j/ports/tmp/ports*
}
-freeze_usage() {
+usage_freeze() {
echo "Usage: $0 freeze [options]
Options:
-v freeze of
@@ -1123,12 +1367,12 @@ jaildk_freeze() {
a) ADDAPPL=1;;
b) ADDBASE=1;;
v) VERSION=${OPTARG};;
- *) freeze_usage;;
+ *) usage_freeze;;
esac
done
if test -z "$jail"; then
- freeze_usage
+ usage_freeze
fi
die_if_not_exist $jail "Jail to freeze" $VERSION
@@ -1231,9 +1475,12 @@ thaw_tarball() {
ex rm -f $srcdir/$tarball
}
+usage_thaw() {
+ fin "Usage: $0 thaw "
+}
+
jaildk_thaw() {
image=$1
- J=$2 # just for testing
if test -n "$J"; then
j=$J
@@ -1243,8 +1490,7 @@ jaildk_thaw() {
version=$(echo $image | cut -d\- -f3 | cut -d\. -f1)
if ! test -n "$version" -o -n "$jail"; then
- err "Usage: $0 thaw "
- die "Image filename pattern: --.tgz"
+ usage_thaw
fi
if test -d $j/etc/$jail/etc-$version; then
@@ -1301,6 +1547,69 @@ jaildk_thaw() {
bold "Done. Thawed jail $jail $version from $image."
}
+usage_ipfw() {
+ echo "Usage: $0 ipfw
+[Un]install ipfw rules. can be start or stop.
+The jail needs to have a ipfw.conf file, containing
+ipfw rules. You can use variables like \$ip and \$ip6
+and you need to omit the 'ipfw add' of the command."
+ exit 1
+}
+
+jaildk_ipfw() {
+ jail=$1
+ mode=$2
+
+ if test -z "$mode"; then
+ usage_ipfw
+ fi
+
+ if test -f "$j/etc/$jail/ipfw.conf"; then
+ echo
+ bold "Managing IPFW Rules..."
+ case $mode in
+ start)
+ jaildk_ipfw_delete $jail "y"
+ jaildk_ipfw_add $jail
+ ;;
+ stop)
+ jaildk_ipfw_delete $jail
+ ;;
+ esac
+ bold "... done"
+ echo
+ fi
+}
+
+jaildk_ipfw_add() {
+ jail=$1
+
+ # support jail variables as well
+ load-jail-config $jail
+
+ # Getting current jails IP..
+ ip=`jls -n -j $jail ip4.addr | cut -d= -f2`
+ if test -z "$ip"; then
+ die "Jail $jail doesn't have an ipv4 address!"
+ fi
+
+ ip6=`jls -n -j $jail ip6.addr | cut -d= -f2` # optional, no checks
+
+ # Adding rules
+ egrep "^[a-z]" $j/etc/$jail/ipfw.conf | while read LINE; do
+ rule=$(eval echo "ipfw add $LINE // $jail")
+ echo $rule
+ $rule
+ done
+}
+
+jaildk_ipfw_delete() {
+ jail=$1
+ noout=$2
+ # Deleting rules
+ ipfw show | grep -E "// $jail\$" | while read rule; do [ -z "$2" ] && bold "Deleting rule $rule"; sh -c "ipfw delete $(echo $rule| awk '{print $1}')"; done
+
+}
##########################
#
@@ -1310,8 +1619,8 @@ jaildk_thaw() {
JAILDIR=/jail
# install modules
-RCSCRIPTS_START="jaildk_rc_mount jaildk_rc_rcoff jaildk_rc_ports jaildk_rc_mtree"
-RCSCRIPTS_STOP="jaildk_rc_rcoff jaildk_rc_mount jaildk_rc_ports"
+RCSCRIPTS_START="jaildk_rc_mount jaildk_rc_rcoff jaildk_rc_ports jaildk_rc_mtree jaildk_rc_pf"
+RCSCRIPTS_STOP="jaildk_rc_pf jaildk_rc_rcoff jaildk_rc_mount jaildk_rc_ports"
# globals
j=$JAILDIR
@@ -1328,9 +1637,12 @@ case $runner in
start|stop|status|restart)
jaildk_jail $runner $*
;;
- setup|reinstall|install|uninstall|build|blogin|login|clone|create|remove|rc|base|fetch|freeze|thaw)
+ setup|reinstall|install|uninstall|build|blogin|login|clone|create|remove|rc|base|fetch|freeze|thaw|ipfw)
jaildk_$runner $*
;;
+ help)
+ usage_help $*
+ ;;
*)
usage_jaildk $*
;;