Vagrant ist ein Werkzeug zum Erstellen und Verwalten von virtuellen Maschinenumgebungen in einem einheitlichen Workflow. Wer schon einmal stundenlang eine Entwicklungsumgebung konfiguriert hat, nur um danach von einem Teammitglied “bei mir läuft es” zu hören, dem schafft Vagrant Abhilfe. Die gesamte Umgebung wird in einer einzigen Datei — dem Vagrantfile — definiert, und jeder im Team kann mit einem einzigen Befehl ein identisches Setup hochfahren.
Dieser Leitfaden behandelt die Vagrant-Installation, Vagrantfile-Konfiguration, Provisioning-Strategien, Netzwerke, Multi-Machine-Setups und produktionstaugliche Workflows, die Entwicklungsumgebungen im gesamten Team konsistent halten.
Voraussetzungen
- Ein 64-Bit-Prozessor mit aktivierter Hardware-Virtualisierung (VT-x/AMD-V)
- Mindestens 8 GB RAM (4 GB für den Host, 4 GB für VMs)
- VirtualBox installiert (oder ein anderer unterstützter Provider)
- Grundkenntnisse in der Kommandozeile
- Git installiert (zum Teilen von Vagrantfiles)
Vagrant installieren und die erste VM starten
Vagrant von der offiziellen Download-Seite installieren. Paketmanager-Versionen sind oft veraltet und sollten vermieden werden.
# Installation überprüfen
vagrant --version
# Neues Projekt mit Ubuntu 22.04 initialisieren
mkdir my-project && cd my-project
vagrant init ubuntu/jammy64
# VM starten
vagrant up
# Per SSH verbinden
vagrant ssh
Beim ersten vagrant up wird das Box-Image (eine vorgefertigte VM-Vorlage) heruntergeladen und eine virtuelle Maschine erstellt. Nachfolgende Starts dauern nur Sekunden, da das Image lokal gecacht wird.
Die wichtigsten Vagrant-Befehle
vagrant up # VM erstellen und starten
vagrant ssh # Per SSH in die laufende VM einloggen
vagrant halt # VM ordnungsgemäß herunterfahren
vagrant reload # VM neu starten (übernimmt Vagrantfile-Änderungen)
vagrant destroy # VM vollständig löschen
vagrant status # VM-Zustand prüfen
vagrant provision # Provisioning-Skripte erneut ausführen
vagrant snapshot save <name> # VM-Zustand speichern
vagrant snapshot restore <name> # Auf gespeicherten Zustand zurücksetzen
Vagrantfile-Konfiguration im Detail
Das Vagrantfile ist Ruby-Code, der die VM-Konfiguration festlegt. Hier ist ein produktionsreifes Beispiel:
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.hostname = "dev-server"
# Netzwerkkonfiguration
config.vm.network "private_network", ip: "192.168.56.10"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 3000, host: 3000
# Synchronisierter Ordner (Host -> Guest)
config.vm.synced_folder "./src", "/var/www/app",
owner: "www-data", group: "www-data"
# Provider-spezifische Einstellungen
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
vb.name = "dev-server"
# Verschachtelte Virtualisierung aktivieren
vb.customize ["modifyvm", :id, "--nested-hw-virt", "on"]
end
# Shell-Provisioning
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y nginx nodejs npm
systemctl enable nginx
SHELL
end
Netzwerkmodi
Vagrant unterstützt drei Netzwerkmodi:
| Modus | Anwendungsfall | Zugriff |
|---|---|---|
| Forwarded Port | Bestimmte Guest-Ports auf den Host weiterleiten | localhost:8080 → Guest:80 |
| Private Network | VM-zu-VM-Kommunikation im Host-only-Netzwerk | 192.168.56.10 vom Host und anderen VMs |
| Public Network | Bridge zum physischen Netzwerk | VM erhält eine LAN-IP, von anderen Geräten erreichbar |
Für die Entwicklung sind private Netzwerke die sicherste Wahl. Sie ermöglichen die Kommunikation zwischen VMs, ohne Dienste dem breiteren Netzwerk preiszugeben.
Provisioning-Strategien
Vagrant unterstützt mehrere Provisioning-Methoden. Die Wahl richtet sich nach den Werkzeugen im Team:
Shell-Provisioner (einfach)
config.vm.provision "shell", path: "scripts/setup.sh"
Ansible-Provisioner (empfohlen für Teams)
config.vm.provision "ansible" do |ansible|
ansible.playbook = "provisioning/playbook.yml"
ansible.inventory_path = "provisioning/inventory"
ansible.become = true
end
Docker-Provisioner
config.vm.provision "docker" do |d|
d.pull_images "nginx"
d.pull_images "postgres:15"
d.run "nginx", args: "-p 80:80"
end
Praxisbeispiel: Ein Team aus 8 Entwicklern arbeitet an einer Webanwendung, die PostgreSQL, Redis, Nginx und Node.js benötigt. Anstatt dass jeder Entwickler diese Komponenten manuell installiert — und dabei unweigerlich unterschiedliche Versionen erhält — wird ein Vagrantfile mit Ansible-Provisioning erstellt. Ein neuer Entwickler klont das Repository, führt vagrant up aus und hat binnen 10 Minuten eine funktionierende Umgebung. Wird PostgreSQL von Version 14 auf 15 aktualisiert, genügt eine Änderung im Playbook, und beim nächsten vagrant provision erhält jeder die Aktualisierung.
Multi-Machine-Umgebungen
Vagrant glänzt besonders bei der lokalen Simulation von Produktionsarchitekturen. Mehrere VMs lassen sich in einem einzigen Vagrantfile definieren:
Vagrant.configure("2") do |config|
# Webserver
config.vm.define "web" do |web|
web.vm.box = "ubuntu/jammy64"
web.vm.hostname = "web-server"
web.vm.network "private_network", ip: "192.168.56.10"
web.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
web.vm.provision "shell", inline: <<-SHELL
apt-get update && apt-get install -y nginx
SHELL
end
# Datenbankserver
config.vm.define "db" do |db|
db.vm.box = "ubuntu/jammy64"
db.vm.hostname = "db-server"
db.vm.network "private_network", ip: "192.168.56.11"
db.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
end
db.vm.provision "shell", inline: <<-SHELL
apt-get update && apt-get install -y postgresql
SHELL
end
# Cache-Server
config.vm.define "cache" do |cache|
cache.vm.box = "ubuntu/jammy64"
cache.vm.hostname = "cache-server"
cache.vm.network "private_network", ip: "192.168.56.12"
cache.vm.provision "shell", inline: <<-SHELL
apt-get update && apt-get install -y redis-server
sed -i 's/bind 127.0.0.1/bind 0.0.0.0/' /etc/redis/redis.conf
systemctl restart redis
SHELL
end
end
Einzelne Maschinen oder alle auf einmal starten:
vagrant up web # Nur den Webserver starten
vagrant up # Alle Maschinen starten
vagrant ssh db # Per SSH in den Datenbankserver einloggen
Vagrant im Vergleich zu Alternativen
| Merkmal | Vagrant | Docker | Multipass | Nix/devenv |
|---|---|---|---|---|
| Isolation | Vollständige VM (komplettes OS) | Container (gemeinsamer Kernel) | Leichtgewichtige VM | Prozessebene |
| Startzeit | 30–120 Sekunden | 1–5 Sekunden | 10–30 Sekunden | Sofort |
| Ressourcenverbrauch | Hoch (volles OS pro VM) | Niedrig (gemeinsamer Kernel) | Mittel | Minimal |
| Mehrere OS | Ja (beliebiges OS auf beliebigem Host) | Nur Linux-Container* | Nur Ubuntu | Linux/macOS |
| Provisioning | Shell, Ansible, Chef, Puppet | Dockerfile | Cloud-init | Nix-Expressions |
| Netzwerksimulation | Ausgezeichnet (Multi-Machine) | Gut (Docker-Netzwerke) | Grundlegend | Nicht vorhanden |
| Produktionsnähe | Hoch | Sehr hoch | Mittel | Niedrig |
| Lernkurve | Flach | Mittel | Flach | Steil |
*Docker Desktop führt auf macOS/Windows eine Linux-VM aus, daher sind Container weiterhin Linux-basiert.
Wann Vagrant die bessere Wahl ist: Vollständige OS-Tests, Multi-Machine-Architekturen, plattformübergreifende Windows/Linux-Entwicklung oder wenn die Produktion auf VMs statt auf Containern läuft.
Fallstricke und Sonderfälle
-
Performance synchronisierter Ordner auf macOS/Windows: VirtualBox Shared Folders sind bei großen Codebasen notorisch langsam. Auf macOS/Linux NFS verwenden (
type: "nfs"), auf Windows SMB. Für maximale Performance eignet sich derrsync-Typ mitvagrant rsync-auto. -
Box-Versionen festschreiben: Die Box-Version immer im Vagrantfile festlegen (
config.vm.box_version = "20231215.0.0"). Ohne Pinning werden Boxes automatisch aktualisiert und können Provisioning-Skripte beschädigen. -
Speicherzuweisung: VirtualBox reserviert Arbeitsspeicher beim Start, nicht bei Bedarf. Wer einer VM 4 GB zuweist, die im Leerlauf nur 512 MB benötigt, verliert dennoch 4 GB auf dem Host. VMs daher eher knapp dimensionieren.
-
Port-Konflikte: Ist Port 8080 auf dem Host bereits belegt, schlägt
vagrant upfehl. Mitauto_correct: truebei weitergeleiteten Ports wählt Vagrant automatisch einen freien Port. -
Vagrant und WSL2: Der Betrieb von Vagrant innerhalb von WSL2 erfordert zusätzliche Konfiguration.
VAGRANT_WSL_ENABLE_WINDOWS_ACCESS=1setzen und sicherstellen, dass VirtualBox unter Windows — nicht innerhalb von WSL — installiert ist. -
Veraltete NFS-Exporte: Auf macOS können fehlgeschlagene
vagrant destroy-Aufrufe veraltete NFS-Exporte in/etc/exportshinterlassen. Bereinigung mitsudo sed -i '' '/# VAGRANT/d' /etc/exports.
Fehlerbehebung
| Problem | Ursache | Lösung |
|---|---|---|
vagrant up bleibt bei “Waiting for machine to boot” hängen | VT-x/AMD-V im BIOS deaktiviert | Virtualisierung in den BIOS-Einstellungen aktivieren |
| SSH-Verbindungs-Timeout | Netzwerkfehler in der Konfiguration | config.vm.network-Einstellungen prüfen, vagrant reload versuchen |
| Synchronisierter Ordner aktualisiert sich nicht | VirtualBox Guest Additions veraltet | Plugin installieren: vagrant plugin install vagrant-vbguest |
| ”The box could not be found” | Tippfehler im Box-Namen oder private Box | Box-Namen auf Vagrant Cloud überprüfen |
| Provisioning schlägt mittendrin fehl | Skriptfehler oder fehlende Abhängigkeit | Skript korrigieren, dann vagrant provision ausführen (idempotente Skripte helfen) |
Zusammenfassung
- Vagrant erstellt reproduzierbare Entwicklungsumgebungen, die in einem einzigen Vagrantfile definiert sind, und beseitigt damit das “bei mir läuft es”-Problem
- Provisioning mit Shell-Skripten, Ansible oder Docker automatisiert die gesamte Software-Installation innerhalb der VMs
- Multi-Machine-Setups simulieren lokale Produktionsarchitekturen mit separaten Web-, Datenbank- und Cache-Servern
- Private Netzwerke ermöglichen sichere VM-zu-VM-Kommunikation, ohne Dienste nach außen offenzulegen
- Box-Versionen festschreiben und NFS für synchronisierte Ordner verwenden, um die zwei häufigsten Vagrant-Frustrationen zu vermeiden
- Vagrant gegenüber Docker bevorzugen, wenn vollständige OS-Isolation, Multi-OS-Tests oder VM-basierte Produktionsnähe erforderlich sind