Vagrant automatisiert die Erstellung und Verwaltung von virtuellen Entwicklungsumgebungen. Es ermöglicht reproduzierbare Setups über verschiedene Plattformen hinweg.

Installation

Voraussetzungen

# VirtualBox (Standard-Provider)
apt install virtualbox

# Oder libvirt
apt install qemu-kvm libvirt-daemon-system

Vagrant installieren

# Debian/Ubuntu
wget https://releases.hashicorp.com/vagrant/2.4.0/vagrant_2.4.0-1_amd64.deb
dpkg -i vagrant_2.4.0-1_amd64.deb

# Version prüfen
vagrant version

Plugins

# Nützliche Plugins
vagrant plugin install vagrant-vbguest
vagrant plugin install vagrant-disksize
vagrant plugin install vagrant-hostmanager

Grundlagen

Projekt initialisieren

mkdir myproject && cd myproject
vagrant init ubuntu/jammy64

Vagrantfile (Grundstruktur)

# Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/jammy64"

  config.vm.network "private_network", ip: "192.168.56.10"
  config.vm.network "forwarded_port", guest: 80, host: 8080

  config.vm.synced_folder "./app", "/var/www/html"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = "2048"
    vb.cpus = 2
  end

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y nginx
  SHELL
end

Grundbefehle

vagrant up        # VM starten
vagrant halt      # VM stoppen
vagrant reload    # Neustart
vagrant destroy   # VM löschen
vagrant ssh       # SSH-Verbindung
vagrant status    # Status anzeigen
vagrant provision # Provisioning erneut ausführen

Boxes

Box suchen

# Vagrant Cloud
https://app.vagrantup.com/boxes/search

# Beliebte Boxes
ubuntu/jammy64    # Ubuntu 22.04
debian/bookworm64 # Debian 12
centos/stream9    # CentOS Stream 9
generic/rocky9    # Rocky Linux 9

Box verwalten

# Box hinzufügen
vagrant box add ubuntu/jammy64

# Boxes auflisten
vagrant box list

# Box aktualisieren
vagrant box update

# Box entfernen
vagrant box remove ubuntu/jammy64

Eigene Box

# Aus bestehender VM
vagrant package --output mybox.box

# Box registrieren
vagrant box add mybox ./mybox.box

Netzwerk

Private Network

# Feste IP
config.vm.network "private_network", ip: "192.168.56.10"

# DHCP
config.vm.network "private_network", type: "dhcp"

Public Network (Bridged)

# Mit DHCP
config.vm.network "public_network"

# Mit Interface
config.vm.network "public_network", bridge: "eth0"

Port Forwarding

# Einzelner Port
config.vm.network "forwarded_port", guest: 80, host: 8080

# Mit Protocol
config.vm.network "forwarded_port", guest: 3306, host: 3306, protocol: "tcp"

# Auto-Korrektur bei Konflikt
config.vm.network "forwarded_port", guest: 80, host: 8080, auto_correct: true

Synced Folders

Standard-Sync

# Projektverzeichnis ist automatisch unter /vagrant verfügbar

# Zusätzlicher Ordner
config.vm.synced_folder "./app", "/var/www/html"

# Berechtigungen
config.vm.synced_folder "./app", "/var/www/html",
  owner: "www-data", group: "www-data"

NFS (Performance)

config.vm.synced_folder "./app", "/var/www/html", type: "nfs"

Rsync

config.vm.synced_folder "./app", "/var/www/html",
  type: "rsync",
  rsync__exclude: [".git/", "node_modules/"]

Provisioning

Shell

# Inline
config.vm.provision "shell", inline: <<-SHELL
  apt-get update
  apt-get install -y nginx
SHELL

# Externes Skript
config.vm.provision "shell", path: "scripts/setup.sh"

# Mit Argumenten
config.vm.provision "shell" do |s|
  s.path = "scripts/setup.sh"
  s.args = ["--env", "development"]
end

Ansible

config.vm.provision "ansible" do |ansible|
  ansible.playbook = "playbook.yml"
  ansible.inventory_path = "inventory"
  ansible.extra_vars = {
    env: "development"
  }
end

# Ansible Local (in der VM)
config.vm.provision "ansible_local" do |ansible|
  ansible.playbook = "playbook.yml"
end

Docker

config.vm.provision "docker" do |d|
  d.pull_images "nginx"
  d.run "nginx",
    args: "-p 80:80 -v /vagrant:/usr/share/nginx/html:ro"
end

Puppet

config.vm.provision "puppet" do |puppet|
  puppet.manifests_path = "manifests"
  puppet.manifest_file = "default.pp"
end

Multi-Machine

Mehrere VMs

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/jammy64"

  config.vm.define "web" do |web|
    web.vm.hostname = "web"
    web.vm.network "private_network", ip: "192.168.56.10"
    web.vm.provision "shell", inline: "apt-get install -y nginx"
  end

  config.vm.define "db" do |db|
    db.vm.hostname = "db"
    db.vm.network "private_network", ip: "192.168.56.11"
    db.vm.provision "shell", inline: "apt-get install -y mysql-server"
  end
end

Mit Loop

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/jammy64"

  (1..3).each do |i|
    config.vm.define "node#{i}" do |node|
      node.vm.hostname = "node#{i}"
      node.vm.network "private_network", ip: "192.168.56.#{10+i}"
    end
  end
end

Befehle für Multi-Machine

# Alle starten
vagrant up

# Bestimmte VM
vagrant up web
vagrant ssh db
vagrant halt db

Provider-Konfiguration

VirtualBox

config.vm.provider "virtualbox" do |vb|
  vb.name = "my-vm"
  vb.memory = "4096"
  vb.cpus = 4

  # GUI aktivieren
  vb.gui = true

  # Nested Virtualization
  vb.customize ["modifyvm", :id, "--nested-hw-virt", "on"]

  # Clipboard
  vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"]
end

Libvirt

config.vm.provider "libvirt" do |libvirt|
  libvirt.memory = 4096
  libvirt.cpus = 4
  libvirt.driver = "kvm"
  libvirt.storage_pool_name = "default"
end

VMware

config.vm.provider "vmware_desktop" do |vmware|
  vmware.vmx["memsize"] = "4096"
  vmware.vmx["numvcpus"] = "4"
end

Praktische Beispiele

LAMP-Stack

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/jammy64"
  config.vm.hostname = "lamp"
  config.vm.network "private_network", ip: "192.168.56.10"
  config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.synced_folder "./www", "/var/www/html"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = "2048"
  end

  config.vm.provision "shell", inline: <<-SHELL
    export DEBIAN_FRONTEND=noninteractive

    apt-get update
    apt-get install -y apache2 mysql-server php php-mysql libapache2-mod-php

    # MySQL sichern
    mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'vagrant';"

    # Apache starten
    systemctl enable apache2
    systemctl start apache2
  SHELL
end

Kubernetes-Cluster

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/jammy64"

  config.vm.define "master" do |master|
    master.vm.hostname = "k8s-master"
    master.vm.network "private_network", ip: "192.168.56.10"
    master.vm.provider "virtualbox" do |vb|
      vb.memory = "4096"
      vb.cpus = 2
    end
  end

  (1..2).each do |i|
    config.vm.define "worker#{i}" do |worker|
      worker.vm.hostname = "k8s-worker#{i}"
      worker.vm.network "private_network", ip: "192.168.56.#{10+i}"
      worker.vm.provider "virtualbox" do |vb|
        vb.memory = "2048"
        vb.cpus = 2
      end
    end
  end

  config.vm.provision "shell", path: "scripts/common.sh"
end

Docker-Entwicklung

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/jammy64"
  config.vm.hostname = "docker-dev"
  config.vm.network "private_network", ip: "192.168.56.10"

  # Ports für Container
  config.vm.network "forwarded_port", guest: 3000, host: 3000
  config.vm.network "forwarded_port", guest: 5432, host: 5432

  config.vm.synced_folder "./", "/vagrant", type: "nfs"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = "4096"
    vb.cpus = 2
  end

  config.vm.provision "docker"
  config.vm.provision "docker_compose",
    compose_version: "2.23.0"
end

Tipps und Tricks

SSH-Konfiguration exportieren

vagrant ssh-config >> ~/.ssh/config

# Danach direkt:
ssh vagrant-vm-name

Snapshots

# Snapshot erstellen
vagrant snapshot save before-update

# Snapshots auflisten
vagrant snapshot list

# Snapshot wiederherstellen
vagrant snapshot restore before-update

# Snapshot löschen
vagrant snapshot delete before-update

Disk-Größe

# Mit vagrant-disksize Plugin
config.disksize.size = "50GB"

Performance

# VirtualBox Paravirtualization
config.vm.provider "virtualbox" do |vb|
  vb.customize ["modifyvm", :id, "--paravirtprovider", "kvm"]
end

# NFS für Synced Folders
config.vm.synced_folder "./", "/vagrant", type: "nfs"

Troubleshooting

Häufige Probleme

# VM hängt beim Booten
# → Netzwerk-Adapter prüfen
vagrant reload

# Synced Folder funktioniert nicht
# → Guest Additions installieren
vagrant plugin install vagrant-vbguest
vagrant reload

# SSH-Timeout
# → Netzwerk prüfen, VirtualBox Netzwerk-Adapter

Logs

# Debug-Modus
VAGRANT_LOG=debug vagrant up

# VirtualBox Logs
cat ~/VirtualBox\ VMs/vm-name/Logs/VBox.log

Zusammenfassung

| Befehl | Funktion | |--------|----------| | vagrant up | VM starten | | vagrant halt | VM stoppen | | vagrant ssh | SSH-Verbindung | | vagrant destroy | VM löschen | | vagrant provision | Provisioning | | vagrant snapshot | Snapshots |

| Provider | Beschreibung | |----------|--------------| | VirtualBox | Standard, kostenlos | | VMware | Kommerziell | | Libvirt/KVM | Linux-nativ | | Docker | Container | | Hyper-V | Windows |

| Provisioner | Verwendung | |-------------|------------| | Shell | Einfache Skripte | | Ansible | Configuration Management | | Docker | Container | | Puppet | Configuration Management |

Fazit

Vagrant macht Entwicklungsumgebungen reproduzierbar und portabel. Mit einem Vagrantfile können alle Teammitglieder identische Umgebungen nutzen. Die Integration mit Provisioning-Tools wie Ansible ermöglicht komplexe Setups. Für produktionsnahe Entwicklung ist Vagrant unschlagbar praktisch. Mit Multi-Machine-Setups lassen sich auch verteilte Systeme lokal testen.