HOWTO: “Blind” remote install of FreeB­SD via tiny disk image

In this post I write how to install FreeB­SD on a remote lin­ux sys­tem by cre­at­ing a root image pre­pared for mir­ror­ing on a local sys­tem. There is no (free) access to the remote con­sole, only access via ssh.

In this post I write how to install FreeB­SD on a remote lin­ux sys­tem by cre­at­ing a root image pre­pared for mir­ror­ing on a local sys­tem. There is no (free) access to the remote con­sole, only access via ssh.

Back­ground story

While I was at the uni­ver­si­ty, I worked remote­ly for an ISP (admin­is­tra­tion of sev­er­al FreeB­SD sys­tems). Dur­ing this time I start­ed to use my own domain, and I was allowed to host it direct­ly at the ISP for free. I tried to not use too much space on the hard­disk (at the end about 400 MB) and to not pro­vide some­thing which attract­ed too much peo­ple to keep the band­with on a sane lev­el. After the uni­ver­si­ty I was still avail­able to answer ques­tions, and I was still allowed to host my web­site there for free. As the num­ber of ques­tions can be count­ed with IIRC one hand since then, I decid­ed at some point (recent­ly, to be exact – bet­ter late than nev­er) to move my web­site to a dif­fer­ent place (I am still avail­able if they have some ques­tions – for free – but I do not expect to get much ques­tions from them).

At the same time my broth­er decid­ed to move to a new serv­er hoster, as his old one decid­ed to increase the amount of mon­ey cus­tomers have to pay for the ser­vice. So we searched togeth­er a new ISP where he either could host his serv­er, or get a root­serv­er for a good price (the idea was to have my domain in a jail on a serv­er of the com­pa­ny of my broth­er, and we share the costs for it). We found Man­i­tu (the own­er has even a blog about his busi­ness), which is even not far away from my place.

Unfor­tu­nate­ly they do not pro­vide FreeB­SD pre­in­stalled on their root­servers, but they offer a remote res­cue sys­tem (read: boot­ing a lin­ux image… I assume via PXE or sim­i­lar) and we knew some­one who has some servers there, so I was able to get a rough idea what kind of hard­ware is used there (the hard facts like PCI IDs and such). The idea was to build a very small disk image, put it on the hard­disk over the net­work via the remote res­cue sys­tem, and then to con­fig­ure the remain­der of the harddisk(s) to use it. And here is how I did it (my broth­er thought “who is bet­ter suit­ed to install a FreeB­SD sys­tem remote­ly with­out access to the con­sole of the machine (the ISP offers to hook up a KVM switch, but only dur­ing busi­ness hours and you have to pay for it) than one of the devel­op­ers of FreeBSD…”).

HOWTO

In the title of this post I wrote “via a tiny disk image”. This is true for a suit­able def­i­n­i­tion of tiny.

What we have in the root­serv­er are two 160 GB hard­disks. They shall be used in a soft­ware mir­ror (via gmir­ror). The root-FS shall have about 5 GB. This is more than need­ed, but as this is only 3% of one hard­disk, I pre­fer to keep it a lit­tle bit big­ger than too small after an remote update or two. The machine has 2 GB of RAM. We do not expect much ker­nel pan­ics (= crash dumps) there, so we do not real­ly need >2 GB of swap (for­get the rule of hav­ing twice as much swap than RAM, with the cur­rent amount of RAM in a machine you are in “trou­ble” when you need even the same amount of swap than RAM). I decid­ed to go with 1 GB of swap (mir­rored too, to pre­vent a hard­disk fail­ure to take down the machine), this is more than enough. The rest of the hard­disk will be used for jails, the distfiles/packages for/of the ports, and as WRKDIRPREFIX when build­ing ports.

Now, pushing/pulling a 160 GB image over the net­work to install a sys­tem is not real­ly some­thing I want to do. I would pre­fer to trans­fer less than 500 MB (that is 0.3% of the entire disk) to get this job done, and this is fea­si­ble. Due to an error or two I had to trans­fer the image sev­er­al times until every­thing was work­ing, so it was more in the area of maybe 2 GB (~1% of the entire disk).

First let us define some vari­ables in the shell, this way you just need to change the val­ues in one place and the rest is copy&paste:

ROOTFS_SIZE=5G
ROOTFS_NAME=root0
FILENAME=rootfs

Then change your cur­rent direc­to­ry to a place where you have enough space for the image. There we will cre­ate a con­tain­er for the image, and make it ready for partitioning:

truncate -s ${ROOTFS_SIZE} ${FILENAME}
mdconfig -a -t vnode -f ${FILENAME}

Cre­ate the rootfs:

# create one active FreeBSD slice with $ROOTFS_SIZE GB
fdisk -e /dev/mdX
gmirror label ${ROOTFS_NAME} /dev/mdXsY
bsdlabel -w /dev/mirror/${ROOTFS_NAME}
# create an "a"-partition for everything
bsdlabel -e /dev/mirror/${ROOTFS_NAME}
newfs -U /dev/mirror/${ROOTFS_NAME}a

Mount the new rootfs to /mnt and install FreeBSD:

mount /dev/mirror/${ROOTFS_NAME}a /mnt
cd /usr/src
make buildworld >&! buildworld.log
make buildkernel >&! build_generic.log
make installworld DESTDIR=/mnt
make distribution DESTDIR=/mnt
make installkernel DESTDIR=/mnt

Now you need to cre­ate /mnt/etc/rc.conf (set the default­router, the IP address via ifconfig_IF (and do not for­get to use the right IF for it), the host­name, set sshd_enable to yes, add an user (I used “vipw ‑d /mnt/etc”) which is in the wheel group so you can login remote­ly, and maybe oth­er things you are inter­est­ed in), /mnt/etc/resolv.conf, /mnt/etc/hosts. Final­ly, do not for­get to load the gmir­ror mod­ule, it will safe a lot of head-scratching (yes, an echo would be short­er, but WP con­verts the single-quotes to double-quotes), and add the rootfs to the fstab:

cat > /mnt/boot/loader.conf <<EOT
geom_mirror_load="YES"
EOT
echo "/dev/mirror/root0a / ufs rw,noatime 1 1" >/mnt/etc/fstab

Now we are ready to install, the image can be unmounted:

umount /mnt

The final steps are to login into the res­cue con­sole (the­o­ret­i­cal­ly you should be able to over­write even a run­ning sys­tem, but then you need to make sure there is a way to power-cycle the sys­tem remote­ly to force a reboot) of the new sys­tem and to install via a com­pressed ssh con­nec­tion (my remote res­cue sys­tem is a lin­ux sys­tem, so linux-syntax has to be used). The login to the res­cue con­sole is not shown here, but the install from the remote sys­tem is sim­ple (this assumes the image resides on a sys­tem which is acces­si­ble from the new system):

ssh -C -o CompressionLevel=9 user@myhost cat /path/to/${FILENAME} | dd of=/dev/hda bs=1m

Alter­na­tive­ly you can com­press it with bzip2 on your sys­tem and add an bunzip2 into the pipe above. This way you could even use an HTTP serv­er to fetch the file from, but then the com­mand to fetch the file needs to have a way to out­put the file it down­loads on std­out. Both ways of trans­fer­ring the image depend upon the sta­bil­i­ty of the trans­fer. If the con­nec­tion is cut, the sys­tem can not boot any­more. So if you do not have a res­cue con­sole which is inde­pen­dent from the con­tent of the hard­disk, you bet­ter have a plan B.

If I did not make an error here (I did this some months ago, I hope I did not for­get to write down some impor­tant step and also cor­rect­ed all steps which where not writ­ten down cor­rect­ly), you did every­thing cor­rect­ly too, and the remote sys­tem does not need oth­er ker­nel mod­ules loaded, you can now reboot the new sys­tem, cross your fin­gers for some moments, and then login to the new system.

Post install TODO

Now you should have a basic sys­tem up and run­ning, and you can start to con­fig­ure it.

I added two more FreeB­SD par­ti­tions, 1 GB for swap, and the rest of the hard­disk (I took care to not have the last par­ti­tion cov­er also the last sec­tor of the hard­disk, else gmir­ror will think it has to mir­ror the entire hard­disk and not only the last par­ti­tion) as one big par­ti­tion. For the sec­ond hard­disk I made the same par­ti­tion­ing as for the first harddisk.

Then I cre­at­ed two more gmir­rors, one mir­ror for the swap, and one for the rest of the space. The mir­ror for the swap I cre­at­ed with the option “-F”, to not syn­chro­nize the par­ti­tion after a pow­er fail­ure (not nec­es­sary for swap). All two I also cre­at­ed with the “-n” option, to not sync the con­tents (there is noth­ing yet, so it does not mat­ter what is writ­ten there).

Now just a quick “bsd­la­bel” on the two mir­rors to cre­ate a “b”-partition for the swap and a “d”-partition for the large par­ti­tion. To add the swap it is just an “echo /dev/mirror/swap0b none swap sw 0 0 >/etc/fstab”. Do not for­get to add the big par­ti­tion to the fstab (after doing a “newfs” off course).

To be sure it will sur­vive a reboot, do a quick test of man­u­al­ly mount­ing the big par­ti­tion (use the easy man­u­al way via “mount /place/where/it/is/mounted” after adding it to the fstab, not the com­plete man­u­al way, this is meant to test the fstab entry too), and a “swapon ‑a” to test the swap. I also made a reboot test, just to be sure every­thing is ok.

The final step was to add the par­ti­tion on the sec­ond hard­disk to the rootfs (“gmir­ror insert ${ROOTFS_NAME} /dev/…”).

WP plu­g­ins and PHP safe_mode

Obvi­ous­ly a lot of WP plu­g­in authors do not check if their plu­g­in is PHP safe_mode/open_basedir com­pat­i­ble. Yes, I know, it is dep­re­cat­ed and does not offer 100% safe­ty, but it is at least an addi­tion­al road-block in some cas­es and may pre­vent some mali­cious behav­ior… If I can choice between 100% break-in pos­si­bil­i­ty and <100% break-in pos­si­bil­i­ty, I chose the later.

I also think most of them also do not check with suhosin. They also fail to list oth­er PHP exten­sion require­ments most of the time, they just assume you have a full install.

  • quick­stats wants the PHP ctype exten­sion, does not seem to play well with sql.safe_mode while the rest of WP does not seem to have an obvi­ous prob­lem with it
  • wp-stats-dashboard wants the PHP curl and json exten­sion (curl does not play well with safe_mode or open_basedir => needs to be dis­abled), needs suhosin.executor.include.max_traversal set to 6; still does not work 100% cor­rect, I delet­ed the cache direc­to­ry con­tents to let it recre­ate the stats, but it still does not dis­play as much vis­its as I can see in the stats on the post­ings page
  • bot-tracker wants the PHP ses­sion extension
  • broken-link-checker tries to write to /var/tmp/ (safe_mode/open_basedir incompatible)
  • one-time-password does not play well with safe_mode/open_basedir
  • smartlink­er tells me that the vari­able cook­ieString is not defined

Easy library depen­den­cies detec­tion for ports

In the last days I com­mit­ted some scripts to $PORTSDIR/Tools/scripts which help in detect­ing the explic­it library depen­den­cies of installed ports. You just have to run $PORTSDIR/Tools/scripts/explicit_lib_depends.sh with the package-name of the installed port (alter­na­tive­ly you can give the path to the reg­is­tered port, e.g. /var/db/pkg/gnome-terminal‑2.18.1). One of the scripts which are called needs por­tup­grade installed. As an exam­ple here’s the com­plete out­put of a script run with the gnome-terminal port:

# /usr/ports/Tools/scripts/explicit_lib_depends.sh gnome-terminal-2.18.1
USE_FREETYPE=yes
USE_GETTEXT=yes
USE_GNOME+=atk
USE_GNOME+=esound
USE_GNOME+=gconf2
USE_GNOME+=glib20
USE_GNOME+=gnomevfs2
USE_GNOME+=gtk20
USE_GNOME+=libartlgpl2
USE_GNOME+=libbonobo
USE_GNOME+=libbonoboui
USE_GNOME+=libglade2
USE_GNOME+=libgnome
USE_GNOME+=libgnomecanvas
USE_GNOME+=libgnomeui
USE_GNOME+=libxml2
USE_GNOME+=orbit2
USE_GNOME+=pango
USE_GNOME+=vte
USE_ICONV=yes
USE_XORG+=ice
USE_XORG+=sm
USE_XORG+=x11
USE_XORG+=xau
USE_XORG+=xcursor
USE_XORG+=xdmcp
USE_XORG+=xext
USE_XORG+=xfixes
USE_XORG+=xft
USE_XORG+=xi
USE_XORG+=xinerama
USE_XORG+=xrandr
USE_XORG+=xrender
audiofile:${PORTSDIR}/audio/libaudiofile
avahi-client:${PORTSDIR}/net/avahi
avahi-common:${PORTSDIR}/net/avahi
avahi-glib:${PORTSDIR}/net/avahi
cairo:${PORTSDIR}/graphics/cairo
dbus-1:${PORTSDIR}/devel/dbus
dbus-glib-1:${PORTSDIR}/devel/dbus-glib
expat:${PORTSDIR}/textproc/expat2
fontconfig:${PORTSDIR}/x11-fonts/fontconfig
gnome-keyring:${PORTSDIR}/security/gnome-keyring
jpeg:${PORTSDIR}/graphics/jpeg
png:${PORTSDIR}/graphics/png
popt:${PORTSDIR}/devel/popt
startup-notification-1:${PORTSDIR}/x11/startup-notification

All those libraries are direct­ly ref­er­enced (dynam­i­cal­ly linked in) in the bina­ries or libs of the gnome-terminal port, indi­rect (depen­den­cies of depen­den­cies) ones are not list­ed (and not need­ed). So the script allows to quick­ly pro­duce a list of libs/ports which

  • should be ref­er­enced in the port Make­file (new port devel­op­ment, port updates)
  • allows to check if a port lists all ref­er­enced LIB_DEPENDS (port maintenance)

To do this with all your ports you can run

for port in /var/db/pkg/*; do
echo $port:
/usr/ports/Tools/scripts/explicit_lib_depends.sh $port
done > explicit_depends.txt

Not all USE_* switch­es of the Ports Col­lec­tion are han­dled yet, if you stum­ble upon such a case, feel free to send me a mail.

Text why pro­pri­etary or no hard­ware docs hurt the manufacturer

I stum­bled about a text which describes why it is ben­e­fi­cial to dis­close hard­ware pro­gram­ming docs and why it does­n’t help in keep­ing this infor­ma­tion away from the com­pe­ti­tion. I don’t repeat it here, so go and read it.

It’s a lit­tle bit old (last mod­i­fied in 2003), but IMO still up-to-date. If some­one approach­es a com­pa­ny for hard­ware docs, please pro­vide this link to them!

Unfor­tu­nate­ly it fails to men­tion that it would even be nice to get docs for obso­lete or not sup­port­ed any­more hard­ware (if your com­pe­ti­tion learns even stuff from your hard­ware which is 3 – 4 gen­er­a­tions old, it is not real­ly a com­pe­ti­tion and you most prob­a­bly are lead­ing because of inno­va­tion, if not you either are too expen­sive and open­ing the docs would be a rea­son to buy regard­less, or your soft­ware devel­op­ment is not good enough and open­ing the docs would allow users to fix this prob­lem them­selves). This could be a first step for a com­pa­ny to “test the water”. It would be an invest­ment with­out any mon­ey in return (the com­pa­ny does­n’t sell such hard­ware any­more), but it would show the com­pa­ny how it affects their image, how much they have to invest and what they can get in return (when peo­ple do cre­ative things with your obso­lete hard­ware you haven’t imag­ined before, you can bet they can do the same with your cur­rent hard­ware too… you may get an entire­ly new mar­ket “for free”).

If you apply some more thoughts about this top­ic and for exam­ple graph­ic cards, you even notice that any infor­ma­tion the com­pe­ti­tion may get by look­ing at freely avail­able hard­ware docs for graph­ic cards (instead of reverse engi­neer­ing it), can only be used 2 – 3 inno­va­tion cycles lat­er. This is caused by the short turn around times between new graph­ic cards. When a new graph­ic card hits the mar­ket, a devel­op­ment team already works at the sec­ond next gen­er­a­tion (and the next gen­er­a­tion is most prob­a­bly not only in fea­ture freeze but at the bug fix­ing and per­for­mance enhance­ment step). Now, how much val­ue does the com­pe­ti­tion gain from this? I would say only the mon­ey need­ed for the reverse engi­neer­ing. At the same time you gain mon­ey from hard­ware sales from those peo­ple which use (the result of) your hard­ware docs. And the com­pe­ti­tion is required to open their docs too (see below for the “com­put­er freaks” part), so you can safe the mon­ey for the reverse engi­neer­ing lat­er too.

For sound­cards this is a lit­tle bit dif­fer­ent. There you don’t have such short cycles, but cur­rent­ly there you have a pub­lished stan­dard (HDA) and you have Cre­ative with no docs at all on the oth­er side. Hey, Cre­ative, if you stum­ble upon this, what about kick­ing Microsoft in the ass by pro­vid­ing your hard­ware doc­u­men­ta­tion to any­one and ben­e­fit­ing from a lot of peo­ple which are pissed off because their shiny Creative-gear does­n’t work on Vista? I’m sure a lot of peo­ple are will­ing to spend their free time to find a way to make your hard­ware use­able on Vista (and on oth­er OS’) with­out get­ting mon­ey from you. And I’m sure peo­ple will find a way to get stuff out of your hard­ware which makes your eyes fall out of your head (and increas­es hard­ware sales). Oh… yes… hey, VIA, what about the docs for your soundgear too? There’s no mar­ket for sell­ing hard­ware docs, but a huge mar­ket to sell sound hard­ware. And those peo­ple which play around with non-mainstream soft­ware are those peo­ple (com­put­er freaks) which rec­om­mend hard­ware to peo­ple (mom, dad, neigh­bors, friends) which don’t play around but just use main­stream soft­ware. Those “ordi­nary” peo­ple may not depend on your hard­ware docs, but the com­put­er freaks will more like­ly rec­om­mend stuff which works not only on the main­stream stuff (just in case some­one wants to try some non-mainstream stuff).

The same (com­put­er freaks rec­om­mend­ing hard­ware) is true for cable TV / satel­lite TV / … stuff.

Hint: using sock­ets across jails

I want to use a sock­et (mysql) in mul­ti­ple jails. Using nullfs to mount it in each jail where you want to use it does not work (bug in nullfs?). Using a hardlink (if the jails reside on the same FS) works. I hope this info safes a lit­tle bit of time in case some­one tries to do the same.

The host­name MySQL sees in such a con­nec­tion is “local­host”. Maybe this is obvi­ous to one or anoth­er, but because jails don’t have a 127.0.0.1 it was not obvi­ous to me.