This is a guide for future tutors of the NoT A Lab that will guide you through the necessary hardware and software setups.

These instructions assume that you have a running installation of Debian Buster or new which, at the time of writing, is the current Debian testing version.

If you have such a system running or are willing to adapt you can continue to generating the lab instructions.

Software Setup

Generating the instructions

The first task will be to generate a more readable form of these setup instructions and of the instructions for the students.

To generate these mdBook is used. To install mdBook and other build requirements you have to follow these steps:

  1. Install requirements from the debian reposiory:
    $ sudo apt install git make cargo
  2. Install mdBook using cargo:
    $ cargo install mdbook
  3. Add cargo’s binary directory to your PATH:
    $ echo 'PATH=${PATH}:${HOME}/.cargo/bin' >> ~/.bashrc`
  4. Open a new terminal and check if everything worked by running:
    $ mdbook

If none of the commands above threw any errors you should now be ready to download and compile the lab instructions using the following steps:

  1. Clone the repository:
    $ cd Downloads
    $ git clone ""
  2. Build the bootstrap instructions:
    $ cd nota-lab/bootstrap/
    $ make
  3. Build the lab instructions:
    $ cd ../instructions/
    $ make
  4. The generated instructions can be found in the bootstrap/book and instructions/book folders and can be viewed using a web browser:
    $ cd ../bootstrap/
    $ firefox book/index.html

You can now change the source files in the bootstrap/src and instructions/src folders as you see fit and re-run make to generate an HTML version.

Generating disk images

The operating system images for the Raspberry Pis and the cloud application are automatically generated using vmdb2. To install it and other build requirements run:

$ sudo apt install make vmdb2 qemu-system qemu-user-static openssl debian-keyring

We will be using the official Debian repositories instead of Raspbian on the Raspberry Pis, this means that first-generation Raspberry Pis, which use an older CPU, will not work with the generated image file.

The cloud image is also based on Debian and is expected to run in a virtual machine in the same network as the Raspberry Pis, or at least be reachable by them.

To generate the image file change into the directory containing the image descriptions and run make to generate the image files.

$ cd ~/Downloads/nota-lab/disk_images
$ make

Note: On a computer with a spinning harddrive (e.g.: not an SSD) this process can take hours, and you will have to check then and now if you have to enter your password.

You may need to enter a password multiple times as parts of the build process use sudo to gain root priviliges.

While the Raspberry Pi image is building you can follow the status using the following command:

$ sudo tail -n 1000 -f ~/Downloads/nota-lab/disk_images/rpi_student.img.log

While the Cloud image is building you can follow the status using this command instead:

$ sudo tail -n 1000 -f ~/Downloads/nota-lab/disk_images/vm_server.img.log

If everything goes well you should, after some minutes, end up with a file called rpi_student.img and another file called vm_server.img.

Server setup

The server setup should be performed first as the Raspberry Pi setup instructions expect the server to be available.

The cloud image can be set as the harddisk image in your virtualization environment of choice. You may also have some luck with writing the image to an USB drive like you would write the Raspberry Pi image to an SD card and boot from that drive.

To simplify the setup the network should be setup to be bridged to the ethernet interface of the server.

To test the image without the necessary network setup you can also try running:

$ make run_server

Server first boot

On the first start the image will ask some questions and setup a tutor account with a provided password.

Raspberry Pi setup

You can flash the Raspberry Pi images on an SD-Card with a dd command like the following:

$ sudo dd if=~/Downloads/nota-lab/disk_images/rpi_student.img bs=8M of=/dev/sd_

Where you replace /dev/sd_ by the drive name of your SD-Card as discovered by e.g. dmesg -w or blkid.

The Raspberry Pi file will be 7Gb large, so that it will fit safely on an 8Gb SD-Card. If you need more storage space you may use cfdisk and resize2fs on the running Raspberry Pi, if you need the image to fit on smaller cards you can change the first lines of rpi_student.vmdb to generate a different image size.

Raspberry Pi first boot

Upon first boot the Raspberry Pis will ask some questions regarding the keyboard layout and timezone.

For most questions you can go with whatever the example says, note however that the keyboard layout is not set before the first reboot, so you will have to deal with an american keyboard layout where the / character is left of the right shift key.

The ids you give the setup script have to be unique in the lab as the hostname and WiFi SSID will be derived from them. You can however use characters or numbers or whatever suits you best.

When you are done answering questions the Pi will reboot and you can log in using the student account and the password you provided.

When asked about the xfce4-panel configuration answer “Use defaults”.

Finally we have to work around a quirk in the firefox version used that makes it difficult for image builders to install custom certificates and easy for enduser, which is totally stupid their design decision.

With the cloud server running in the same network perform the following steps in the webbrowser to install the certificate:

You can also perform this step on other computers in the network in order to access the lab materials from them.


You should run the image creation process each year before the lab takes place to stay on top of security updates.

Even if you do not generate a new image you should at least re-flash the image to the SD-Cards to make sure the students work in a fresh environment.

Flashing NodeMCU


The Microcontroller boards need to be manually flashed with the NodeMCU firmware in order to run the Lua programs developed by the students.

Luckily we do not need to set up the complex ESP8266 SDK and can instead use the Online builder provided by the NodeMCU devs.

Go to the builder website, enter a valid mail address and select the following modules to include:

  • DHT
  • file
  • GPIO
  • MQTT
  • net
  • node
  • PWM
  • timer
  • UART
  • WiFi

Finally hit “Build” and wait for the firmware file to arrive via E-Mail.


In the E-Mail you will receive a link to a float and an integer version of the firmware. We will be using the float version.

Download the firmware and use esptool (which comes pre-installed on the Raspberry Pi images) to upload it to the microcontroller boards:

$ --port /dev/ttyUSB0  write_flash 0 nodemcu-master-…-float.bin v2.5.0
Serial port /dev/ttyUSB0
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
MAC: 12:34:56:78:9A:CD
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash params set to 0x0240
Compressed 430704 bytes to 277188...
Wrote 430704 bytes (277188 compressed) at 0x00000000 in 24.4 seconds (effective 141.2 kbit/s)...
Hash of data verified.

Hard resetting via RTS pin...

Note: Depending on the source of your esptool installation the command name may be or esptool.

This flashing has to be performed once per board.


You should run the image creation process each year before the lab takes place to stay on top of security updates.

Even if you do not generate a new image you should at least re-flash the image to the microcontrollers to make sure the students work in a fresh environment.

Hardware Setup

Behind the scenes

This chapter tries to document how certain aspects of the lab work to make future work on it easier.

Network configuration

Address configuration

The student Raspberry Pis and the virtual machine try getting an IPv4 address on their ethernet adapter via DHCP.

The simplest setup is to connect them all to a simpler consumer router that hands out IP addresses from a pool.

Each Raspberry Pi will, in addition, run an isolated network on the WiFi interface on which it gives out IP addresses using DHCP.

Clients connected to that network can not access the internet, the other Raspberry Pis, or the cloud server.

The network is condigured using systemd-networkd in the configuration files in /etc/system/network.

The WiFi setup is done using hostapd. The WiFi interface can not be used to connect to wireless networks.

The old ifconfig line of tools are deprecated, use for example ip addr to show the IP addresses assigned to you network interfaces.


The Raspberry Pis and the virtual machine get assigned their DNS server to use using DHCP.

It is not assumed that custom domain names can be added to the zones of that DNS server. In order to get human-readable names for e.g. the nota-cloud virtual machine LLMNR is used, which sends DNS requests to the whole subnet using multicast packets and the corresponding host answers with its IP address.

This will not work if the virtual machine and the Pis are not in the same multicast domain (≈ separated by a router). The you will have to configure DNS to resolve the domain name of the cloud server and generate an appropriate server certificate.

Internet Access

Also the Lab is mostly self contained there are reasons to give internet access to the Raspberry Pis and virtual machine, namely:

  • The Raspberry Pis do not contain a real time clock, they need access to an NTP server to get the correct time. The server certificates can appear invalid when the the time is wrong.
  • The students should be able to look up programming ressources while working.

Certificate Authority

A design goal of the cloud unit is for the students to learn that communication over the public internet may not happen unencrypted.

This is why the fake cloud environment also uses encrypted HTTPS.

In order to enable HTTPS we need certificates signed by a certificate authority trusted by all the participants in the network. Acquiring certificates signed by a real CA would complicate the lab setup so a fake CA is created during the disk image build process.

This is all done by the Makefile in disk_images/certificates/ that sets up the CA, creates a key for the cloud server to use and creates a signed certificate for that key.

If you decide to run the server with a custom domain name you should add that domain name to the disk_images/certificates/nota-cloud.conf file.


  • The certificates appear invalid:
    • Check that the system time is correct and that the devices can reach an NTP server.
    • Make sure the virtual machine and Raspberry Pi images ware built on the same host and in one go.

Cloud Server

Web Server

Running on the virtual machine is an instance of nginx that serves static files and acts as reverse proxy.

When connected to on port 80, using unencrypted HTTP, it serves the files in /var/www/nota-nossl.

When connected to on port 443, using encrypted HTTPS, it serves the files in /var/www/nota and will proxy requests to URLs below https://nota-cloud/api/ to the cloud API server.

This server is configured using the files in /etc/nginx and controlled using $ sudo systemctl restart nginx.

API Server

The API server serves the interactive part of the cloud app, it runs with the user id of the tutor user.

It is written in Python 3, using Bottle to perform the request routing and gevents to realize the event streaming. Gunicorn is used to deploy the server.

This server is controlled using $ systemctl --user restart nota_api.

The server expects data to be POSTed to the /api/log/<sensor> endpoints, where <sensor> is replaced by an arbitrary name for the sensor.

The request Body has to be JSON encoded and contain a “value” key with a float value ({ "value" : 10.0 }).

Such a request can be created like this, using HTTPie:

http POST https://nota-cloud/api/log/nota_2 value:=-2.0

The other important endpoint is /api/stream, which sends a history of the most recent sensor values and newly ariving ones as server sent events.

You can watch this stream using the command below:

curl https://nota-cloud/api/stream

Web App

The web app subscribes to the /api/stream using EventSource and plots a new point on a line diagram whenever an event is received using Chart.js.

Recording Screencasts

The process of recording screencasts can not be performed on a Raspberry Pi and must instead be performed on a powerful computer as the video encoding slows the Pi to much for fluent screencasts.

Getting a fresh browser instance

For screencasts you want a browser session that is fresh as-installed.

The command below sets the language to be english and uses a newly generated browser profile.

$ LANG= firefox --new-instance --profile $(mktemp -d)

Cathing the window

The command below starts recording the screen with the correct size for screencasts and shows it in a new window.

Adjust the window you want to film to fit.

Adjust the +2,28 to catch another part of the screen.

$ ffplay -video_size 750x480 -framerate 30 -f x11grab -i :0.0+2,28

Starting the recording

The command below will record the screen into the file screencast.mp4. Hit Ctrl+C when you are done.

$ ffmpeg -video_size 750x480 -framerate 30 -f x11grab -i :0.0+2,28 -an -vcodec libx264 -pix_fmt yuv420p -profile:v baseline -level 3 screencast.mp4

Extract still images

The command takes a screenshot 16.1 seconds into screencast.mp4 and saves it as still_image.png.

$ ffmpeg -ss 16.1 -i screencast.mp4 -vframes 1 still_image.png