OpenTofu lab: infrastructure as code with plan, apply and state on one VM

This lab gives each student OpenTofu on an Ubuntu machine of their own. Infrastructure as code means describing what should exist in files and letting a tool work out how to get there: it compares the files with a record of what it has already made, shows the difference as a plan, and only then changes anything. The student writes a small project, reads plans, looks at the state and fixes a broken project.

OpenTofu is free and open source, and no licence is needed. Nothing is installed on the student’s computer. The one thing the lab leaves out is a real cloud: it explains so itself, and so does this page.

What students learn

The working habits of infrastructure as code, in six parts. A first plan and apply and the state file they leave behind. Variables and outputs. Several of a thing from one description, with count and with for_each, and why for_each is the one that keeps names. Reading a plan after a change and saying what will be created, changed or destroyed before anything happens. What the state is for, shown by deleting it and watching the plan want to create everything again. And finding three mistakes in a project, a wrong type, a missing variable and a cycle, with tofu validate. Along the way tofu fmt, tofu console and dependencies between resources.

What is real here, and what is not

Real clouds and services are reached through providers, plug-ins that OpenTofu downloads from a registry. A student’s VM can only reach Ubuntu’s archive, PyPI, npm and GitHub, so no provider can be downloaded and nothing real is ever made in this lab. What is built into OpenTofu needs no download: the terraform_data resource, which only stores a value and hands it back. With it, variables, outputs, count, for_each, dependencies, plan, apply, destroy and the state are all the real thing. A provider such as AWS or Docker changes only what a resource block makes. The README shows one as text to read and the lab never runs it.

The three folders

Three folders are in the home folder. hello works as given, for the first plan and apply, a variable and the state. campus is the student’s project, written from nothing to a list in the README: three variables, servers made with for_each, rooms made with count, a summary that reads them both, and two outputs. fix is a project with three mistakes to find and correct.

Run it in your browser

VM labs are set as a lab task in a module, and the sample is on the lab’s page. The machine is small: one CPU, 1 GB of memory and 10 GB of disk. OpenTofu itself uses about 80 MB while it works.

  1. Add the lab. In a module you teach, add a task and choose the Ubuntu VM lab card. The page shows a short description of the machine instead of a compose file.
  2. Start from the sample. The page offers ready-made labs to start from. Choose OpenTofu. Using a sample replaces the text, and Undo brings yours back.
  3. Publish and start your own copy. Publish, then Start. The lab’s own setup script installs a few tools from Ubuntu’s archive, downloads OpenTofu 1.13.2 from its GitHub release, checks the file against a fixed checksum and installs it, the first time the VM starts, in a minute or two. The download needs an account: a visitor’s VM reaches Ubuntu’s archive alone.
  4. Open the terminal. Open its terminal and read README.md in the home folder: it says what to do in six parts and gives none of the answers.

A basic lesson on this lab

OpenTofu Basics is a small lesson worked in this lab, which is an Ubuntu VM. It has a hook, an I can outcome, key words, a starter, a check after the ideas, a common mistake and an exit check, and each step has a Run button that types its command into the machine’s terminal. A student reads a project, runs init and plan, applies and lists the state, changes one value and reads the plan, then deletes the state and sees the plan want to create what exists.

The lesson looks around and leaves the lab’s own task, the project and the broken one, to the student, so it hands out no answers.

How it is marked

The lab has a check. It copies the student’s two folders to a new place, so their own state does not count, and refuses providers and provisioners. It then validates and requires tidy files (tofu fmt). For the campus project it chooses values of its own for the variables, a site name nobody has seen and its own servers and rooms, plans, and applies. The state must hold one server for each name, each with the site and the name as its input, the rooms numbered from one, and an output summary that reads a resource rather than being typed in, and the names. A resource with no input fails, and so does an output that does not follow the variables. The check then removes one server and adds two, plans again, and requires that only the one is destroyed and only the two created. It applies, requires that nothing is left to change, and destroys. Last, the broken project has to validate, apply, keep its resources and follow its variable. The first line of what the check printed says why.

  1. Hand it out. Assign the lab like any task, with a due date if you want one. Each student gets a VM of their own, kept between sessions.
  2. Run the check. On a student’s row in the class list, press Run the check. It starts a copy of their saved machine that is not saved back, runs the lab’s check script as root and shows whether it passed, what it printed and when. The student is not told the result.
  3. Mark it. Read the first line of what the check printed: it says what is not right, such as servers that do not match the variables, a summary that does not read the servers, or a plan that still wants to change something after apply. Send the work back with a reason if it needs more.

The definition on GitHub

The file is the whole lab definition, the same text the platform runs: size, setup script, the tofulab command, the three projects, README and check. Copy it and change the project, the variables or the mistakes to make a longer lab.

Try this lab, and what it costs

A free personal account can work through the basic lessons in this lab, with enough free credit each month to follow most lessons and no card. For a class, a school or college has its first 365 days free for up to 50 students, then pays per student a year, with every lab included and staff free.

Questions people ask

Does the OpenTofu lab need a licence?
No. OpenTofu is open source under the Mozilla Public Licence 2.0, a Linux Foundation project that began as a fork of Terraform. The lab uses OpenTofu and never Terraform, whose licence is not open source. It is downloaded from the project’s own release when the student’s VM starts, and nothing of it is distributed by us.
Why can students not make a real server?
A real server is made through a provider, and providers are downloaded from a registry that a student’s VM cannot reach: it reaches only Ubuntu’s archive, PyPI, npm and GitHub. So the lab teaches everything except the provider, with the one resource OpenTofu has built in. Plan, apply and state behave the same with a real one, which is the point of learning them here.
Who can run it?
Somebody with an account, free or in a college. The lab downloads OpenTofu from GitHub when the VM first starts, and a visitor’s VM, which reaches Ubuntu’s archive alone, cannot. If a download fails, sudo tofulab install tries again, and the check says OpenTofu is missing rather than failing for another reason.
Can students harm anything?
Only their own copy. Nothing the lab makes is outside OpenTofu’s own state, and the VM reaches Ubuntu’s archive, PyPI, npm and GitHub and nothing else. If a student breaks a folder, sudo tofulab reset puts its files back.
Was the lab tested in a real student VM?
The setup, with the real download and its checksum, the lesson’s commands and the check were run in a real Ubuntu 26.04, in a container standing in for the VM, with no network needed after the download. A booted student VM behind the platform’s allowed-list proxy, which GitHub’s download has to pass, is worth one try before a class.