This post is all about setting up an automatic Kali Linux installation with packer and/or vagrant
General Information
The following article assumes the use of Kali Linux & Virtualbox. Vmware is not included, so changes for this have to be done manually.
Setting up a Vagrantfile as configuration for your pentesting environment is particularly useful to set up a machine on the get-go. When a machine is compromised, multiple pentesting environments with a default configuration are needed or you just want to be able to spawn new ready-to-go pentesting machines on other devices, you can just copy the Configuration file(s), run (packer &) vagrant and you're all set.
When no configuration for the installation process of the Kali image is necessary you may as well proceed right to the Vagrantfile configuration step
Technically you could do all the configuration when creating a base image with packer, but this article focuses on creating a base image with custom installation options and then modifying the system afterwards with vagrant. This allows you to have a custom base installation, while being able to automate the configuration with vagrant afterwards. So if you have to change some configuration, but need the same base installation, you don't have to run through the whole installation process again.
vagrant: tool to import boxes from either the official repositories or self-made
packer: tool to create self-made boxes (from an iso image)
Creating a custom Kali Linux image with packer
This template will be useful in order to pass custom instructions to the installation of Kali Linux, which will be automatically executed when the vm starts.
The following configuration will create a basic Kali Linux installation, you can adjust the settings as needed. Just refer to the mentioned template and add the options accordingly.
packer.json: configuration for the packer binary
preseed.cfg: configuration for the installer (here: Kali Linux)
After using packer to create a box, note that the vagrant user will have sudo permissions without requiring a password. This will be revoked when using the pre-configured Vagrantfile from this article. However if another Vagrantfile is used, you should take into account that you'll have to revoke this permission in order to have a save system.
Folder structure
The folder structure matters when the installer trys to load the preseed.cfg from the localhosts http server (that will be created automatically).
According to packer when working with a preseed file the structure should be as follows:
# Preseeding only locale sets language, country and locale.
d-i debian-installer/locale string en_US
# Keyboard selection.
d-i console-setup/ask_detect boolean false
d-i keyboard-configuration/xkb-keymap select us
choose-mirror-bin mirror/http/proxy string
### Clock and time zone setup
d-i clock-setup/utc boolean true
d-i time/zone string UTC
# Avoid that last message about the install being complete.
d-i finish-install/reboot_in_progress note
# This is fairly safe to set, it makes grub install automatically to the MBR
# if no other operating system is detected on the machine.
d-i grub-installer/only_debian boolean true
# This one makes grub-installer install to the MBR if it also finds some other
# OS, which is less safe as it might not be able to boot that other OS.
d-i grub-installer/with_other_os boolean true
### Mirror settings
# If you select ftp, the mirror/country string does not need to be set.
d-i mirror/country string manual
d-i mirror/http/hostname string http.kali.org
d-i mirror/http/directory string /kali
d-i mirror/http/proxy string
### apt setup
d-i apt-setup/kali-rolling boolean true
d-i apt-setup/non-free boolean true
d-i apt-setup/contrib boolean true
d-i apt-setup/main boolean true
### Partitioning
d-i partman-auto/method string lvm
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
# This makes partman automatically partition without confirmation.
d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
### Account setup
d-i passwd/user-fullname string vagrant
d-i passwd/user-uid string 1000
d-i passwd/user-password password vagrant
d-i passwd/user-password-again password vagrant
d-i passwd/username string vagrant
# The installer will warn about weak passwords. If you are sure you know
# what you're doing and want to override it, uncomment this.
d-i user-setup/allow-password-weak boolean true
d-i user-setup/encrypt-home boolean false
### Package selection
tasksel tasksel/first standard
d-i pkgsel/include string openssh-server coreutils build-essential
d-i pkgsel/install-language-support boolean false
# disable automatic package updates
d-i pkgsel/update-policy select none
d-i pkgsel/upgrade select none
# enable sudo without password for vagrant and start ssh for further configuration done by the Vagrantfile
d-i preseed/late_command string \
in-target systemctl enable ssh ; \
in-target usermod -G sudo vagrant ; \
echo "%vagrant ALL=NOPASSWD:ALL" > /target/etc/sudoers.d/vagrant ; \
echo "Defaults:vagrant !requiretty" >> /target/etc/sudoers.d/vagrant ; \
in-target chmod 440 /etc/sudoers.d/vagrant
packer.json
Consider changing the following options:
iso_urls => which kali image should be used (local path is also possible); images can be found here
iso_checksum => checksum of the iso file (e.g. sha1, sha256 etc.)
disk_size => size of the virtual disk to be created
With the configuration provided here, this will create a new directory and export the installed image to this directory (which can be found at builds/virtualbox-kali.box)
packer build packer.json
Configure the Kali Linux image with vagrant
Configuration options for Vagrantfiles can be found here. Something I find particularly useful are triggers, which allow you for example to execute commands before and after vagrant up.
Vagrantfile
The following configuration pulls the latest official vagrant-kali image, upgrades it and installs some packages that can be defined in the $installsoftware variable.
$upgrade =<<-SCRIPTDEBIAN_FRONTEND=noninteractive apt update# the following command omits the grub-pc prompt when upgrading (might be version specific)echo "set grub-pc/install_devices /dev/sda" | debconf-communicateDEBIAN_FRONTEND=noninteractive apt -y upgradeSCRIPT$installsoftware =<<-SCRIPT# additional software to be installed goes hereSCRIPT$vagrantcleanup =<<-SCRIPTecho "#!/bin/bash\nrm /etc/sudoers.d/vagrant\nsystemctl disable ssh\nrm VBoxGuestAdditions.iso\nrm cleanup.sh && shutdown -P now" > cleanup.sh
chown root:root cleanup.sh chmod +sx cleanup.sh ./cleanup.shSCRIPTVagrant.configure("2") do|config| config.vm.box ="kalilinux/rolling" config.vm.hostname ="kali" config.vm.provider "virtualbox"do|vb| vb.gui =true vb.cpus =1 vb.name ="kali" vb.memory ="2048"end config.ssh.username ="vagrant" config.ssh.password ="vagrant" config.vm.provision "shell", inline: $upgrade config.vm.provision "shell", inline: $installsoftware# do this one last config.vm.provision "shell", inline: $vagrantcleanup# Additional VBoxManage configuration# more information about VBoxManage are in the documentation (link in the references).# To set some options you have to shutdown the machine first.## via trigger## config.trigger.after :up do |trigger|# trigger.info = "Setting up some configuration"# trigger.ruby do |env,machine|# # the following command is used to unlock the machine state, by stopping it ungracefully (workaround)# # you can also do this by using a shutdown command and implement a small delay here # puts `VBoxManage startvm #{machine.id} --type emergencystop`# puts `VBoxManage modifyvm #{machine.id} --some-option`# end# end## or via vagrant (note that this won't be necessarily executed at the end of the configuration;# use a trigger for this)## config.vm.provider "virtualbox" do |vb|# vb.customize ["modifyvm", :id, "--some-option"]# endend
Installation
In order to have a "save" installation the default password of user vagrant has to be changed.
Installing an already existing box
When using the configuration from here, this will create a pre-configured kali linux image from the official website.
The Vagrantfile has to be in the current directory or any subdirectory starting at VAGRANT_CWD
vagrantup
Importing a self-made box and installing it
This will be necessary when a custom box has been created at this step
change the name of the box in the Vagrantfile
config.vm.box = "custom/kali"
add and install the box
vagrant box add --name custom/kali builds/virtualbox-kali.box
vagrant up
Automating the process
The following script is a quick & dirty solution to automate the installation process based on the files in the current directory and the boxes already imported into vagrant
if overwrite yes => run packer (and overwrite base image $boxpath (file) and $boxname (vagrant import) )
if $vagrantfile exists => run vagrant
if there's already an image in virtualbox with the same name/id, vagrant will most likely fail here