├── .editorconfig ├── .travis.yml ├── LICENSE ├── Makefile ├── README.adoc ├── alpine-make-vm-image └── kvm ├── configure.sh ├── packages └── repositories /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 4 8 | indent_style = tab 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.{adoc,yml}] 13 | indent_size = 2 14 | indent_style = space 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: bionic 2 | sudo: required 3 | language: minimal 4 | addons: 5 | apt: 6 | packages: 7 | - qemu-utils 8 | script: 9 | - sudo ./alpine-make-vm-image 10 | --image-format qcow2 11 | --image-size 2G 12 | --repositories-file example/repositories 13 | --packages "$(cat example/packages)" 14 | --script-chroot 15 | alpine-virthardened-$(date +%Y-%m-%d).qcow2 -- ./example/configure.sh 16 | #deploy: 17 | # provider: releases 18 | # api_key: 19 | # secure: 20 | # file: "*.qcow2" 21 | # file_glob: true 22 | # skip_cleanup: true 23 | # on: 24 | # tags: true 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2017-2020 Jakub Jirutka . 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SCRIPT_NAME := alpine-make-vm-image 2 | 3 | DESTDIR := / 4 | PREFIX := /usr/local 5 | 6 | SED := sed 7 | SHA1SUM := sha1sum 8 | 9 | ifeq ($(shell uname -s),Darwin) 10 | SED := gsed 11 | SHA1SUM := shasum -a 1 12 | endif 13 | 14 | #: Update version in the script and README.adoc to $VERSION. 15 | bump-version: 16 | test -n "$(VERSION)" # $$VERSION 17 | $(SED) -E -i "s/^(readonly VERSION)=.*/\1='$(VERSION)'/" $(SCRIPT_NAME) 18 | $(SED) -E -i "s/^(:version:).*/\1 $(VERSION)/" README.adoc 19 | 20 | #: Install the script into $DESTDIR. 21 | install: 22 | mkdir -p $(DESTDIR)$(PREFIX)/bin 23 | install -m 755 $(SCRIPT_NAME) $(DESTDIR)$(PREFIX)/bin/$(SCRIPT_NAME) 24 | 25 | #: Update variable :script-sha1: in README.adoc with SHA1 checksum of the script. 26 | readme-update-checksum: 27 | $(SED) -E -i \ 28 | -e "s/^(:script-sha1:).*/\1 $(shell $(SHA1SUM) $(SCRIPT_NAME) | cut -d ' ' -f 1)/" \ 29 | README.adoc 30 | 31 | #: Bump version to $VERSION, create release commit and tag. 32 | release: .check-git-clean | bump-version readme-update-checksum 33 | test -n "$(VERSION)" # $$VERSION 34 | git add . 35 | git commit -m "Release version $(VERSION)" 36 | git tag -s v$(VERSION) -m v$(VERSION) 37 | 38 | #: Print list of targets. 39 | help: 40 | @printf '%s\n\n' 'List of targets:' 41 | @$(SED) -En '/^#:.*/{ N; s/^#: (.*)\n([A-Za-z0-9_-]+).*/\2 \1/p }' $(MAKEFILE_LIST) \ 42 | | while read label desc; do printf '%-30s %s\n' "$$label" "$$desc"; done 43 | 44 | .check-git-clean: 45 | @test -z "$(shell git status --porcelain)" \ 46 | || { echo 'You have uncommitted changes!' >&2; exit 1; } 47 | 48 | .PHONY: bump-version install readme-update-checksum release help .check-git-clean 49 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Make Alpine Linux VM Image 2 | :script-name: alpine-make-vm-image 3 | :script-sha1: a0fc0b4886b541bb4dd7b91b4e1e99719a1700da 4 | :gh-name: alpinelinux/{script-name} 5 | :version: 0.6.0 6 | 7 | ifdef::env-github[] 8 | image:https://travis-ci.org/{gh-name}.svg?branch=master["Build Status", link="https://travis-ci.org/{gh-name}"] 9 | endif::env-github[] 10 | 11 | This project provides a script for making customized https://alpinelinux.org/[Alpine Linux] disk images for virtual machines. 12 | It’s quite simple (300 LoC of shell), fast (~22 seconds on Travis CI, without Travis VM initialization) and requires minimum dependencies (QEMU and filesystem tools). 13 | 14 | TIP: Don’t need VM, just want to chroot into Alpine Linux (e.g. on CI)? 15 | Try https://github.com/alpinelinux/alpine-chroot-install[alpine-chroot-install]! 16 | 17 | 18 | == Requirements 19 | 20 | * Linux system with common userland (Busybox or GNU coreutils) 21 | * POSIX-sh compatible shell (e.g. Busybox ash, dash, Bash, ZSH) 22 | * qemu-img and qemu-nbd (automatically installed by the script if running on Alpine) 23 | * e2fsprogs (for ext4), btrfs-progs (for Btrfs), or xfsprogs (for XFS) (automatically installed by the script if running on Alpine) 24 | 25 | 26 | == Usage 27 | 28 | Read documentation in link:{script-name}[{script-name}]. 29 | See link:.travis.yml[.travis.yml] for Travis example. 30 | 31 | You can copy link:{script-name}[{script-name}] into your repository or download it on demand, e.g.: 32 | 33 | [source, sh, subs="+attributes"] 34 | wget https://raw.githubusercontent.com/{gh-name}/v{version}/{script-name} \ 35 | && echo '{script-sha1} {script-name}' | sha1sum -c \ 36 | || exit 1 37 | 38 | 39 | == Pitfalls 40 | 41 | === Creating Image for VMware (ESXi) 42 | 43 | VMware and disk images (virtual disks) is one big mess. 44 | You can find that VMware uses the VMDK format, but the problem is that this is not a single format. 45 | Actually it has many subformats with very different structure and various (in)compatibility with VMware hypervisors. 46 | 47 | When I’ve created a disk image using `qemu-img create -f vmdk` or converted Qcow2 to VMDK using `qemu-img convert -O vmdk`, vSphere client loaded this image without any problem, but the data was corrupted. 48 | Eventually I found in some old documentation that ESXi does not support “sparse” disks… 49 | 50 | So after many trials I found out that the least bad and functional solution is to create Qcow2 image and then convert it to VMDK using: 51 | 52 | [source, sh] 53 | qemu-img convert -f qcow2 -O vmdk -o adapter_type=lsilogic,subformat=monolithicFlat alpine.qcow2 alpine.vmdk 54 | 55 | Unfortunately, this creates a “thick” image, i.e. its size equals the “provisioned space”, not actually used space as in Qcow2. 56 | However, you can compress it with gzip to avoid transferring multiple gigabytes of zeros over network. 57 | 58 | 59 | == License 60 | 61 | This project is licensed under http://opensource.org/licenses/MIT/[MIT License]. 62 | For the full text of the license, see the link:LICENSE[LICENSE] file. 63 | -------------------------------------------------------------------------------- /alpine-make-vm-image: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim: set ts=4: 3 | #---help--- 4 | # Usage: alpine-make-vm-image [options] [--] [