Skip to content
Complete Guide to Running Live Technical Online Courses with Hands-On Exercises

Complete Guide to Running Live Technical Online Courses with Hands-On Exercises

In this guide, I would like to walk you through setting up a complete environment for the practical labs of live online courses. It is meant for instructor-led courses with a live cohort. Participants will access the environment through a web terminal (no setup required) supporting various features commonly needed for technical training (e.g., request help, inline chat, access to files and graphics).

Our toy example will be a Linux command-line data workshop where participants will inspect files, process CSV data, and generate plots with the goal of showcasing requirements like a custom package manager and visualization. Adapt and tweak to your needs!

Guide Overview

The guide will comprise the following steps

  1. Obtain a Linux server (e.g. a VPS or cloud compute instance).
  2. Set up a custom package manager
  3. Create a template for user workspaces
  4. Add files needed for exercises
  5. Create separate training environments based on a user table
  6. Start the session
  7. Run the live training

The steps 2-4 are entirely optional, and can be skipped if not relevant to your training.

1. Obtain a Linux server

You can use any Linux server for your training, be it a local workstation, a VM, an HPC, or a compute instance in the cloud. I prefer to use cloud servers, as it allows me to get a server with the exact specifications/resources I want for only the time needed. We will later create a Linux user for each participant and trainer; with a VPS, there is no need to clean up as we can simply delete it.

You can rely on any cloud provider of your choice, like AWS, Google Cloud, DigitalOcean, Hetzner, or OVHcloud. There is usually no need for extensive networking or firewall setup, because the connection to the server is managed through ShellRoom. You only need to make sure that you can remotely access the server during setup (e.g., with SSH).

Personally, I like to use Hetzner as the server setup is very simple and the price-to-performance is also great for more powerful servers. Here is how you would create a cloud server on Hetzner:

  1. Log in to the cloud console and create a new project
  2. Create Resource -> Server
  3. Select the server type best suited for your training, for example, CPX52 with 12 vCPUs, 24 GB RAM, and 480 GB SSD.
  4. Select a Linux OS image of your choice, for example, Ubuntu. If you previously created a snapshot of your customized image, you can select it here.
  5. Select Networking: Free public IPv6 addresses are sufficient.
  6. SSH keys: upload your public SSH key for easy access to the server.
  7. Click “Create and Buy Now.” The new server will be available in a few seconds, and you can copy its public IP.
  8. Connect to the server via ssh -f [SSH_KEY_FILE] root@[PUBLIC_IP]

That’s it - we can now prepare our server for the training.

2. Set up a custom package manager

Oftentimes, installing software packages through the OS package manager is not flexible enough. A solution is specialized package managers such as Conda, Pixi, or uv. We will therefore set up Conda to install specific tools needed for our training. Specifically, we have to install Conda in a way that multiple users can use its packages.

Note

This guide assumes that you are logged in as the root user, which is the default for many cloud servers after creation.

First, we will download conda and install into the folder /opt/conda:

wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/conda

All users on the Linux system will be able to run conda from this single installation folder. Next, we will install some software packages into a shared enviroment:

/opt/conda/bin/conda create -y --override-channels \
  -p /opt/conda/envs/linux-intro \
  -c conda-forge \
  csvkit pandas matplotlib plotly libsixel

At this point, we have an environment called linux-intro that contains our required tools. To automatically activate that environment for all training users, we will add a short snippet to the .bashrc file.

3. Create a template for user workspaces

Each course participant should have a separate workspace that contains all the files needed for the exercises and configuration. To this end, we will create a skeleton - a template of files and folders that will later be available for each user. These files will simply be copied into each user’s home folder.

Thus, we can add a customized .bashrc file to the skeleton. This allows us to add commands that will be automatically executed once a user logs in. In our case, we will add a snippet that activates our conda environment and prints a greeting message to our users.

mkdir -p /opt/skeleton/ # create the skeleton folder
cp /etc/skel/.bashrc /opt/skeleton/ # optional: start with the OS's default

cat >> /opt/skeleton/.bashrc <<'EOF'
. /opt/conda/etc/profile.d/conda.sh
conda activate linux-intro
echo "Welcome to our course!"
EOF

4. Add files for exercises

We can now add more files to the skeleton, like data or scripts required for the exercises. In our case, we will download a toy dataset as well as a Python script to create a plot.

mkdir -p /opt/skeleton/exercise-1
wget -P /opt/skeleton/exercise-1 https://raw.githubusercontent.com/allisonhorst/palmerpenguins/main/inst/extdata/penguins.csv
wget -P /opt/skeleton/exercise-1 https://raw.githubusercontent.com/mfasold/example-data/main/plot_data.py

Tip

Create a snapshot of the server after this step to easily re-use the environment for future trainings.

5. Create separate training environments based on a user table

At this point we can define our user table containing the participants, instructors, and assistants of our training. I typically have such a table in a spreadsheet app from where I copy the usernames and passwords and paste them into a text file using the nano editor available on most Linux systems. Here, we will just store a list of names and passwords into a my-users.csv file:

cat > my-users.csv <<'EOF'
harry,lumos1
ron,lumos2
luna,lumos3
lupin*,lumos4
snape*,lumos5
EOF

Users marked with an asterisk * get the trainer role; others get the participant role. Here, we defined three participants (harry, ron and luna) and two trainers (lupin and snape). Each user gets a unique password that consists of “lumos” and a number.

Next, we will download ShellRoom, which we use to manage our training session:

curl -sSf https://shellroom.io/dl | sh

Finally, we can setup the complete training environment using

./shellroom setup --users-csv my-users.csv --skeleton-copy-dir /opt/skeleton/

Tip

If you have large data files that you do not want to duplicate, consider using --skeleton-hardlink-dir.

6. Start the session

Run the following command to start the session:

shellroom start --users-csv my-users.csv

Congrats - your training session is now live! The dashboard shows your webterm URL that you can share with your participants and trainers together with their usernames and passwords.

7. Run the live training: participant examples

This section provides example tasks that you might adapt for your workshop. Start by opening the displayed Webterm URL in your browser and logging in as participant harry with password lumos1.

Inspecting the exercise data

Each user has their own copy of the exercises we previously stored in the skeleton directory:

cd exercise-1/
csvlook penguins.csv
csvstat penguins.csv

Downloading and viewing files

First, let’s plot the data using a python script that we prepared:

python plot_data.py

The output of this script is the file penguins.png, which we would like to inspect. To open the PNG file in the browser, first create a public link to the file using shellroom link or the open alias:

open penguins.png

Middle-click on the link, and it will be opened in a new browser tab. File types that the browser cannot display will be downloaded.

Tip

Chrome and Firefox have a convenient split-tab function, allowing you to view the terminal and the image side by side. To do this, right-click on the new browser tab containing the image and select “New split view with current tab.”

Since this file is an image, we could also display it in the terminal using SIXEL:

img2sixel penguins.png

Tip

Various tools allow you to print SIXEL graphics. For example, euporie is a Jupyter notebook that runs on the terminal and displays images in SIXEL.

Editing files and image auto-update

Let’s modify the plot by editing the script:

nano plot_data.py

Now remove the line that plots the legend (plt.legend()), and press CTRL-S to save, then CTRL-Q to quit nano. Update the plot by running python plot_data.py again. You will see that the image in the other browser tab updates automatically. You can also use F2 to split the window in two panes to keep both the editor and the shell open. All functions available to participants are described here

8. Run the live training: trainer examples

To better experience the trainer functions with multiple participants, open the Webterm URL in a second browser tab and login as ron / lumos2.

Now open the same URL in another browser tab, then log in as lupin / lumos4.

You see the trainer overview: a shell to the left, the participant activty to the right and the menu at the bottom. You might want to try the following trainer commands:

  • Ctrl + B Browse: Enter Browse Mode to quickly cycle through participants using the Cursor Up/Down keys.
  • Ctrl + S Search: Type in a username (shown in the menu bar). Press Enter to attach to the participant’s terminal. You can now access all participant commands, for example F3 Chat, and use this to help participants.
  • F8 Presenter View: Invoke this in the trainer overview (Ctrl + O) for sharing your screen during the training.

The full list of available trainer commands is described at trainer usage.