Teaching Platform-Spanning Systems Again

I reprised my gig from last year and taught the course Platform-Spanning Systems at Uppsala university during the first quarter of 2025. It is always fun to get back the university and enjoy the atmosphere and the enthusiasm and fearlessness of students. The course went better than last year (in my opinion), in part thanks to the sponsorship from Bahnhof that provided us with virtual machines for the students to run their code.

The Course

A longer description is available in the blog about the 2024 edition. In short, in the Platform-Spanning Systems (PSS) course the students should build a system that:

  • Solves a single problem/implements a single application.
  • Using at least three physical processes (i.e., separate process instances on the same or different hosts).
  • With at least three different software components (i.e., separate code bases or applications).
  • Running on at least three different hosts (such as phone, server, and server).
  • With network connections between the software components.

Each application was built by a small group of students. The student groups were smaller this year than last year, with four students per group instead of five or six last year. This did mean that teamwork was slightly easier. But also limited what they had time to build, making the final programs slightly simpler than in 2024.

Bahnhof Virtual Machines

Since the goal of the course is to build an application split into multiple tiers, the students need access to something apart from their own laptops and phones typically. To solve that for this year, I talked to the nice folks at Bahnhof Cloud here in Sweden and got access to a set of small virtual machines for the duration of the course. Thanks a lot to Bahnhof for providing VMs for my students to run their code!

Having to use plain Linux VMs with no pre-existing cloud infrastructure or APIs forced more insights compared to last year when the students relied on various online services to host their applications. It forced basics to the surface, such as connecting between machines using plain IP addresses (no DNS here!).

Deploying code to a VM also required some work. It could be as simple as logging in and pulling code from git and putting it in place. Some groups used containers and container deployment systems like K3S or Docker Compose, which made it a lot easier both to deploy changes and to set up local test environments matching the “production” environment. Groups that did not set up such deployment systems had a harder time testing code, especially when developing in a branch. It also indicates that maybe we should have set up a “staging” environment for each group – which I did not realize until after the class.

As a bonus, we got to visit one the “Thule” data center in downtown Stockholm to literally see the power behind the scenes. This was a wonderfully educational excursion (and it would be good to see if we could do excursions in more courses), seeing what is behind “the cloud”. Not just the racks of computers, but also what literally powers it all. The power, cooling, and networking systems that make the computers stay online. Basically everything was double or triple redundant, using different methods to reduce the risk of single points of failure.

It was particularly impressive to see the huge banks of batteries that would cover the first minutes of a power outage, covering the time needed for the diesel generators to come online. Or, if that failed, give the computers enough time for orderly shutdowns.

If you get a chance to go an Bahnhof data center tour, take it! They seem to offer this from time to time in conjunction with various events and trade shows.

Bahnhof Virtual Datacenter

One unexpected effect of the Bahnhof sponsorship was that I became a system administrator for a little virtual data center. It was managed through OpenStack, which took some getting used to. Since there were not all that many students, I ended up launching and configuring each virtual machine (VM) manually. It was pretty click-heavy work that I am sure can be automated.  

This picture from OpenStack shows the topology of the system:

All the VMs sit on an internal network and can reach each other using 192.168-series IPv4 addresses with no intervening firewall. This made life quite easy inside the internal network. Each VM also had an external IP which was provided by a NAT bridge sitting in from of the datacenter.

Inbound connections from the Internet were secured by a firewall that only admitted specific ports. To make it possible for the students to even reach their servers over SSH (for administration) or HTTP (for actual traffic) I had to open some ports. Once again, interesting to see this in action for real.

Why we Cannot have Nice Things

As mentioned, the VMs did have Internet-visible IP addresses and some ports open. That was unfortunately enough to invite some hackers.

One team got their backend MySQL server hacked by a password-guessing attack! The attack encrypted the database and demanded a ransom. It took a while for the students to figure out what was going on, as the symptom of the problem was that the database stopped working after it had been running for a while. However, at some point, they looked at the file system and found the ransom note! The solution was to add a strong password to the database which solved the immediate problem. Later on, they also set up a reverse proxy to protect the entire backend.

It is a bit sad that you cannot simply setup a private server for some experimentation. Even if you do not advertise it, it will be found by IP and port scans. To play with servers you need to have them on your own local network (or properly secured in the cloud).

We can’t have nice things.

Security Thinking

Speaking of security, it was clear that the students had a decent grasp of what I would call “physical” security. Basic techniques like encryption, firewalling, authentication, etc.

However, there was almost no thought given to application-level shenanigans. Things like malicious users, intentionally bad inputs, and subverting application logic and flows.

For example, there was an application that was designed to crowd-source information about the queue lengths of the student nations. To me, this opens for obvious abuse like trying to scare people away from the nation you want to go to by faking lots of “long queue” reports. Another example was a multiplayer quiz game, where you really need to think about how you avoid revealing the right answer to a player – it is not a problem if you assume the endpoint application is trusted. But since there is an exposed API… well you could see opportunities to try to exploit that using your own code.

This kind of security thinking seems like it might need a bit more attention.

Tooling

Using GitHub was mandatory for the class. Most students were quite familiar with it, but some got their first exposure to actual collaboration flows like pull requests in the course. Learning goal achieved!

The students had to track their backlog in a tool of their own choice. Trello was the most popular, with some teams using GitHub projects, and one using a free JIRA project.

When it came to group internal communications, Discord appears to have been used by almost everyone. It is a very popular tool in this particular demographic.

Use of AI

Finally, AI. The current Uppsala University policy is that students are allowed to use generative AI tools (i.e., LLMs), unless there are good reasons not to. In a course like this, I saw no point at all in limiting its use. Instead, I asked the students about HOW they used the tools. Here are the main findings.

LLMs were used to generate code. In particular, code to handle APIs and common frameworks. Another common use was to build SQL code snippets – especially useful for a language that you know a little bit about. There was a realization that generated code might be hard to understand, changed, and maintain over the long run. Sometimes writing the code in all its details by yourself is better.

Inversely, LLMs were used to explain code and look for problems with code that did not work. To variable success. Sometimes it was really helpful, but other times an LLM might miss an error like a missing comma in a list of arguments. Hit or miss.

LLMs were also used a “sparring partner” or “discussion partner” when trying to solve problems. This came from several students, and I must admit to feeling behind the curve as I have never managed to figure that out for myself.

Finally, LLMs were used to polish English text. Which is really one of the most reliable uses of the technology as far as I am concerned.

In terms of tools, ChatGPT was the most commonly cited, followed by GitHub CoPilot.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.