comparison sbin/fjail @ 177:9ffbe53dbc35

Flag for creating a separatate dataset for freebsd-update data. By default this is not needed in jails.
author Franz Glasner <hg@dom66.de>
date Tue, 16 Aug 2022 11:44:56 +0200
parents cf0a91fde79c
children 00fbf2b4b44f
comparison
equal deleted inserted replaced
176:cf0a91fde79c 177:9ffbe53dbc35
32 32
33 Create ZFS datasets to be used within a jail 33 Create ZFS datasets to be used within a jail
34 34
35 PARENT must exist already and CHILD must not exist. 35 PARENT must exist already and CHILD must not exist.
36 36
37 -s Also create a dataset for freebsd-update data files
37 -u Do not automatically mount newly created datasets 38 -u Do not automatically mount newly created datasets
38 39
39 privs MOUNTPOINT 40 privs MOUNTPOINT
40 41
41 Adjust some Unix privileges to mounted jail datasets 42 Adjust some Unix privileges to mounted jail datasets
119 local _pds _cds 120 local _pds _cds
120 # and its mount point 121 # and its mount point
121 local _pmp _get _dummy 122 local _pmp _get _dummy
122 # full name of the dataset 123 # full name of the dataset
123 local _ds 124 local _ds
125 # dynamic ZFS options -- create cache for freebsd-update
126 local _zfsopts _fbsdupdate
127
128 _zfsopts=""
129 _fbsdupdate=""
130 while getopts "us" _opt ; do
131 case ${_opt} in
132 u)
133 # do not mount newly created datasets
134 _zfsopts="${_zfsopts} -u"
135 ;;
136 s)
137 # create also a dataset for freebsd-update data
138 _fbsdupdate="yes"
139 \?|:)
140 return 2;
141 ;;
142 esac
143 done
144 shift $((OPTIND-1))
145 OPTIND=1
146
147 _pds="$1"
148 if [ -z "${_pds}" ]; then
149 echo "ERROR: no parent dataset given" >&2
150 return 2
151 fi
152 _get=$(zfs get -H mountpoint "${_pds}" 2>/dev/null) || { echo "ERROR: dataset \`${_pds}' does not exist" >&2; return 1; }
153 IFS=$'\t' read _dummy _dummy _pmp _dummy <<EOF
154 ${_get}
155 EOF
156 case "${_pmp}" in
157 none)
158 echo "ERROR: dataset \`${_pds}' has no mountpoint" >&2
159 return 1
160 ;;
161 legacy)
162 echo "ERROR: dataset \`${_pds}' has a \`${_mp}' mountpoint" >&2
163 return 1
164 ;;
165 *)
166 # VOID
167 ;;
168 esac
169 _cds="$2"
170 if [ -z "${_cds}" ]; then
171 echo "ERROR: no child dataset given" >&2
172 return 2
173 fi
174 _ds="${_pds}/${_cds}"
175 echo "Resulting new root dataset is \`${_ds}' at mountpoint \`${_pmp}/${_cds}'"
176 if zfs get -H mountpoint "${_ds}" >/dev/null 2>/dev/null; then
177 echo "ERROR: dataset \`${_ds}' does already exist" >&2
178 return 1
179 fi
180 zfs create ${_zfsopts} -o atime=off "${_ds}"
181 zfs create ${_zfsopts} -o sync=disabled -o setuid=off "${_ds}/tmp"
182 zfs create ${_zfsopts} "${_ds}/usr"
183 zfs create ${_zfsopts} -o setuid=off "${_ds}/usr/home"
184 zfs create ${_zfsopts} "${_ds}/usr/local"
185 zfs create ${_zfsopts} "${_ds}/var"
186 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/audit"
187 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/cache"
188 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata -o compression=off "${_ds}/var/cache/pkg"
189 zfs create ${_zfsopts} -o exec=off -o setuid=off -o compression=off "${_ds}/var/crash"
190 if [ "$_fbsdupdate" = "yes" ]; then
191 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata -o compression=off "${_ds}/var/db/freebsd-update"
192 fi
193 zfs create ${_zfsopts} -o readonly=on -o exec=off -o setuid=off "${_ds}/var/empty"
194 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata "${_ds}/var/log"
195 zfs create ${_zfsopts} -o exec=off -o setuid=off -o atime=on "${_ds}/var/mail"
196 zfs create ${_zfsopts} -o sync=disabled -o exec=off -o setuid=off -o compression=off -o primarycache=all "${_ds}/var/run"
197 zfs create ${_zfsopts} -o sync=disabled -o setuid=off "${_ds}/var/tmp"
198 }
199
200
201 #
202 # "populate" -- populate the datasets with content from a FreeBSD base.txz
203 #
204 # command_populate mountpoint basetxz
205 #
206 command_populate() {
207 # MOUNTPOINT -- base.txz
208 local _mp _basetxz
209
210 _mp="$1"
211 _basetxz="$2"
212
213 if [ -z "${_mp}" ]; then
214 echo "ERROR: no mountpoint given" >&2
215 return 2
216 fi
217 if [ -z "${_basetxz}" ]; then
218 echo "ERROR: no base.txz given" >&2
219 return 2
220 fi
221 if [ ! -d "${_mp}" ]; then
222 echo "ERROR: mountpoint \`${_mp}' does not exist" >&2
223 return 1
224 fi
225 if [ ! -r "${_basetxz}" ]; then
226 echo "ERROR: file \`${_basetxz}' is not readable" >&2
227 return 1
228 fi
229
230 #
231 # Handle /var/empty separately later: could be already there and
232 # mounted read-only.
233 #
234 tar -C "${_mp}" --exclude=./var/empty -xJp -f "${_basetxz}" || { echo "ERROR: tar encountered errors" >&2; return 1; }
235 if [ -d "${_mp}/var/empty" ]; then
236 #
237 # If /var/empty exists already try to extract with changing the
238 # flags (e.g. `schg'). But be tolerant with errors here.
239 #
240 tar -C "${_mp}" -xJp -f "${_basetxz}" ./var/empty
241 else
242 # Just extract /var/empty normally
243 tar -C "${_mp}" -xJp -f "${_basetxz}" ./var/empty || { echo "ERROR: tar encountered errors" >&2; return 1; }
244 fi
245
246 find "${_mp}/boot" -type f -delete
247 }
248
249
250 #
251 # "copy" -- ZFS copy of datasets
252 #
253 # command_copy source-dataset destination-dataset
254 #
255 command_copy() {
256 # source dataset -- destination dataset
257 local _source _dest
124 # dynamic ZFS options 258 # dynamic ZFS options
125 local _zfsopts 259 local _zfsopts
126 260
127 _zfsopts="" 261 _zfsopts=""
128 while getopts "u" _opt ; do 262 while getopts "u" _opt ; do
137 esac 271 esac
138 done 272 done
139 shift $((OPTIND-1)) 273 shift $((OPTIND-1))
140 OPTIND=1 274 OPTIND=1
141 275
142 _pds="$1"
143 if [ -z "${_pds}" ]; then
144 echo "ERROR: no parent dataset given" >&2
145 return 2
146 fi
147 _get=$(zfs get -H mountpoint "${_pds}" 2>/dev/null) || { echo "ERROR: dataset \`${_pds}' does not exist" >&2; return 1; }
148 IFS=$'\t' read _dummy _dummy _pmp _dummy <<EOF
149 ${_get}
150 EOF
151 case "${_pmp}" in
152 none)
153 echo "ERROR: dataset \`${_pds}' has no mountpoint" >&2
154 return 1
155 ;;
156 legacy)
157 echo "ERROR: dataset \`${_pds}' has a \`${_mp}' mountpoint" >&2
158 return 1
159 ;;
160 *)
161 # VOID
162 ;;
163 esac
164 _cds="$2"
165 if [ -z "${_cds}" ]; then
166 echo "ERROR: no child dataset given" >&2
167 return 2
168 fi
169 _ds="${_pds}/${_cds}"
170 echo "Resulting new root dataset is \`${_ds}' at mountpoint \`${_pmp}/${_cds}'"
171 if zfs get -H mountpoint "${_ds}" >/dev/null 2>/dev/null; then
172 echo "ERROR: dataset \`${_ds}' does already exist" >&2
173 return 1
174 fi
175 zfs create ${_zfsopts} -o atime=off "${_ds}"
176 zfs create ${_zfsopts} -o sync=disabled -o setuid=off "${_ds}/tmp"
177 zfs create ${_zfsopts} "${_ds}/usr"
178 zfs create ${_zfsopts} -o setuid=off "${_ds}/usr/home"
179 zfs create ${_zfsopts} "${_ds}/usr/local"
180 zfs create ${_zfsopts} "${_ds}/var"
181 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/audit"
182 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/cache"
183 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata -o compression=off "${_ds}/var/cache/pkg"
184 zfs create ${_zfsopts} -o exec=off -o setuid=off -o compression=off "${_ds}/var/crash"
185 zfs create ${_zfsopts} -o exec=off -o setuid=off "${_ds}/var/db"
186 zfs create ${_zfsopts} -o readonly=on -o exec=off -o setuid=off "${_ds}/var/empty"
187 zfs create ${_zfsopts} -o exec=off -o setuid=off -o primarycache=metadata "${_ds}/var/log"
188 zfs create ${_zfsopts} -o exec=off -o setuid=off -o atime=on "${_ds}/var/mail"
189 zfs create ${_zfsopts} -o sync=disabled -o exec=off -o setuid=off -o compression=off -o primarycache=all "${_ds}/var/run"
190 zfs create ${_zfsopts} -o sync=disabled -o setuid=off "${_ds}/var/tmp"
191 }
192
193
194 #
195 # "populate" -- populate the datasets with content from a FreeBSD base.txz
196 #
197 # command_populate mountpoint basetxz
198 #
199 command_populate() {
200 # MOUNTPOINT -- base.txz
201 local _mp _basetxz
202
203 _mp="$1"
204 _basetxz="$2"
205
206 if [ -z "${_mp}" ]; then
207 echo "ERROR: no mountpoint given" >&2
208 return 2
209 fi
210 if [ -z "${_basetxz}" ]; then
211 echo "ERROR: no base.txz given" >&2
212 return 2
213 fi
214 if [ ! -d "${_mp}" ]; then
215 echo "ERROR: mountpoint \`${_mp}' does not exist" >&2
216 return 1
217 fi
218 if [ ! -r "${_basetxz}" ]; then
219 echo "ERROR: file \`${_basetxz}' is not readable" >&2
220 return 1
221 fi
222
223 #
224 # Handle /var/empty separately later: could be already there and
225 # mounted read-only.
226 #
227 tar -C "${_mp}" --exclude=./var/empty -xJp -f "${_basetxz}" || { echo "ERROR: tar encountered errors" >&2; return 1; }
228 if [ -d "${_mp}/var/empty" ]; then
229 #
230 # If /var/empty exists already try to extract with changing the
231 # flags (e.g. `schg'). But be tolerant with errors here.
232 #
233 tar -C "${_mp}" -xJp -f "${_basetxz}" ./var/empty
234 else
235 # Just extract /var/empty normally
236 tar -C "${_mp}" -xJp -f "${_basetxz}" ./var/empty || { echo "ERROR: tar encountered errors" >&2; return 1; }
237 fi
238
239 find "${_mp}/boot" -type f -delete
240 }
241
242
243 #
244 # "copy" -- ZFS copy of datasets
245 #
246 # command_copy source-dataset destination-dataset
247 #
248 command_copy() {
249 # source dataset -- destination dataset
250 local _source _dest
251 # dynamic ZFS options
252 local _zfsopts
253
254 _zfsopts=""
255 while getopts "u" _opt ; do
256 case ${_opt} in
257 u)
258 # do not mount newly created datasets
259 _zfsopts="${_zfsopts} -u"
260 ;;
261 \?|:)
262 return 2;
263 ;;
264 esac
265 done
266 shift $((OPTIND-1))
267 OPTIND=1
268
269 _source="$1" 276 _source="$1"
270 if [ -z "${_source}" ]; then 277 if [ -z "${_source}" ]; then
271 echo "ERROR: no source dataset given" >&2 278 echo "ERROR: no source dataset given" >&2
272 return 2 279 return 2
273 fi 280 fi