initial commit
This commit is contained in:
commit
597398a9db
|
|
@ -0,0 +1,555 @@
|
||||||
|
<style>
|
||||||
|
body { margin-left: 16px;
|
||||||
|
margin-right: 16px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: georgia;
|
||||||
|
}
|
||||||
|
tt { color: #444444; }
|
||||||
|
pre { color: #444444;
|
||||||
|
background: #eeeeee;
|
||||||
|
border-left: solid 5px #2222dd;
|
||||||
|
padding: 1px 1px 1px 7px; }
|
||||||
|
pre b, tt b { color: #2222dd; }
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<h1>FreeBSD ZFS Madness</h1>
|
||||||
|
<h3>Slawomir Wojtczak (vermaden)</h3>
|
||||||
|
<h4>2012/04/27</h4>
|
||||||
|
|
||||||
|
<p>Some time ago I found a good, reliable way of using and installing FreeBSD
|
||||||
|
and described it in my <i>Modern FreeBSD Install</i> <b>[1] [2]</b> HOWTO. Now, more
|
||||||
|
then a year later I come back with my experiences about that setup and a
|
||||||
|
proposal of newer and probably better way of doing it.</p>
|
||||||
|
|
||||||
|
<hr style="border: 1px solid lightgray">
|
||||||
|
|
||||||
|
<h3>1. Introduction</h3>
|
||||||
|
|
||||||
|
<p>Same as year ago, I assume that You would want to create fresh installation of
|
||||||
|
FreeBSD using one or more hard disks, but also with (laptops) and without GELI
|
||||||
|
based full disk encryption.</p>
|
||||||
|
|
||||||
|
<p>This guide was written when FreeBSD 9.0 and 8.3 were available and definitely
|
||||||
|
works for 9.0, but I did not try all this on the older 8.3, if You find some
|
||||||
|
issues on 8.3, let me know I will try to address them in this guide.</p>
|
||||||
|
|
||||||
|
<p>Earlier, I was not that confident about booting from the ZFS pool, but there
|
||||||
|
is some very neat feature that made me think ZFS boot is now mandatory. If You
|
||||||
|
just smiled, You know that I am thinking about <i>Boot Environments</i> feature
|
||||||
|
from Illumos/Solaris systems.</p> In case You are not familiar with the <i>Boot
|
||||||
|
Environments</i> feature, check the <i>Managing Boot Environments with Solaris
|
||||||
|
11 Express</i> PDF white paper <b>[3]</b>. Illumos/Solaris has the
|
||||||
|
<tt>beadm(1M)</tt> <b>[4]</b> utility and while Philipp Wuensche wrote the
|
||||||
|
<tt>manageBE</tt> script as replacement <b>[5]</b>, it uses older style used
|
||||||
|
at times when OpenSolaris (and SUN) were still having a great time.</p>
|
||||||
|
|
||||||
|
<p>I spent last couple of days writing an up-to-date replacement for FreeBSD
|
||||||
|
compatible <tt>beadm</tt> utility, and with some tweaks from today I just made
|
||||||
|
it available at <i>SourceForge</i> <b>[6]</b> if You wish to test it. Currently its
|
||||||
|
about 200 lines long, si it should be pretty simple to take a look at it. I
|
||||||
|
tried to make it as compatible as possible with the 'upstream' version, along
|
||||||
|
with some small improvements, it currently supports basic functions like list,
|
||||||
|
create, destroy and activate.</p>
|
||||||
|
|
||||||
|
<pre># <b>beadm</b>
|
||||||
|
usage:
|
||||||
|
beadm subcommand cmd_options
|
||||||
|
|
||||||
|
subcommands:
|
||||||
|
|
||||||
|
beadm activate beName
|
||||||
|
beadm create [-e nonActiveBe | beName@snapshot] beName
|
||||||
|
beadm create beName@snapshot
|
||||||
|
beadm destroy beName
|
||||||
|
beadm destroy beName@snapshot
|
||||||
|
beadm list</pre>
|
||||||
|
|
||||||
|
<p>There are several subtle differences between mine implementation and
|
||||||
|
Philipp's one, he defines and then relies upon ZFS property called
|
||||||
|
<tt>freebsd:boot-environment=1</tt> for each boot environment, I do not set
|
||||||
|
any other additional ZFS properties. There is already <tt>org.freebsd:swap</tt>
|
||||||
|
property used for SWAP on FreeBSD, so we may use <tt>org.freebsd:be</tt> in the
|
||||||
|
future, but is just a thought, right now its not used. My version also supports
|
||||||
|
activating boot environments received with <tt>zfs recv</tt> command from other
|
||||||
|
systems (it just updates appreciate <tt>/boot/zfs/zpool.cache</tt> file).</p>
|
||||||
|
My implementation is also style compatible with current Illumos/Solaris
|
||||||
|
<tt>beadm(1M)</tt> which is like the example below.</p>
|
||||||
|
|
||||||
|
<pre># <b>beadm create -e default upgrade-test</b>
|
||||||
|
Created successfully
|
||||||
|
|
||||||
|
# <b>beadm list</b>
|
||||||
|
BE Active Mountpoint Space Policy Created
|
||||||
|
default N / 1.06M static 2012-02-03 15:08
|
||||||
|
upgrade-test R - 560M static 2012-04-24 22:22
|
||||||
|
new - - 8K static 2012-04-24 23:40
|
||||||
|
|
||||||
|
# <b>zfs list -r sys/ROOT</b>
|
||||||
|
NAME USED AVAIL REFER MOUNTPOINT
|
||||||
|
sys/ROOT 562M 8.15G 144K none
|
||||||
|
sys/ROOT/default 1.48M 8.15G 558M legacy
|
||||||
|
sys/ROOT/new 8K 8.15G 558M none
|
||||||
|
sys/ROOT/upgrade-test 560M 8.15G 558M none
|
||||||
|
|
||||||
|
# <b>beadm activate default</b>
|
||||||
|
Activated successfully
|
||||||
|
|
||||||
|
# <b>beadm list</b>
|
||||||
|
BE Active Mountpoint Space Policy Created
|
||||||
|
default NR / 1.06M static 2012-02-03 15:08
|
||||||
|
upgrade-test - - 560M static 2012-04-24 22:22
|
||||||
|
new - - 8K static 2012-04-24 23:40</pre>
|
||||||
|
|
||||||
|
<p>The boot environments are located in the same plase as in Illumos/Solaris, at
|
||||||
|
<tt>pool/ROOT/environment</tt> place.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>2. Now You're Thinking with Portals</h3>
|
||||||
|
|
||||||
|
<p>The main purpose of the <i>Boot Environments</i> concept is to make all
|
||||||
|
risky tasks harmless, to provide an easy way back from possible troubles.
|
||||||
|
Think about upgrading the system to newer version, an update of 30+ installed
|
||||||
|
packages to latest versions, testing software or various solutions before
|
||||||
|
taking the final decision, and much more. All these tasks are now harmless
|
||||||
|
thanks to the <i>Boot Environments</i>, but this is just the tip of the
|
||||||
|
iceberg.</p>
|
||||||
|
|
||||||
|
<p>You can now move desired boot environment to other machine, physical or
|
||||||
|
virtual and check how it will behave there, check hardware support on the other
|
||||||
|
hardware for example or make a painless hardware upgrade. You may also clone
|
||||||
|
Your desired boot environment and ... start it as a Jail for some more
|
||||||
|
experiments or move Your old physical server install into FreeBSD Jail because
|
||||||
|
its not that heavily used anymore but it still have to be available.</p>
|
||||||
|
|
||||||
|
<p>Other good example may be just created server on Your laptop inside
|
||||||
|
VirtualBox virtual machine. After you finish the creation process and tests,
|
||||||
|
You may move this boot environment to the real server and put it into
|
||||||
|
production. Or even move it into VMware ESX/vSphere virtual machine and use
|
||||||
|
it there.</p>
|
||||||
|
|
||||||
|
<p>As You see the possibilities with <i>Boot Environments</i> are unlimited.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>3. The Install Process</h3>
|
||||||
|
|
||||||
|
<p>I created 3 possible schemas which should cover most demands, choose one
|
||||||
|
and continue to the next step.</p>
|
||||||
|
|
||||||
|
<h4>3.1. Server with Two Disks</h4>
|
||||||
|
|
||||||
|
<p>I assume that this server has 2 disks and we will create ZFS mirror across
|
||||||
|
them, so if any of them will be gone the system will still work as usual.
|
||||||
|
I also assume that these disks are <tt>ada0</tt> and <tt>ada1</tt>. If You
|
||||||
|
have SCSI/SAS drives there, they may be named <tt>da0</tt> and <tt>da1</tt>
|
||||||
|
accordingly. The <b>procedures below will wipe all data on these disks</b>,
|
||||||
|
You have been warned.</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Boot from the FreeBSD USB/DVD.</li>
|
||||||
|
<li>Select the '<tt>Live CD</tt>' option.</li>
|
||||||
|
<li><tt>login: root</tt></li>
|
||||||
|
<li><tt># sh</tt></li>
|
||||||
|
<li><tt># DISKS="<b>ada0 ada1</b>"</tt></li>
|
||||||
|
<li><tt># for I in ${DISKS}; do<br>
|
||||||
|
> NUMBER=$( echo ${I} | tr -c -d '0-9' )<br>
|
||||||
|
> gpart destroy -F ${I}<br>
|
||||||
|
> gpart create -s GPT ${I}<br>
|
||||||
|
> gpart add -t freebsd-boot -l bootcode${NUMBER} -s 128k ${I}<br>
|
||||||
|
> gpart add -t freebsd-zfs -l sys${NUMBER} ${I}<br>
|
||||||
|
> gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ${I}<br>
|
||||||
|
> done</tt></li>
|
||||||
|
<li><tt># zpool create -f -o cachefile=/tmp/zpool.cache sys mirror /dev/gpt/sys*</tt></li>
|
||||||
|
<li><tt># zfs set mountpoint=none sys</tt></li>
|
||||||
|
<li><tt># zfs set checksum=fletcher4 sys</tt></li>
|
||||||
|
<li><tt># zfs set atime=off sys</tt></li>
|
||||||
|
<li><tt># zfs create sys/ROOT</tt></li>
|
||||||
|
<li><tt># zfs create -o mountpoint=/mnt sys/ROOT/default</tt></li>
|
||||||
|
<li><tt># zpool set bootfs=sys/ROOT/default sys</tt></li>
|
||||||
|
<li><tt># cd /usr/freebsd-dist/</tt></li>
|
||||||
|
<li><tt># for I in base.txz kernel.txz; do<br>
|
||||||
|
> tar --unlink -xvpJf ${I} -C /mnt<br>
|
||||||
|
> done</tt></li>
|
||||||
|
<li><tt># cp /tmp/zpool.cache /mnt/boot/zfs/</tt></li>
|
||||||
|
<li><tt># cat << EOF >> /mnt/boot/loader.conf<br>
|
||||||
|
> zfs_load=YES<br>
|
||||||
|
> vfs.root.mountfrom="zfs:sys/ROOT/default"<br>
|
||||||
|
> EOF</tt></li>
|
||||||
|
<li><tt># cat << EOF >> /mnt/etc/rc.conf<br>
|
||||||
|
> zfs_enable=YES<br>
|
||||||
|
> EOF</tt></li>
|
||||||
|
<li><tt># :> /mnt/etc/fstab</tt></li>
|
||||||
|
<li><tt># zfs umount -a</tt></li>
|
||||||
|
<li><tt># zfs set mountpoint=legacy sys/ROOT/default</tt></li>
|
||||||
|
<li><tt># reboot</tt></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>After these instructions and reboot we have these GPT partitions available,
|
||||||
|
this example is on a 512MB disk.</p>
|
||||||
|
|
||||||
|
<pre># <b>gpart show</b>
|
||||||
|
=> 34 1048509 ada0 GPT (512M)
|
||||||
|
34 256 1 freebsd-boot (128k)
|
||||||
|
290 1048253 2 freebsd-zfs (511M)
|
||||||
|
|
||||||
|
=> 34 1048509 ada1 GPT (512M)
|
||||||
|
34 256 1 freebsd-boot (128k)
|
||||||
|
290 1048253 2 freebsd-zfs (511M)
|
||||||
|
|
||||||
|
# <b>gpart list | grep label</b>
|
||||||
|
label: bootcode0
|
||||||
|
label: sys0
|
||||||
|
label: bootcode1
|
||||||
|
label: sys1
|
||||||
|
|
||||||
|
# <b>zpool status</b>
|
||||||
|
pool: sys
|
||||||
|
state: ONLINE
|
||||||
|
scan: none requested
|
||||||
|
config:
|
||||||
|
|
||||||
|
NAME STATE READ WRITE CKSUM
|
||||||
|
sys ONLINE 0 0 0
|
||||||
|
mirror-0 ONLINE 0 0 0
|
||||||
|
gpt/sys0 ONLINE 0 0 0
|
||||||
|
gpt/sys1 ONLINE 0 0 0
|
||||||
|
|
||||||
|
errors: No known data errors</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4>3.2. Server with One Disk</h4>
|
||||||
|
|
||||||
|
<p>If Your server configuration has only one disk, lets assume its
|
||||||
|
<tt>ada0</tt>, then You need different points 5. and 7. to make, use these
|
||||||
|
instead of the ones above.</p>
|
||||||
|
|
||||||
|
<ol start="5">
|
||||||
|
<li><tt># DISKS="<b>ada0</b>"</tt></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<ol start="7">
|
||||||
|
<li><tt># zpool create -f -o cachefile=/tmp/zpool.cache sys /dev/gpt/sys*</tt></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>All other steps are the same.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4>3.3. Read Warrior Laptop</h4>
|
||||||
|
|
||||||
|
<p>The procedure is quite diffrent for Laptop because we will use the full disk
|
||||||
|
encryption mechanism provided by GELI and then setup the ZFS pool. Its not
|
||||||
|
currently possible to boot off from the ZFS pool on top of encrypted GELI
|
||||||
|
provider, so we will use setup similar to the <i>Server with ...</i> one but
|
||||||
|
with additional <tt>local</tt> pool for <tt>/home</tt> and <tt>/root</tt>
|
||||||
|
partitions. It will be password based and You will be asked to type-in that
|
||||||
|
password at every boot. The install process is generally the same with new
|
||||||
|
instructions added for the GELI encrypted <tt>local</tt> pool, I put them with
|
||||||
|
<b style="color:green">different color</b> to make the difference more visible.</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Boot from the FreeBSD USB/DVD.</li>
|
||||||
|
<li>Select the '<tt>Live CD</tt>' option.</li>
|
||||||
|
<li><tt>login: root</tt></li>
|
||||||
|
<li><tt># sh</tt></li>
|
||||||
|
<li><tt># DISKS="<b>ada0</b>"</tt></li>
|
||||||
|
<li><tt># for I in ${DISKS}; do<br>
|
||||||
|
> NUMBER=$( echo ${I} | tr -c -d '0-9' )<br>
|
||||||
|
> gpart destroy -F ${I}<br>
|
||||||
|
> gpart create -s GPT ${I}<br>
|
||||||
|
> gpart add -t freebsd-boot -l bootcode${NUMBER} -s 128k ${I}<br>
|
||||||
|
> gpart add -t freebsd-zfs -l sys${NUMBER} -s 10G ${I}<br>
|
||||||
|
> gpart add -t freebsd-zfs -l local${NUMBER} ${I}<br>
|
||||||
|
> gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ${I}<br>
|
||||||
|
> done</tt></li>
|
||||||
|
<li><tt># zpool create -f -o cachefile=/tmp/zpool.cache sys /dev/gpt/sys0</tt></li>
|
||||||
|
<li><tt># zfs set mountpoint=none sys</tt></li>
|
||||||
|
<li><tt># zfs set checksum=fletcher4 sys</tt></li>
|
||||||
|
<li><tt># zfs set atime=off sys</tt></li>
|
||||||
|
<li><tt># zfs create sys/ROOT</tt></li>
|
||||||
|
<li><tt># zfs create -o mountpoint=/mnt sys/ROOT/default</tt></li>
|
||||||
|
<li><tt># zpool set bootfs=sys/ROOT/default sys</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># geli init -b -s 4096 -e AES-CBC -l 128 /dev/gpt/local0</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># geli attach /dev/gpt/local0</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># zpool create -f -o cachefile=/tmp/zpool.cache local /dev/gpt/local0.eli</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># zfs set mountpoint=none local</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># zfs set checksum=fletcher4 local</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># zfs set atime=off local</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># zfs create local/home</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># zfs create -o mountpoint=/mnt/root local/root</tt></li>
|
||||||
|
<li><tt># cd /usr/freebsd-dist/</tt></li>
|
||||||
|
<li><tt># for I in base.txz kernel.txz; do<br>
|
||||||
|
> tar --unlink -xvpJf ${I} -C /mnt<br>
|
||||||
|
> done</tt></li>
|
||||||
|
<li><tt># cp /tmp/zpool.cache /mnt/boot/zfs/</tt></li>
|
||||||
|
<li><tt># cat << EOF >> /mnt/boot/loader.conf<br>
|
||||||
|
> zfs_load=YES<br>
|
||||||
|
<tt style="color:green;font-weight:bold">> geom_eli_load=YES</tt><br>
|
||||||
|
> vfs.root.mountfrom="zfs:sys/ROOT/default"<br>
|
||||||
|
> EOF</tt></li>
|
||||||
|
<li><tt># cat << EOF >> /mnt/etc/rc.conf<br>
|
||||||
|
> zfs_enable=YES<br>
|
||||||
|
> EOF</tt></li>
|
||||||
|
<li><tt># :> /mnt/etc/fstab</tt></li>
|
||||||
|
<li><tt># zfs umount -a</tt></li>
|
||||||
|
<li><tt># zfs set mountpoint=legacy sys/ROOT/default</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># zfs set mountpoint=/home local/home</tt></li>
|
||||||
|
<li><tt style="color:green;font-weight:bold"># zfs set mountpoint=/root local/root</tt></li>
|
||||||
|
<li><tt># reboot</tt></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>After these instructions and reboot we have these GPT partitions available,
|
||||||
|
this example is on a 4GB disk.</p>
|
||||||
|
|
||||||
|
<pre># <b>gpart show</b>
|
||||||
|
=> 34 8388541 ada0 GPT (4.0G)
|
||||||
|
34 256 1 freebsd-boot (128k)
|
||||||
|
290 2097152 2 freebsd-zfs (1.0G)
|
||||||
|
2097442 6291133 3 freebsd-zfs (3G)
|
||||||
|
|
||||||
|
# <b>gpart list | grep label</b>
|
||||||
|
label: bootcode0
|
||||||
|
label: sys0
|
||||||
|
label: local0
|
||||||
|
|
||||||
|
# <b>zpool status</b>
|
||||||
|
pool: local
|
||||||
|
state: ONLINE
|
||||||
|
scan: none requested
|
||||||
|
config:
|
||||||
|
|
||||||
|
NAME STATE READ WRITE CKSUM
|
||||||
|
sys ONLINE 0 0 0
|
||||||
|
gpt/local0.eli ONLINE 0 0 0
|
||||||
|
|
||||||
|
errors: No known data errors
|
||||||
|
|
||||||
|
pool: sys
|
||||||
|
state: ONLINE
|
||||||
|
scan: none requested
|
||||||
|
config:
|
||||||
|
|
||||||
|
NAME STATE READ WRITE CKSUM
|
||||||
|
sys ONLINE 0 0 0
|
||||||
|
gpt/sys0 ONLINE 0 0 0
|
||||||
|
|
||||||
|
errors: No known data errors</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>4. Basic Setup after Install</h3>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Login as <b>root</b> with empty password.</li>
|
||||||
|
<pre>login: <b>root</b>
|
||||||
|
password: <b>[ENTER]</b></pre>
|
||||||
|
|
||||||
|
<li>Create initial <b>snapshot</b> after install.</li>
|
||||||
|
<tt># zfs snapshot -r sys/ROOT/default@install</tt>
|
||||||
|
|
||||||
|
<li>Set new <b>root</b> password.</li>
|
||||||
|
<tt># passwd</tt>
|
||||||
|
|
||||||
|
<li>Set machine's <b>hostname</b>.</li>
|
||||||
|
<tt># echo hostname=hostname.domain.com >> /etc/rc.conf</tt>
|
||||||
|
|
||||||
|
<li>Set proper <b>timezone</b>.</li>
|
||||||
|
<tt># tzsetup</tt>
|
||||||
|
|
||||||
|
<li>Add some <b>swap</b> space.</li>
|
||||||
|
<p>If You used the <i>Server with ...</i> type, then use this to add swap.</p>
|
||||||
|
<pre># <b>zfs create -V 1G -o org.freebsd:swap=on \
|
||||||
|
-o checksum=off \
|
||||||
|
-o sync=disabled \
|
||||||
|
-o primarycache=none \
|
||||||
|
-o secondarycache=none sys/swap</b>
|
||||||
|
# <b>swapon /dev/zvol/sys/swap</b></pre>
|
||||||
|
<p>If You used the <i>Road Warrior Laptop</i> one, then use this one below,
|
||||||
|
this was the swap space will also be encrypted.</p>
|
||||||
|
<pre># <b>zfs create -V 1G -o org.freebsd:swap=on \
|
||||||
|
-o checksum=off \
|
||||||
|
-o sync=disabled \
|
||||||
|
-o primarycache=none \
|
||||||
|
-o secondarycache=none local/swap</b>
|
||||||
|
# <b>swapon /dev/zvol/local/swap</b></pre>
|
||||||
|
|
||||||
|
<li>Create <b>snapshot</b> called <tt>configured</tt> or <tt>production</tt></li>
|
||||||
|
<p>After You configured Your fresh FreeBSD system, added needed packages
|
||||||
|
and services, create <b>snapshot</b> called <tt>configured</tt> or
|
||||||
|
<tt>production</tt> so if You mess something, You can always go back in time
|
||||||
|
to bring working configuration back. mess something.</p>
|
||||||
|
<tt># zfs snapshot -r sys/ROOT/default@configured</tt>
|
||||||
|
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>5. Enable Boot Environments</h3>
|
||||||
|
|
||||||
|
<p>Here are some simple instructions on how to download and enable the
|
||||||
|
<tt>beadm</tt> command line utility for easy <i>Boot Environments</i>
|
||||||
|
administration. </p>
|
||||||
|
|
||||||
|
<pre># <b>fetch https://downloads.sourceforge.net/project/beadm/beadm -o /usr/sbin/beadm</b>
|
||||||
|
# <b>chmod +x /usr/sbin/beadm</b>
|
||||||
|
# <b>rehash</b>
|
||||||
|
# <b>beadm list</b>
|
||||||
|
BE Active Mountpoint Space Policy Created
|
||||||
|
default NR / 592M static 2012-04-25 02:03</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>6. WYSIWTF</h3>
|
||||||
|
|
||||||
|
<p>Now we have a working ZFS only FreeBSD system, I will put some example here
|
||||||
|
about what You now can do with this type of installation and of course the
|
||||||
|
<i>Boot Environments</i> feature.</p>
|
||||||
|
|
||||||
|
<h4>6.1. Create New Boot Environmnent Before Upgrade</h4>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Create new environment from the current one.</li>
|
||||||
|
<tt># beadm create upgrade</tt>
|
||||||
|
|
||||||
|
<li>Activate it.</li>
|
||||||
|
<tt># beadm activate upgrade</tt>
|
||||||
|
|
||||||
|
<li>Reboot into it.</li>
|
||||||
|
<tt># shutdown -r now</tt>
|
||||||
|
|
||||||
|
<li>Mess with it.</li>
|
||||||
|
<p>You are now free to do anything You like fo or the upgrade process,
|
||||||
|
but even if You break everything, You still have a working <tt>default</tt>
|
||||||
|
working environment.</p>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
<h4>6.2. Perform Upgrade within a Jail</h4>
|
||||||
|
|
||||||
|
<p>This concept is about creating new boot environment from the
|
||||||
|
desired one, lets call it <tt>jailed</tt>, then start that new environment
|
||||||
|
inside a FreeBSD Jail and perform upgrade there. After You have finished all
|
||||||
|
tasks related to this upgrade and You are satisfied with the achieved results,
|
||||||
|
shutdown that Jail, set the boot environment into that just upgraded Jail
|
||||||
|
called <tt>jailed</tt> and reboot into just upgraded system without any
|
||||||
|
risks.</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Create new boot environment called <tt>jailed</tt>.</li>
|
||||||
|
<pre># <b>beadm create -e default jailed</b>
|
||||||
|
Created successfully</pre>
|
||||||
|
|
||||||
|
<li>Create <tt>/usr/jails</tt> directory.</li>
|
||||||
|
<tt># <b>mkdir /usr/jails</b></tt>
|
||||||
|
|
||||||
|
<li>Set mount point of new boot environment to <tt>/usr/jails/jailed</tt> dir.</li>
|
||||||
|
<tt># <b>zfs set mountpoint=/usr/jails/jailed sys/ROOT/jailed</b></tt>
|
||||||
|
|
||||||
|
<li>Enable FreeBSD Jails mechanism and the <tt>jailed</tt> Jail in
|
||||||
|
<tt>/etc/rc.conf</tt> file.</li>
|
||||||
|
<tt># <b>cat << EOF >> /etc/rc.conf</b><br>
|
||||||
|
> <b>jail_enable=YES</b><br>
|
||||||
|
> <b>jail_list="jailed"</b><br>
|
||||||
|
> <b>jail_jailed_rootdir="/usr/jails/jailed"</b><br>
|
||||||
|
> <b>jail_jailed_hostname="jailed"</b><br>
|
||||||
|
> <b>jail_jailed_ip="10.20.30.40"</b><br>
|
||||||
|
> <b>jail_jailed_devfs_enable="YES"</b><br>
|
||||||
|
> <b>EOF</b></tt>
|
||||||
|
|
||||||
|
<li>Start the Jails mechanism.</li>
|
||||||
|
<pre># <b>/etc/rc.d/jail start</b>
|
||||||
|
Configuring jails:.
|
||||||
|
Starting jails: jailed.</pre>
|
||||||
|
|
||||||
|
<li>Check if the <tt>jailed</tt> Jail started.</li>
|
||||||
|
<pre># <b>jls</b>
|
||||||
|
JID IP Address Hostname Path
|
||||||
|
1 10.20.30.40 jailed /usr/jails/jailed</pre>
|
||||||
|
|
||||||
|
<li>Login into the <tt>jailed</tt> Jail.</li>
|
||||||
|
<tt># <b>jexec 1 tcsh</b></tt>
|
||||||
|
|
||||||
|
<li><b>PERFORM ACTUAL UPGRADE.</b></li>
|
||||||
|
|
||||||
|
<li>Stop the <tt>jailed</tt> Jail.</li>
|
||||||
|
<pre># <b>/etc/rc.d/jail stop</b>
|
||||||
|
Stopping jails: jailed.</pre>
|
||||||
|
|
||||||
|
<li>Disable Jails mechanism in <tt>/etc/rc.conf</tt> file.</li>
|
||||||
|
<tt># <b>sed -i '' -E s/"^jail_enable.*$"/"jail_enable=NO"/g /etc/rc.conf</b></tt>
|
||||||
|
|
||||||
|
<li>Activate just upgraded <tt>jailed</tt> boot environment.</li>
|
||||||
|
<pre># <b>bootfs-beadm activate jailed</b>
|
||||||
|
Activated successfully</pre>
|
||||||
|
|
||||||
|
<li>Restart the system into upgraded system.</li>
|
||||||
|
<tt># <b>shutdown -r now</b></tt>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
<h4>6.3. Import Boot Environmnent from Other Machine</h4>
|
||||||
|
|
||||||
|
<p>Lets assume, that You need to upgrade or do some major modification to
|
||||||
|
some of Your servers, You will then create new boot environment from the
|
||||||
|
default one, move it to other 'free' machine, perform these tasks there
|
||||||
|
and after everything is done, move the modified boot environment to the
|
||||||
|
production without any risks. You may as well trasnport that environment
|
||||||
|
into You laptop/workstation and upgrade it in a Jail like in step 6.2 of
|
||||||
|
this guide.</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>Create new environment on the <i>production</i> server.</li>
|
||||||
|
<pre># <b>beadm create upgrade</b>
|
||||||
|
Created successfully.</pre>
|
||||||
|
|
||||||
|
<li>Send the <tt>upgrade</tt> environment to <i>test</i> server.</li>
|
||||||
|
<tt># <b>zfs send sys/ROOT/upgrade | ssh TEST zfs recv -u sys/ROOT/upgrade</b></tt>
|
||||||
|
|
||||||
|
<li>Activate the <tt>upgrade</tt> environment on the <i>test</i> server.</li>
|
||||||
|
<pre># <b>beadm activate upgrade</b>
|
||||||
|
Activated successfully.</pre>
|
||||||
|
|
||||||
|
<li>Reboot into the <tt>upgrade</tt> environment on the <i>test</i> server.</li>
|
||||||
|
<tt># <b>shutdown -r now</b></tt>
|
||||||
|
|
||||||
|
<li><b>PERFORM ACTUAL UPGRADE AFTER REBOOT.</b></li>
|
||||||
|
|
||||||
|
<li>Sent the upgraded <tt>upgrade</tt> environment onto <i>production</i> server.</li>
|
||||||
|
<tt># <b>zfs send sys/ROOT/upgrade | ssh PRODUCTION zfs recv -u sys/ROOT/upgrade</b></tt>
|
||||||
|
|
||||||
|
<li>Activate upgraded <tt>upgrade</tt> environment on the <i>production</i> server.</li>
|
||||||
|
<pre># <b>beadm activate upgrade</b>
|
||||||
|
Activated successfully.</pre>
|
||||||
|
|
||||||
|
<li>Reboot into the <tt>upgrade</tt> environment on the <i>production</i> server.</li>
|
||||||
|
<tt># <b>shutdown -r now</b></tt>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h3>7. References</h3>
|
||||||
|
<ul>
|
||||||
|
<li><b><tt>[1]</tt></b> <a style="color:blue">http://forums.freebsd.org/showthread.php?t=10334</a></li>
|
||||||
|
<li><b><tt>[2]</tt></b> <a style="color:blue">http://forums.freebsd.org/showthread.php?t=12082</a></li>
|
||||||
|
<li><b><tt>[3]</tt></b> <a style="color:blue">http://docs.oracle.com/cd/E19963-01/pdf/820-6565.pdf</a></li>
|
||||||
|
<li><b><tt>[4]</tt></b> <a style="color:blue">http://docs.oracle.com/cd/E19963-01/html/821-1462/beadm-1m.html</a></li>
|
||||||
|
<li><b><tt>[5]</tt></b> <a style="color:blue">http://anonsvn.h3q.com/projects/freebsd-patches/wiki/manageBE</a></li>
|
||||||
|
<li><b><tt>[6]</tt></b> <a style="color:blue">https://sourceforge.net/projects/beadm/</a></li>
|
||||||
|
</ul>
|
||||||
|
</tt>
|
||||||
|
|
||||||
|
<p>The last part of the HOWTO remains the same as Year ago ...</p>
|
||||||
|
|
||||||
|
<p>You can now add your users, services and packages as usual on any FreeBSD system, have fun ;)</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
@ -0,0 +1,215 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Copyright (c) 2012 Slawomir Wojciech Wojtczak (vermaden)
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that following conditions are met:
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS 'AS IS' AND ANY
|
||||||
|
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
unset LC_ALL
|
||||||
|
unset LANG
|
||||||
|
PATH=${PATH}:/bin:/usr/bin:/sbin:/usr/sbin
|
||||||
|
|
||||||
|
[ $( uname -r | cut -d '.' -f1 ) -lt 8 ] \
|
||||||
|
&& echo "ERROR: beadm only works on FreeBSD 8.0 or later."
|
||||||
|
|
||||||
|
__usage() {
|
||||||
|
NAME=${0##*/}
|
||||||
|
echo "usage:"
|
||||||
|
echo " ${NAME} subcommand cmd_options"
|
||||||
|
echo
|
||||||
|
echo " subcommands:"
|
||||||
|
echo
|
||||||
|
echo " ${NAME} activate beName"
|
||||||
|
echo " ${NAME} create [-e nonActiveBe | beName@snapshot] beName"
|
||||||
|
echo " ${NAME} create beName@snapshot"
|
||||||
|
echo " ${NAME} destroy beName"
|
||||||
|
echo " ${NAME} destroy beName@snapshot"
|
||||||
|
echo " ${NAME} list"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
__be_exist() { # 1=DATASET
|
||||||
|
zfs list -H -o name ${1} 1> /dev/null 2> /dev/null || {
|
||||||
|
echo "ERROR: Boot environment '${1##*/}' does not exist"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__be_snapshot() { # 1=DATASET/SNAPSHOT
|
||||||
|
echo "${1}" | grep -q "@"
|
||||||
|
}
|
||||||
|
|
||||||
|
__be_new() { # 1=SOURCE 2=TARGET
|
||||||
|
__be_snapshot && {
|
||||||
|
zfs clone ${1} ${2}
|
||||||
|
} || {
|
||||||
|
zfs list -H -o name ${1}@${2##*/} 1> /dev/null 2> /dev/null && {
|
||||||
|
echo "ERROR: Snapshot '${1}@${2##*/}' exists"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
zfs snapshot -r ${1}@${2##*/} 1> /dev/null 2> /dev/null || {
|
||||||
|
echo "ERROR: Cannot create snapshot '${1}@${2##*/}'"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
zfs clone ${1}@${2##*/} ${2}
|
||||||
|
}
|
||||||
|
BASENAME=${1##*/}
|
||||||
|
zfs list -H -o name -t filesystem -r ${1} \
|
||||||
|
| grep -v -E "${1}$" \
|
||||||
|
| while read I
|
||||||
|
do
|
||||||
|
DATASET=$( echo ${I} | sed s/"${POOL}\/ROOT\/${BASENAME}\/"//g )
|
||||||
|
zfs clone ${I}@${2##*/} ${2}/${DATASET}
|
||||||
|
done
|
||||||
|
echo "Created successfully"
|
||||||
|
}
|
||||||
|
|
||||||
|
ROOTFS=$( mount | awk '/ \/ / {print $1}' )
|
||||||
|
echo ${ROOTFS} | grep -q -E "^/dev/" && {
|
||||||
|
echo "ERROR: This system does not boot from ZFS pool"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
POOL=$( echo ${ROOTFS} | awk -F '/' '{print $1}' )
|
||||||
|
BOOTFS=$( zpool list -H -o bootfs ${POOL} )
|
||||||
|
|
||||||
|
case ${1} in
|
||||||
|
(list) # --------------------------------------------------------------------
|
||||||
|
POOL_PREFIX="${POOL}/ROOT"
|
||||||
|
LIST=$( zfs list -o name,used,mountpoint,creation -s creation -H -d 1 -r ${POOL}/ROOT | grep -E "^${POOL}/ROOT/" )
|
||||||
|
WIDTH_CREATION=$( echo "${LIST}" | awk '{print $5}' | wc -L )
|
||||||
|
WIDTH_NAME=$( echo "${LIST}" | awk '{print $1}' | wc -L )
|
||||||
|
WIDTH_NAME=$(( ${WIDTH_NAME} - ${#POOL_PREFIX} - 1 ))
|
||||||
|
printf "%-${WIDTH_NAME}s %-6s %-10s %5s %6s %s\n" \
|
||||||
|
BE Active Mountpoint Space Policy Created
|
||||||
|
echo "${LIST}" \
|
||||||
|
| while read NAME USED MOUNTPOINT C R E A T
|
||||||
|
do
|
||||||
|
NAME=${NAME##*/}
|
||||||
|
unset ACTIVE
|
||||||
|
[ "${POOL_PREFIX}/${NAME}" = "${ROOTFS}" ] && ACTIVE="${ACTIVE}N"
|
||||||
|
[ "${POOL_PREFIX}/${NAME}" = "${BOOTFS}" ] && ACTIVE="${ACTIVE}R"
|
||||||
|
[ -z "${ACTIVE}" ] && ACTIVE="-"
|
||||||
|
printf "%-${WIDTH_NAME}s %-6s " ${NAME} ${ACTIVE}
|
||||||
|
case ${ACTIVE} in
|
||||||
|
(N|NR) MOUNT="/" ;;
|
||||||
|
(*) MOUNT="-" ;;
|
||||||
|
esac
|
||||||
|
printf "%-10s %5s %-6s " ${MOUNT} ${USED} "static"
|
||||||
|
date -j -f "%a %b %d %H:%M %Y" "${C} ${R} ${E} ${A} ${T}" +"%Y-%m-%d %H:%M"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
(create) # ------------------------------------------------------------------
|
||||||
|
case ${#} in
|
||||||
|
(4)
|
||||||
|
[ ${2} = "-e" ] || __usage
|
||||||
|
__be_exist ${POOL}/ROOT/${3}
|
||||||
|
zfs list -H -o name ${POOL}/ROOT/${4} 2> /dev/null && {
|
||||||
|
echo "ERROR: Boot environment '${4}' already exists"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
__be_new ${POOL}/ROOT/${3} ${POOL}/ROOT/${4}
|
||||||
|
;;
|
||||||
|
(2)
|
||||||
|
__be_snapshot ${2} && {
|
||||||
|
zfs snapshot ${POOL}/ROOT/${2} 2> /dev/null || {
|
||||||
|
echo "ERROR: Cannot create '${2}' snapshot"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
echo "Created successfully"
|
||||||
|
} || {
|
||||||
|
__be_new ${ROOTFS} ${POOL}/ROOT/${2}
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
__usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
(activate) # ----------------------------------------------------------------
|
||||||
|
[ "${BOOTFS}" = "${POOL}/ROOT/${2}" ] || {
|
||||||
|
[ "${ROOTFS}" = "${POOL}/ROOT/${2}" ] || {
|
||||||
|
MNT="/tmp/BE"
|
||||||
|
mkdir -p ${MNT} || {
|
||||||
|
echo "ERROR: Cannot create '${MNT}' directory"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
zfs set mountpoint=${MNT} ${POOL}/ROOT/${2}
|
||||||
|
cp /boot/zfs/zpool.cache ${MNT}/boot/zfs/zpool.cache
|
||||||
|
sed -i '' -E s/"^vfs.root.mountfrom=.*$"/"vfs.root.mountfrom=\"zfs:${POOL}\/ROOT\/${2##*/}\""/g ${MNT}/boot/loader.conf
|
||||||
|
zfs set mountpoint=legacy ${POOL}/ROOT/${2}
|
||||||
|
}
|
||||||
|
zpool set bootfs=${POOL}/ROOT/${2} ${POOL} && {
|
||||||
|
} || {
|
||||||
|
echo "ERROR: Failed to activate '${POOL}/ROOT/${2}'"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zfs list -H -o name -t filesystem -r ${POOL}/ROOT/${2} \
|
||||||
|
| while read I
|
||||||
|
do
|
||||||
|
zfs promote ${POOL}/ROOT/${2} 2> /dev/null
|
||||||
|
done
|
||||||
|
echo "Activated successfully"
|
||||||
|
;;
|
||||||
|
(destroy) # ----------------------------------------------------------------
|
||||||
|
__be_exist ${POOL}/ROOT/${2}
|
||||||
|
[ "${BOOTFS}" = "${POOL}/ROOT/${2}" ] && {
|
||||||
|
echo "ERROR: '${POOL}/ROOT/${2}' is current active boot environment"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
echo "Are you sure you want to destroy '${2}'?"
|
||||||
|
echo -n "This action cannot be undone (y/[n]): "
|
||||||
|
read CHOICE
|
||||||
|
case ${CHOICE} in
|
||||||
|
(Y|y|[Yy][Ee][Ss])
|
||||||
|
__be_snapshot ${POOL}/ROOT/${2} && {
|
||||||
|
zfs destroy ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null || {
|
||||||
|
echo "ERROR: Snapshot '${2}' is origin for other boot environment(s)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
} || {
|
||||||
|
ORIGINS=$( zfs list -r -H -o origin ${POOL}/ROOT/${2} )
|
||||||
|
zfs destroy ${POOL}/ROOT/${2} 1> /dev/null 2> /dev/null || {
|
||||||
|
zfs destroy -r ${POOL}/ROOT/${2} 2>&1 \
|
||||||
|
| grep "${POOL}/ROOT/" \
|
||||||
|
| grep -v "@" \
|
||||||
|
| while read I
|
||||||
|
do
|
||||||
|
zfs promote ${I} 2> /dev/null
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "${ORIGINS}" \
|
||||||
|
| while read I
|
||||||
|
do
|
||||||
|
zfs destroy -r ${I} 2> /dev/null
|
||||||
|
done
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "Destroyed successfully"
|
||||||
|
;;
|
||||||
|
(*)
|
||||||
|
echo "'${2}' has not been destroyed"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
(*) # -----------------------------------------------------------------------
|
||||||
|
__usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Loading…
Reference in New Issue