GästebuchIhr Eintrag in unser Gästebuch KontaktNehmen Sie Kontakt mit den Autoren auf ArchivAlle Unixwerk- Artikel seit 2003
16. August 2014

Linux NAS Server

Teil I: Installation und grundlegender Aufbau

Inhalt

  1. Einleitung
  2. Platten partitionieren
  3. Linux redundant installieren
  4. NAS-Storage vorbereiten
  5. «nasvg» und «bckvg» synchron halten
  6. Starten und Stoppen des NAS

1. Einleitung

Immer mehr Geräte zum Abspielen von Musik, Videos, etc. Doch der lokale Speicher der Geräte reicht nicht aus, um alles aufzunehmen, auf das man so zugreifen möchte. Die laut propagierte Lösung ist die Wolke irgendwo da draußen. Wir wollen uns in einem zunächst dreiteiligen Kurs aber unser eigenes NAS mit Linux-Bordmitteln bauen.

Im ersten Teil geht es um den grundsätzlichen Aufbau eines Linux-Systems als NAS. Dabei wollen wir zwei Dinge erreichen

  1. Verschlüsselte NAS Volumes - dies hilft gegen Datenpreisgabe, falls der NAS-Server gestohlen werden sollte. Ein verschlüsselter Zugriff wird dadurch nicht ersetzt!
  2. Redundanz gegen Datenverlust durch Harwareausfälle - hier vor allem der Festplatte

2. Platten partitionieren

Als Beispiel soll ein System mit zwei großen Festplatten dienen - sda und sdb. Hier zeigt sich Linux flexibel - so können wir die Platten partitioneren und insgesamt 4 Volume Groups anlegen - zwei für's System und zwei für's NAS. Die Partitionierung würde dann etwa so aussehen:

# fdisk -l
Disk /dev/sda: 1500.3 GB, 1500301910016 bytes
255 heads, 63 sectors/track, 182401 cylinders, total 2930277168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000c9d55

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048      526335      262144   83  Linux
/dev/sda2          526336   134744063    67108864   8e  Linux LVM
/dev/sda3       134744064  2930277167  1397766552    5  Extended
/dev/sda5       134746112  2930277167  1397765528   8e  Linux LVM

Disk /dev/sdb: 1500.3 GB, 1500301910016 bytes
255 heads, 63 sectors/track, 182401 cylinders, total 2930277168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x46ba1a6d

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048      526335      262144   83  Linux
/dev/sdb2          526336   134744063    67108864   8e  Linux LVM
/dev/sdb3       134744064  2930277167  1397766552    5  Extended
/dev/sdb5       134746112  2930277167  1397765528   8e  Linux LVM

Auf den beiden kleinen Partitionen legen wir dann die System Volume Groups an - eine auf der wir unser Linux installieren und eine auf der wir eine Kopie des Systems anlegen. Wenn eine Platte ausfällt, können wir von der zweiten booten.

# pvcreate /dev/sda2
# vgcreate sysvg /dev/sda2
# pvcreate /dev/sdb2
# vgcreate altsysvg /dev/sdb2

3. Linux redundant installieren

Aus Performance- und Flexibilitätsgründen habe ich mich entschieden, die Partitionen nicht zu spiegeln wie z.B. im Artikel   Slackware 13.1 mit Software Raid und LVM   beschrieben, sondern das Betriebssystem auf die erste Platte zu installieren und dann einen Klon auf der zweiten Platte anzulegen. Neben der Performancesteigerung ergibt sich dadurch auch die Möglichkeit eines OS Updates auf der einen Platte, während auf der zweiten Platte immer noch die alte Installation als Fallback zur Verfügung steht - ähnlich der AIX-Methode der   Alternate Disk Installation.

Die Installation auf die sysvg geschieht mit der Installations-CD der gewählten Linux-Distribution und soll nicht Gegenstand dieses Artikels sein.

Klonen der sysvg auf die altsysvg
Sobald Linux installiert und grundlegend konfiguriert ist, können wir die sysvg klonen. Dazu werden zunächst in der altsysvg die gleichen LVs angelegt wie in der sysvg, also z.B.

nas# lvs | grep -w sysvg
  local    sysvg    -wi-ao--   5.00g                                           
  opt      sysvg    -wi-ao--   5.00g                                           
  root     sysvg    -wi-ao--   5.00g                                           
  swap     sysvg    -wi-ao--   8.00g                                           
  usr      sysvg    -wi-ao--  15.00g                                           
  var      sysvg    -wi-ao--   5.00g                       
nas# lvcreate -L 5G -n local altsysvg
nas# lvcreate -L 5G -n opt altsysvg
nas# lvcreate -L 5G -n root altsysvg
nas# lvcreate -L 8G -n swap altsysvg
nas# lvcreate -L 15G -n usr altsysvg
nas# lvcreate -L 5G -n var altsysvg

Die angelegten Dateisysteme werden dann eingehängt:

nas# mkdir /.altroot
nas# mount /dev/altsysvg/root /.altroot
nas# mount /dev/altsysvg/usr /.altsys/usr

und so weiter. Zusätzlich muss /dev/sdb1 unter /.altroot/boot eingeghängt werden:

nas# mount /dev/sdb1 /.altroot/boot

Um keine Pseudodateien zu kopieren muss auch das aktuelle System noch einmal an anderer Stelle eingehängt werden:

nas# mkdir /.root
nas# mount /dev/sysvg/root /.root
nas# mount /dev/sysvg/usr /.sys/usr

und so weiter. Auch hier /boot nicht vergessen:

nas# mount /dev/sda1 /.root/boot

Dann können wir mit rsync einen Klon anlegen:

nas# rsync -avz --delete /.root/ /.altroot

Diesen rsync können wir grundsätzlich immer wieder laufen lassen, um das System synchron zu halten. Allerdings sollten wir dabei die nächsten Schritte im Auge behalten:

Alternate Boot ermöglichen
Damit von der altsysvg auch gebootet werden kann, muss die /etc/fstab nach dem rsync angepasst werden, also etwa

nas# cat /etc/fstab | sed -e 's%/sysvg%/altsysvg%' -e 's%/sda%/sdb%' > /.altroot/etc/fstab

Danach muss das initrd für die alternative Installation neu geschrieben werden - unter Slackware ginge das ungefähr so:

nas# chroot /.altroot
altnas# mkinitrd -c -f ext4 -r /dev/altsysvg/root -m usbhid:ehci-hcd:xhci-hcd:mbcache:jbd2:ext4 -L -u -o /boot/initrd.gz
altnas# exit
nas# _

In der /etc/lilo.conf bzw. /etc/grub.conf müssen beide Linux-Systeme eingetragen sein. Falls Sie LILO benutzen, muss der Bootlader auch auf beide Platten geschrieben werden:

nas# lilo -b /dev/sda
nas# lilo -b /dev/sdb

Für GRUB ist ein solcher Schritt nicht nötig.

4. NAS-Storage vorbereiten

Die Linux-Systempartitionen haben wir nicht verschlüsselt. Hier liegen keine sensiblen Daten. Anders sieht es mit den NAS Volumina selbst aus, diese wollen wir nicht nur redundant auslegen sondern auch verschlüsseln. Wie das geht, wurde im Artikel   Festplatte verschlüsseln   eingehend erläutert, hier nur die Kurzfassung für unser Beispiel-Setup:

nas# dd if=/dev/urandom of=/dev/sda5
nas# root# cryptsetup -s 256 -y luksFormat /dev/sda5
nas# root# cryptsetup luksDump /dev/sda5
nas# root# cryptsetup luksOpen /dev/md3 crypt0

nas# dd if=/dev/urandom of=/dev/sdb5
nas# root# cryptsetup -s 256 -y luksFormat /dev/sdb5
nas# root# cryptsetup luksDump /dev/sdb5
nas# root# cryptsetup luksOpen /dev/sdb5 crypt1

Auf den verschlüsselten Devices werden dann die Daten Volume Groups angelegt:

nas# pvcreate /dev/mapper/crypt0
nas# vgcreate nasvg /dev/mapper/crypt0
nas# pvcreate /dev/mapper/crypt1
nas# vgcreate bckvg /dev/mapper/crypt1

In der nasvg werden dann die NAS-Volumina angelegt. Beispielhaft legen wir einmal 5 Volumina an:

nas# lvcreate -L 40.00G -n sda5lv01 nasvg
nas# lvcreate -L 100.00G -n sda5lv02 nasvg
nas# lvcreate -L 70.00G -n sda5lv03 nasvg
nas# lvcreate -L 30.00G -n sda5lv04 nasvg
nas# lvcreate -L 10.00G -n sda5lv05 nasvg

Analog die Backup Volumina in der bckvg:

nas# lvcreate -L 40.00G -n sdb5lv01 bckvg
nas# lvcreate -L 100.00G -n sdb5lv02 bckvg
nas# lvcreate -L 70.00G -n sdb5lv03 bckvg
nas# lvcreate -L 30.00G -n sdb5lv04 bckvg
nas# lvcreate -L 10.00G -n sdb5lv05 bckvg

Auf allen LVs (NAS Volumina und Backup Volumina) legen wir Dateisysteme an, also etwa

nas#  mkfs.ext4 -m 0 -O resize_inode /dev/nasvg/sda5lv01

und so weiter.

In der /etc/fstab verankern wir die Volumina wie folgt:

# NAS Volumes
/dev/nasvg/sda5lv01   /export/diska/vol01  ext4     noauto                        0   0
/dev/nasvg/sda5lv02   /export/diska/vol02  ext4     noauto                        0   0
/dev/nasvg/sda5lv03   /export/diska/vol03  ext4     noauto                        0   0
/dev/nasvg/sda5lv04   /export/diska/vol04  ext4     noauto                        0   0
/dev/nasvg/sda5lv05   /export/diska/vol05  ext4     noauto                        0   0

# Backup Volumes
/dev/bckvg/sdb5lv01   /var/nas/.snapshots/diska/vol01  ext4     noauto            0   0
/dev/bckvg/sdb5lv02   /var/nas/.snapshots/diska/vol02  ext4     noauto            0   0
/dev/bckvg/sdb5lv03   /var/nas/.snapshots/diska/vol03  ext4     noauto            0   0
/dev/bckvg/sdb5lv04   /var/nas/.snapshots/diska/vol04  ext4     noauto            0   0
/dev/bckvg/sdb5lv05   /var/nas/.snapshots/diska/vol05  ext4     noauto            0   0

Man beachte, dass die verschlüsselten NAS-Volumina nicht automatisch eingehängt werden (noauto)

5. «nasvg» und «bckvg» synchron halten

Wie eingangs erläutert, soll Datensicherheit nicht durch eine Plattenspiegelung sondern durch eine inaktive Kopie gewährleistet werden. Der Vorteil liegt unter Linux eindeutig in der Performance, doch es gibt noch einen positiven Nebeneffekt. Die Kopie ist auch eine Art Backup, denn eine versehentlich gelöschte Datei ist auf der Kopie -ganz im Gegensatz zum Spiegel- noxh vorhanden. Diesem Umstand wird im folgenden Skript noch einmal gesondert Rechnung getragen.

Damit eine Kopie wirklich Sicherheit gegen Datenverlust bietet, muss sie regelmäßig aktualisiert werden. Dazun installieren wir folgendes Skript:

#!/bin/bash
#
# purpose: sync active nas volumes to passive disk
# (c) aml, 2013-01-12

# Defaults:
# =========
delete=""

# Names:
# ======
ACTVG=nasvg
PASVG=bckvg

ACTMNT=/export
PASMNT=/var/nas/.snapshots

# Helper functions
#=================
fskip()
{
 if [ "$skip" = "fs" ]
 then
  echo "skipping filesystem »$afs«...."
 elif [ "$skip" = "dir" ]
 then
   echo "skipping folder »$dir«....."
 fi
}

# Delete removed files from backup only if requested
# ==================================================
if [ "$1" = "-d" ]
then
  delete="--delete"
fi

# get list of volumes to be backed up
# ===================================
VOLUMELIST=$(lvs | awk -v avg="$ACTVG" '$2 == avg {print $1}')

for avol in $VOLUMELIST
do

  afs=$(mount | sed -e "s%/dev/mapper/$ACTVG-%/dev/$ACTVG/%" | awk -v vol=/dev/$ACTVG/$avol '($1 == vol) {print $3}')
  bfs=$(echo $afs | sed -e "s%^$ACTMNT%$PASMNT%")
  echo "$(date  +%Y/%m/%d-%H:%M): $afs  -> $bfs"

  # if backup volume not mounted, do it now
  mount | grep $bfs >/dev/null 2>&1 ; RC=$?
  [ "$RC" = "0" ] || { mount $bfs || { skip=fs fskip ; continue ; } ; }  

  for dir in $(ls $afs | grep -v lost+found)
  do
    cwd=$PWD
    cd $afs
    
    # if dir does not exist yet on backup volume, create it!
    [ -x "$bfs/$dir" ] || { mkdir "$bfs/$dir" || { skip=dir fskip ; continue ; } ; }

    # start sync process
    rsync -auvz $delete $afs/"$dir"/ $bfs/"$dir"
    cd $cwd
  done

  umount $bfs

done

Das Skript könnte z.B. in der crontab verankert werden, um einmal täglich zu laufen, z.B.:

30 13 * * * /usr/local/sbin/syncjob >> /var/adm/nassync.log 2>&1

Man beachte, dass dieses Skript auf den Backup Volumina Dateien nicht löscht, die auf dem NAS schon gelöscht wurden. Dies ist eine Versicherung gegen versehentliches Löschen, führt aber dazu, dass auf lange Sicht die Backup Volumina voll laufen. Deshalb kann das Skript von Zeit zu Zeit manuell mit der Option »-d« aufgerufen werden, um die Backup Volumina zu bereinigen.

6. Starten und Stoppen des NAS

Der NAS-Server hat typischerweise keine Ein- und Ausgabegeräte, weshalb er ohne Administrator-Interaktion hochfahren soll. Die verschlüsselten NAS-Volumina können dann aber nicht automatisch eingehängt werden - sie benötigen eine manuelle Passworteingabe. Deshalb starten wir das eigentliche NAS über eine ssh-Session. Ein bisschen erinnert das an Novells Netware-Fileserver, die anfangs ein DOS starteten. Der Fileserver wurde dann manuell vom DOS-Prompt mit

> server

hochgefahren.

Wir installieren dazu ein Skript nas mit dem das NAS im SysV-Stil hoch- und heruntergefahren werden kann:

#!/bin/bash
#
# start/stop NAS volumes

nasstart()
{
 echo "decrypting your NAS devices...."

 cryptsetup luksOpen /dev/sda5 crypt0
 cryptsetup luksOpen /dev/sdb5 crypt1

 echo "opening primary volume group..."
 vgchange -a y nasvg

 echo "opening backup volume group..."
 vgchange -a y bckvg

 echo "mounting volumes...."

 lvs | awk  '$2 ~ /^nasvg$/ {print "fsck -C -a /dev/nasvg/"$1" && mount -v /dev/nasvg/"$1}' | sh

 sh /etc/init.d/nfs-server start
 sh /etc/init.d/samba start
}

nasstop()
{
 echo "stopping NFS exports..."
 exportfs -u -a
 echo "unmounting backup volumes...."
 for vol in $(mount | awk '$3 ~ /^\/\.snapshots/ {print $3}')
 do
   umount $vol
 done

 echo "unmounting primary volumes..."
 for vol in $(mount | awk '$3 ~ /^\/export/ {print $3}')
 do
   umount $vol
 done

 sleep 5

 echo "closing volume groups..."
 vgchange -an bckvg
 vgchange -an nasvg

 sleep 5

 echo "encrypting your NAS devices..."
 cryptsetup luksClose crypt0
 cryptsetup luksClose crypt1
}

case $1 in

  start) nasstart ;;
  stop) nasstop ;;
  *) echo "Usage $(basename $0)  { start | stop }"

esac

Im Skript bitte beachten, dass der Aufruf zum Start des NFS-Servers und des Samba-Servers sich von Distribution zu Distribution unterscheiden kann. Da das Skript die NFS- und Samba-Server startet, sollte überdies sicher gestellt werden, dass diese Dienste nicht bereits vom Boot-Prozess gestartet werden.

 

Weitere Artikel zum Thema bei unixwerk