2020-11-06 20:37:13 +01:00
#!/bin/sh
2023-09-13 10:38:47 +02:00
version = 2.0.0
# this will be completed during build. Don't touch it, just execute
# make and use the resulting script!
JAILDK_COMPLETION = $(
cat<<'EOF'
# will be modified during installation (jaildk setup)
JAILDIR = /jail
COMPLETIONCODE
EOF
)
2020-11-06 20:37:13 +01:00
usage_jaildk( ) {
beg = ` tput -T ${ TERM :- cons25 } md`
end = ` tput -T ${ TERM :- cons25 } me`
usage = $( cat <<EOF
This is jaildk version $version , a jail management toolkit.
2023-09-13 10:38:47 +02:00
Usage: $0 <command> <command-args>
2020-11-06 20:37:13 +01:00
${ beg } Building Jails:${ end }
2023-09-13 10:38:47 +02:00
base -b <name> [ -w] - build a new base
build <jail> -m <mode> [ -b <base>] [ -v <version>] - install a build chroot of a jail
create - create a new jail from a template
clone -s <src> -d <dst> [ -o <v>] [ -n <v>] - clone an existing jail or jail version
fetchports [ -v <version>] - fetch current port collection
2020-11-06 20:37:13 +01:00
2022-02-16 12:22:13 +01:00
${ beg } ( Un) installing Jails:${ end }
2023-09-13 10:38:47 +02:00
install <jail> -m <mode> [ -r function ] - install a jail ( prepare mounts, devfs etc)
uninstall <jail> [ -w] - uninstall a jail
remove <jail> - remove a jail or a jail version
reinstall <jail> [ -b <base>] [ -v <version>] - stop, remove, install and start a jail, if
-b and/or -v is set, update the jail config
prune [ -b | -a | -j <jail> - display unused directories
2020-11-06 20:37:13 +01:00
${ beg } Maintaining Jails:${ end }
2023-09-13 10:38:47 +02:00
start <jail> - start a jail
stop <jail> - stop a jail
restart <jail> - restart a jail
status [ <jail>] [ -v] - display status of jails or <jail>
rc <jail> -m <mode> [ -r <rc.d script>] - execute an rc-script inside a jail
ipfw <jail> -m <mode> - add or remove ipfw rules
2020-11-06 20:37:13 +01:00
${ beg } Managing Jails:${ end }
2023-09-13 10:38:47 +02:00
login <jail> [ <user>] - login into a jail
blogin <jail> - chroot into a build jail
2020-11-06 20:37:13 +01:00
2020-11-28 20:41:05 +01:00
${ beg } Transferring Jails:${ end }
2023-09-13 10:38:47 +02:00
freeze <jail> [ -a -b -v <version>] - freeze ( build an image of) a jail
thaw <image> - thaw ( install) an image of a jail
2020-11-28 20:41:05 +01:00
2021-07-06 12:11:23 +02:00
${ beg } Getting help and internals:${ end }
2023-09-13 10:38:47 +02:00
completion - print completion code. to use execute in a bash:
source <( jaildk completion)
help <command> - request help on <command>
version - print program version
update [ -f] - update jaildk from git repository
2020-11-06 20:37:13 +01:00
EOF
)
2020-11-29 18:46:50 +01:00
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
2020-11-06 20:37:13 +01:00
}
ex( ) {
echo $rcscript - $*
2021-07-07 11:27:18 +02:00
logger -p local0.notice -t jaildk " $rcscript $* "
2020-11-06 20:37:13 +01:00
$*
}
err ( ) {
2020-11-27 19:08:57 +01:00
echo " $@ " >& 2
2020-11-06 20:37:13 +01:00
}
bold( ) {
2021-01-25 00:22:54 +01:00
if [ -z " $NO_BOLD " ] ; then
if [ -z " $BOLD_ON " ] ; then
BOLD_ON = ` tput -T ${ TERM :- cons25 } md`
export BOLD_ON
BOLD_OFF = ` tput -T ${ TERM :- cons25 } me`
export BOLD_OFF
fi
echo -n " $BOLD_ON "
echo " $@ "
echo -n " $BOLD_OFF "
else
echo " $@ "
2020-11-06 20:37:13 +01:00
fi
}
2020-11-29 18:46:50 +01:00
fin( ) {
echo " $* " >& 2
exit
}
2020-11-06 20:37:13 +01:00
die( ) {
bold " $* " >& 2
exit 1
}
load-jail-config( ) {
2021-07-05 14:26:10 +02:00
local jail = $1
2020-11-06 20:37:13 +01:00
if test -d $j /etc/$jail ; then
2021-07-05 14:26:10 +02:00
# everything inside gets global
2020-11-06 20:37:13 +01:00
. $j /etc/$jail /jail.conf
else
die " Jail $jail is not configured! "
fi
}
die_if_not_exist( ) {
2021-07-05 14:26:10 +02:00
local jail which jailversion
2020-11-06 20:37:13 +01:00
jail = $1
which = $2
2020-12-13 14:49:39 +01:00
jailversion = $3
2020-11-06 20:37:13 +01:00
if test -z " $which " ; then
which = "Jail"
fi
2020-11-28 20:41:05 +01:00
2020-11-06 20:37:13 +01:00
if ! test -d $j /etc/$jail ; then
die " $which $jail doesn't exist! "
fi
2020-11-28 20:41:05 +01:00
2020-12-13 14:49:39 +01:00
if test -n " $jailversion " ; then
if ! test -d $j /etc/$jail /etc-$jailversion ; then
die " $which $jail $jailversion doesn't exist! "
2020-11-28 20:41:05 +01:00
fi
fi
2020-11-06 20:37:13 +01:00
}
2020-12-03 19:01:05 +01:00
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.
2021-07-05 14:26:10 +02:00
local jail = $1
local search = $2
local JAIL list
2020-12-03 19:01:05 +01:00
# 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
}
2020-11-29 16:22:36 +01:00
usage_build( ) {
2023-09-13 10:38:47 +02:00
fin " Usage: $0 build <jail> [-m <start|stop|status>] [-b <base>] [-v <version>]
2020-11-29 18:46:50 +01:00
Mount <jail> to $j /build read-writable for maintenance. Options:
-b <base> Use specified <base>. default: use configured base.
-v <version> Mount <version> of <jail>.
2023-09-13 10:38:47 +02:00
-m <mode> One of start, stop or status. default: start."
2020-11-29 16:22:36 +01:00
}
2020-11-06 20:37:13 +01:00
jaildk_build( ) {
2021-07-05 14:26:10 +02:00
local jail mode BASE VERSION base version
2020-11-06 20:37:13 +01:00
jail = $1
2023-09-13 10:38:47 +02:00
mode = start
2020-11-29 16:22:36 +01:00
shift
shift
2020-12-13 14:58:54 +01:00
BASE = ''
2020-12-13 14:54:16 +01:00
VERSION = ''
2020-11-06 20:37:13 +01:00
2023-09-13 10:38:47 +02:00
while getopts "b:v:m:" arg; do
2020-11-29 16:22:36 +01:00
case $arg in
2020-12-13 14:58:54 +01:00
b) BASE = ${ OPTARG } ; ;
2020-12-13 14:54:16 +01:00
v) VERSION = ${ OPTARG } ; ;
2023-09-13 10:38:47 +02:00
m) mode = ${ OPTARG } ; ;
2020-11-29 16:22:36 +01:00
*) usage_build; ;
esac
done
2020-11-27 08:52:58 +01:00
2020-12-13 14:24:14 +01:00
if test -z " $jail " ; then
usage_build
fi
2020-12-13 14:54:16 +01:00
die_if_not_exist $jail $VERSION
2020-11-29 16:22:36 +01:00
load-jail-config $jail
2020-12-13 14:54:16 +01:00
if test -n " $VERSION " ; then
# overridden with -v
version = $VERSION
fi
2020-12-13 14:58:54 +01:00
if test -n " $BASE " ; then
# dito
base = $BASE
fi
2020-11-27 23:21:34 +01:00
if test -n " $buildbase " ; then
2020-11-27 19:08:57 +01:00
base = " $buildbase "
2020-11-27 08:52:58 +01:00
elif test -z " $base " ; then
2020-11-29 16:22:36 +01:00
# nothing configured, use default: latest
2020-11-06 20:37:13 +01:00
base = ` ls $j /base | tail -1`
fi
2020-11-28 11:51:38 +01:00
# install the jail to build/
2023-09-13 10:38:47 +02:00
jaildk_install $jail -m $mode -r all -w -b $base -v $version
2020-11-28 11:18:39 +01:00
2020-11-28 11:51:38 +01:00
case $mode in
start)
# make it usable
ex chroot $j /build/$jail /etc/rc.d/ldconfig onestart
2020-11-28 12:35:48 +01:00
ex mkdir -p $j /build/$jail /usr/local/db
2020-11-28 11:51:38 +01:00
; ;
esac
}
2021-07-05 14:26:10 +02:00
pf_ruleset( ) {
2021-07-02 13:03:33 +02:00
# internal helper to [un]install a pf ruleset
2021-07-05 14:26:10 +02:00
local conf mode anchor jail
conf = $1
mode = $2
anchor = $3
jail = $4
2021-07-02 13:03:33 +02:00
2021-07-05 14:26:10 +02:00
case $mode in
2021-07-02 13:03:33 +02:00
start)
2021-07-05 14:26:10 +02:00
bold " Installing PF rules for jail $jail : "
pfctl -a /jail/$anchor -f $conf -v
2021-07-02 13:03:33 +02:00
; ;
status)
2021-07-05 14:26:10 +02:00
bold " PF NAT rules for jail $jail : "
pfctl -a /jail/$anchor -s nat -v
2021-07-02 13:03:33 +02:00
echo
2021-07-05 14:26:10 +02:00
bold " PF rules for jail $jail : "
pfctl -a /jail/$anchor -s rules -v
2021-07-02 13:03:33 +02:00
; ;
stop)
2021-07-05 14:26:10 +02:00
bold " Removing PF rules for jail $jail : "
pfctl -a /jail/$anchor -v -F all
2021-07-02 13:03:33 +02:00
; ;
restart)
2021-07-05 14:26:10 +02:00
pf_ruleset $conf stop $anchor $jail
pf_ruleset $conf start $anchor $jail
2021-07-02 13:03:33 +02:00
; ;
esac
}
2021-07-05 14:26:10 +02:00
pf_map( ) {
local extif proto eip eport mport ip v6
2021-07-02 13:03:33 +02:00
extif = $1
proto = $2
eip = $3
eport = $4
mport = $5
ip = $6
2021-07-06 20:12:27 +02:00
from = $7
2021-07-10 19:44:55 +02:00
v6 = ${ 8 :- inet }
2021-07-02 13:03:33 +02:00
2021-07-06 20:12:27 +02:00
echo " rdr pass on $extif $v6 proto ${ proto } from ${ from } to ${ eip } port ${ eport } -> ${ ip } port ${ mport } "
2021-07-02 13:03:33 +02:00
}
2021-07-05 14:26:10 +02:00
pf_rule( ) {
local extif proto eip eport v6
2021-07-02 13:03:33 +02:00
extif = $1
proto = $2
eip = $3
eport = $4
v6 = $5
2021-07-03 16:32:19 +02:00
echo " pass in quick on $extif $v6 proto ${ proto } from any to ${ eip } port ${ eport } "
2021-07-02 13:03:33 +02:00
}
2021-07-05 14:26:10 +02:00
pf_nat( ) {
local extif srcip dstip v6
2021-07-03 16:32:19 +02:00
extif = $1
srcip = $2
dstip = $3
v6 = $4
echo " nat on $extif $v6 from $srcip to any -> $dstip "
}
2021-07-02 13:03:33 +02:00
2021-07-05 14:26:10 +02:00
rc_pf( ) {
2021-07-06 23:21:02 +02:00
local jail mode conf ruleset extif ipv4 anchor proto eport mport eports eip allowfrom port
2021-07-05 14:26:10 +02:00
2020-12-03 19:01:05 +01:00
jail = $1
mode = $2
conf = $j /etc/$jail /pf.conf
2021-07-02 13:03:33 +02:00
ruleset = $j /etc/$jail /pf-ruleset.conf
load-jail-config $jail
2021-07-02 19:46:56 +02:00
# TODO:
# - put this into a separate function
# - clean up if generation of pf-ruleset.conf fails somehow
# - make a syntax check of the generated rules, if possible
case $mode in
start| restart)
2021-07-03 16:32:19 +02:00
if test -n " $masq_ip " -o -n " $rules " -o -n " $maps " ; then
2021-07-02 19:46:56 +02:00
# generate a pf.conf based on config variables
echo "# generated pf ruleset for jail, generated on ` date`" > $ruleset
extif = $( netstat -rnfinet | grep default | cut -f4 -w)
2021-07-03 16:32:19 +02:00
2022-04-24 15:39:30 +02:00
# we need to make sure the ip address doesn't contain a mask which
# is not required for these rules
ipv4 = $( dirname $ip )
ipv6 = $( dirname $ip6 )
2021-07-03 16:32:19 +02:00
2022-04-24 15:39:30 +02:00
if test -n " $ipv4 " -a -n " $maps " ; then
# nat and rdr come first
2021-07-02 19:46:56 +02:00
2022-04-24 15:39:30 +02:00
# SAMPLE ruleset
# maps="web ntp kjk"
# map_web_proto="tcp"
# map_web_exposed_port=80
# map_web_mapped_port=8080
# map_web_exposed_ip="123.12.12.3"
# map_web_allow_from="any" # | ip | ip list | table
# map_ntp_proto="udp"
# map_ntp_exposed_port=123
# map_ntp_mapped_port=1234
# map_ntp_exposed_ip="123.12.12.33"
# map_kjk_proto="tcp"
# map_kjk_exposed_port="1501 1502 1502}" # maped 1:1
# map_kjk_exposed_ip="123.12.12.33"
for map in $maps ; do
# slurp in the values for this map
eval proto = \$ { map_${ map } _proto:-tcp}
eval eport = \$ { map_${ map } _exposed_port}
eval mport = \$ { map_${ map } _mapped_port:-" ${ eport } " }
eval eip = \$ { map_${ map } _exposed_ip:-$extif }
eval allowfrom = \$ { map_${ map } _allow_from:-any} # == from any|ips
if test -z " ${ eport } " -o -z " ${ eip } " ; then
echo " Warning: ignoring incomplete map: $map ! "
continue
fi
if test -n " ${ eport } " ; then
echo " # from map $map " >> $ruleset
for port in $eport ; do
if echo " ${ eport } " | grep -q " " ; then
# multiple eports, map 1:1
mport = ${ port }
elif test -z " ${ mport } " ; then
mport = ${ port }
fi
pf_map " $extif " " ${ proto } " " ${ eip } " " ${ port } " " ${ mport } " " ${ ipv4 } " " ${ allowfrom } " >> $ruleset
done
fi
done
fi
# masq_ip="123.12.12.33"
if test -n " $ipv4 " -a -n " ${ masq_ip } " ; then
pf_nat $extif $ipv4 ${ masq_ip } >> $ruleset
fi
2021-07-03 16:32:19 +02:00
2022-04-24 15:39:30 +02:00
if test -n " $ip6 " -a -n " $rules " ; then
# only required for ipv6, ipv4 is already opened with exposed ports
# rules="open web"
# rule_open="any"
# rule_web_proto="tcp"
# rule_web_port="80,443"
for rule in $rules ; do
eval proto = \$ { rule_${ rule } _proto:-tcp}
eval eport = \$ { rule_${ rule } _port}
if test -n " ${ eport } " ; then
echo " # from rule $rule " >> $ruleset
pf_rule $extif ${ proto } ${ ipv6 } ${ eport } inet6 >> $ruleset
else
echo " Warning: incomplete rule: $rule ! "
continue
fi
done
fi
2021-07-02 13:03:33 +02:00
fi
2021-07-02 19:46:56 +02:00
; ;
esac
2021-07-02 13:03:33 +02:00
if test -s $ruleset ; then
2021-07-03 16:32:19 +02:00
anchor = " ${ jail } -jaildk "
2021-07-05 14:26:10 +02:00
pf_ruleset $ruleset $mode $anchor $jail
2021-07-02 13:03:33 +02:00
fi
2020-12-03 19:01:05 +01:00
2021-07-03 16:32:19 +02:00
if test -s $conf ; then
anchor = " ${ jail } -custom "
2021-07-05 14:26:10 +02:00
pf_ruleset $conf $mode $anchor $jail
2020-12-03 19:01:05 +01:00
fi
}
2021-07-05 14:26:10 +02:00
rc_mtree( ) {
local jail mode base version rw conf
2020-11-28 12:26:24 +01:00
jail = $1
mode = $2
base = $3
version = $4
rw = $5
2020-11-29 18:46:50 +01:00
rcscript = mtree
2020-11-28 12:26:24 +01:00
2021-07-05 14:26:10 +02:00
conf = $j /etc/$jail /$rcscript .conf
if test -s $conf ; then
2022-02-01 13:16:06 +01:00
case $mode in
2021-07-05 14:26:10 +02:00
start| restart)
if test -n " $rw " ; then
run = $j /build/$jail /
else
run = $j /run/$jail /
fi
2022-02-01 13:23:16 +01:00
# needs to run inside jail
echo " cat $j /etc/ $jail /mtree.conf | chroot $run mtree -p / -Ue | grep -v extra: "
cat $j /etc/$jail /mtree.conf | chroot $run mtree -p / -Ue | grep -v "extra:"
2021-07-05 14:26:10 +02:00
; ;
esac
2020-11-28 12:26:24 +01:00
fi
}
2021-07-05 14:26:10 +02:00
rc_rcoff( ) {
2020-11-28 11:51:38 +01:00
# avoid starting services inside the build chroot
2021-07-05 14:26:10 +02:00
# + rc_rcoff db start 12.1-RELEASE-p10 20201026
local jail mode base VERSION BASE rw
2020-11-28 11:51:38 +01:00
jail = $1
mode = $2
2020-11-28 12:26:24 +01:00
BASE = $3
VERSION = $4
rw = $5
2020-11-28 11:51:38 +01:00
rcscript = rcoff
if test -n " $rw " ; then
# not required in run mode
case $mode in
start)
2020-11-28 11:59:19 +01:00
if mount | egrep -q " rcoff.*build/ $jail " ; then
bold " union mount $j /build/jail/etc already mounted "
else
if ! test -d $j /etc/rcoff; then
# in order to be backwards compatible to older jaildk
# create the rcoff directory on the fly
2020-11-28 12:36:49 +01:00
mkdir -p $j /etc/rcoff
2020-11-28 11:59:19 +01:00
( echo "#!/bin/sh"
echo 'echo "$0 disabled in build chroot!"' ) > $j /etc/rcoff/rc
fi
ex mount -t unionfs $j /etc/rcoff $j /build/$jail /etc
2020-11-28 11:51:38 +01:00
fi
; ;
stop)
# might fail if executed on a yet not union'ed etc
if mount | egrep -q " rcoff.*build/ $jail " ; then
ex umount $j /build/$jail /etc
fi
; ;
esac
fi
2020-11-06 20:37:13 +01:00
}
2021-07-05 14:26:10 +02:00
rc_ports( ) {
local jail mode BASE VERSION rw
2020-11-27 08:52:58 +01:00
jail = $1
mode = $2
2020-11-28 12:26:24 +01:00
BASE = $3
VERSION = $4
rw = $5
2020-11-27 08:52:58 +01:00
rcscript = ports
load-jail-config $jail
2020-12-13 14:37:20 +01:00
if test -z " $ports " ; then
# ports not configured, abort
return
fi
if ! test -d " $j /ports/ $VERSION " ; then
die " Ports tree $j /ports/ $VERSION doesn't exist yet. Consider creating it with 'jaildk fetchports [-v <version>]' "
2020-11-27 19:08:57 +01:00
fi
2020-11-27 08:52:58 +01:00
if test -n " $buildbase " -a -n " $rw " ; then
# we only support ports if a buildbase is configured
case $mode in
start)
if mount -v | grep -q " $j /build/ $jail /usr/ports " ; then
bold " $j /build/ $jail /usr/ports already mounted! "
else
ex mount -t nullfs -o rw $j /ports/$version $j /build/$jail /usr/ports
fi
; ;
stop)
if mount -v | grep -q " $j /build/ $jail /usr/ports " ; then
ex umount $j /build/$jail /usr/ports
else
bold " $j /build/ $jail /usr/ports not mounted! "
fi
; ;
esac
fi
}
2021-07-05 14:26:10 +02:00
rc_mount( ) {
local jail mode BASE VERSION rw conf run base version \
src dest fs opts size perm source
2020-11-06 20:37:13 +01:00
jail = $1
mode = $2
2020-11-28 12:26:24 +01:00
BASE = $3
VERSION = $4
rw = $5
2020-11-06 20:37:13 +01:00
rcscript = mount
load-jail-config $jail
conf = $j /etc/$jail /$rcscript .conf
if ! test -e " $conf " ; then
return
fi
if test -n " $rw " ; then
run = $j /build
if test -n " $BASE " ; then
base = $BASE
fi
if test -n " $VERSION " ; then
version = $VERSION
fi
else
run = $j /run
fi
die_if_not_exist $jail
# parse the config and (u)mount
case $mode in
stop)
tail -r $conf | grep -v "#"
; ;
*)
grep -v "#" $conf
; ;
esac | while read LINE; do
# This command expands variables and performs field-splitting:
set -- $( eval echo \" " $LINE " \" )
# Skip empty lines:
case " $1 " in
"" ) continue ; ;
esac
src = $1
dest = $2
fs = $3
opts = $4
size = $5
perm = $6
if test -n " $rw " ; then
2020-11-25 11:09:10 +01:00
if ! echo $src | grep -q base/; then
opts = ` echo " $opts " | sed 's/ro/rw/g' `
fi
2020-11-06 20:37:13 +01:00
fi
case $mode in
start)
if mount -v | grep " $run / $dest " > /dev/null ; then
bold " $run / $dest already mounted! "
else
case $fs in
mfs)
ex mdmfs -o $opts -s $size -p $perm md $run /$dest
; ;
2021-06-25 07:52:03 +02:00
nullfs| unionfs)
2020-11-06 20:37:13 +01:00
source = $j /$src
if echo $src | egrep -q "^/" ; then
source = $src
fi
2020-11-27 19:08:57 +01:00
if ! test -d " $source " ; then
die " Source dir $source doesn't exist! "
fi
if ! test -d " $run / $dest " ; then
die " Dest dir $run / $dest doesn't exist! "
fi
2020-11-06 20:37:13 +01:00
ex mount -t $fs -o $opts $source $run /$dest
; ;
devfs)
ex mount -t devfs dev $run /$dest
; ;
*)
bold " unknown filesystem type $fs ! "
; ;
esac
fi
; ;
stop)
if mount -v | grep " $run / $dest " > /dev/null ; then
ex umount $run /$dest
if mount -v | grep " $run / $dest " > /dev/null ; then
# still mounted! forcing
ex umount -f $run /$dest
fi
else
bold " $run / $dest not mounted! "
fi
; ;
status)
if mount -v | grep " $run / $dest " > /dev/null ; then
echo " $run / $dest mounted "
else
bold " $run / $dest not mounted "
fi
; ;
*)
bold " Usage: $0 install <jail> mount {start|stop|status|restart} "
; ;
esac
done
}
2020-12-01 18:40:32 +01:00
2020-11-29 16:22:36 +01:00
usage_install( ) {
2023-09-13 10:38:47 +02:00
fin " Usage: $0 install <jail> [-m <mode>] [-r rc-function]
2020-11-29 16:22:36 +01:00
Install <jail> according to its config. Options:
2023-09-13 10:38:47 +02:00
-m <mode> Mode can either be start, stop or status. default: start
2020-11-29 16:22:36 +01:00
-r <function > Only execute function with <mode> parameter. default: all.
Available rc.d-scripts: $RCSCRIPTS_START "
2020-11-06 20:37:13 +01:00
}
jaildk_install( ) {
2021-07-05 14:26:10 +02:00
local jail mode rcd rw base version rcscripts type
2020-11-06 20:37:13 +01:00
jail = $1
2023-09-13 10:38:47 +02:00
mode = start
2020-11-29 16:22:36 +01:00
shift
rcd = ''
2020-11-06 20:37:13 +01:00
2020-11-29 16:22:36 +01:00
# options -b -w -v are undocumented, used by jaildk_build() only
rw = ''
base = ''
version = ''
2023-09-13 10:38:47 +02:00
while getopts "r:b:v:wm:" arg; do
2020-11-29 16:22:36 +01:00
case $arg in
w) rw = 1; ;
b) base = ${ OPTARG } ; ;
v) version = ${ OPTARG } ; ;
r) rcd = ${ OPTARG } ; ;
2023-09-13 10:38:47 +02:00
m) mode = ${ OPTARG } ; ;
2020-11-29 19:03:57 +01:00
*) usage_install; ;
2020-11-29 16:22:36 +01:00
esac
done
2020-11-06 20:37:13 +01:00
if test -z " $jail " ; then
2020-11-29 16:22:36 +01:00
usage_install
2020-11-06 20:37:13 +01:00
fi
2020-11-29 16:22:36 +01:00
if test -z " $rcd " ; then
# default just install everything
rcd = all
2020-11-06 20:37:13 +01:00
fi
2020-11-29 16:22:36 +01:00
case $mode in
start| stop| restart| status) :; ;
*) usage_install; ;
esac
2020-11-06 20:37:13 +01:00
die_if_not_exist $jail
if test " $rcd " = "all" ; then
2020-12-13 14:43:18 +01:00
if test -n " $rw " ; then
case $mode in
start) rcscripts = " $RW_RCSCRIPTS_START " ; ;
stop) rcscripts = " $RW_RCSCRIPTS_STOP " ; ;
esac
else
case $mode in
start) rcscripts = " $RCSCRIPTS_START " ; ;
stop) rcscripts = " $RCSCRIPTS_STOP " ; ;
esac
fi
2020-11-06 20:37:13 +01:00
else
2021-07-05 14:26:10 +02:00
rcscripts = " rc_ ${ rcd } "
2020-11-06 20:37:13 +01:00
if ! type " $rcscripts " > /dev/null 2>& 1; then
die " rc function $rcd doesn't exist! "
fi
fi
2021-01-28 20:18:35 +01:00
type = "jail"
if test -n " $rw " ; then
type = "build chroot"
fi
2020-11-06 20:37:13 +01:00
case $mode in
start)
2021-01-28 20:18:35 +01:00
bold " Installing $type $jail "
2020-11-06 20:37:13 +01:00
; ;
stop)
2021-01-28 20:18:35 +01:00
bold " Unstalling $type $jail "
2020-11-06 20:37:13 +01:00
; ;
esac
2020-11-26 22:25:45 +01:00
2020-11-06 20:37:13 +01:00
for rcscript in $rcscripts ; do
2020-11-28 12:26:24 +01:00
$rcscript $jail $mode $base $version $rw || exit 1
2020-11-06 20:37:13 +01:00
done
}
2020-11-29 18:46:50 +01:00
usage_uninstall( ) {
fin " Usage: $0 uninstall <jail> [-w]
Uninstall <jail>. Options:
2021-01-28 20:18:35 +01:00
-w Uninstall writable build chroot.
-a Uninstall jail and build chroot."
2020-11-29 18:46:50 +01:00
}
2020-11-06 20:37:13 +01:00
jaildk_uninstall( ) {
# wrapper around _install
2021-07-05 14:26:10 +02:00
local jail mode base version all rw
2020-11-06 20:37:13 +01:00
jail = $1
2020-11-29 18:46:50 +01:00
shift
rw = ''
2021-01-28 20:18:35 +01:00
all = ''
base = ''
version = ''
2020-11-29 18:46:50 +01:00
2021-01-28 20:18:35 +01:00
while getopts "wa" arg; do
2020-11-29 18:46:50 +01:00
case $arg in
2021-01-28 20:00:33 +01:00
w) rw = "-w" ; ;
2021-01-28 20:18:35 +01:00
a) all = 1; rw = "-w" ; ;
2020-11-29 18:46:50 +01:00
*) usage_uninstall; ;
esac
done
2020-11-06 20:37:13 +01:00
if test -z " $jail " ; then
2020-11-29 18:46:50 +01:00
usage_uninstall
2020-11-06 20:37:13 +01:00
fi
die_if_not_exist $jail
if jls | egrep -q " ${ jail } " ; then
die " Jail $jail ( $version ) is still running, stop it before removing! "
fi
2021-01-28 20:18:35 +01:00
if test -n " $rw " ; then
# we need to find out base and version of actually
# mounted jail, but cannot just use the jail config
# since the user might have mounted another version
base = $( mount | egrep " /base/.*/ $jail " | cut -d' ' -f1 | sed 's|.*/||' )
version = $( mount | egrep " /appl/.*/ $jail / " | cut -d' ' -f1 | sed 's/.*\-//' )
fi
if test -z " $base " ; then
# no base no umount!
rw = ''
all = ''
fi
if test -n " $all " ; then
2023-09-13 10:38:47 +02:00
jaildk_install $jail -m stop -r all
jaildk_install $jail -m stop -r all -b $base -v $version -w
2021-01-28 20:18:35 +01:00
else
2023-09-13 10:38:47 +02:00
jaildk_install $jail -m stop -r all -b $base -v $version $rw
2021-01-28 20:18:35 +01:00
fi
2020-11-29 16:22:36 +01:00
}
usage_base( ) {
2021-06-26 20:31:02 +02:00
fin " Usage: $0 base [-f] -b <basename|basedir> [-w]
2020-11-29 18:46:50 +01:00
Build a base directory from bsd install media. Options:
2020-11-29 16:22:36 +01:00
-b <name> <name> 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
2021-06-26 20:31:02 +02:00
collection.
-f force mode, remove any old dist files.
"
2020-11-06 20:37:13 +01:00
}
jaildk_base( ) {
2021-07-05 14:26:10 +02:00
local jail mode base force removelist basedir clean file rw
2020-11-29 16:22:36 +01:00
base = ""
2021-06-26 20:31:02 +02:00
force = ""
2020-11-29 16:22:36 +01:00
rw = ""
2021-06-26 20:31:02 +02:00
while getopts "b:wf" arg; do
2020-11-29 16:22:36 +01:00
case $arg in
w) rw = 1; ;
b) base = ${ OPTARG } ; ;
2021-06-26 20:31:02 +02:00
f) force = 1; ;
2020-11-29 16:22:36 +01:00
*) usage_base; ;
esac
done
2020-11-27 08:52:58 +01:00
if test -z " $base " ; then
2020-11-29 16:22:36 +01:00
usage_base
2020-11-06 20:37:13 +01:00
fi
removelist = " tests
usr/bin/objdump
usr/bin/llvm-profdata
usr/bin/ranlib
usr/bin/ar
usr/bin/as
usr/bin/llvm-tblgen
usr/bin/llvm-symbolizer
usr/bin/llvm-cov
usr/bin/llvm-objdump
usr/bin/ld.lld
usr/bin/lldb
usr/bin/cpp
usr/bin/clang-cpp
usr/bin/clang++
usr/bin/clang
usr/bin/cc
usr/bin/c++
usr/bin/lex
usr/bin/lex++
usr/bin/flex
usr/bin/flex++
usr/bin/telnet
usr/bin/kadmin
usr/bin/kcc
usr/bin/kdestroy
usr/bin/kdump
usr/bin/keylogin
usr/bin/keylogout
usr/bin/kf
usr/bin/kgetcred
usr/bin/kinit
usr/bin/klist
usr/bin/kpasswd
usr/bin/krb5-config
usr/bin/ksu
usr/bin/kswitch
usr/bin/ktrace
usr/bin/ktrdump
usr/bin/finger
usr/bin/crunch*
usr/bin/ibv*
usr/bin/nc
usr/bin/pftp
usr/bin/ssh*
usr/bin/scp
usr/bin/sftp
usr/bin/svn*
usr/bin/yacc
usr/include
usr/lib/*.a
usr/lib32/*.a
usr/share/doc
usr/share/dict
usr/share/examples
usr/share/man
rescue
media
mnt
2020-11-27 23:21:34 +01:00
boot
var/run
var/cache
var/tmp"
2020-11-27 08:52:58 +01:00
if echo " $base " | egrep -vq "^/" ; then
basedir = $j /base/$base
else
basedir = $base
2020-11-06 20:37:13 +01:00
fi
if test -d " $basedir " ; then
echo " base $basedir already exist! "
exit 1
else
ex mkdir -p $basedir
2021-06-26 20:31:02 +02:00
if test -e /usr/freebsd-dist/MANIFEST; then
clean = ''
if test -n " $force " ; then
clean = 1
else
echo "Found old dist files:"
ls -l /usr/freebsd-dist
2021-06-28 07:34:08 +02:00
echo -n "Want to remove them [nY]? "
2021-06-26 20:31:02 +02:00
read yesno
2021-06-28 07:34:08 +02:00
case $yesno in
y| Y) clean = 1; ;
*) clean = '' ; ;
2021-06-26 20:31:02 +02:00
esac
fi
if test -n " $clean " ; then
ex rm -f /usr/freebsd-dist/*
fi
fi
2020-11-29 18:46:50 +01:00
bsdinstall jail $basedir || exit 1
2020-11-06 20:37:13 +01:00
2020-11-27 19:08:57 +01:00
if test -z " $rw " ; then
# run base
2020-11-27 08:52:58 +01:00
for file in $removelist ; do
ex rm -rf $basedir /$file
done
2020-11-27 19:08:57 +01:00
else
# build base with ports support
2020-11-27 08:52:58 +01:00
ex mkdir -p $basedir /usr/ports
fi
2020-11-27 19:08:57 +01:00
ex mkdir $basedir /home
2020-11-06 20:37:13 +01:00
ex rm -rf $basedir /var/db
ex ln -s /usr/local/db $basedir /var/db
2020-11-27 19:08:57 +01:00
2020-11-27 23:21:34 +01:00
# add some symlinks from /var to /tmp to make pkg work properly
2020-11-28 11:18:39 +01:00
ex rm -rf $basedir /var/tmp $basedir /var/cache $basedir /var/run
ex ln -s /tmp $basedir /var/tmp
ex ln -s /tmp $basedir /var/cache
ex ln -s /tmp $basedir /var/run
2020-11-27 23:21:34 +01:00
2020-11-27 19:08:57 +01:00
if test -n " $rw " ; then
echo "You have choosen to create a build base with ports support"
echo -n "Want to fetch the ports collection now [Yn]? "
read yesno
case $yesno in
y| Y| yes| YES)
2020-12-13 14:37:20 +01:00
jaildk_fetchports
2020-11-27 19:08:57 +01:00
; ;
esac
fi
2020-11-06 20:37:13 +01:00
fi
}
clone( ) {
2021-07-05 14:26:10 +02:00
local srcdir dstdir
2020-11-06 20:37:13 +01:00
srcdir = $1
dstdir = $2
if test -d $srcdir ; then
if ! test -d $dstdir ; then
mkdir -p $dstdir
fi
2020-12-14 15:26:32 +01:00
if test $srcdir = $dstdir ; then
echo " $srcdir == $dstdir , ignored "
else
2021-07-18 19:49:30 +02:00
if test " $( ls -l $dstdir ) " = "total 0" ; then
ex cpdup -x $srcdir $dstdir
2021-07-10 20:17:16 +02:00
else
2021-07-18 19:49:30 +02:00
echo " $dstdir already exists, ignored "
2021-07-10 20:17:16 +02:00
fi
2020-12-14 15:26:32 +01:00
fi
2020-11-06 20:37:13 +01:00
else
echo " $srcdir doesn't exist, ignored "
fi
}
2020-11-29 16:22:36 +01:00
usage_clone( ) {
2020-11-29 18:46:50 +01:00
fin " Usage: $0 clone -s <jail> -d <jail> [-o <version>] [-n <version>]
2020-11-29 16:22:36 +01:00
-s <jail> Source jail to clone from
-d <jail> Destionation jail to create from source
-o <version> Old version
-n <version> 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) "
}
2020-11-06 20:37:13 +01:00
jaildk_clone( ) {
2021-07-05 14:26:10 +02:00
local src new srcversion newversion update cloneto clonefrom fs srcmount dstmount opts size perm
2020-11-29 16:22:36 +01:00
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
2020-11-06 20:37:13 +01:00
if test -z " $new " ; then
2020-11-29 16:22:36 +01:00
usage_clone
2020-11-06 20:37:13 +01:00
fi
if test " $src " = " $new " ; then
# same jail, expect different versions
if test -z " $newversion " -o -z " $srcversion " ; then
die "source and new version required!"
fi
if test " $srcversion " = " $newversion " ; then
die "new version must be different from source version!"
fi
update = 1
2020-12-14 15:26:32 +01:00
fi
2020-11-06 20:37:13 +01:00
2020-12-14 15:26:32 +01:00
die_if_not_exist $src "Source jail"
2021-07-05 19:05:45 +02:00
load-jail-config $src
2020-12-14 15:26:32 +01:00
if test -z " $srcversion " ; then
srcversion = $version
fi
if test -z " $newversion " ; then
newversion = $version
2020-11-06 20:37:13 +01:00
fi
2020-12-14 15:26:32 +01:00
if ! test -d $j /etc/$src /etc-$srcversion ; then
die " Version $srcversion of source jail $src doesn't exist! "
fi
2020-11-06 20:37:13 +01:00
2020-12-14 15:26:32 +01:00
if test -e " $j /etc/ $src /mount.conf " ; then
grep -v "#" $j /etc/$src /mount.conf | while read srcmount dstmount fs opts size perm; do
# we are not automatically interpolating variables here,
# because it's much more easier to replace \$name with the
# jail name than an already resolved $name which might be
# part of the path and cause confusion what to clone and
# what not.
if test -z " $srcmount " ; then
continue
fi
2020-11-06 20:37:13 +01:00
2020-12-14 15:26:32 +01:00
cloneto = $( echo " $srcmount " | sed -e " s/\$version/ $newversion /g " -e " s/\$name/ $new /g " )
clonefrom = $( echo " $srcmount " | sed -e " s/\$version/ $srcversion /g " -e " s/\$name/ $src /g " )
case $fs in
nullfs)
if ! echo " $srcmount " | egrep -q "^/" ; then
# only clone mounts relative to $j, which are
# either versioned or have the src jail name
# in it
if echo " $srcmount " | egrep -q '\$version|\$name' ; then
# srcversion versioned nullfs mount at $j/
clone $j /$clonefrom $j /$cloneto
fi
fi
; ;
esac
done
else
die " Error: $j /etc/ $src /mount.conf doesn't exist, cannot clone! "
fi
if test -z " $update " ; then
echo "Copying configs"
ex cp -pRp $j /etc/$src /*.conf $j /etc/$new /
2020-11-06 20:37:13 +01:00
echo " Creating $j /etc/ $src /jail.conf "
cat $j /etc/$src /jail.conf | egrep -v "^(name|version)=" > $j /etc/$new /jail.conf
( echo " name= $new " ; echo " version= $newversion " ) >> $j /etc/$new /jail.conf
echo "Creating run and build dirs"
ex mkdir -p $j /run/$new
ex mkdir -p $j /build/$new
fi
echo "DONE."
if test -z " $update " ; then
if ! egrep -q " ^ $new " /etc/jail.conf; then
bold " Consider adding the jail $new to /etc/jail.conf! "
echo
fi
bold "To mount the build chroot of the new jail, execute:"
echo " jaildk build $new start "
echo
bold "To login into the build chroot"
echo " jaildk blogin $new "
echo
bold "To mount the production chroot of the new jail, execute:"
echo " jaildk install $new "
echo
bold "To login into the build chroot"
echo " jaildk login $new "
echo
bold "To start the jail, execute:"
echo " jaildk start $new "
echo
else
. $j /etc/$src /jail.conf
2021-07-05 14:26:10 +02:00
# FIXME: possibly not needed! see comment in jaildk_create()
# jail=$new
2020-11-06 20:37:13 +01:00
bold "To mount the build chroot of the new jail, execute:"
2020-12-14 15:26:32 +01:00
echo " jaildk build $new start -b $base -v $newversion "
2020-11-06 20:37:13 +01:00
fi
}
2020-11-29 16:22:36 +01:00
usage_create( ) {
2020-11-29 18:46:50 +01:00
fin " Usage: $0 create <jail>
Create a new jail from template."
2020-11-29 16:22:36 +01:00
}
2020-11-06 20:37:13 +01:00
jaildk_create( ) {
2021-07-05 14:26:10 +02:00
local jail newjail src srcversion newversion jailhostname
2020-11-06 20:37:13 +01:00
jail = $1
2020-11-30 22:22:36 +01:00
# $jail gets overwritten in jaildk_clone or some subcall to .template :-( ...
2020-11-29 22:18:34 +01:00
newjail = $jail
2020-11-06 20:37:13 +01:00
src = .template
if test -z " $jail " ; then
2020-11-29 16:22:36 +01:00
usage_create
2020-11-06 20:37:13 +01:00
fi
. $j /etc/$src /jail.conf
srcversion = $version
newversion = ` date +%Y%m%d`
mkdir -p $j /etc/$jail
2020-11-29 22:18:34 +01:00
2020-11-29 16:22:36 +01:00
jaildk_clone -s $src -d $jail -o $srcversion -n $newversion
2020-11-29 22:18:34 +01:00
# 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)
2020-11-30 22:22:36 +01:00
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
2020-11-06 20:37:13 +01:00
}
remove( ) {
2021-07-05 14:26:10 +02:00
local dir = $1
2020-11-06 20:37:13 +01:00
if test -d $dir ; then
ex rm -rf $dir
else
echo " $dir doesn't exist anymore "
fi
}
2020-11-29 18:46:50 +01:00
usage_remove( ) {
fin " Usage: $0 remove <jail> [-v <version>]
Remove <jail> from disk."
}
2020-11-06 20:37:13 +01:00
jaildk_remove( ) {
2021-07-05 14:26:10 +02:00
local jail version
2020-11-06 20:37:13 +01:00
jail = $1
2020-11-29 18:46:50 +01:00
shift
version = ''
while getopts "v:" arg; do
case $arg in
v) version = ${ OPTARG } ; ;
*) usage_remove; ;
esac
done
2020-11-06 20:37:13 +01:00
if test -z " $jail " ; then
2020-11-29 18:46:50 +01:00
usage_remove
2020-11-06 20:37:13 +01:00
fi
if jls | egrep -q " ${ jail } " ; then
die " Jail $jail ( $version ) is still running, stop it before removing! "
fi
if mount | egrep -q " ${ jail } .* ${ version } " ; then
die " Jail $jail ( $version ) is still mounted, umount it before removing! "
fi
die_if_not_exist $jail
if test -n " $version " ; then
if ! test -d $j /etc/$jail /etc-$version ; then
die " Jail $jail $version doesn't exist! "
fi
remove $j /etc/$jail /etc-$version
remove $j /etc/$jail /local-etc-$version
remove $j /home/$jail /root-$version
remove $j /log/$jail -$version
remove $j /data/$jail /www
remove $j /data/$jail /spool
else
remove $j /etc/$jail
remove $j /home/$jail
remove $j /log/$jail -*
remove $j /data/$jail
fi
}
jaildk_jail_usage( ) {
2020-11-29 18:46:50 +01:00
fin " Usage: $0 <start|stop|restart|status> <jail> | status "
}
usage_start( ) {
fin " Usage $0 start <jail>
Start <jail>."
}
usage_stop( ) {
fin " Usage $0 stop <jail>
Stop <jail>."
}
usage_restart( ) {
fin " Usage $0 restart <jail>
Restart <jail>."
}
usage_status( ) {
fin " Usage $0 status [<jail>]
Show status of <jail>. Without <jail>, show status of all jails."
2020-11-06 20:37:13 +01:00
}
jaildk_jail( ) {
2021-07-05 14:35:24 +02:00
# reversed argument order here so that $jail is optional, in which
# case the command works on all jails
local jail mode jid ip path runs build base _eip ip4addr osrelease path build lookup
2020-11-29 18:46:50 +01:00
mode = $1
2021-07-05 14:26:10 +02:00
jail = $2
2020-11-06 20:37:13 +01:00
2021-07-05 14:37:17 +02:00
if test " x $mode " = "xstatus" ; then
2021-06-30 15:15:28 +02:00
(
2021-07-05 14:35:24 +02:00
if test -z " $jail " ; then
2021-07-05 14:37:17 +02:00
bold "Running jails:"
2021-07-05 14:35:24 +02:00
lookup = '*'
else
2021-07-05 14:37:17 +02:00
bold " Status $jail : "
2021-07-05 14:35:24 +02:00
lookup = $jail
fi
2021-07-04 20:46:52 +02:00
echo "Jail IP-Address Path Is-Running RW-mounted Current-Version Base"
2021-07-05 14:35:24 +02:00
grep -h "name=" $j /etc/$lookup /jail.conf | cut -d= -f2 | while read jail; do
2021-06-30 15:15:28 +02:00
jid = ''
ip = ''
path = ''
runs = ''
build = 'no'
base = ''
2021-07-04 20:46:52 +02:00
2021-06-30 15:15:28 +02:00
load-jail-config $jail
2021-07-04 20:46:52 +02:00
_eip = ''
for map in $maps ; do
eval _eip = \$ { map_${ map } _exposed_ip}
if test -n " ${ _eip } " ; then
# we only display the first exposed ip we find, if any
break
fi
done
2021-06-30 15:15:28 +02:00
if jls -j $jail > /dev/null 2>& 1; then
# jail is running
eval ` jls -j $jail -qn | perl -n -e 'chomp; %j = map { ($a,$b) = split /=/; $a=~ s/\.//g; $a => $b } split/ /; foreach (keys %j) {print "$_=$j{$_}\n"}' `
if test -n " $ip4addr " ; then
ip = $ip4addr
else
if test -z " $ip " ; then
ip = "n/a"
2021-07-04 20:46:52 +02:00
else
# ip configured
if test -n " ${ _eip } " ; then
ip = " ${ _eip } -> ${ ip } "
fi
2021-06-30 15:15:28 +02:00
fi
fi
jid = " yes,jid= $jid "
else
jid = "no"
path = $j /run/$jail
if test -z " $ip " ; then
ip = "n/a"
fi
fi
2020-11-06 20:37:13 +01:00
2021-06-30 15:15:28 +02:00
if mount | egrep " $j /build/ $jail " > /dev/null 2>& 1; then
build = 'yes'
fi
2021-07-10 20:17:16 +02:00
echo " $jail $ip $path $jid $build $version $base "
2021-06-30 15:15:28 +02:00
done
) | column -t
2021-07-05 14:35:24 +02:00
if test -n " $jail " ; then
2023-09-13 10:38:47 +02:00
jaildk_rc $jail -m status
2021-07-05 14:35:24 +02:00
fi
2020-12-13 14:17:13 +01:00
elif test -z " $jail " ; then
usage_$mode
2020-11-06 20:37:13 +01:00
else
bold " Jail $jail $mode : "
case $mode in
*)
service jail $mode $jail
2020-11-30 22:17:49 +01:00
jaildk_ipfw $jail $mode
2020-11-06 20:37:13 +01:00
; ;
esac
fi
}
2020-11-28 12:26:24 +01:00
get_rc_scripts( ) {
2023-09-13 10:38:47 +02:00
local jail jailpath files rcvar name
2020-11-28 15:16:40 +01:00
jail = " $1 "
2021-01-25 00:22:54 +01:00
jailpath = ` get_jail_path $jail `
2020-11-06 20:37:13 +01:00
2021-01-25 00:22:54 +01:00
files = $( ls $j /run/$jailpath /usr/local/etc/rc.d/* $j /run/$jailpath /etc/rc.d/* 2>/dev/null)
2020-11-28 15:16:40 +01:00
2021-01-25 00:22:54 +01:00
rcorder $files 2>/dev/null | while read SCRIPT; do
2023-09-13 10:38:47 +02:00
# we need to fetch the rcvar variable. sometimes these scripts
# use ${name}_enable, so we also fetch the $name variable and
# interpolate $rcvar accordingly
2020-11-28 15:16:40 +01:00
rcvar = ` egrep "^rcvar=" $SCRIPT | cut -d= -f2 | sed 's/"//g' | tail -1`
2023-09-13 10:38:47 +02:00
name = ` egrep "^name=" $SCRIPT | cut -d= -f2 | sed 's/"//g' | tail -1`
rcvar = $( eval echo " $rcvar " )
2021-01-25 00:22:54 +01:00
if egrep -iq " ^ ${ rcvar } =.*yes " $j /run/$jailpath /usr/local/etc/rc.conf; then
echo $SCRIPT | sed " s| $j /run/ $jailpath || "
2020-11-28 15:16:40 +01:00
fi
done
2020-11-06 20:37:13 +01:00
}
2020-11-29 18:46:50 +01:00
usage_rc( ) {
2023-09-13 10:38:47 +02:00
fin " Usage: $0 rc <jail> [-m <mode>] [-r <rc.d script]
2020-11-29 18:46:50 +01:00
Execute an rc.d script inside <jail> with parameter <mode>. Options:
-r <rc.d script> Execute <rc.d script>. default: execute all enabled scripts."
2020-11-06 20:37:13 +01:00
}
jaildk_rc( ) {
2021-07-05 14:26:10 +02:00
local jail mode rcd jailpath ok script jid
2020-11-06 20:37:13 +01:00
jail = $1
2020-11-29 18:46:50 +01:00
shift
2020-12-19 17:34:53 +01:00
rcd = ''
2020-11-29 18:46:50 +01:00
2023-09-13 10:38:47 +02:00
while getopts "r:m:" arg; do
2020-11-29 18:46:50 +01:00
case $arg in
r) rcd = ${ OPTARG } ; ;
2023-09-13 10:38:47 +02:00
m) mode = ${ OPTARG } ; ;
2020-11-29 18:46:50 +01:00
*) usage_rc; ;
esac
done
2020-11-06 20:37:13 +01:00
2020-12-19 17:34:53 +01:00
if test -z " $rcd " ; then
rcd = 'all'
2020-11-06 20:37:13 +01:00
fi
2020-11-29 18:46:50 +01:00
if test -z " $jail " -o -z " $mode " ; then
usage_rc
2020-11-06 20:37:13 +01:00
fi
if ! jls | egrep -q " ${ jail } " ; then
die " Jail $jail is not running. "
fi
2021-01-25 00:22:54 +01:00
2020-11-28 12:26:24 +01:00
rcs = ` get_rc_scripts $jail `
2021-07-05 14:54:35 +02:00
2021-01-25 00:22:54 +01:00
jid = ` get_jid $jail `
jailpath = ` get_jail_path $jail `
2020-12-19 17:34:53 +01:00
if test $rcd = "all" ; then
2021-01-25 00:22:54 +01:00
if [ " $jail " = = " $jailpath " ] ; then
bold " Jail $jail rc status: "
else
bold " Jail $jail / $jailpath rc status: "
fi
2020-11-06 20:37:13 +01:00
for script in $rcs ; do
2021-01-25 00:22:54 +01:00
jexec $jid $script $mode
2020-11-06 20:37:13 +01:00
done
else
ok = ''
for script in $rcs ; do
2020-12-19 17:34:53 +01:00
if echo " $script " | egrep -q " / ${ rcd } \$ " ; then
2021-01-25 00:22:54 +01:00
jexec $jid $script $mode
2020-11-06 20:37:13 +01:00
ok = 1
fi
done
if test -z " $ok " ; then
die " Script $rc doesn't exist in $jail or is not enabled. "
fi
fi
}
2021-01-25 00:22:54 +01:00
get_jail_path( ) {
2021-07-05 14:26:10 +02:00
local jail = " $1 "
2021-07-05 14:54:35 +02:00
echo " $( jls | grep -E " ${ jail } " | awk '{print $NF}' | xargs basename) "
2021-01-25 00:22:54 +01:00
}
get_jid( ) {
2021-07-05 14:26:10 +02:00
local jail = " $1 "
2021-07-05 14:54:35 +02:00
echo " $( jls | grep -E " ${ jail } " | awk '{print $1}' | xargs basename) "
2021-01-25 00:22:54 +01:00
}
2020-11-29 18:46:50 +01:00
usage_blogin( ) {
err " Usage: $file <jail>
Chroot into a build jail.
Mounted build chroot' s:"
mount| egrep "base.*build" | awk '{print $3}' | cut -d/ -f 4
exit 1
}
2020-11-27 23:21:34 +01:00
2020-11-06 20:37:13 +01:00
jaildk_blogin( ) {
2021-07-05 14:26:10 +02:00
local jail chroot file shell term home path
2020-11-06 20:37:13 +01:00
jail = $1
if test -z " $jail " ; then
file = ` basename $0 `
if test " $file " = "jaildk" ; then
file = " $0 blogin "
else
file = " $0 "
fi
2020-11-29 18:46:50 +01:00
usage_blogin
2020-11-06 20:37:13 +01:00
fi
chroot = " $j /build/ $jail "
if ! test -d $chroot /root; then
echo " build jail $jail not mounted! "
echo " Mount it with jaildk build $jail start "
exit 1
fi
shell = /bin/csh
term = vt100
home = /root
path = /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
if test -e $chroot /root/.bashrc; then
shell = /usr/local/bin/bash
fi
chroot $chroot /etc/rc.d/ldconfig onestart > /dev/null 2>& 1
2020-11-28 14:34:10 +01:00
env - HOME = $home TERM = $term SHELL = $shell PATH = $path chroot $chroot $shell
2020-11-06 20:37:13 +01:00
}
2020-11-29 18:46:50 +01:00
usage_login( ) {
err " Usage: $file <jail-name|jail-domain|jail-ip> [<user>]
Login into a jail by name, ip or domain. If <user> has not been
specified, login as root.
Available jails:"
jls
exit 1
}
2020-11-06 20:37:13 +01:00
jaildk_login( ) {
2021-07-05 14:26:10 +02:00
local jail user chroot file shell term home path me
2020-11-06 20:37:13 +01:00
jail = $1
user = $2
me = ` id -u`
jexec = "jexec"
if test -z " $jail " ; then
file = ` basename $0 `
if test " $file " = "jaildk" ; then
file = " $0 jlogin "
else
file = " $0 "
fi
2020-11-29 18:46:50 +01:00
usage_login
2020-11-06 20:37:13 +01:00
fi
jid = ""
2020-11-27 23:21:34 +01:00
jid = ` jls | grep " $jail " | awk '{print $1}' `
2020-11-06 20:37:13 +01:00
if test -z " $jid " ; then
echo " jail $jail doesn't run! "
exit 1
fi
2021-01-14 13:10:09 +01:00
shell = /bin/csh
2020-11-06 20:37:13 +01:00
home = /home/$user
term = vt100
path = /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
2021-01-14 13:10:09 +01:00
chroot = " $j /run/ $jail "
2020-11-06 20:37:13 +01:00
if test -z " $user " ; then
user = root
2021-01-14 13:10:09 +01:00
home = /root
2020-11-06 20:37:13 +01:00
fi
2021-01-14 13:10:09 +01:00
if test -e $chroot /$home /.bashrc; then
shell = /usr/local/bin/bash
2020-11-06 20:37:13 +01:00
fi
2021-01-14 13:10:09 +01:00
if test " $me " != "0" ; then
jexec = " sudo $jexec "
2020-11-06 20:37:13 +01:00
fi
2021-01-14 13:10:09 +01:00
echo " # Logging into jail $jail with jid $jid # "
2020-11-06 20:37:13 +01:00
env - JAIL = $jail HOME = $home TERM = $term SHELL = $shell PATH = $path $jexec -U $user $jid $shell
}
2020-11-29 18:46:50 +01:00
usage_reinstall( ) {
2020-12-14 20:18:20 +01:00
fin " Usage: $0 reinstall <jail> [-b <base>] [-v <version>]
Stop, uninstall, install and start <jail>. If <base> and/or
<version> is given, modify the jail config before reinstalling.
2020-11-29 18:46:50 +01:00
"
}
2020-11-06 20:37:13 +01:00
jaildk_reinstall( ) {
2021-07-05 14:26:10 +02:00
local jail NEWBASE NEWVERSION ts change base version
2020-11-06 20:37:13 +01:00
jail = $1
2020-12-14 20:18:20 +01:00
shift
while getopts "b:v:" arg; do
case $arg in
b) NEWBASE = ${ OPTARG } ; ;
v) NEWVERSION = ${ OPTARG } ; ;
*) usage_reinstall; ;
esac
done
2020-11-06 20:37:13 +01:00
2020-11-29 18:46:50 +01:00
if test -z " $jail " ; then
usage_reinstall
fi
2020-11-06 20:37:13 +01:00
die_if_not_exist $jail
if jls | egrep -q " ${ jail } " ; then
jaildk_jail stop $jail
fi
jaildk_uninstall $jail
sleep 0.2
sync
2020-12-14 20:18:20 +01:00
if test -n " $NEWBASE " -o -n " $NEWVERSION " ; then
load-jail-config $jail
ts = ` date +%Y%m%d%H%M`
change = ''
if test $NEWBASE != $base ; then
base = $NEWBASE
change = 1
fi
if test $NEWVERSION != $version ; then
version = $NEWVERSION
change = 1
fi
if test -n " $change " ; then
bold " Saving current $jail config "
ex cp -p $j /etc/$jail /jail.conf $j /etc/$jail /jail.conf-$ts
bold " Creating new $jail config "
cat $j /etc/$jail /jail.conf-$ts \
| sed -e " s/^base=.*/base= $base / " -e " s/^version=.*/version= $version / " \
> $j /etc/$jail /jail.conf
fi
fi
2023-09-13 10:38:47 +02:00
jaildk_install -m $jail start
2020-11-06 20:37:13 +01:00
jaildk_jail start $jail
sleep 0.2
jaildk_jail status $jail
}
2023-09-13 10:38:47 +02:00
_install_jaildk( ) {
realj = ` cd $j ; pwd `
sed " s|^JAILDIR=.*|JAILDIR= $realj | " $0 > $j /bin/jaildk
ex chmod 755 $j /bin/jaildk
}
2020-11-06 20:37:13 +01:00
jaildk_setup( ) {
2021-07-05 14:26:10 +02:00
local j version subdir
2020-11-06 20:37:13 +01:00
j = $1
if test -z " $j " ; then
2020-11-29 18:46:50 +01:00
fin " Usage: $0 setup <base dir for jail environment> "
2020-11-06 20:37:13 +01:00
fi
2023-09-13 10:38:47 +02:00
if test -e " $j /bin/jaildk " ; then
bold " $j /bin/jaildk aleady exists, updating... "
_install_jaildk $j
return
fi
2020-11-06 20:37:13 +01:00
bold "preparing directories"
ex mkdir -p $j
2020-11-26 22:08:19 +01:00
for subdir in etc bin appl base data home log run ports; do
2020-11-06 20:37:13 +01:00
ex mkdir -p $j /$subdir
done
version = ` date +%Y%m%d`
2020-11-27 23:21:34 +01:00
for subdir in appl/default-$version /db/ports appl/default-$version /etc etc/.template/etc-$version etc/.template/local-etc-$version home/.template/root-$version log/.template-$version ; do
2020-11-06 20:37:13 +01:00
ex mkdir -p $j /$subdir
done
bold "building jail template"
2020-11-26 12:36:36 +01:00
ex cpdup /etc $j /etc/.template/etc-$version
2020-11-06 20:37:13 +01:00
echo " creating $j /etc/.template/etc- $version /rc.conf "
2020-11-27 23:21:34 +01:00
rm -f $j /etc/.template/etc-$version /rc.conf
2020-11-06 20:37:13 +01:00
echo 'rc_conf_files="/etc/rc.conf /etc/rc.conf.local /usr/local/etc/rc.conf"' > $j /etc/.template/etc-$version /rc.conf
echo " creating $j /etc/.template/local-etc- $version /rc.conf "
echo ' hostname = "TEMPLATE"
sendmail_enable = "NO"
sendmail_submit_enable = "NO"
sendmail_outbound_enable = "NO"
sendmail_msp_queue_enable = "NO" ' > $j /etc/.template/local-etc-$version /rc.conf
bold " creating template config $j /etc/.template/jail.conf "
os = ` uname -r`
( echo " base= $os " ; echo " version= $version " ; name = template) > $j /etc/.template/jail.conf
bold " creating template config $j /etc/.template/mount.conf "
echo ' base/$base $name nullfs ro
md $name /tmp mfs rw,nosuid,async 128m 1777
dev $name /dev devfs
log/$name -$version $name /var/log nullfs rw
appl/default-$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
home/$name /root-$version $name /root nullfs rw' > $j /etc/.template/mount.conf
bold " creating template config $j /etc/.template/ports.conf "
( echo bash; echo ca_root_nss) > $j /etc/.template/ports.conf
2020-11-30 22:37:18 +01:00
bold " creating template config $j /etc/.template/ipfw.conf "
touch $j /etc/.template/ipfw.conf
2020-11-06 20:37:13 +01:00
bold " creating template config $j /etc/.template/mtree.conf "
2020-11-27 23:21:34 +01:00
echo ' /set type = dir uid = 0 gid = 0 mode = 01777
. type = dir mode = 0755
tmp
var
cache
pkg
..
..
run
..
tmp' > $j /etc/.template/mtree.conf
2020-11-06 20:37:13 +01:00
bold "installing jaildk"
2023-09-13 10:38:47 +02:00
_install_jaildk $j
2020-11-06 20:37:13 +01:00
2020-11-25 10:42:52 +01:00
bold "configuring root shell template"
echo " # root shell inside jail
alias h history 25
alias j jobs -l
alias la ls -a
alias lf ls -FA
alias ll ls -lA
alias l ls -laF
alias .. cd ..
alias ... cd ../..
alias .... cd ../../../
umask 22
set path = ( /sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin)
setenv EDITOR vi
setenv PAGER less
setenv BLOCKSIZE K
if ( \$ ?prompt) then
2020-11-27 23:21:34 +01:00
set chroot = ` ps axu| grep /sbin/init | grep -v grep | awk '{print $1}' `
2020-11-25 10:45:13 +01:00
if ( "\$chroot" = = \" \" ) then
set prompt = \" ( jail) %N@%m:%~ %# \"
2020-11-25 10:42:52 +01:00
else
2020-11-25 10:45:13 +01:00
set prompt = \" ( build chroot) %N@%m:%~ %# \"
2020-11-25 10:42:52 +01:00
endif
set promptchars = \" %#\"
set filec
set history = 1000
set savehist = ( 1000 merge)
set autolist = ambiguous
# Use history to aid expansion
set autoexpand
set autorehash
endif
" > $j /home/.template/root- $version /.cshrc
2020-11-06 20:37:13 +01:00
bold "building base"
echo -n "Do you want to build a base directory [Yn]? "
read yesno
case $yesno in
y| Y| yes| YES)
2020-11-29 16:22:36 +01:00
jaildk_base -b $j /base/$os
2020-11-06 20:37:13 +01:00
; ;
esac
}
2021-07-06 12:11:23 +02:00
jaildk_version( ) {
# parser friendly output
echo " This is jaildk.
version = $version
jailbase = $j
"
}
usage_update( ) {
die " Usage $0 update [f]
Update jaildk via git, needs internet access and git.
Use -f to force the update ignoring the version check.
"
}
jaildk_update( ) {
local repo gitversion force
rcscript = update
force = ''
repo = "https://github.com/TLINDEN/jaildk.git"
mustberoot
while getopts "f" arg; do
case $arg in
f) force = 1; ;
*) usage_update; ;
esac
done
if test -w $j ; then
if ! test -d $j /git/jaildk; then
ex mkdir -p $j /git || die " Could not mkdir $j /git "
cd $j /git && ex git clone $repo || die " Could not clone $repo ! "
else
cd $j /git/jaildk && ex git pull || die " Could not pull from $repo ! "
fi
gitversion = $( egrep "^version=" $j /git/jaildk/jaildk | head -1 | cut -d= -f2)
if test -n " $gitversion " ; then
2021-07-06 12:12:46 +02:00
if test 1 -eq $( echo " $gitversion > $version " | bc) -o -n " $force " ; then
2021-07-06 12:11:23 +02:00
echo " Updating jaildk from $version to version $gitversion ... "
2023-09-13 10:38:47 +02:00
ex make -C $j /git/jaildk
2021-07-06 12:11:23 +02:00
ex install -o root -g wheel $j /git/jaildk/jaildk $j /bin/jaildk || die "Failed to update self!"
else
die "jaildk git version unchanged, aborting"
fi
else
die " git version of jaildk in $j /git/jaildk/jaildk has no version! "
fi
else
die " directory $j must be writable! "
fi
}
2020-12-13 14:37:20 +01:00
usage_fetchports( ) {
die " Usage $0 fetchports [-v <version>]
Fetch current portscollection, use <version> or todays timestamp as new version"
}
jaildk_fetchports( ) {
2021-07-05 14:26:10 +02:00
local version = ` date +%Y%m%d`
2020-12-13 14:37:20 +01:00
while getopts "v:" arg; do
case $arg in
v) version = ${ OPTARG } ; ;
*) usage_fetchports; ;
esac
done
2020-11-27 19:08:57 +01:00
if test -d " $j /ports/ $version " ; then
echo -n " Ports dir $version already exist. Do you want to recreate it [y/N]? "
2020-11-26 22:08:19 +01:00
read yesno
case $yesno in
y| Y| yes| YES)
2020-11-27 19:08:57 +01:00
ex rm -rf $j /ports/$version
2021-07-05 14:26:10 +02:00
fetch_ports
2020-11-26 22:08:19 +01:00
; ;
esac
else
2021-07-05 14:26:10 +02:00
fetch_ports
2020-11-26 22:08:19 +01:00
fi
}
2021-07-05 14:26:10 +02:00
fetch_ports( ) {
2020-11-27 19:08:57 +01:00
ex mkdir -p $j /ports/tmp
ex fetch -o $j /ports/tmp/ports.tar.gz http://ftp.freebsd.org/pub/FreeBSD/ports/ports/ports.tar.gz
2020-11-27 23:21:34 +01:00
ex tar xzfC $j /ports/tmp/ports.tar.gz $j /ports/tmp
2020-11-27 19:08:57 +01:00
ex mv $j /ports/tmp/ports $j /ports/$version
ex rm -rf $j /ports/tmp/ports*
2020-11-26 22:08:19 +01:00
}
2020-11-06 20:37:13 +01:00
2020-11-29 16:22:36 +01:00
usage_freeze( ) {
2020-11-28 20:41:05 +01:00
echo " Usage: $0 freeze <jail> [options]
Options:
-v <version> freeze <version> of <jail>
-b include the base layer ( default: no)
-a include the application layer ( default: no) "
exit 1
}
freeze_dir( ) {
2021-07-05 14:26:10 +02:00
local dstdir src srcdir layer layerfile
2020-11-28 20:41:05 +01:00
dstdir = $1
src = $2
srcdir = $( echo $src | cut -d/ -f1)
layer = $( echo $src | sed " s| $srcdir /|| " )
layerfile = $( echo $layer | sed 's|/|-|g' )
2021-07-05 14:26:10 +02:00
2020-11-28 20:41:05 +01:00
ex tar -C $j /$srcdir -cpf $dstdir /$srcdir -$layerfile .tar $layer
}
2020-11-28 15:16:40 +01:00
jaildk_freeze( ) {
2021-07-05 14:26:10 +02:00
local jail VERSION ADDBASE ADDAPPL version host freeze tmp mountconf \
src dest fs opts size perm files
2020-11-28 15:16:40 +01:00
jail = $1
2020-11-28 20:41:05 +01:00
shift
VERSION = ""
ADDBASE = ""
ADDAPPL = ""
while getopts "abv:" arg; do
case $arg in
a) ADDAPPL = 1; ;
b) ADDBASE = 1; ;
v) VERSION = ${ OPTARG } ; ;
2020-11-29 16:22:36 +01:00
*) usage_freeze; ;
2020-11-28 20:41:05 +01:00
esac
done
if test -z " $jail " ; then
2020-11-29 16:22:36 +01:00
usage_freeze
2020-11-28 20:41:05 +01:00
fi
die_if_not_exist $jail "Jail to freeze" $VERSION
if jls | egrep -q " ${ jail } " ; then
echo " The jail $jail is actually running. It's recommended "
echo -n "to stop it before freezing. Stop the jail now [Ny]? "
read yesno
case $yesno in
y| Y| yes| YES| Yes)
service jail stop $jail
; ;
esac
fi
load-jail-config $jail
if test -n " $VERSION " ; then
version = $VERSION
fi
bold " Freezing jail $jail $version "
host = $( hostname | cut -d\. -f1)
freeze = $j /images/$host -$jail -$version .tgz
tmp = $j /images/tmp/$jail -$version
ex mkdir -p $tmp
mountconf = $j /etc/$jail /mount.conf
if ! test -e " $mountconf " ; then
die " $mountconf doesn't exist! "
fi
# create sub tarballs from every layer
grep -v "#" $mountconf | while read LINE; do
2021-07-05 14:26:10 +02:00
# this is a copy of the code in rc_mount()
2020-11-28 20:41:05 +01:00
# FIXME: put this into a function somehow
set -- $( eval echo \" " $LINE " \" )
# Skip empty lines:
case " $1 " in
"" ) continue ; ;
esac
src = $1
dest = $2
fs = $3
opts = $4
size = $5
perm = $6
case $fs in
nullfs)
if ! echo $src | egrep -q "^/" ; then
# only freeze nullfs mounts relative to $j
if echo $src | egrep -q "^base/" ; then
if test -n " $ADDBASE " ; then
freeze_dir $tmp $src
fi
elif echo $src | egrep -q "^appl/" ; then
if test -n " $ADDAPPL " ; then
freeze_dir $tmp $src
fi
else
freeze_dir $tmp $src
fi
fi
; ;
esac
done
# add the jail config
files = $( find $j /etc/$jail -type f -maxdepth 1)
for file in $files ; do
cp -pP $file $tmp /
done
# build the final image file
ex tar -C $j /images/tmp -cpf $freeze $jail -$version
# cleaning up
ex rm -rf $j /images/tmp
bold " Done, jail $jail frozen to $freeze . "
}
thaw_tarball( ) {
2021-07-05 14:26:10 +02:00
local srcdir tarball layer
2020-11-28 20:41:05 +01:00
srcdir = $1
tarball = $2
# etc-test-local-etc-20201128.tar
layer = $( echo $tarball | cut -d\- -f1)
if ! test -d $j /$layer ; then
ex mkdir -p $j /$layer
fi
ex tar -C $j /$layer -xf $srcdir /$tarball
ex rm -f $srcdir /$tarball
}
2020-11-29 16:22:36 +01:00
usage_thaw( ) {
2020-11-29 18:46:50 +01:00
fin " Usage: $0 thaw <image> "
2020-11-29 16:22:36 +01:00
}
2020-11-28 20:41:05 +01:00
jaildk_thaw( ) {
2021-07-05 14:26:10 +02:00
local image j version jail tmp files bak
2020-11-28 20:41:05 +01:00
image = $1
if test -n " $J " ; then
j = $J
fi
jail = $( echo $image | cut -d\- -f2)
version = $( echo $image | cut -d\- -f3 | cut -d\. -f1)
if ! test -n " $version " -o -n " $jail " ; then
2020-11-29 16:22:36 +01:00
usage_thaw
2020-11-28 20:41:05 +01:00
fi
if test -d $j /etc/$jail /etc-$version ; then
bold -n " Jail $jail $version already exists, overwrite [Ny]? "
read yesno
case $yesno in
y| Y| yes| YES| Yes)
:; ;
*)
echo "abort." ; ;
esac
fi
bold " Thawing jail $image "
tmp = $j /images/tmp
ex mkdir -p $tmp
# too many things can go wrong from here, so better abort on error
set -e
ex tar -C $tmp -xf $image
if ! test -d $tmp /$jail -$version ; then
die "Invalid image format!"
ex rm -rf $tmp
fi
for tarball in ` cd $tmp /$jail -$version && ls *.tar` ; do
thaw_tarball $tmp /$jail -$version $tarball
done
files = $( find $tmp -type f)
bak = ""
if test -e $j /etc/$jail /jail.conf; then
bold -n " $j /etc/ $jail /jail.conf already exist. Overwrite configs [Ny]? "
read yesno
case $yesno in
y| Y| yes| YES| Yes)
:; ;
*)
bold " Copying configs with extension - $version "
bak = " - $version "
; ;
esac
fi
for file in $files ; do
filename = $( basename $file )
ex cp -Pp $file $j /etc/$jail /$filename $bak
done
bold " Done. Thawed jail $jail $version from $image . "
2020-11-28 15:16:40 +01:00
}
2020-12-01 18:40:32 +01:00
usage_ipfw( ) {
2023-09-13 10:38:47 +02:00
echo " Usage: $0 ipfw <jail> -m <mode>
2020-12-01 18:40:32 +01:00
[ Un] install ipfw rules. <mode> 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
}
2020-11-30 22:17:49 +01:00
jaildk_ipfw( ) {
2021-07-05 14:26:10 +02:00
local jail mode
2020-11-30 22:17:49 +01:00
jail = $1
2023-09-13 10:38:47 +02:00
while getopts "m:" arg; do
case $arg in
m) mode = ${ OPTARG } ; ;
*) usage_ipfw; ;
esac
done
2020-12-01 18:40:32 +01:00
if test -z " $mode " ; then
usage_ipfw
fi
if test -f " $j /etc/ $jail /ipfw.conf " ; then
2020-11-30 22:17:49 +01:00
echo
bold "Managing IPFW Rules..."
case $mode in
start)
2021-07-05 14:26:10 +02:00
ipfw_delete $jail "y"
ipfw_add $jail
2020-11-30 22:17:49 +01:00
; ;
stop)
2021-07-05 14:26:10 +02:00
ipfw_delete $jail
2020-11-30 22:17:49 +01:00
; ;
esac
bold "... done"
echo
fi
}
2021-07-05 14:26:10 +02:00
ipfw_add( ) {
local jail ipv4 ipv6 rule
2020-11-30 23:04:30 +01:00
jail = $1
2020-12-01 18:40:32 +01:00
# support jail variables as well
load-jail-config $jail
2021-07-05 14:26:10 +02:00
if test -z $ip ; then
# Getting current jails IP..
ipv4 = ` jls -n -j $jail ip4.addr | cut -d= -f2`
else
ipv4 = $ip
fi
2020-12-01 18:40:32 +01:00
2021-07-05 14:26:10 +02:00
if test -z " $ipv4 " ; then
2020-12-01 18:40:32 +01:00
die " Jail $jail doesn't have an ipv4 address! "
fi
2021-07-05 14:26:10 +02:00
if test -z $ip6 ; then
ip6 = ` jls -n -j $jail ip6.addr | cut -d= -f2` # optional, no checks
else
ipv6 = $ip6
fi
2020-12-01 18:40:32 +01:00
2020-11-30 23:04:30 +01:00
# Adding rules
2020-12-01 18:40:32 +01:00
egrep "^[a-z]" $j /etc/$jail /ipfw.conf | while read LINE; do
rule = $( eval echo " ipfw add $LINE // $jail " )
echo $rule
$rule
done
2020-11-30 23:04:30 +01:00
}
2021-07-05 14:26:10 +02:00
ipfw_delete( ) {
local jail noout
2020-11-30 23:04:30 +01:00
jail = $1
noout = $2
2021-07-05 14:26:10 +02:00
2020-11-30 23:04:30 +01:00
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
}
2020-11-28 20:41:05 +01:00
2021-06-30 15:15:28 +02:00
usage_vnet( ) {
2021-07-05 14:26:10 +02:00
echo " $0 vnet <jail> <mode> -b <bridge>
Configure VIMAGE ( vnet) networking for a jail. Usually called from
jail.conf. You need to configure the bridge manually in advance.
You need the following in your /etc/rc.conf:
cloned_interfaces = \" bridge0\"
2022-02-25 12:08:25 +01:00
ifconfig_bridge0 = \" inet 172.20.20.1/24 up\"
ifconfig_bridge0_ipv6 = \" 2a01:...:1e::1/80 auto_linklocal\"
2021-07-05 14:26:10 +02:00
ipv6_gateway_enable = \" YES\"
And something like this in your jail.conf:
billa {
vnet;
2022-02-25 12:08:25 +01:00
exec.poststart = \" /jail/bin/jaildk vnet $name start -b jailsw0\" ;
exec.prestop = \" /jail/bin/jaildk vnet $name stop -b jailsw0\" ;
2021-07-05 14:26:10 +02:00
}
Finally, the jail.conf for a vnet jail needs to contain these parameters:
ip = 172.20.20.10/24
gw = 172.20.20.1
and if using v6 v6 address in bridge subet, gw6 is default gw = > bridge interface
ip6 = 2a01:.....ff
gw6 = 2a01:.....1
You' ll also need PF nat rules in order to be able to reach the outside
from the jail or vice versa."
2021-07-02 13:03:33 +02:00
exit
2021-06-30 15:15:28 +02:00
}
jaildk_vnet( ) {
2021-07-02 13:03:33 +02:00
#
# This is no rc.d subcommand, but a standalone command, because it must
# be executed by jail(8) via exec.created hook.
2021-07-05 14:26:10 +02:00
local jail mode BRIDGE vnethost vnetjail epairA epairB
2021-06-30 15:15:28 +02:00
jail = $1
mode = $2
shift
shift
BRIDGE = ''
while getopts "b:i:r:" arg; do
case $arg in
b) BRIDGE = ${ OPTARG } ; ;
*) usage_vnet; ;
esac
done
if test -z " $mode " ; then
usage_vnet
fi
die_if_not_exist $jail
load-jail-config $jail
2021-07-02 13:03:33 +02:00
if test -z " $ip " -a -z " $gw " ; then
usage_vnet
fi
2021-06-30 15:15:28 +02:00
vnethost = " ep ${ jail } .h "
vnetjail = " ep ${ jail } .j "
2021-07-04 12:49:34 +02:00
epairA = ''
epairB = ''
2021-06-30 15:15:28 +02:00
case $mode in
start)
2021-07-04 12:49:34 +02:00
if ! ifconfig $vnethost > /dev/null 2>& 1; then
# setup epair
epairA = $( ifconfig epair create)
epairB = " ${ epairA %? } b "
2021-06-30 15:15:28 +02:00
2021-07-04 12:49:34 +02:00
ex ifconfig $epairA name $vnethost || true
ex ifconfig $epairB name $vnetjail || true
2021-06-30 15:15:28 +02:00
2021-07-04 12:49:34 +02:00
ex ifconfig $vnetjail up
ex ifconfig $vnethost up
fi
2021-06-30 15:15:28 +02:00
2021-07-04 12:49:34 +02:00
if ! ifconfig $BRIDGE | egrep member:.$vnethost > /dev/null 2>& 1; then
# add the host to the bridge
ex ifconfig $BRIDGE addm $vnethost up || true
2021-06-30 15:15:28 +02:00
2021-07-04 12:49:34 +02:00
# add the jail to the bridge (gets invisible from host)
ex ifconfig $vnetjail vnet $jail || true
fi
2021-07-03 20:35:05 +02:00
2021-07-04 12:49:34 +02:00
if ! jexec $jail ifconfig $vnetjail inet | grep netmask > /dev/null 2>& 1; then
# configure the jail v4 network stack inside the jail
ex jexec $jail ifconfig $vnetjail $ip up || true
ex jexec $jail route add default $gw || true
2021-07-04 11:52:04 +02:00
fi
2021-07-04 12:49:34 +02:00
2021-07-04 11:52:04 +02:00
if test -n " $ip6 " -a -n " $gw6 " ; then
2021-07-04 12:49:34 +02:00
if ! jexec $jail ifconfig $vnetjail inet6 | grep -v fe80 | grep prefixlen > /dev/null 2>& 1; then
2022-02-25 12:08:25 +01:00
# configure the jail v6 network stack inside the jail
ex jexec $jail ifconfig $vnetjail inet6 $ip6 || true
ex jexec $jail ifconfig $vnetjail inet6 -ifdisabled accept_rtadv auto_linklocal|| true
2021-07-04 12:49:34 +02:00
ex jexec $jail route -6 add default $gw6 || true
fi
2021-07-03 20:35:05 +02:00
fi
2021-06-30 15:15:28 +02:00
; ;
stop)
# remove vnet from the jail
ifconfig $vnetjail -vnet $jail || true
# remove interfaces (removes jail interface as well, since this is an epair)
ifconfig $vnethost destroy || true
; ;
*)
usage_vnet; ;
esac
}
2021-01-14 13:10:09 +01:00
2022-02-16 12:22:13 +01:00
usage_prune( ) {
echo " $0 prune [-b | -a | -j]
List unused directories. Important: ALL jails must be running while
executing this command! Options:
-b list active and unused bases
-a list active and unused appls
-j <jail> list version and unused jail specific directories for <jail>
-u only list unused dirs
Use the option -u to omit active dirs and '|xargs rm -rf' to actually
delete directories. Be sure to have backups available!
"
}
jaildk_prune( ) {
local BASE APPL JAIL UNUSED
while getopts "baj:u" arg; do
case $arg in
b) BASE = 1; ;
a) APPL = 1; ;
j) JAIL = ${ OPTARG } ; ;
u) UNUSED = 1; ;
*) usage_bootstrap; ;
esac
done
dirs = " /tmp/jaildk- $$ -dirs "
if test -n " $BASE " ; then
(
mount | grep /base/ | cut -d' ' -f1
ls -1d /jail/base/*
) > $dirs
if test -z " $UNUSED " ; then
bold "Active BASE mounts:" > /dev/stderr
cat $dirs | sort -V | uniq -c | grep -v " 1" | awk '{print $2}'
echo
fi
bold "Unused BASE mounts (be aware of build mounts!):" > /dev/stderr
cat $dirs | sort -V | uniq -c | grep " 1" | awk '{print $2}'
rm -f $dirs
elif test -n " $APPL " ; then
(
mount | grep /appl/ | cut -d' ' -f1
ls -1d /jail/appl/*
) > $dirs
if test -z " $UNUSED " ; then
bold "Active APPL mounts:" > /dev/stderr
cat $dirs | sort -V | uniq -c | grep -v " 1" | awk '{print $2}'
echo
fi
bold "Unused APPL mounts:" > /dev/stderr
cat $dirs | sort -V | uniq -c | grep " 1" | awk '{print $2}'
rm -f $dirs
elif test -n " $JAIL " ; then
die_if_not_exist $JAIL
load-jail-config $JAIL
if test -z " $UNUSED " ; then
bold " Current Active jail version for jail $JAIL : " > /dev/stderr
echo $version ; echo
fi
bold " Unused jail specific mounts for jail $JAIL : " > /dev/stderr
ls -1d $j /etc/$JAIL /*[ 0-1] * $j /log/$JAIL -*[ 0-1] * $j /home/$JAIL /*[ 0-1] * | grep -v $version | sort -V
fi
}
2021-01-14 13:10:09 +01:00
usage_bootstrap( ) {
echo " $0 bootstrap <jail> [-b <base>] [-v <version>] [-p <port,...>] [-a <appl>] [-i <ip,..>]
Create, build and install a new jail with name <jail>. Options:
-b <base> Use <base> as base, create if not existent.
-v <version> Assign <version> to new jail, otherwise use YYYYMMDD.
-p <port,...> Install specified ports into jail.
-a <appl> Use <appl>-<version> as /usr/local/, create if not existent.
-i <ip,..> Configure the jail in /etc/jail.conf with ip addresses <ip,...>
"
exit 1
}
jaildk_bootstrap( ) {
# combines base, create and build functions into a oneshot command
# to create a new jail
2021-07-05 14:26:10 +02:00
local jail BASE VERSION APPL PORTS IP loadbase RUN subdir port
2021-01-14 13:10:09 +01:00
jail = $1
shift
BASE = ''
VERSION = ''
APPL = ''
PORTS = ''
IP = ''
2022-02-16 12:22:13 +01:00
while getopts "i:b:v:p:a:" arg; do
2021-01-14 13:10:09 +01:00
case $arg in
b) BASE = ${ OPTARG } ; ;
v) VERSION = ${ OPTARG } ; ;
p) PORTS = ${ OPTARG } ; ;
a) APPL = ${ OPTARG } ; ;
2022-02-16 12:22:13 +01:00
i) IP = ${ OPTARG } ; ;
2021-01-14 13:10:09 +01:00
*) usage_bootstrap; ;
esac
done
if test -z " $jail " ; then
usage_bootstrap
fi
# if no base specified, use last existing one or create one if no
# base exists at all
if test -z " $BASE " ; then
lastbase = $( ls -1tr $j /base/ | grep -v build | tail -1)
if test -n " $lastbase " ; then
BASE = $lastbase
else
BASE = $( uname -r)
$( jaildk_base -b $BASE )
fi
else
if ! test -d " $j /base/ $BASE " ; then
# base specified but doesnt exist, so create
$( jaildk_base -b $BASE )
fi
fi
# version no specified
if test -z " $VERSION " ; then
VERSION = $( date +%Y%m%d)
fi
# creation
$( jaildk_create $jail )
# appl specified, do NOT clone but start empty IF it doesnt' exist yet
if test -n " $APPL " ; then
if ! test -d " $j /appl/ $APPL - $VERSION " ; then
for subdir in db/ports etc; do
ex mkdir -p $j /$APPL -$VERSION /$subdir
done
fi
# also fix mount.conf
echo " Setting appl to $APPL "
sed -iE " s|appl/.+-\$version|appl/ $APPL -\$version| " $j /etc/$jail /mount.conf
fi
# mount build
if test -n " $PORTS " ; then
2023-09-13 10:38:47 +02:00
jaildk_build $jail -m start -b $BASE -v $VERSION
2021-01-14 13:10:09 +01:00
echo "Installing ports"
for port in ` echo " $PORTS " | sed 's/,/ /g' ` ; do
chroot $j /build/$jail pkg install $port
done
fi
# install
2023-09-13 10:38:47 +02:00
jaildk_install $jail -m start
2021-01-14 13:10:09 +01:00
# run
RUN = ''
if egrep -q " ^ ${ jail } " /etc/jail.conf; then
RUN = 1
else
if test -n " $IP " ; then
echo " Adding $jail with ip addrs $IP to /etc/jail.conf "
( echo
echo " $jail { "
for addr in ` echo " $IP " | sed 's/,/ /g' ` ; do
if echo " $addr " | egrep -q :; then
echo " ip6.addr = \" $addr \"; "
else
echo " ip4.addr = \" $addr \"; "
fi
done
echo "}"
) >> /etc/jail.conf
RUN = 1
fi
fi
if test -n " $RUN " ; then
service jail start $jail
fi
}
2021-07-04 12:27:17 +02:00
mustberoot( ) {
if test " $( id -u ) " -ne 0; then
echo "Must run as root!" >& 2
exit 1
fi
}
2021-01-14 13:10:09 +01:00
2020-11-06 20:37:13 +01:00
##########################
#
# main()
# will be modified during installation
JAILDIR = /jail
2020-11-27 08:52:58 +01:00
# install modules
2021-07-05 14:26:10 +02:00
RCSCRIPTS_START = "rc_mount rc_ports rc_mtree rc_pf"
RCSCRIPTS_STOP = "rc_pf rc_mount rc_ports"
RW_RCSCRIPTS_START = "rc_mount rc_ports rc_mtree"
RW_RCSCRIPTS_STOP = "rc_mount rc_ports"
2020-11-27 08:52:58 +01:00
2020-11-06 20:37:13 +01:00
# globals
j = $JAILDIR
rcdir = $j /bin
runner = $1
shift
2020-11-27 19:08:57 +01:00
if test -z " $runner " ; then
usage_jaildk
fi
2020-11-06 20:37:13 +01:00
case $runner in
2021-07-04 12:27:17 +02:00
start| stop| restart)
2021-07-04 20:46:52 +02:00
# running jails
2021-07-04 12:27:17 +02:00
mustberoot
2020-11-06 20:37:13 +01:00
jaildk_jail $runner $*
; ;
2021-07-04 12:27:17 +02:00
status)
2021-07-04 20:46:52 +02:00
# same, w/o root
2021-07-04 12:27:17 +02:00
jaildk_jail status $*
; ;
login)
2021-07-04 20:46:52 +02:00
# login into jail as non root user allowed
# eventually calls sudo
2021-07-04 12:49:34 +02:00
jaildk_login $*
2021-07-04 12:27:17 +02:00
; ;
2023-09-13 10:38:47 +02:00
completion)
echo " $JAILDK_COMPLETION "
; ;
_get_rc_scripts)
get_rc_scripts $*
; ;
2020-11-06 20:37:13 +01:00
*)
2021-07-04 20:46:52 +02:00
# every other management command, if it exists
2021-07-05 14:26:10 +02:00
if type " jaildk_ $runner " 2>& 1 > /dev/null; then
2021-07-04 20:46:52 +02:00
mustberoot
jaildk_$runner $*
else
usage_jaildk $*
fi
2020-11-06 20:37:13 +01:00
; ;
esac
2023-09-13 10:38:47 +02:00