Debian auf der DiskStation
Anleitung zur Installation von Debian auf der Synology DiskStation (Hier: ARMEL auf DS210j/DS211+)
Einleitung
Ich übernehme keine Haftung/Garantie für diese Anleitung. Die Gefahr, etwas zu zerstören, ist bei einem chroot aber seeeehr klein.
Vorbereitung
Man braucht einen Debian-Rechner, auf dem man die Pakete herunterlädt. Auf diesem führt man diese Befehle aus:
apt-get install debootstrap -y apt-get clean debootstrap --foreign --arch armel squeeze debian "http://ftp.de.debian.org/debian"
Bitte armel durch die richtige Architektur der DS ersetzen. Dieses Beispiel funktioniert für DS210j/211+ und wahrscheinlich noch viele weitere (110j, 410j etc).
Sobald der Vorgang abgeschlossen ist, muss das Archiv gepackt werden. Das geht mit diesem Befehl:
tar -czf debian.tar.gz debian
Jetzt nur noch das tar.gz auf die Synology kopieren auf einem Volume (z.B. /volume1/)
Weiter auf der Synology
Entpacken:
gunzip debian.tar.gz tar -xvf debian.tar cd debian
proc mounten
mount -t proc none ./proc
chrooten
chroot ./ /bin/bash
System installieren
/debootstrap/debootstrap --second-stage
Hostname anpassen
echo "diskstation" >/etc/hostname
Hosts kopieren
exit cp /etc/hosts ./etc/hosts
erneut chrooten
mount -t proc none ./proc chroot ./ /bin/bash
apt-get einrichten
nano /etc/apt/sources.list
Folgendes einfügen:
deb http://ftp2.de.debian.org/debian/ squeeze main deb-src http://ftp2.de.debian.org/debian/ squeeze main deb http://security.debian.org squeeze/updates main
Mit CTRL+X speichern und verlassen
System aktualisieren
apt-get update apt-get upgrade apt-get dist-upgrade
Nun haben wir ein aktuelles Debian Squeeze auf der Synology. Um in dieses zu wechseln, einfach nach /volume1/debian wechseln und ein
mount -t proc none ./proc chroot ./ /bin/bash
absetzen. Falls eine Meldung kommt wie proc ist schon gemountet, einfach ignorieren. Zum Verlassen einfach exit eingeben.
Viel Spaß
Anpassungen am System der Firmware
Startscripte (basic)
Der chroot kann seine Dienste nicht selbständig starten. Das muss von ausserhalb, also der Firmware der DS passieren. Dazu kann man eigene Startscripte erstellen und diese dann entweder in /usr/syno/etc.defaults/rc.d oder /opt/etc/init.d platzieren. Hier mal ein Beispiel eines Startscriptes für den Apache des Debian
#!/bin/sh if [ "$*" = 'start' ] ; then chroot /volume1/debian /etc/init.d/apache2 start else chroot /volume1/debian /etc/init.d/apache2 stop fi
dabei ist /volume1/debian der Pfad zum chroot des Debian Systems und das Kommando dahinter wird dann **innerhalb des chroots ausgeführt**.
Wichtig wäre es noch, dass man im chroot gesetzte mounts beim Shutdown ebenfalls entfernt, sonst bleibt die DS hängen
#!/bin/sh if [ "$*" = 'start' ] ; then mount -t proc none /volume1/debian/proc chroot /volume1/debian /etc/init.d/apache2 start else chroot /volume1/debian /etc/init.d/apache2 stop umount /volume1/debian/proc fi
wichtig ist folgender Grundsatz: Beim Starten immer erst die mounts und dann die Prozesse starten und beim Beenden erst die Prozesse killen und dann die mounts entfernen.
Startscripte (erweitert)
Viele Prozesse starten
Sobald man eine bestimmte Anzahl Prozesse starten will tippt man sich einen Wolf, wenn man jeden Prozess einzeln stop und starten will. Dazu bietet sich dann die for-Schleife an
#!/bin/sh case "$*" in 'start') for i in cron apache2 postfix dovecot dnsmasq lighttpd webmin ; do chroot /volume1/debian /etc/init.d/$i start done ;; 'stop') for i in cron apache2 postfix dovecot dnsmasq lighttpd webmin ; do chroot /volume1/debian /etc/init.d/$i stop done ;; *) echo 'Usage stop|start' ;; esac
SSH sauber beenden
Wenn man sich im chroot einen ssh Server installiert und diesen auch nutzt gibt es zwei wichtige Punkte für den Stop-Teil des Scriptes:
1. SSH muss komplett beendet werden
2. alle Loginshells müssen beendet werden
1) ist relativ einfach. Dazu muss man einfach das Startscript anpassen
2) wird oft vergessen :-)
Solange noch eine Loginshell aktiv ist - und mit kill sshd werden Loginshells NICHT beendet - kann man den pts mount nicht entfernen. Damit würde der reboot hängen bleiben. Damit man die Loginshells alle erwischt, ist es nützlich zu wissen, dass der chroot per default bash als Login Shell nutzt und die Firmware aber sh resp ash. Damit kann man relativ einfach ein Script schreiben, welches alle Bash Prozesse beendet. Diese Lösung hat jedoch einen Nachteil: Sobald man auch in der Firmware Prozesse mit bash nutzt, werden diese natürlich auch gekillt. Daher meine Empfehlung: bash nur im chroot und sh und ash in der Firmware :-)
#!/bin/sh case "$1" in 'start') echo "$(date '+%d.%m.%Y %H:%M:%S') Starting debian chroot" mount -t proc none /volume1/debian/proc > /dev/null 2>&1 mount -t devpts devpts /volume1/debian/dev/pts > /dev/null 2>&1 for i in ssh ; do chroot /volume1/debian /etc/init.d/$i start done ;; 'stop') echo "$(date '+%d.%m.%Y %H:%M:%S') Stoping debian chroot" for i in ssh ; do chroot /volume1/debian /etc/init.d/$i stop done for i in $(ps | grep '\-bash' | grep -v grep | awk '{print $1}') ; do kill -s 9 $i > /dev/null 2>&1 done umount /volume1/debian/proc umount /volume1/debian/dev/pts ;; esac
ein Backupvolume einbinden
Hilfreich kann es sein beim Start des chroot ein Verzeichnis der Diskstation für Backups einzubinden. Dazu habe ich bei mir (chroot im RAID1 auf volume1) eine dritte Platte als Basic eingebaut (volume2), welche ich für Backups nutze.
#!/bin/sh if [ "$*" = 'start' ] ; then mkdir -p /volume1/debian/backup mount --bind /volume2/.debian_backup /volume1/debian/backup fi
natürlich den umount beim stop keinesfalls vergessen ;-) Innerhalb des chroot kann man dann nach /backup sichern und die Daten landen effektiv in /volume2/.debian_backup
Geräte aus /dev einbinden
Da das Startscript ja effektiv ausserhalb des chroots läuft kann man mittels mount --bind auch Geräte für den chroot erreichbar machen. Man könnte versucht sein einfach das gesamte /dev der Firmware in den chroot zu mounten. Das ist aber keine gute Idee, ich würde empfehlen das selektiv zu machen
#!/bin/sh if [ "$*" = 'start' ] ; then #die LED der DS für den chroot erreichbar machen mount --bind /dev/ttyS1 /volume1/debian/dev/ #eine externe HD erreichbar machen mount /dev/sdk1 /volume1/debian/dev/ fi
zum Thema LED kann man sich mal das folgende angucken
Wichtig wäre zudem beim mount einer externen Platte via /dev, dass das Gerät nicht bereits von der Firmware als volume gemounted wurde. Falls das Gerät bereits als volume von der Firmware gemountet wurde kann man sich mit mount --bind abhelfen und einfach ein Verzeichnis auf dieser Platte in den chroot mounten (siehe oben beim Backupverzeichnis mounten)
Stop des chroot verhindern solange ein Backup läuft
Es kann sehr ägerlich sein, wenn man den chroot stoppt solange noch wichtige Prozesse z.B. ein Backup am laufen sind. Das kann man realtiv einfach verhindern. Hier am Beispiel eines Backups durch den Prozess rsnapshot
#!/bin/sh if [ "$*" = 'stop' ] ; then [ -n "$(ps | grep rsnapshot | grep -v grep)" ] && echo "$(date '+%d.%m.%Y %H:%M:%S') Backup running. Delay Shutdown" while [ -n "$(ps | grep rsnapshot | grep -v grep)" ] do echo "$(date '+%d.%m.%Y %H:%M:%S') Checking again in 30s" sleep 30 echo "$(date '+%d.%m.%Y %H:%M:%S') Checking for backup running..." done echo "$(date '+%d.%m.%Y %H:%M:%S') Backup ended or not running. Resume Shutdown/Reboot" fi
eigene "Sachen" beenden
Oft hat der geneigte Administrator (aka root) ein paar Scripte am laufen, die in einer Endlosschleife laufen. Solche Script hat man z.B. wenn man ein Script öfter ausführen will als cron mininal zulässt d.h. cron kann minimal jede Minute ein Script ausführen. Wenn man das Script aber alle 25 Sekunden braucht, dann hat man eine Endlosschleife (oft mit sleep) Um solche Prozesse beim Beeenden des chroot auch beendet werden kann man folgendes benutzen
#!/bin/sh if [ "$*" = 'stop' ] ; then for i in script script.sh script1.php script2.pl script3.py sleep ; do for ii in $(ps | grep $i | grep -v grep | awk '{print $1}') ; do kill -s 9 $ii done done fi
Wichtig
Testet das Start/Stopscript für euren chroot unbedingt bevor ihr einen reboot macht. Die Wahrscheinlichkeit ist groß, dass man am Anfang noch Prozesse des chroots verpasst hat (oder mounts), welche dann den reboot verhindern würden. Ruft das Script manuell mit dem Stop-Parameter auf und prüft danach mittels htop oder top oder ps dass kein einziger Prozess des chroot noch läuft. Eine einzige Shell des chroot kann den reboot verhindern. Auch den Startparameter solltet ihr unbedingt testen, damit ihr seht ob allenfalls noch Fehler im Script sind. Nichts ist schlimmer als ein ein Fehler beim Startteil des Script, der dann den Start der DS komplett verhindern könnte. Drum testen, testen und nochmals testen :-D