I wanted a clean VM for compiling some software. Since the host computer is headless, and I rarely run a desktop on it, I wanted the build and VM to be purely console-based, accessed over SSH.
Obtain installer ISO
Download the "Current weekly snapshot" CD ISO image linked from here: https://www.debian.org/releases/testing/
I usually rename these images to have the date I downloaded it, in the filename, so I called it debian-testing-amd64-netinst.2016-05-04.iso
and stuck it in my ~/ISO
directory.
Setup
Make working directory, and create an empty 8GB HDD image to install into.
user@vmhost:~$ mkdir VM/debian_testing
user@vmhost:~$ cd VM/debian_testing
user@vmhost:~/VM/debian_testing$
user@vmhost:~/VM/debian_testing$ qemu-img create -f qcow2 sda_8G.qcow2 8G
Formatting 'sda_8G.qcow2', fmt=qcow2 size=8589934592 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
Get the kernel and initrd
Mount the CD, find out where the kernel and initrd are, and copy them out.
user@vmhost:~/VM/debian_testing$ sudo mount ~/ISO/debian-testing-amd64-netinst.2016-05-04.iso mnt
mount: /dev/loop2 is write-protected, mounting read-only
user@vmhost:~/VM/debian_testing$ grep Expert -A4 mnt/boot/grub/grub.cfg
menuentry '... Expert install' {
set background_color=black
linux /install.amd/vmlinuz priority=low vga=788 ---
initrd /install.amd/initrd.gz
}
user@vmhost:~/VM/debian_testing$ cp mnt/install.amd/vmlinuz vmlinuz_install
'mnt/install.amd/vmlinuz' -> 'vmlinuz_install'
user@vmhost:~/VM/debian_testing$ cp mnt/install.amd/initrd.gz initrd_install.gz
'mnt/install.amd/initrd.gz' -> 'initrd_install.gz'
user@vmhost:~/VM/debian_testing$ sudo umount mnt
Setup script
These are the files I have, and the content of my initial boot script:
user@vmhost:~/VM/debian_testing$ ls
go_cd_boot.sh initrd_install.gz sda_8G.qcow2 vmlinuz_install
user@vmhost:~/VM/debian_testing$ cat go_cd_boot.sh
#! /bin/sh
qemu-system-x86_64 \
-kernel vmlinuz_install \
-initrd initrd_install.gz \
-append "priority=low console=ttyS0" \
-hda sda_8G.qcow2 \
-cdrom /home/user/ISO/debian-testing-amd64-netinst.2016-05-04.iso \
-net nic \
-net user \
-m 1024 \
-enable-kvm \
-nographic
Start it up!
user@vmhost:~/VM/debian_testing$ ./go_cd_boot.sh
Install Debian
I chose things which suited me - mostly just defaults. When it asked for tasks, I deselected everything but the ssh server
task.
Note, you can find out what the tasks consist of like this (run on a Debian system - this is somewhat chicken/egg if you haven't yet got a Debian system built):
user@vmhost:~/ISO$ sudo tasksel --list-tasks
i desktop Debian desktop environment
u gnome-desktop GNOME
u xfce-desktop Xfce
u kde-desktop KDE
u cinnamon-desktop Cinnamon
u mate-desktop MATE
i lxde-desktop LXDE
u web-server web server
u print-server print server
i ssh-server SSH server
u laptop laptop
user@vmhost:~/ISO$ sudo tasksel --task-packages ssh-server
task-ssh-server
user@vmhost:~/ISO$ sudo aptitude show task-ssh-server
Package: task-ssh-server
State: installed
Automatically installed: no
Version: 3.34
Priority: optional
Section: tasks
Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
Architecture: all
Uncompressed Size: 6,144
Depends: tasksel (= 3.34), openssh-server
Recommends: openssh-client
Description: SSH server
This task sets up your system to be remotely accessed through SSH connections.
Also see http://www.csmojo.com/2015/07/what-debians-standard-system-utilities.html for info on the "standard system utilities" task.
Finish install
Finish the installation process, then shut down the VM. Actually, I let it reboot into the installer, then killed qemu - not exactly elegant. You should be able to use the qemu monitor to unmount the CD image, then reboot into the installed system - if you're doing this then you'll need to edit the boot options when the grub menu pops up.
First real boot
This is my boot script:
user@vmhost:~/VM/debian_testing$ cat go.sh
#! /bin/sh
qemu-system-x86_64 \
-hda sda_8G.qcow2 \
-net nic \
-net user \
-m 1024 \
-enable-kvm \
-nographic
Start it up and be ready to press an arrow key...
user@vmhost:~/VM/debian_testing$ ./go.sh
Wait for this screen to appear, then press cursor-down (fairly soon after the screen appears) to let it know that you want to do something. If you wait too long, it'll start booting, and won't be set for serial console, so you won't see what you need to see - in which case you probably need to kill qemu (or maybe use the qemu monitor to shut it down).
GNU GRUB version 2.02~beta2-36
+----------------------------------------------------------------------------+
|*Debian GNU/Linux |
| Advanced options for Debian GNU/Linux |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
+----------------------------------------------------------------------------+
Use the ^ and v keys to select which entry is highlighted.
Press enter to boot the selected OS, `e' to edit the commands
before booting or `c' for a command-line.
Move the cursor (the asterisk "*") to the first line and press e
to edit it. Scroll down to the linux
line
GNU GRUB version 2.02~beta2-36
+----------------------------------------------------------------------------+
| search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --\|^
|hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 3bd74887-1631-43fd-ada5-\|
|8e00892b5dd9 |
| else |
| search --no-floppy --fs-uuid --set=root 3bd74887-1631-43fd-ada5-8\|
|e00892b5dd9 |
| fi |
| echo 'Loading Linux 4.5.0-1-amd64 ...' |
| linux /boot/vmlinuz-4.5.0-1-amd64 root=/dev/sda1 ro quiet |
| echo 'Loading initial ramdisk ...' |
| initrd /boot/initrd.img-4.5.0-1-amd64 |
| |
+----------------------------------------------------------------------------+
Minimum Emacs-like screen editing is supported. TAB lists
completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for
a command-line or ESC to discard edits and return to the GRUB menu.
Delete that annoying quiet
option (quiet is for people who are afraid to know what their computer is doing) and replace it with console=ttyS0,115200
GNU GRUB version 2.02~beta2-36
+----------------------------------------------------------------------------+
|hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 3bd74887-1631-43fd-ada5-\|^
|8e00892b5dd9 |
| else |
| search --no-floppy --fs-uuid --set=root 3bd74887-1631-43fd-ada5-8\|
|e00892b5dd9 |
| fi |
| echo 'Loading Linux 4.5.0-1-amd64 ...' |
| linux /boot/vmlinuz-4.5.0-1-amd64 root=/dev/sda1 ro console=\|
|ttyS0,115200 |
| echo 'Loading initial ramdisk ...' |
| initrd /boot/initrd.img-4.5.0-1-amd64 |
| |
+----------------------------------------------------------------------------+
Minimum Emacs-like screen editing is supported. TAB lists
completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for
a command-line or ESC to discard edits and return to the GRUB menu.
Press Ctrl-X
and wait for it to boot
Booting a command list
Loading Linux 4.5.0-1-amd64 ...
Loading initial ramdisk ...
[ 0.000000] Linux version 4.5.0-1-amd64 (debian-kernel@lists.debian.org) (gcc version 5.3.1 20160409 (Debian 5.3.1-14) ) #1 SMP Debian 4.5.1-1 (2016-04-14)
[ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.5.0-1-amd64 root=/dev/sda1 ro console=ttyS0,115200
[ 0.000000] x86/fpu: Legacy x87 FPU detected.
...SNIP...
[ OK ] Reached target Graphical Interface.
Starting Update UTMP about System Runlevel Changes...
[ OK ] Started Update UTMP about System Runlevel Changes.
Debian GNU/Linux stretch/sid testing ttyS0
testing login:
Make console boot permanent
Login using whatever credentials you setup for the root
user. Use vi
to edit grub options. The listing here shows which things I changed (I usually also set the timeout to be 1s):
root@testing:~# vi /etc/default/grub
root@testing:~# grep -A2 KMW /etc/default/grub
# KMW 2016-05-04 - change to serial console and get rid of stupid quiet
#GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX_DEFAULT="console=ttyS0,115200"
--
# KMW 2016-05-04 - change to serial console
#GRUB_TERMINAL=console
GRUB_TERMINAL=console
--
# KMW 2016-05-04 - increase speed, in case it makes a difference
#GRUB_SERIAL_COMMAND="serial --unit=0 --speed=9600 --stop=1"
GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200 --stop=1"
Run update-grub
to update the actual files read at boot time. I saw a few error messages, but they appear not to be relevant.
root@testing:~# update-grub
[ 278.405923] device-mapper: uevent: version 1.0.3
[ 278.410901] device-mapper: ioctl: 4.34.0-ioctl (2015-10-28) initialised: dm-devel@redhat.com
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.5.0-1-amd64
Found initrd image: /boot/initrd.img-4.5.0-1-amd64
[ 279.213528] SGI XFS with ACLs, security attributes, realtime, no debug enabled
[ 279.232881] JFS: nTxBlock = 7971, nTxLock = 63774
[ 279.271794] ntfs: driver 2.1.32 [Flags: R/O MODULE].
[ 279.314018] QNX4 filesystem 0.2.3 registered.
[ 279.404671] raid6: sse2x1 gen() 1133 MB/s
[ 279.472672] raid6: sse2x1 xor() 2203 MB/s
[ 279.540708] raid6: sse2x2 gen() 1027 MB/s
[ 279.608673] raid6: sse2x2 xor() 2551 MB/s
[ 279.676667] raid6: sse2x4 gen() 1633 MB/s
[ 279.744675] raid6: sse2x4 xor() 1805 MB/s
[ 279.747849] raid6: using algorithm sse2x4 gen() 1633 MB/s
[ 279.751961] raid6: .... xor() 1805 MB/s, rmw enabled
[ 279.756338] raid6: using intx1 recovery algorithm
[ 279.764205] xor: measuring software checksum speed
[ 279.804668] prefetch64-sse: 6775.000 MB/sec
[ 279.844670] generic_sse: 6120.000 MB/sec
[ 279.847586] xor: using function: prefetch64-sse (6775.000 MB/sec)
[ 279.884725] Btrfs loaded
[ 279.902527] fuse init (API version 7.24)
[ 280.004351] EXT4-fs (sda2): unable to read superblock
[ 280.010945] EXT4-fs (sda2): unable to read superblock
[ 280.017672] EXT4-fs (sda2): unable to read superblock
[ 280.025434] XFS (sda2): Invalid superblock magic number
[ 280.039873] FAT-fs (sda2): utf8 is not a recommended IO charset for FAT filesystems, filesystem will be case sensitive!
[ 280.049289] FAT-fs (sda2): bogus number of reserved sectors
[ 280.053966] FAT-fs (sda2): Can't find a valid FAT filesystem
[ 280.062174] FAT-fs (sda2): utf8 is not a recommended IO charset for FAT filesystems, filesystem will be case sensitive!
[ 280.074227] FAT-fs (sda2): bogus number of reserved sectors
[ 280.079580] FAT-fs (sda2): Can't find a valid FAT filesystem
[ 280.092136] ntfs: (device sda2): read_ntfs_boot_sector(): Primary boot sector is invalid.
[ 280.100723] ntfs: (device sda2): read_ntfs_boot_sector(): Mount option errors=recover not used. Aborting without trying to recover.
[ 280.108948] ntfs: (device sda2): ntfs_fill_super(): Not an NTFS volume.
[ 280.116124] MINIX-fs: unable to read superblock
[ 280.123983] attempt to access beyond end of device
[ 280.128096] sda2: rw=16, want=3, limit=2
[ 280.132866] hfsplus: unable to find HFS+ superblock
[ 280.141723] qnx4: no qnx4 filesystem (no root dir).
[ 280.150349] ufs: You didn't specify the type of your ufs filesystem
[ 280.150349]
[ 280.150349] mount -t ufs -o ufstype=sun|sunx86|44bsd|ufs2|5xbsd|old|hp|nextstep|nextstep-cd|openstep ...
[ 280.150349]
[ 280.150349] >>>WARNING<<< Wrong ufstype may corrupt your filesystem, default is ufstype=old
[ 280.173616] hfs: can't find a HFS filesystem on dev sda2
done
Optionally check that we now have console options configured:
root@testing:~# grep console /boot/grub/grub.cfg
linux /boot/vmlinuz-4.5.0-1-amd64 root=UUID=3bd74887-1631-43fd-ada5-8e00892b5dd9 ro console=ttyS0,115200
linux /boot/vmlinuz-4.5.0-1-amd64 root=UUID=3bd74887-1631-43fd-ada5-8e00892b5dd9 ro console=ttyS0,115200
Test
Poweroff the VM and start it again - it should boot without any need for fiddling.