Categories
Dokumentation Internet Unix

Ein echtes ZFS-only FreeBSD-System

Als ich meinen neuen FreeBSD-Server installieren sollte, wollte ich ihn nun komplett mit ZFS einrichten. Im Internet existieren genügend Anleitungen, die beschreiben, wie man dies bewerkstelligt. Doch sie gingen alle nicht den allerletzten Schritt, um auch das Swap ins ZFS zu legen. Hier also die Anleitung, wie man ein echtes ZFS-only System einrichtet.

Zunächst einmal ein paar Daten. Ich habe 5 SATA-Festplatten im Rechner, die nach dem Booten von FreeBSD 8.1-RELEASE als ad4, ad6, ad8, ad10 und ad12 erkannt wurden. Die Installation ist nichts für schwache Nerven. Es gibt keine Menüs, alles wird von der Kommandozeile erledigt und Tippfehler werden mit einem kaputten System bestraft.

Ich habe den Rechner mit der Installations-DVD gestartet. Anstatt die übliche Installation zu starten, bin ich jedoch gleich in die Rettungskonsole (Fixit) gegangen. Hier habe ich nochmal mit dmesg nachgeprüft, daß auch wirklich alle Platten korrekt erkannt wurden und mir die Gerätenamen notiert.

Als erstes habe ich die Festplatten mit GPT partitioniert.

gpart create -s gpt ad4
gpart create -s gpt ad6
gpart create -s gpt ad8
gpart create -s gpt ad10
gpart create -s gpt ad12

So vorbereitet habe ich dann die Partitionen auf den Festplatten angelegt. Zuerst die Bootpartition.

gpart add -b 34 -s 128 -t freebsd-boot ad4
gpart add -b 34 -s 128 -t freebsd-boot ad6
gpart add -b 34 -s 128 -t freebsd-boot ad8
gpart add -b 34 -s 128 -t freebsd-boot ad10
gpart add -b 34 -s 128 -t freebsd-boot ad12

Anders als in den oben erwähnten Anleitungen, habe ich keine separate Swap-Partition angelegt. Den verbliebenen Platz auf den Platten habe ich vollständig für das ZFS verwendet.

gpart add -t freebsd-zfs -l disk0 ad4
gpart add -t freebsd-zfs -l disk1 ad6
gpart add -t freebsd-zfs -l disk2 ad8
gpart add -t freebsd-zfs -l disk3 ad10
gpart add -t freebsd-zfs -l disk4 ad12

Natürlich gehört der Boot-Code auf alle Festplatten. Man weiß ja nie, welche Festplatte ausfällt, in dem Fall möchte ich natürlich auch von den verbliebenen Platten booten können.

gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad4
gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad6
gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad8
gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad10
gpart bootcode -b /mnt2/boot/pmbr -p /mnt2/boot/gptzfsboot -i 1 ad12

Um das ZFS anzulegen, habe ich die ZFS-Kernelmodule geladen.

kldload /mnt2/boot/kernel/opensolaris.ko
kldload /mnt2/boot/kernel/zfs.ko

Das Dateisystem habe ich dann mit diesen Befehlen angelegt. (Die ersten beiden Zeilen gehören zusammen und sind hier nur wegen der Breite umgebrochen)

zpool create zroot raidz2 /dev/gpt/disk0 /dev/gpt/disk1 /dev/gpt/disk2 \
/dev/gpt/disk3 /dev/gpt/disk4
zpool set bootfs=zroot zroot

An dieser Stelle mußte ich dann nochmal von den Anleitungen abweichen, um Swap einzurichten. Die Idee dazu stammt von hier.

zfs create -V 2G zroot/swap
zfs set org.freebsd:swap=on zroot/swap
zfs set checksum=off zroot/swap

Hier kehrte ich dann zu den vorhandenen Anleitungen zurück. Es ist nicht zwingend notwendig, all diese Dateisysteme anzulegen, aber wenn man schon ein Dateisystem wie ZFS hat, sollte man seine Stärken richtig ausspielen.

zfs set checksum=fletcher4 zroot
zfs create -o compression=on -o exec=on -o setuid=on zroot/tmp
chmod 1777 /zroot/tmp
zfs create zroot/usr
zfs create zroot/usr/home
cd /zroot ; ln -s /usr/home home
zfs create -o compression=lzjb -o setuid=off zroot/usr/ports
zfs create -o compression=off -o exec=off -o setuid=off zroot/usr/ports/distfiles
zfs create -o compression=off -o exec=off -o setuid=off zroot/usr/ports/packages
zfs create zroot/var
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/crash
zfs create -o exec=off -o setuid=off zroot/var/db
zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/var/db/pkg
zfs create -o exec=off -o setuid=off zroot/var/empty
zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/log
zfs create -o compression=gzip -o exec=off -o setuid=off zroot/var/mail
zfs create -o exec=off -o setuid=off zroot/var/run
zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/var/tmp
chmod 1777 /zroot/var/tmp

Damit habe ich alle Dateisysteme angelegt und kann mit der eigentlichen Installation beginnen. Auch das muß von der Kommandozeile geschehen.

cd /dist/8.1-RELEASE
export DESTDIR=/zroot
for dir in base manpages ports ; do (cd $dir ; ./install.sh) ; done
cd src ; ./install.sh all
cd ../kernels ; ./install.sh generic
cd /zroot/boot ; cp -Rlp GENERIC/* /zroot/boot/kernel/

Nachdem alle Dateien installiert sind, kann /var/empty read-only geschaltet werden.

zfs set readonly=on zroot/var/empty

Nun konnte ich in das frisch installierte System chrooten, um noch wichtige Einstellungen am System vorzunehmen.

chroot /zroot

Damit alle ZFS-Dateisysteme beim booten gemountet werden.

echo 'zfs_enable="YES"' > /etc/rc.conf

Der Bootloader soll natürlich auch wissen, wovon er booten soll.

echo 'vfs.root.mountfrom="zfs:zroot"' > /boot/loader.conf
echo 'zfs_load="YES"' >> /boot/loader.conf

Folgende Zeile ist nur bei Systemen mit 1GB RAM oder weniger nötig.

echo 'vfs.zfs.prefetch_disable="1"' >> /boot/loader.conf

Sollte ich je auf die Idee kommen, mit make buildworld mein System upzudaten, will ich auch wieder einen Bootloader mit ZFS-Support haben. Dies ist nicht notwendig, um das System zum laufen zubekommen. Es verhindert nur, daß ich mir zukünftig ins Knie schieße.

echo 'LOADER_ZFS_SUPPORT=YES' > /etc/src.conf

Damit das System nach dem Booten auch lauffähig und benutzbar ist, fehlen noch einige Einstellungen wie root-Passwort, Zeitzone und Mail-Aliase für Sendmail.

passwd root
tzsetup
cd /etc/mail ; make aliases

Das System wird am Ende komplett aus dem ZFS laufen und benötigt eigentlich keine /etc/fstab mehr. Allerdings geht FreeBSD beim Booten davon aus, daß diese Datei existiert. Es fährt zwar auch ohne hoch, spuckt jedoch beim Hochfahren unschöne Fehlermeldungen aus. Um dem vorzubeugen, habe ich eine leere /etc/fstab angelegt.

touch /etc/fstab

Dies war nur das allernötigste. Die restlichen Einstellungen wie Netzwerk, Dienste, Tastaturlayout kann ich nach dem ersten Booten mit sysinstall vornehmen. Ich war an dieser Stelle fertig und konnte die chroot-Umgebung verlassen.

exit

Damit das System beim Booten die Dateisysteme wiederfindet, braucht es den zpool.cache. Dieser wird erst beim Exportieren des ZFS erzeugt. Ich habe also kurz das Dateisystem exportiert und gleich wieder importiert, um die Cache-Datei zu erzeugen und dann ins System zu kopieren.

mkdir /boot/zfs
cd /boot/zfs
zpool export zroot && zpool import zroot
cp /boot/zfs/zpool.cache /zroot/boot/zfs/zpool.cache

Und zuletzt habe ich die Mountpunkte den einzelnen Dateisystemen zugewiesen.

export LD_LIBRARY_PATH=/mnt2/lib
zfs unmount -a
zfs set mountpoint=legacy zroot
zfs set mountpoint=/tmp zroot/tmp
zfs set mountpoint=/usr zroot/usr
zfs set mountpoint=/var zroot/var

Damit war die Installation abgeschlossen. Ich habe die Rettungskonsole verlassen. Der FreeBSD-Installer erschien wieder und ich wählte unten den Punkt zum Beenden des Installers. Der Rechner startete neu und startete danach das frisch installierte System vom ZFS.

Wie vorhin erwähnt mußte ich nach dem ersten Login noch das Netzwerk, SSH und Tastatur einrichten. Danach war das System voll betriebsbereit.

Categories
Unix

ZFS auf FreeBSD

Die Portierung von ZFS auf FreeBSD macht große Fortschritte. Wie auf der FreeBSD Filesystems Mailing-Liste zu lesen hat Pawel Jakub Dawidek ZFS soweit laufen, daß er ein ZFS gemountet hat und auf Dateien darauf zugreifen kann. Und das ganze nach nur 10 Tagen Arbeit. Respekt!

Dies macht mir große Hoffnung, daß bald noch weitere Betriebssysteme ZFS verstehen werden.

Categories
Software

Wecker stellen!

Wenn mal wieder der make buildworld mit so unerklärlichen Fehlern wie /usr/obj/usr/src/amd64/usr/bin/ld: cannot find -ll abbricht, sollte man als erstes mal schauen, ob die Uhr richtig geht.

Categories
Dokumentation Internet Software Unix

Sendmail für den Hausgebrauch

Ich habe bei mir Zuhause einen eigenen kleinen Mailserver stehen, der sich um die Abwicklung der Mails aus meinem ganzen Netzwerk kümmert. Als der alte Server erste Anzeichen seines baldigen ablebens von sich gab, beschloß ich einen neuen Server aufzusetzten. Als Basis habe ich diesmal FreeBSD 5.3(BETA4) genommen. (Der alte Server lief noch mit FreeBSD 4.5-STABLE)

Vorarbeit

Das bei FreeBSD mitgelieferte Sendmail hat einen kleinen Schönheitsfehler. Es ist ohne SASL kompiliert. Es gibt zwei Wege, diesen Umstand zu beheben. Man installiert aus den Ports Sendmail mit SASL oder linkt das mitgelieferte Sendmail gegen SASL. Ich habe mich für letzteres entschieden. Dafür habe ich zuerst Cyrus-SASL2 installiert. Danach habe ich diese drei Zeilen zur /etc/make.conf hinzugefügt:

SENDMAIL_CFLAGS=-I/usr/local/include -DSASL=2
SENDMAIL_LDFLAGS=-L/usr/local/lib
SENDMAIL_LDADD=-lsasl2

Nach einem (langwierigen) make buildworld war nun das Sendmail gegen SASL gelinkt. Dies habe ich einfach mit sendmail -d0.1 < /dev/null überprüft. Die Ausgabe von Sendmail sollte dann so aussehen:

Version 8.13.1
 Compiled with: DNSMAP LOG MAP_REGEX MATCHGECOS MILTER MIME7TO8 MIME8TO7
                NAMED_BIND NETINET NETINET6 NETUNIX NEWDB NIS PIPELINING SASLv2
                SCANF STARTTLS TCPWRAPPERS USERDB XDEBUG

Damit wäre alles vorbereitet. Ich versende meine Mails in der Regel über GMX. Sendmail wird also die Mails über den SMTP-Server von GMX versenden. Der Server von GMX läßt mich Emails nur dann abliefern, wenn er sich sicher ist, daß ich es auch wirklich bin. Hierzu bietet GMX zwei Alternativen. SMTP-after-POP und SMTP-AUTH. Ich habe mich für letzteres entschieden. SMTP-AUTH funktioniert nur mit SASL, deshalb war die kleine Vorarbeit nötig.

Konfiguration mit m4

Nun muß man Sendmail noch zu verstehen geben, was es tun soll. Dies ist der Inhalt meiner /etc/mail/anubis.shadowrun.not.mc (Das Makefile benutzt als Dateinamen automatisch $(hostname).mc):

divert(0)
VERSIONID(`$Id: anubis.shadowrun.not.mc,v 1.2 2004/09/19 22:47:42 fastjack Exp fastjack $‘)
OSTYPE(freebsd5)
DOMAIN(generic)
FEATURE(access_db, `hash -o -T /etc/mail/access’)
FEATURE(local_lmtp)
FEATURE(mailertable, `hash -o /etc/mail/mailertable’)
FEATURE(virtusertable, `hash -o /etc/mail/virtusertable’)
define(`confCW_FILE’, `-o /etc/mail/local-host-names’)
define(`SMART_HOST’, `mail.gmx.net’)
MASQUERADE_AS(`gmx.net’)
FEATURE(`local_no_masquerade’)
MASQUERADE_DOMAIN(`shadowrun.not’)
FEATURE(`masquerade_entire_domain’)
FEATURE(`masquerade_envelope’)
dnl Process login names through the genericstable
FEATURE(`genericstable’)
GENERICS_DOMAIN(`shadowrun.not’)
FEATURE(`generics_entire_domain’)
FEATURE(`authinfo’)
FEATURE(`relay_hosts_only’)
dnl The group needs to be mail in order to read the sasldb2 file
define(`confRUN_AS_USER’,`root:mail’)
define(`confDONT_BLAME_SENDMAIL’,`GroupReadableSASLDBFile’)
dnl Enable for both IPv4 and IPv6 (optional)
DAEMON_OPTIONS(`Name=IPv4, Family=inet’)
DAEMON_OPTIONS(`Name=IPv6, Family=inet6, Modifiers=O’)
define(`confBIND_OPTS’, `WorkAroundBrokenAAAA’)
define(`confNO_RCPT_ACTION’, `add-to-undisclosed’)
define(`confPRIVACY_FLAGS’, `authwarnings,noexpn,novrfy’)
MAILER(local)
MAILER(smtp)

Zusätzliche Konfigurationsdateien

Während mein Login auf allen meinen Rechnern „fastjack“ ist, habe ich bei GMX einen anderen Namen. Das Umschreiben des Benutzernamens übernimmt die genericstable. Der Hostname wird vom Masquerading geändert. In der /etc/mail/genericstable steht bei mir folgendes:

fastjack        mmaciaszek

Nun muß sich Sendmail beim Abliefern der Mails bei GMX noch authentifizieren. Hierzu steht in meiner /etc/mail/authinfo diese Zeile:

AuthInfo:mail.gmx.net “U:123456” “P:sehrgeheim” “M:CRAM-MD5”

Die „123456“ steht für meine GMX-Kundennummer und „sehrgeheim“ ist stellvertretend für mein Paßwort bei GMX. (Beides habe ich natürlich hier geändert)

Fehlen jetzt noch die Hosts, für die Sendmail Emails relayen soll. Ich habe hier bewußt auf SMTP-AUTH innerhalb des Netzwerkes verzichtet, da einige Hosts (z.B.: die NeXTSTEP-Maschine) ein altes Sendmail ohne SASL und SMTP-AUTH fahren. Diese Hosts stehen in der /etc/mail/relay-domains. Pro Zeile sollte ein Host stehen. Meine /etc/mail/relay-domains sieht so aus:

renraku.shadowrun.not
nexus.shadowrun.not
fuchi.shadowrun.not
sprawl.shadowrun.not

Dies wären alle Einstellungen, die nötig sind. Die genericstable und authinfo habe ich dann mit makemap(8) in eine entsprechende Map umgewandelt. Dies geht mit makemap hash genericstable < genericstable (für die authinfo muß man entsprechend die Namen ändern). Da sich in der /etc/mail/authinfo das Paßwort für den SMTP-Server befindet, sollte es nach Möglichkeit nur für root lesbar sein.

Die sendmail.cf habe erzeugt man dann mit make cf und make install in /etc/mail/. Ein beherztes make restart startet Sendmail mit der neuen Konfiguration neu. Nun liefert Sendmail nicht-lokale Mails über GMX aus.

Troubleshooting

Falls etwas schiefgegangen ist und es nicht wie gewünscht klappt, sind hier ein paar Tips zum „Debugging“. Falls das Masquerading/Generics nicht wie erwartet funktioniert, kann man Sendmail anweisen eine Email-Adresse durch seine Regeln zu schicken. Dazu muß man Sendmail mit sendmail -bt im sogenannten „Rule-testing mode“ starten. Da das Umschreiben der Absenderadresse getestet werden soll, muß man dies Sendmail mitteilen. Dies geschieht mit /tryflags HS. Nun können beliebige Absender-Adressen getestet werden. z.B: /try smtp fastjack. Sendmail wird nun genau beschreiben, wie es den Absender umschreiben würde, wenn die Mail über SMTP verschickt würde.

Falls der Fehler weniger genau einzugrenzen ist, kann man Sendmail beim SMTP-Dialog über die Schulter schauen. Dazu muß man Sendmail mit sendmail -Am -v -t starten. Danach erwartet Sendmail, daß man ihm eine Mail incl. Headern zu futtern gibt und mit Strg-D abschließt. Vorausgesetzt der Empfänger der Mail ist über SMTP erreichbar (also nicht lokal), wird Sendmail nun versuchen, diese Mail zuzustellen und gibt dabei die gesamte SMTP-Konversation auf dem Bildschirm aus. Damit sollte man den kniffeligeren Fehlern auf die Spur kommen können.

Eine ähnliche Anleitung für NetBSD hat tecneeq auf Newbie-Net geschrieben.