diff --git a/imgs/boot.sh b/imgs/boot.sh
index f1a1adcfcc89c609fb8780124d1a42cac71a5f3f..0b6c909cc58f5adf2aff85fff73af4a5fa7336a4 100755
--- a/imgs/boot.sh
+++ b/imgs/boot.sh
@@ -4,3 +4,22 @@
 # This is image used to boot medkit. It provides TFTP server with prepared image
 # for u-boot.
 ##################################################################################
+set -e
+
+# Make prepare script executable so we can later run it
+chmod +x "/bin/prepare_turris_image"
+
+# Configure WAN interface for static local network
+cat >> /etc/network/interfaces <<EOF
+auto wan
+iface wan inet static
+        address 192.168.1.1
+        netmask 255.255.255.0
+EOF
+
+# Install utilities we need to repack image
+apk add uboot-tools
+
+# Install and enable TFTP server
+apk add tftp-hpa
+rc-update add "in.tftpd" default
diff --git a/imgs/boot/bin/prepare_turris_image b/imgs/boot/bin/prepare_turris_image
new file mode 100755
index 0000000000000000000000000000000000000000..a5e8d6eb81f83f3f1df87b18fdfb6ae59bd4a48a
--- /dev/null
+++ b/imgs/boot/bin/prepare_turris_image
@@ -0,0 +1,27 @@
+#!/bin/bash
+set -e
+TFTP_ROOT="/var/tftpboot"
+
+# TODO use this
+BOARD="$1"
+MODE="$2"
+TARGET="$3"
+# TODO
+
+# Get appropriate medkit
+wait4network
+wget "https://repo.turris.cz/hbk/medkit/omnia-medkit-latest.tar.gz" -O medkit.tar.gz
+
+# Repack as CPIO
+mkdir root
+tar -xzf medkit.tar.gz -C root
+( cd root && find . | cpio -H newc -o > ../root.cpio )
+mkimage -A arm -O linux -T ramdisk -C none -d root.cpio root.uimage
+
+# Prepare to TFTP
+cp root/boot/zImage "$TFTP_ROOT/zImage"
+cp -L root/boot/dtb "$TFTP_ROOT/dtb"
+mv root.uimage "$TFTP_ROOT/root.uimage"
+
+# Clean after ourself
+rm -rf root root.cpio medkit.tar.gz
diff --git a/nsfarm/board.py b/nsfarm/board.py
index 4f5d09ddecd2402c46918a2ea0f111398bd640f4..49e0c939f2fb60659e6eaa82e003528d67065f60 100644
--- a/nsfarm/board.py
+++ b/nsfarm/board.py
@@ -7,6 +7,7 @@ import serial
 import serial.tools.miniterm
 from pexpect import fdpexpect
 from . import cli
+from .lxd import Container
 
 MINITERM_DEFAULT_EXIT = '\x1d'  # Ctrl+]
 MINITERM_DEFAULT_MENU = '\x14'  # Ctrl+T
@@ -50,15 +51,28 @@ class Board():
         self.pexpect.sendline("")
         return cli.Uboot(self.pexpect)
 
-    def bootup(self):
+    def bootup(self, device_wan):
         """Boot board using TFTP boot. This ensures that board is booted up and ready to accept commands.
 
+        device_wan: Wan device to board. This is instance of nsfarm.lxd.NetInterface.
+
         Returns instance of cli.Shell
         """
         # First get U-Boot prompt
         uboot = self.uboot()
-        # Now load FIT image from TFTP
-        # TODO
+        # Now load image from TFTP
+        with Container("boot", devices=[device_wan, ]) as cont:
+            ccli = cli.Shell(cont.pexpect())
+            ccli.run("prepare_turris_image")
+            assert uboot.batch([
+                'setenv ipaddr 192.168.1.142',
+                'setenv serverip 192.168.1.1',
+                'tftpboot 0x01000000 192.168.1.1:zImage',
+                'tftpboot 0x02000000 192.168.1.1:dtb',
+                'tftpboot 0x03000000 192.168.1.1:root.uimage',
+                'setenv bootargs "earlyprintk console=ttyS0,115200 rootfstype=ramfs initrd=0x03000000"',
+            ], timeout=120)
+        self.pexpect.sendline('bootz 0x01000000 0x03000000 0x02000000')
         # Wait for bootup
         self.pexpect.expect_exact(["Router Turris successfully started.", ])
         # Note Shell sends new line which opens terminal for it
diff --git a/nsfarm/cli.py b/nsfarm/cli.py
index 3017c2917724dd6c556f2fcc5d379e539bf8741d..6e95b41867e3bf603ea8d768d0f2e0adf42ba2b6 100644
--- a/nsfarm/cli.py
+++ b/nsfarm/cli.py
@@ -68,7 +68,7 @@ class Console:
         command from output.
         """
         self.sendline(cmd)
-        if not self.sexpect_exact(cmd + '\r\n'):
+        if not self.sexpect_exact(cmd) or not self.sexpect("(\r\n|\n\r)"):
             # TODO better exception
             raise Exception("cmd used but terminal probably does not echoes.")
 
@@ -129,11 +129,11 @@ class Shell(Cli):
     This is tested to handle busybox and bash.
     """
     _SET_NSF_PROMPT = r"export PS1='nsfprompt:$(echo -n $?)\$ '"
-    _NSF_PROMPT = r"(\r\n|^)nsfprompt:([0-9]+)($|#) "
+    _NSF_PROMPT = r"(\r\n|\n\r|^)nsfprompt:([0-9]+)($|#) "
     _INITIAL_PROMPTS = [
-        r"(\r\n|^).+? ($|#) ",
-        r"(\r\n|^)bash-.+?($|#) ",
-        r"(\r\n|^)root@[a-zA-Z0-9_-]*:",
+        r"(\r\n|\n\r|^).+? ($|#) ",
+        r"(\r\n|\n\r|^)bash-.+?($|#) ",
+        r"(\r\n|\n\r|^)root@[a-zA-Z0-9_-]*:",
         _NSF_PROMPT,
     ]
     # TODO compile prompt regexp to increase performance
@@ -143,7 +143,6 @@ class Shell(Cli):
         # Firt check if we are on some sort of shell prompt
         self.cmd()
         if not self.sexpect(self._INITIAL_PROMPTS):
-            print(self.before)
             # TODO better exception
             raise Exception("Initial shell prompt not found")
         # Now sanitize prompt format
@@ -164,7 +163,7 @@ class Shell(Cli):
 class Uboot(Cli):
     """U-boot prompt support class.
     """
-    _PROMPT = "(\r\n|^)=> "
+    _PROMPT = "(\r\n|\n\r|^)=> "
     _EXIT_CODE_ECHO = "echo $?"
 
     def __init__(self, pexpect_handle, flush=True):
@@ -190,3 +189,9 @@ class Uboot(Cli):
     @property
     def output(self):
         return self._output
+
+
+# Notest on some of the hacks in this file
+#
+# There are new line character matches in regular expressions. Correct one is \r\n but some serial controlles for some
+# reason also use \n\r so we match both alternatives.
diff --git a/nsfarm/lxd/container.py b/nsfarm/lxd/container.py
index 519a2a0578b11bc5c441dea0e0d58ceaadd296ef..535c5255ece1e602236dcccfd4adb2c73d588cfd 100644
--- a/nsfarm/lxd/container.py
+++ b/nsfarm/lxd/container.py
@@ -203,6 +203,7 @@ class Container():
     def pexpect(self, shell="/bin/sh"):
         """Returns pexpect handle for shell in container.
         """
+        # TODO some logging of this session
         assert self._lxd_container is not None
         return pexpect.spawn('lxc', ["exec", self._lxd_container.name, shell])
 
@@ -247,16 +248,8 @@ class Container():
         """
         return self._hash
 
+    @property
     def image_alias(self):
         """Alias of image for this container.
         """
         return self._image_alias
-
-
-class BootContainer(Container):
-    """Extension for Container handling specific tasks for container used to boot medkit on board.
-    """
-
-    # TODO branch or build to pull?
-    def __init__(self, *args, **kwargs):
-        super().__init__("boot", *args, **kwargs)
diff --git a/tests/conftest.py b/tests/conftest.py
index 53b6a17e392ccca70e16474d605225ebc551bfd9..e04bc6308558d2620749a7441f9cee4be878670a 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,6 +1,7 @@
 import pytest
 import nsfarm.board
 import nsfarm.cli
+import nsfarm.lxd
 
 
 @pytest.fixture(scope="session", name="board", params=[pytest.param(None, marks=pytest.mark.serial)])
@@ -23,11 +24,17 @@ def board_uboot(request, board):
     return board.uboot()
 
 
+@pytest.fixture(scope="session", name="wan", params=[pytest.param(None, marks=pytest.mark.wan)])
+def fixture_wan(request):
+    """Top level fixture used to share WAN interface handler.
+    """
+    return nsfarm.lxd.NetInterface("wan", request.config.target_config['wan'])
+
+
 @pytest.fixture(scope="session")
-def board_shell(request, board):
+def board_shell(request, board, wan):
     """Boot board to Shell.
     Provides instance of nsfarm.cli.Shell()
     """
     request.addfinalizer(lambda: board.reset(True))
-    # TODO prepare wan container with appropriate medkit
-    return board.bootup()
+    return board.bootup(wan)
diff --git a/tests/test_experiments.py b/tests/test_experiments.py
index e8ad30c636cde7924876bce34f5e1c3b9a2285bb..27b137ecf859b7c765bad8d8856afa01d8016217 100644
--- a/tests/test_experiments.py
+++ b/tests/test_experiments.py
@@ -1,11 +1,11 @@
 import pytest
 
 
-def no_test_help(board, board_uboot):
+def test_terminal(board, board_shell):
     board.serial_miniterm()
 
 
-def test_cpu_env(board, board_uboot):
+def no_test_cpu_env(board, board_uboot):
     assert board_uboot.run("printenv cpu")
     assert board_uboot.output == "cpu=armv7"