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
- Obtain a Linux server (e.g. a VPS or cloud compute instance).
- Set up a custom package manager
- Create a template for user workspaces
- Add files needed for exercises
- Create separate training environments based on a user table
- Start the session
- 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:
- Log in to the cloud console and create a new project
- Create Resource -> Server
- Select the server type best suited for your training, for example, CPX52 with 12 vCPUs, 24 GB RAM, and 480 GB SSD.
- 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.
- Select Networking: Free public IPv6 addresses are sufficient.
- SSH keys: upload your public SSH key for easy access to the server.
- Click “Create and Buy Now.” The new server will be available in a few seconds, and you can copy its public IP.
- 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/condaAll 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 libsixelAt 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!"
EOF4. 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.pyTip
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
EOFUsers 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 | shFinally, 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.csvCongrats - 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.csvDownloading and viewing files
First, let’s plot the data using a python script that we prepared:
python plot_data.pyThe 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.pngMiddle-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.pngTip
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.pyNow 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 + BBrowse: Enter Browse Mode to quickly cycle through participants using the Cursor Up/Down keys.Ctrl + SSearch: Type in a username (shown in the menu bar). PressEnterto attach to the participant’s terminal. You can now access all participant commands, for exampleF3Chat, and use this to help participants.F8Presenter 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.