This is the build script to create the Kali Linux Virtual Machine (VM) images.
Currently there are two build methods are possible:
build.sh
- build straight from your machinebuild-in-container.sh
- build from within a container (Docker or Podman)
Either way, the build actually happens from within a virtual machine that is created on-the-fly by the build tool debos. Debos uses fakemachine under the hood, which in turn relies on QEMU/KVM.
Make sure that the git repository is cloned locally:
$ sudo apt install -y git
$ git clone https://gitlab.com/kalilinux/build-scripts/kali-vm.git
$ cd kali-vm/
Due to the requirements of QEMU/KVM, you must be part of the kvm
group.
You can check by doing:
$ # Not apart of the group
$ grep kvm /etc/group
kvm:x:104:
$
$ # In the group
$ grep kvm /etc/group
kvm:x:104:kali
If your username does not appear in the line returned, it means that you are not in the group, and you must add yourself to the kvm
group:
$ sudo adduser $USER kvm
Then log out and log back in for the change to take effect.
If building straight from your machine, using build.sh
, you will need to install debos
:
$ sudo apt install -y debos p7zip qemu-utils zerofree
Then use the script build.sh
to build an VM image directly on your machine.
If you prefer to build from within a container, you will need to install and configure either docker
or podman
on your machine.
Then use the script build-in-container.sh
to build a image.
build-in-container.sh
is simply a wrapper on top of build.sh
.
It will detect which OCI-compliant container engine to use, takes care of creating the container image if missing, and then finally it starts the container to perform the build from within.
docker
requires the user to be added to the Docker group, just like the above with KVM, or using the root account (e.g. $ sudo ./build-in-container.sh
).
podman
has been tested with both as rootful (e.g. $ sudo ./build-in-container.sh
) and rootless (e.g. $ ./build-in-container.sh
).
Use either build.sh
or build-in-container.sh
, at your preference.
From this point we will use build.sh
for brevity.
The best starting point, as always, is the usage message:
$ ./build.sh -h
Usage: build.sh <options> [-- <debos options>]
Build a Kali Linux VM image
Build options:
-a ARCH Build an image for this architecture, default: amd64
Supported values: amd64 i386
-b BRANCH Kali branch used to build the image, default: kali-rolling
Supported values: kali-dev kali-last-snapshot kali-rolling
-f FORMAT Format to export the image to, default depends on the VARIANT
Supported values: hyperv ova ovf qemu raw virtualbox vmware
-k Keep raw disk image and other intermediary build artifacts
-m MIRROR Mirror used to build the image, default: http://http.kali.org/kali
-r ROOTFS rootfs to use to build the image, default: none
-s SIZE Size of the disk image in GB, default: 86
-v VARIANT Variant of image to build (see below for details), default: generic
Supported values: generic hyperv qemu rootfs virtualbox vmware
-x VERSION What to name the image release as, default: rolling
-z Zip images and metadata files after the build
Customization options:
-D DESKTOP Desktop environment installed in the image, default: xfce
Supported values: e17 gnome i3 kde lxde mate xfce none
-L LOCALE Set locale, default: en_US.UTF-8
-P PACKAGES Install extra packages (comma/space separated list)
-T TOOLSET The selection of tools to include in the image, default: default
Supported values: default everything headless large none
-U USERPASS Username and password, separated by a colon, default: kali:kali
-Z TIMEZONE Set timezone, default: America/New_York
The different variants of images are:
generic Image with all virtualization support pre-installed, default format: raw
hyperv Image pre-configured for Hyper-V "Enhanced Session Mode", default format: hyperv
qemu Image with QEMU and SPICE guest agents pre-installed, default format: qemu
rootfs Not an image, a root filesystem (no bootloader/kernel), packed in a .tar.gz
virtualbox Image with VirtualBox guest utilities pre-installed, default format: virtualbox
vmware Image with Open VM Tools pre-installed, default format: vmware
The different formats are:
hyperv VHDX disk image, powershell install scripts
ova streamOptimized VMDK disk image, OVF metadata file, packed in a OVA archive
ovf monolithicSparse VMDK disk image, OVF metadata file
qemu QCOW2 disk image, no metadata
raw sparse disk image, no metadata
virtualbox VDI disk image, .vbox metadata file
vmware 2GbMaxExtentSparse VMDK disk image, VMX metadata file
Supported environment variables:
http_proxy HTTP proxy URL, refer to the README.md for more details
Most useful debos options:
--artifactdir DIR Set artifact directory, default: images
--memory, -m SIZE Limit amount of memory to build VM in GB, default: 4G
--scratchsize SIZE Limit amount of HDD to build VM in GB, default: 45G
--debug-shell Get a shell on the VM
--help, -h See the complete list of options for debos
Refer to the README.md for examples
The default options will build a Kali rolling image, default desktop and default toolset for AMD64 architecture.
This is a raw disk image, i.e. a plain binary image of the disk (which can be started with QEMU).
Example:
$ ./build.sh
To build a Kali Linux image tailored for VMware. It means that it comes with the Open VM Tools pre-installed, and the image produced is ready to be imported "as is" in VMware.
Also, we are going to build it from the last stable release of Kali, and we will using GNOME as the desktop environment, rather than the usual default Xfce:
./build.sh -v vmware -b kali-last-snapshot -D gnome
To build a Kali Linux image designed for VirtualBox. It comes with the VirtualBox guest utilities pre-installed, and the image can be imported "as is" in VirtualBox.
Moreover, we want a 150 GB virtual disk, and we will install the "everything" tool selection:
./build.sh -v virtualbox -s 150 -S everything
To build a lightweight Kali image, which has no desktop environment and no default toolset. This is a generic image, it comes with support for most VM engines out there. We will export it to the OVA format, suitable for both VMware and VirtualBox.
You can install additional packages with the -P
option.
Either use the option several times (e.g. -P pkg1 -P pkg2 ...
), or give a comma/space separated value (e.g. -P "pkg1,pkg2, pkg3 pkg4"
), or a mix of both.
Let's also install the package metasploit-framework
:
./build.sh -v generic -f ova -D headless -P metasploit-framework
To set the locale
, use the option -L
.
Pick a value in the 1st column of /usr/share/i18n/SUPPORTED
, or check what's configured on your system with grep -v ^# /etc/locale.gen
, or simply echo $LANG
.
There is also a shortcut of -L same
to match the host system.
To set the timezone
, use the option -Z
.
Look into /usr/share/zoneinfo
and pick a directory and a sub-directory.
In doubt, run tzselect
to guide you, or look at what's configured on your system with realpath /etc/localtime
.
There is also a shortcut of -Z same
to match the host system.
To set the name and password for the unprivileged user, use the option -U
.
The value is a single string and the :
is used to separate the username from the password.
Here we will build a Kali image, and configure it to mimic the host system: same locale and same timezone and same username (with the password of password
):
./build.sh -L same -Z same -U $USER:password
Different variants of image can be built, depending on what VM engine you want to run the Kali image in. The VARIANT mostly defines what extra package gets installed into the image, to add support for a particular VM engine. Then the FORMAT defines what format for the virtual disk, and what additional metadata files to produce.
If unset, the format (option -f
) is automatically set according to the variant (option -v
).
Not every combination of variant and format make sense, so the table below tries to summarize the most common combinations.
variant | format | disk format | metadata | pack |
---|---|---|---|---|
generic | raw | raw (sparse file) | none | |
generic | ova | streamOptimized VMDK | OVF | OVA |
generic | ovf | monolithicSparse VMDK | OVF | |
qemu | qemu | QCOW2 | none | |
virtualbox | virtualbox | VDI | VBOX | |
vmware | vmware | 2GbMaxExtentSparse VMDK | VMX |
The generic
images come with virtualization support packages pre-installed for QEMU, VirtualBox and VMware, hence the name "generic".
While other images, that target a specific VM engine, only come with support for this particular virtualization engine.
Only the format ova
defines a container: the result of the build is a .ova
file, which is simply a tar archive.
For other formats, the build produce separate files.
They can be bundled together in a 7z archive with the option -z
.
There is also a rootfs
type: this is not an image.
It's simply a Kali Linux root filesystem tree, without the kernel and the bootloader, and packed in a .tar.gz
archive.
The main use-case is to reuse it as input to build an OS image, and it's not meant to be used outside of the build system.
When building OS images, it is useful to have a caching mechanism in place, to avoid having to download all the packages from the Internet, again and again.
To this effect, the build script attempts to detect known caching proxies that would be running on the local host, such as apt-cacher-ng
, approx
and squid-deb-proxy
.
Alternatively, you can setup a local mirror.
To override this detection, you can export the environment variable http_proxy
yourself.
However, you should remember that the build happens within a QEMU Virtual Machine, therefore localhost
in the build environment refers to the VM, not to the host.
If you want to reach the host from the VM, you probably want to use http://10.0.2.2
.
For example, if you want to use a proxy that is running on your machine on the port 9876, use: export http_proxy=10.0.2.2:9876
.
If you want to make sure that no proxy is used: export http_proxy= ./build.sh [...]
.
Also refer to https://github.com/go-debos/debos#environment-variables for more details.
It's possible to break the build in two steps.
You can first build a rootfs with ./build.sh -v rootfs
, and then build an image based on this rootfs with ./build.sh -r ROOTFS_NAME.tar.gz
.
It makes sense if you plan to build several image types, for example.
When the scratch area gets full (i.e. the --scratchsize
value is too low), the build might fail with this kind of error messages:
[...]: failed to write (No space left on device)
[...]: Cannot write: No space left on device
Solution: bump the value of --scratchsize
.
You can pass arguments to debos after the special character --
, so if you need for example 50G, you can do ./build.sh [...] -- --scratchsize=50G
.
When debugging build failures, it's convenient to be dropped in a shell within the VM where the build takes place.
This is possible by giving the option --debug-shell
to debos: ./build.sh [...] -- --debug-shell
.
This is a known issue, refer to https://gitlab.com/kalilinux/build-scripts/kali-vm/-/issues/25#note_1301070132 for a workaround.