Headless VirtualBox auf Linux Server

Auf einem Linux Server sollen ein paar zusätzliche (virtuelle) Maschinen laufen. Diese
sollen dann einzelne Dienste übernehmen, wie z.B. mySql oder auch einen Starboundserver.

Hierbei habe ich folgende Anforderungen:

  • Eine beliebe Anzahl an zusätzlichen Maschinen
  • Eingermaßen einfache Administration
  • Keine zusätzlichen IPs nötig; das Host-Linux muss den Traffic routen
  • Virtuelle Maschinen müssen von extern erreichbar sein

KVM, Xen und wie sie alle heißen waren mir zu komplex und übertrieben für diese eigentlich
einfachen Aufgaben. Daher kam ich auf die Idee, auf dem Server die zusätzlichen Gäste mit
VirtualBox zu virtualisieren. Der Traffic wird dann über iptables zu / von den virtuellen Machinen
geroutet. Hier meine Schritte.

Installation VirtualBox

Mein Hostsystem ist ein Ubuntu Server 12.04.3 LTS, d.h. ich kann einfach die VirtualBox Sourcen
von Oracle verwenden. Also folgenden Eintrag in die /etc/apt/sources.list:

deb http://download.virtualbox.org/virtualbox/debian precise contrib

Für andere Distributionen gibt es hier die Details:https://www.virtualbox.org/wiki/Linux_Downloads
Dann noch den Key von Oracle importieren:

wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add -

Und installieren:

apt-get update
apt-get install virtualbox-4.3  --no-install-recommends

Das --no-install-recommends ist nötig, da VirtualBox ansonsten als Abhängigkeit
einen kompletten X-Server mitinstallieren möchte, was auf einen reinen Headless Server ziemlicher
Quark ist. So werden nur die nötigsten Abhängigkeiten aufgelöst (was immer noch eine Menge Pakte sind…).
Oracle empfiehlt nun noch das dkms Paket zu installieren, machen wir mit apt-get install dkms.
VirtualBox ist jetzt installieret und theoretisch einsatzbereit. Ich möchte allerdings eine „einigermaßen“
einfache Administration, also:

Installation phpVirtualBox

phpVirtualBox ist eine sehr schöne Webadministrationsoberfläche für VirtualBox, die als Vorraussetzung
nur einen Webserver mit PHP mitbringt. Ich installiere diese auf meinem nginx mit php5-fpm.
Da ich bereits VirtualBox 4.3 einsetze, benötige ich auch mindestens phpVirtualBox 4.3, diese gibt es hier
bei SourceForge: http://sourceforge.net/projects/phpvirtualbox
Ich möchte die virtuellen Maschinen nicht im root Kontext laufen lassen, daher lege ich
für diesen Zweck einen neuen Benutzer an:

adduser vboxadmin
usermod -g vboxusers vboxadmin

phpVirtualBox setzt die Web-Services von VirtualBox vorraus, damit diese funktionieren muss die
Datei /etc/default/virtualbox angelegt werden, danach sollte sich der Daemon starten lassen:

> /etc/default/virtualbox
/etc/init.d/vboxweb-service start

Damit dieser auch beim nächsten Serverreboot mit hoch kommt noch folgendes:

update-rc.d vboxweb-service defaults

Die Installation von phpVirtualBox selbst ist recht einfach, hier meine Schritte dazu:

unzip phpvirtualbox-4.3-1.zip
ln -s phpvirtualbox-4.3-1 phpvirtualbox
cd phpvirtualbox
mv config.php-example config.php

In der config.php den vorhin angelegten Benutzer vboxadmin mit dem entsprechenden
Passwort hinterlegen. Für nginx verwende ich diese Konfiguration, danach ist die Seite grundsätzlich
schon erreichbar.

server {
        listen                  1.2.3.4:80;
        server_name             hostname;
        root                    /srv/phpvirtualbox;
        index                   index.html;

        location = /favicon.ico {
                log_not_found off;
                access_log off;
        }

        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }

        location / {
                try_files $uri $uri/ /index.php?$args;
        }
        location ~ \.php$ {
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_param HTTPS on;
                include fastcgi_params;
                try_files $uri =404;
        }
        # Deny access to hidden files
        location ~ /\. {
                deny all;
                access_log off;
                log_not_found off;
        }
}

Erstellen und installieren einer VM

Das Webinterface (Login mit admin/admin, das Passwort sollte natürlich schleunigst geändert werden)
kommt der Desktop Version schon sehr nahe, wer einmal mit VirtualBox gearbeitet hat sollte sich sofort
zurechtfinden. Ich überspringe deshalb mal die Anlage einer virtuellen Maschine und komme direkt zum
nächsten Punkt.

Netzwerkkonfiguration VirtualBox

Hier wirds spannend (so denke ich 😉 ).
Das Betriebssytem in der virtuellen Maschine (bei mir der Einfachheit halber auch ein Ubuntu Linux) soll
ins Internet kommen und einzelne Ports des Systems sollen aus dem Internet erreichbar sein (z.B. SSH).
VirtualBox bietet hierfür den Host-only Adapter an. Ist dieser einer VM zugeordnet kann sie mit dem Host
reden und der Host mit der VM. Das Ganze wird über einen lokalen Netzwerkadapter bewerkstelligt.
Diesen lege ich zunächst an (das geht auch über die Weboberfläche, um zu zeigen, das sich VirtualBox auch
wunderbar über Konsole administrieren läßt mache ich diese einmaligen Schritte dort).
Um mit VBoxManage eine virtuelle Maschine administrieren zu können, muss zunächst in den
Kontext des vboxadmin Benutzers gewechselt werden:

su - vboxadmin

Jetzt schauen wir mal, ob unter Umständen der Host-Only Adapter schon angelegt wurde, dies geht mit
/sbin/ifconfig -a. Taucht hier ein „vboxnet0“ auf ist schon alles gut, wenn nicht legen wir
das Interface an und weisen es der angelegten virtuellen Maschine zu:

VBoxManage hostonlyif create
VBoxManage modifyvm "vboxserver" --nic1 hostonly

Standartmäßig legt VirtualBx den Adapter mit dem Netz 192.168.56.0/24 und einen DHCP Server an, der IPs
im Bereich 192.168.56.101-192.168.56.200 vergibt. Wenn alles funktioniert hat, hat die virtuelle Maschine
eine IP per DHCP bekommen (vermutlich die erste, also 192.168.56.101).
Da ich mich aber nicht darauf verlassen möchte, das die VM immer dieselbe IP bekommt, konfiguriere ich sie
fest auf die IP 192.168.56.10, mit dem Gateway 192.168.56.1. Da die Hostmaschine allerdings noch nicht als
Router konfiguriert ist, hat die virtuelle Maschine jetzt noch keinen Zugriff auf das Internet.

Netzwerkkonfiguration iptables

Damit das funktioniert müssen eine Handvoll iptables Regeln angelegt werden und Linux gesagt werden, das es
routen soll. Letzteres erreicht man so:

sysctl -w net.ipv4.ip_forward=1
echo "1" > /proc/sys/net/ipv4/ip_forward

Die iptables Regeln, die für das Routing und NAT nötig sind werden wie folgt angelegt:

iptables -A FORWARD -o eth0 -i vboxnet0 -s 192.168.56.0/24 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Sollten die Interfaces andere Namen haben, müssen diese natürlich geändert werden.
Die virtuelle Maschine sollte jetzt bereits Internetzugriff haben, durch die drei neuen iptables Regeln
haben wir ein einfaches NATting aufgebaut.
Für den anderen Weg, also aus dem Internet auf die virtuelle Maschine brauchen wir zusätzlich diese Regeln:

iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 20022 -j DNAT --to-destination 192.168.56.10:22
iptables -A FORWARD -p tcp -d 192.168.56.10 --dport 22 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

Dies sorgt dafür, das die Hostmaschine auf Port 20022 Verbindungen entgegen nimmt und diese an unsere
virtuelle Maschine auf Port 22 weitergibt. Die zweite Regel ist nötig, damit die Pakete den Rückweg finden.
Wenn nach einem Test alles funktioniert die Regeln speichern: iptables-save > /etc/iptables.rules

VM beim Hochfahren starten

Im Grunde sind jetzt alle Anforderungen erfüllt. Leider kann VirtualBox eine Maschine nicht beim Boot des
Hostsystems herauf- oder herunterfahren. Daher bauen wir uns noch ein kleines Init-Skript mit vi /etc/init.d/start-vm

#! /bin/sh
### BEGIN INIT INFO
# Provides:          startvms
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start VM at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

#Edit these variables!
VMUSER=vboxadmin
VMNAME="vmserver"

case "$1" in
  start)
    echo "Starting VirtualBox VM..."
    sudo -H -b -u $VMUSER /usr/bin/VBoxVRDP -s "$VMNAME"
    ;;
  stop)
    echo "Saving state of Virtualbox VM..."
    sudo -H -u  $VMUSER /usr/bin/VBoxManage controlvm "$VMNAME" savestate
    ;;
  *)
    echo "Usage: /etc/init.d/StartVM {start|stop}"
    exit 1
    ;;
esac

exit 0

Das Script noch ausführbar machen (chmod +x /etc/init.d/start-vm) und zum Systemstart
hinzufügen: update-rc.d start-vm defaults.

Fertig 🙂

2 Responses

  1. Benjamin Toth sagt:

    Warum so aufwendig, ich kann hier nur docker.io zur Virtualisierung von Diensten empfehlen.Docker brauch so gut wie kaum Speicher etc..

  2. Philipp sagt:

    Docker virtualisiert (wie du sagst) „nur“ Dienste, es ging mir hier um die vollständige Virtualisierung von kompletten Systemem.
    Mit Docker dürfte es schwierig werden einen Windows Server laufen zu lassen 😉

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.