Bug#934753: dropbear-initramfs: please add an autopkgtest

2020-06-15 Thread Guilhem Moulin
Control: tag -1 pending

Hi Johannes,

On Tue, 31 Dec 2019 at 09:19:29 +0100, Johannes Schauer wrote:
> thanks again for all your very helpful comments! I think I now implemented
> everything that you suggested. I created a merge request on salsa containing
> what I think is ready to be merged:
> 
> https://salsa.debian.org/debian/dropbear/merge_requests/3

Sorry, this fell a bit off screen.  Better late than never though, it's
now merged :-)  Many thanks for this patch (incl. the CI tests), much
appreciated!

Cheers,
-- 
Guilhem.


signature.asc
Description: PGP signature


Bug#934753: dropbear-initramfs: please add an autopkgtest

2019-12-31 Thread Johannes Schauer
Hi Guilhem,

thanks again for all your very helpful comments! I think I now implemented
everything that you suggested. I created a merge request on salsa containing
what I think is ready to be merged:

https://salsa.debian.org/debian/dropbear/merge_requests/3

In case you prefer something you can "git am" yourself, I attached my commit to
this Email.

Thanks!

cheers, josch
>From 9811a149637c2680a753862db246199cdc21ee97 Mon Sep 17 00:00:00 2001
From: Johannes 'josch' Schauer 
Date: Wed, 13 Nov 2019 16:04:37 +0100
Subject: [PATCH] Add autopkgtest to test dropbear-openssh

Also add debian/salsa-ci.yml to run autopkgtest on salsa CI.
---
 debian/salsa-ci.yml  |   4 +
 debian/tests/control |   3 +
 debian/tests/on_lvm_and_luks | 469 +++
 3 files changed, 476 insertions(+)
 create mode 100644 debian/salsa-ci.yml
 create mode 100644 debian/tests/control
 create mode 100644 debian/tests/on_lvm_and_luks

diff --git a/debian/salsa-ci.yml b/debian/salsa-ci.yml
new file mode 100644
index 000..33c3a64
--- /dev/null
+++ b/debian/salsa-ci.yml
@@ -0,0 +1,4 @@
+---
+include:
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 000..877522d
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,3 @@
+Tests: on_lvm_and_luks
+Depends: mmdebstrap, qemu-system-x86, libguestfs-tools, linux-image-amd64, sleepenh, openssh-client, time
+Restrictions: allow-stderr needs-root
diff --git a/debian/tests/on_lvm_and_luks b/debian/tests/on_lvm_and_luks
new file mode 100644
index 000..6b9e24b
--- /dev/null
+++ b/debian/tests/on_lvm_and_luks
@@ -0,0 +1,469 @@
+#!/bin/sh
+
+# Copyright 2019 Johannes 'josch' Schauer 
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+
+
+# dropbear-initramfs is used in situations where the user does not have
+# physical access to a remote machine and still wants to supply a passphrase
+# to unlock an encrypted system. This script tests this setup by creating a
+# bootable (using extlinux) Debian system with guestfish. That system is booted
+# inside qemu and used to setup an encrypted second system. The second system
+# is then booted again using qemu and the encrypted disk is unlocked by
+# connecting to dropbear-initramfs via ssh.
+#
+# We call the first system the "setup" because it is used to setup the second
+# system. We call the second system "crypt" because everything except /boot is
+# encrypted.
+
+set -exu
+
+# We do not use debootstrap to create the chroot tarballs, because debootstrap
+# is not able to create a system containing only essential:yes packages and
+# their dependencies. We do want to create the most minimal system so that we
+# can also find possibly missing dependencies.
+#
+# We don't use multistrap because it's unmaintained. Thus we create the initial
+# tarballs using mmdebstrap.
+
+# Some packages are used in the setup system as well as in the crypt system:
+#   openssh-server:  required on both to connect to them from this script
+#   systemd-sysv:since init is not Essential:yes anymore, we have to pick
+#an init system ourselves. We pick the one that is
+#currently the default
+#   ifupdown:for /etc/network/interfaces
+#   netbase: for networking
+#   isc-dhcp-client: to acquire the IP address from qemu via dhcp
+#   udev:to populate /dev
+#   lvm2:for LVM volumes
+#   policykit-1: or otherwise systemctl will error with
+#"Failed to connect to bus: No such file or directory"
+common_pkgs="openssh-server,systemd-sysv,ifupdown,netbase,isc-dhcp-client,udev,lvm2,policykit-1"
+
+# Some packages are only installed on the setup system
+#   linux-image-amd64: if we install it on the crypt system outside of qemu,
+#  then the resulting system will not boot with grub - why?
+#   e2fsprogs: to create filesystems for crypt
+#   cryptsetup:to encrypt a partition for crypt
+#   fdisk: to create partitions for crypt
+#   util-linux:for mkswap
+setup_pkgs="$common_pkgs,linux-image-amd64,e2fsprogs,cryptsetup,fdisk,util-linux"
+
+if [ -z ${AUTOPKGTEST_TMP+x} ]; then
+	# if AUTOPKGTEST_TMP is not set, then this script is probably not
+	# executed under 

Bug#934753: dropbear-initramfs: please add an autopkgtest

2019-12-08 Thread Guilhem Moulin
Hi josch,

On Wed, 20 Nov 2019 at 11:21:31 +0100, Johannes Schauer wrote:
> Indeed it would not. The autopkgtest does not even test upgrades. But when I
> re-installed the system after the upgrade failed I also was unsure in many
> points of how to do it correctly. The autopkgtest does not only serve as a
> constant assurance that the current state does work but also serves as
> documentation of which knobs have to be turned to successfully set it up. It
> can thus serve as an addition to
> /usr/share/doc/dropbear-initramfs/README.Debian

Fair enough :-)

>> I'd also bind to INADDR_LOOPBACK, change the NIC and drive model from the
>> default (resp. e1000 and ide) to virtio, and pass `-no-user-config
>> -nodefaults`.  Maybe also set the CPU model to host.  Might also help to
>> create a virtio-rng device, given that key material is generated on the
>> guest.
> 
> I'm unsure about -no-user-config -nodefaults. This will require a much larger
> command line for what benefit?

For ‘-nodefaults’ it might be reasonable to assume that the qemu
maintainers make sure to have sane default that don't break on upgrade,
however ‘-no-user-config’ shouldn't require a larger command line and will
be really useful for those who run the pkgtest in unclean environments.
(One could have tons of stuff there, including extra disks, different
boot priorities, etc. and shoot oneself in the foot.)
 
> What benefit would changing the nic and drive to virtio have? Sorry, I'm not 
> an
> expert on this. :)

I guess QEMU defaults to “full virtualization” (incl. hardware
emulation) because not all guest OS are VirtIO-aware.  When the guest OS
can speak VirtIO it makes little sense to emulate a particular hardware.
That said saving the abstraction cost won't give a huge perf gain here
because there is not much I/O.  Another advantage is the reliable block
device paths (/dev/vda for the first drive), while otherwise that
depends on the bus (SATA, IDE) and driver in use.
 
> Yes, adding something like this might be useful:
> 
> -object rng-random,filename=/dev/urandom,id=rng0 -device 
> virtio-rng-pci,rng=rng0
> 
> I'll benchmark this to see whether there is a noticeable difference.

That's a hard requirement when the guest calls getrandom(,,GRND_RANDOM)
or reads from the blocking PRNG.  dropbear(8) doesn't *right now*, but
other components in the software stack do and on headless VMs there is a
real risk of entropy starvation without virtual hardware RNG (cf. last
year's “Handling of entropy during boot” thread on debian-devel.)

>>> printf myinsecurepassphrase | cryptsetup luksFormat /dev/sdb3 -
>> To speep up things I suggest to skip the the PBKDF benchmark by passing
>> `--pbkdf-force-iterations 4 --pbkdf-memory 32` (for Argon2), or
>> `--pbkdf-force-iterations 1000` (for PBKDF2).  cryptsetup <2.0 (up to
>> Stretch) are only able to format and open LUKSv1 volumes, which only
>> supports PBKDF2 as PBKDF algorithm; since cryptsetup 2.0 a new LUKS
>> version format is available (and is the default as for Buster) with
>> support for both Argon2i/d (default) and PBKDF2.
> 
> Is this only for a potential speedup? Is it not better to test the default
> setup?

PBKDF are by design expensive functions; when a new keyslot is added, a
benchmark is run to choose parameters that are 1/ expensive enough to
defeat bruteforce attacks, and 2/ reasonable enough to avoid waiting too
long for the device to unlock.  When `luksFormat` and `luksOpen` are
called from machines with different clock speed and/or RAM size, the
benchmark is just moot; and when the former machine is much more beefy
than the latter, which is likely the case here (though maybe not in the
CI pipeline), unlocking might take a lng time, or even trigger the
OOM killer and cause the test to fail.  With my cryptsetup maintainer
hat on, the general recommendation when `luksFormat` and `luksOpen` are
called from different machines, is to collect parameters on the latter
machine, and use them when creating the keyslot.  For a test though it
makes sense to skip the benchmark altogether and PBKDF parameters that
are as cheap as possible, to avoid wasting RAM and CPU cycles.  FWIW
this is also what I do in the tests for cryptsetup-initramfs (which I
mean to turn into autopkgtests as well). :-)

Thanks!
Cheers,
-- 
Guilhem.


signature.asc
Description: PGP signature


Bug#934753: dropbear-initramfs: please add an autopkgtest

2019-11-20 Thread Johannes Schauer
Control: unblock -1 by 944729

Hi Guilhem,

thanks for your very helpful review!

Quoting Guilhem Moulin (2019-08-16 14:45:17)
> On Wed, 14 Aug 2019 at 14:54:08 +0200, Johannes 'josch' Schauer wrote:
> > when I upgraded my Squeeze box to Jessie, remote unlocking via dropbear
> > in my initramfs stopped working. This is a remote host in a datacenter,
> > so I cannot directly investigate the issue.
> Interesting, once you manage to boot I'd be interested to know the
> reason.  Also FWIW I also use remote unlocking via dropbear on
> production systems, and my setups have survived all upgrade paths, incl.
> Squeeze → Jessie.  And AFAICT you're the first to report a breakage at
> dist-upgrade stage, so I'm not entirely convinced this would have been
> caught by a simple autopkgtest :-P

Indeed it would not. The autopkgtest does not even test upgrades. But when I
re-installed the system after the upgrade failed I also was unsure in many
points of how to do it correctly. The autopkgtest does not only serve as a
constant assurance that the current state does work but also serves as
documentation of which knobs have to be turned to successfully set it up. It
can thus serve as an addition to
/usr/share/doc/dropbear-initramfs/README.Debian

> Oh wait, you upgraded from Squeeze to Jessie via Wheezy, right?
> Directly upgrading from Squeeze to Jessie is not a supported upgrade
> path.

No, I always only upgraded foo to foo+1. It doesn't matter now because the
situation is fixed and I could not've investigated anyways because I have no
way to observe the boot process.

> > If you like the script, then I could prepare a patch against src:dropbear
> > which implements an autopkgtest that runs the script.
> Can't hurt indeed, thanks!  A few comments inlined below.

Thanks, those were very helpful.

> > pkgs="linux-image-amd64,openssh-server,systemd-sysv,libpam-systemd,policykit-1"
> > pkgs="$pkgs,iproute2,util-linux,e2fsprogs,ifupdown,net-tools,netbase"
> > pkgs="$pkgs,iputils-ping,isc-dhcp-client,lvm2,parted,cryptsetup"
> > pkgs="$pkgs,dropbear-initramfs,busybox,fdisk,mmdebstrap,udev"
> 
> If you include ‘dropbear-initramfs’ I guess you want ‘cryptsetup-initramfs’
> not ‘cryptsetup’.

Yes. cryptsetup is only required on the system setting up the encrypted disks
(but cryptsetup-initramfs is not needed there) and cryptsetup-initramfs is
required on the system with the encrypted disks (but cryptsetup is not needed
there). Fixed.

> Also AFAICT ‘iputils-ping’, ‘parted’ and ‘busybox’ are not needed (the latter
> will be pulled by ‘cryptsetup-initramfs’ and ‘dropbear-initramfs’).

Yes. All removed. Those were leftovers from when I was testing the whole thing
and I didn't clean up the packages yet. I removed a few more things now.

> > auto ens3
> Is the interface name reliable?  I was under the impression it wasn't because
> it depends on how QEMU arranges its devices, unlike the use of ‘eth0’ after
> adding ‘net.ifnames=0’ to the kernel cmdline.

Yes. The interface name is not reliable under qemu unless (I guess) you
manually add the network card on a certain interface. Otherwise it might break
on the next qemu update when the defaults change. I now use eth0 and
net.ifnames=0 instead.

> > qemu-img convert -O qcow2 debian-unstable.img debian-unstable.qcow2
> The conversion from raw to qcow2 format is not needed, is it?

Correct. Removed.

> > qemu-system-x86_64 -enable-kvm -m 4G -net user,hostfwd=tcp::10022-:22 \
> 4GiB sounds really overkill here, surely 1GiB is enough?  This is what I use
> for testing the various device stacks before src:cryptsetup uploads.

Yes, 1G is sufficient. Fixed.

> I'd also bind to INADDR_LOOPBACK, change the NIC and drive model from the
> default (resp. e1000 and ide) to virtio, and pass `-no-user-config
> -nodefaults`.  Maybe also set the CPU model to host.  Might also help to
> create a virtio-rng device, given that key material is generated on the
> guest.

I'm unsure about -no-user-config -nodefaults. This will require a much larger
command line for what benefit?

What benefit would changing the nic and drive to virtio have? Sorry, I'm not an
expert on this. :)

Yes, adding something like this might be useful:

-object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0

I'll benchmark this to see whether there is a noticeable difference.

> > printf myinsecurepassphrase | cryptsetup luksFormat /dev/sdb3 -
> To speep up things I suggest to skip the the PBKDF benchmark by passing
> `--pbkdf-force-iterations 4 --pbkdf-memory 32` (for Argon2), or
> `--pbkdf-force-iterations 1000` (for PBKDF2).  cryptsetup <2.0 (up to
> Stretch) are only able to format and open LUKSv1 volumes, which only
> supports PBKDF2 as PBKDF algorithm; since cryptsetup 2.0 a new LUKS
> version format is available (and is the default as for Buster) with
> support for both Argon2i/d (default) and PBKDF2.

Is this only for a potential speedup? Is it not better to test the default
setup?

> > cat > 

Bug#934753: dropbear-initramfs: please add an autopkgtest

2019-11-14 Thread Johannes Schauer
Control: block -1 by 944729

Hi,

On Fri, 16 Aug 2019 14:45:17 +0200 Guilhem Moulin  wrote:
> > If you like the script, then I could prepare a patch against src:dropbear
> > which implements an autopkgtest that runs the script.
> Can't hurt indeed, thanks!

just a quick status update: it seems to be impossible right now to have tests
of this kind run on our CI. We don't have user namespaces, cannot mount, cannot
do kpartx and using guestfish fails for an unknown reason which leads to the
resulting disk image being corrupted. Fixing the guestfish bug is tricky
because the error only occurs on Debian CI and not locally, so I prepared
another autopkgtest for libguestfs-tools only to see that libguestfs-tools
cannot even be built on salsa CI because the artifacts are too large:

https://salsa.debian.org/salsa/support/issues/175

Since I cannot test on ci.debian.net myself, I filed a bug with patch to
src:libguestfs and we will see whether that works or not:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=944729

Since all kinds of other operations are not permitted on salsa CI, using
libguestfs is as far as I know the only way to create a dropbear-initramfs test
which creates the disk image by itself instead of downloading it from
elsewhere. This I'm blocking this bug by the libguestfs bug. If we can make the
latter work, then I can continue working on this one.

Thanks!

cheers, josch


signature.asc
Description: signature


Bug#934753: dropbear-initramfs: please add an autopkgtest

2019-08-16 Thread Guilhem Moulin
On Fri, 16 Aug 2019 at 14:45:17 +0200, Guilhem Moulin wrote:
> On Wed, 14 Aug 2019 at 14:54:08 +0200, Johannes 'josch' Schauer wrote:
>> when I upgraded my Squeeze box to Jessie, remote unlocking via dropbear
>> in my initramfs stopped working. This is a remote host in a datacenter,
>> so I cannot directly investigate the issue.
> 
> Interesting, once you manage to boot I'd be interested to know the
> reason.

Oh wait, you upgraded from Squeeze to Jessie via Wheezy, right?
Directly upgrading from Squeeze to Jessie is not a supported upgrade
path.

-- 
Guilhem.


signature.asc
Description: PGP signature


Bug#934753: dropbear-initramfs: please add an autopkgtest

2019-08-16 Thread Guilhem Moulin
On Wed, 14 Aug 2019 at 14:54:08 +0200, Johannes 'josch' Schauer wrote:
> when I upgraded my Squeeze box to Jessie, remote unlocking via dropbear
> in my initramfs stopped working. This is a remote host in a datacenter,
> so I cannot directly investigate the issue.

Interesting, once you manage to boot I'd be interested to know the
reason.  Also FWIW I also use remote unlocking via dropbear on
production systems, and my setups have survived all upgrade paths, incl.
Squeeze → Jessie.  And AFAICT you're the first to report a breakage at
dist-upgrade stage, so I'm not entirely convinced this would have been
caught by a simple autopkgtest :-P

> If you like the script, then I could prepare a patch against
> src:dropbear which implements an autopkgtest that runs the script.

Can't hurt indeed, thanks!  A few comments inlined below.

> pkgs="linux-image-amd64,openssh-server,systemd-sysv,libpam-systemd,policykit-1"
> pkgs="$pkgs,iproute2,util-linux,e2fsprogs,ifupdown,net-tools,netbase"
> pkgs="$pkgs,iputils-ping,isc-dhcp-client,lvm2,parted,cryptsetup"
> pkgs="$pkgs,dropbear-initramfs,busybox,fdisk,mmdebstrap,udev"

If you include ‘dropbear-initramfs’ I guess you want ‘cryptsetup-initramfs’
not ‘cryptsetup’.  Also AFAICT ‘iputils-ping’, ‘parted’ and ‘busybox’
are not needed (the latter will be pulled by ‘cryptsetup-initramfs’ and
‘dropbear-initramfs’).

> auto ens3

Is the interface name reliable?  I was under the impression it wasn't
because it depends on how QEMU arranges its devices, unlike the use of
‘eth0’ after adding ‘net.ifnames=0’ to the kernel cmdline.

> qemu-img convert -O qcow2 debian-unstable.img debian-unstable.qcow2

The conversion from raw to qcow2 format is not needed, is it?

> qemu-system-x86_64 -enable-kvm -m 4G -net user,hostfwd=tcp::10022-:22 \

4GiB sounds really overkill here, surely 1GiB is enough?  This is what I
use for testing the various device stacks before src:cryptsetup uploads.

I'd also bind to INADDR_LOOPBACK, change the NIC and drive model from
the default (resp. e1000 and ide) to virtio, and pass `-no-user-config
-nodefaults`.  Maybe also set the CPU model to host.  Might also help to
create a virtio-rng device, given that key material is generated on the
guest.

> printf myinsecurepassphrase | cryptsetup luksFormat /dev/sdb3 -

To speep up things I suggest to skip the the PBKDF benchmark by passing
`--pbkdf-force-iterations 4 --pbkdf-memory 32` (for Argon2), or
`--pbkdf-force-iterations 1000` (for PBKDF2).  cryptsetup <2.0 (up to
Stretch) are only able to format and open LUKSv1 volumes, which only
supports PBKDF2 as PBKDF algorithm; since cryptsetup 2.0 a new LUKS
version format is available (and is the default as for Buster) with
support for both Argon2i/d (default) and PBKDF2.

> cat > "/mnt/etc/initramfs-tools/conf.d/dropbear" << END
> IP=":ens3:dhcp"
> END

AFAICT it's redundant since you have the same thing as boot parameter.
 
> chroot "/mnt" apt-get -y install lvm2 grub2 linux-image-amd64 openssl 
> cryptsetup dropbear-initramfs busybox udev mount systemd-sysv util-linux 
> e2fsprogs initramfs-tools cryptsetup-initramfs cryptsetup-run console-setup 
> openssh-server ifupdown net-tools netbase iproute2 libpam-systemd policykit-1 
> iputils-ping isc-dhcp-client

Some of these are redundant, and might not be marked as manually
installed on a normal installation.  ‘cryptsetup-run’, ‘busybox’,
‘initramfs-tools’ at least.

Thanks!
-- 
Guilhem.


signature.asc
Description: PGP signature


Bug#934753: dropbear-initramfs: please add an autopkgtest

2019-08-14 Thread Johannes 'josch' Schauer
Package: dropbear-initramfs
Severity: wishlist

Hi,

when I upgraded my Squeeze box to Jessie, remote unlocking via dropbear
in my initramfs stopped working. This is a remote host in a datacenter,
so I cannot directly investigate the issue.

I propose to add an autopkgtest for dropbear-initramfs to make sure that
the functionality continues to work even as the packages around it
change over time.

I attached a shell script which uses qemu to prepare a system that has
an unencrypted /boot and / and swap on an LVM on luks, which I guess is
the classical layout.

If you like the script, then I could prepare a patch against
src:dropbear which implements an autopkgtest that runs the script.

Thanks!

cheers, josch
#!/bin/sh

set -exu

ssh="ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -i id_rsa"

pkgs="linux-image-amd64,openssh-server,systemd-sysv,libpam-systemd,policykit-1"
pkgs="$pkgs,iproute2,util-linux,e2fsprogs,ifupdown,net-tools,netbase"
pkgs="$pkgs,iputils-ping,isc-dhcp-client,lvm2,parted,cryptsetup"
pkgs="$pkgs,dropbear-initramfs,busybox,fdisk,mmdebstrap,udev"

mmdebstrap --mode=unshare --variant=apt --include=$pkgs \
--customize-hook='chroot "$1" passwd --delete root' \
--customize-hook='chroot "$1" useradd --home-dir /home/user 
--create-home user' \
--customize-hook='chroot "$1" passwd --delete user' \
--customize-hook='echo host > "$1/etc/hostname"' \
--customize-hook='echo "127.0.0.1 localhost host" > "$1/etc/hosts"' \
--customize-hook='echo "/dev/sda1 / auto errors=remount-ro 0 1" > 
"$1/etc/fstab"' \
unstable debian-unstable.tar

fallocate -l 2G crypt.img

cat << END > extlinux.conf
default linux
timeout 0

label linux
kernel /vmlinuz
append initrd=/initrd.img root=/dev/sda1 console=ttyS0
END

cat << END > interfaces
auto lo
iface lo inet loopback

auto ens3
iface ens3 inet dhcp
END

[ -e ./id_rsa ] && [ -e ./id_rsa.pub ] || ssh-keygen -q -t rsa -f ./id_rsa -N ""

guestfish -N debian-unstable.img=disk:2G -- \
part-disk /dev/sda mbr : \
part-set-bootable /dev/sda 1 true :  \
mkfs ext2 /dev/sda1 : \
mount /dev/sda1 / : \
tar-in debian-unstable.tar / : \
extlinux / : \
mkdir /root/.ssh : \
copy-in id_rsa.pub /root/ : \
mv /root/id_rsa.pub /root/.ssh/authorized_keys : \
chown 0 0 /root/.ssh/authorized_keys : \
copy-in extlinux.conf / : \
copy-in interfaces /etc/network

qemu-img convert -O qcow2 debian-unstable.img debian-unstable.qcow2

qemu-system-x86_64 -enable-kvm -m 4G -net user,hostfwd=tcp::10022-:22 \
-net nic -nographic -serial mon:stdio \
-drive file=debian-unstable.qcow2 \
-drive file=crypt.img,format=raw >qemu1.log &1 &

QEMUPID=$!

trap "kill $QEMUPID" EXIT

TIMESTAMP=$(sleepenh 0 || [ $? -eq 1 ])
TIMEOUT=3
i=0
while true; do
rv=0
$ssh -p 10022 -o ConnectTimeout=$TIMEOUT root@localhost echo success || 
rv=1
[ $rv -eq 0 ] && break
# if the command before took less than $TIMEOUT seconds, wait the 
remaining time
TIMESTAMP=$(sleepenh $TIMESTAMP $TIMEOUT || [ $? -eq 1 ]);
i=$((i+1))
if [ $i -ge 10 ]; then
break
fi
done

if [ $i -eq 10 ]; then
echo "timeout reached: unable to connect to qemu via ssh"
exit 1
fi

$ssh -p 10022 root@localhost << 'SSHSCRIPT'
set -exu

cat << END | sfdisk /dev/sdb
label: gpt
unit: sectors

start=   2048, size=2048, type=21686148-6449-6E6F-744E-656564454649
start=   4096, size=  999424, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4
start=1003520,type=CA7D7CCB-63ED-4C53-861C-1742536059CC
END

fdisk -l

printf myinsecurepassphrase | cryptsetup luksFormat /dev/sdb3 -
printf myinsecurepassphrase | cryptsetup luksOpen /dev/sdb3 mycrypt
pvcreate /dev/mapper/mycrypt
vgcreate myvg /dev/mapper/mycrypt
lvcreate --name swap --size 15M myvg
mkswap /dev/myvg/swap
swapon /dev/myvg/swap
lvcreate --name root --size 1G myvg
mkfs.ext4 /dev/myvg/root
mkfs.ext2 /dev/sdb2

BOOTUUID=`blkid -s UUID -o value /dev/sdb2`
SDB3UUID=`blkid -s UUID -o value /dev/sdb3`
SWAPUUID=`blkid -s UUID -o value /dev/myvg/swap`

mount /dev/myvg/root /mnt

# need to use /dev/null on stdin because of #934199
mmdebstrap --debug --mode=root --variant=apt unstable /mnt  
"/mnt/etc/apt/apt.conf.d/99no-install-recommends"

cat > "/mnt/etc/apt/apt.conf.d/99autoremove" << END
APT::AutoRemove::SuggestsImportant false;
APT::AutoRemove::RecommendsImportant false;
END

mkdir -p "/mnt/etc/default"

cat > "/mnt/etc/default/grub" << 'END'
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX="ip=:ens3:dhcp cgroup_enable=memory swapaccount=1 
console=ttyS0 "
END

cat > "/mnt/etc/fstab" << END
/dev/myvg/root  / autoerrors=remount-ro 0 1
UUID=$BOOTUUID  /boot autodefaults  0 2
/dev/myvg/swap  none