Piztu. Computer lab management

Attention: Although the user of each classroom computer won’t need sudo privileges in the next piztu version, in this version it is required, and it must run without prompting for a password.

Piztu is built on Python and Ansible. The automation engine is Ansible, which runs actions on the classroom computers over SSH with public-key authentication: an agentless model where clients only need OpenSSH and sudo, while every operation (power on, suspend, shut down, lock, send or collect assignments) is launched in parallel as a playbook, with Wake-on-LAN support for remote power-on. On top of that engine, the entire server side is written in Python: the web interface relies on Flask and Flask-SocketIO (real-time WebSockets for the noise VU meter, transfer progress and an SSH terminal embedded in the browser), the desktop application is built with PyQt6, and a standalone noise monitor captures the microphone with arecord to issue warnings and automatic lockdowns. Configuration is centralised in a YAML file, persistent data (computer positions and noise threshold) is stored in SQLite, the interface is multilingual (Galician, Spanish, English and Portuguese) and the graphical installer is written in Go with the Fyne framework.

Installation steps

The first thing to do is rename the classroom computers with a name followed by the computer number, for example: tux01, tux02… You should do this by editing the /etc/hosts and /etc/hostname files:

You also need to install openssh-server on the clients, so the server can access them:

$ sudo apt update
$ sudo apt install openssh-server

Next, edit the SSH service configuration file, uncommenting or changing these lines:

$ sudo nano /etc/ssh/sshd_config
Port 22
PermitRootLogin yes
PubkeyAuthentication yes
PasswordAuthentication yes

And finally, you must grant sudo privileges to the default user on the clients:

$ su root
# visudo

and add:

usuario ALL=(ALL) NOPASSWD:ALL

On the server side, Python 3 must be installed.

Piztu application features

a. Power management

  • Power on classroom — turns on the computers over the network via Wake-on-LAN (magic packets), with no need to touch them physically.
  • Suspend classroom — suspends the computers to save energy while keeping them ready to resume.
  • Shut down classroom — shuts down all computers in an orderly way (with a prior confirmation to avoid mistakes).

These can be applied to the whole classroom at once or to a specific computer from its card on the map.

b. Locking and class control

  • Lock — locks the screens of all computers (or the selected ones) to get the students’ attention at a given moment.
  • Release — unlocks the computers. Includes automatic verification with retries to make sure none of them remained locked.

c. SSH terminal

  • SSH — opens a remote terminal to any computer directly from the interface (embedded in the browser with xterm.js, or in the desktop GUI), for administration or diagnostics without leaving your seat.

d. Noise control

  • Noise monitor — watches the classroom microphone and computes the moving average of the last 30 s. If it exceeds the threshold set by the teacher, it warns students on their screens; if the noise persists for another 30 s, it automatically locks the computers. The threshold is adjusted with a slider.

e. Sending and collecting assignments

  • Send assignment — distributes files to the computers (drag and drop), to all of them or to a manual selection.
  • Anti-copy mode — sends different files to even- and odd-numbered computers (sorted by the number in their name), useful to prevent copying during exams.
  • Collect work — downloads each computer’s assignments folder to the server via SFTP.
  • File explorer — browse the work collected from each computer and download it individually or as a ZIP.
  • Clear folder — deletes the contents of the assignments folder on the selected computers.

f. Interactive classroom map

  • Represents each computer as a card with a status indicator (online/offline) and a badge showing the collected files. Cards can be dragged to mirror the real physical layout of the classroom (saved automatically).

g. Other

  • Multilingual interface (Galician, Spanish, English, Portuguese).
  • About Piztu — authorship, version, contact and licence information.

Configuring computers and installing software with Ansible

Every Piztu action on the computers is, under the hood, an Ansible playbook. That means you can configure the classroom computers and install software on all of them at once just by writing (or reusing) a playbook. No need to touch each computer: Ansible connects over SSH and does the work in parallel.

The three pieces

1. The hosts file (inventory)

Defines which computers make up the classroom. Each line is one computer, grouped under [aula]:

[aula]
tux01.local mac=c4:34:6b:7a:a1:a8
tux02.local mac=00:23:24:9c:fa:cd
...

[aula:vars]
ansible_become=yes                              # escalates privileges with sudo
ansible_become_method=sudo
ansible_python_interpreter=/usr/bin/python3
  • [aula] is the group the playbooks target (hosts: aula).
  • The mac= value is used by Wake-on-LAN to power computers on.
  • [aula:vars] applies common variables to all of them (here, automatic sudo).

2. The playbooks/ folder

Each .yaml is an action. Several come bundled: acenderAula, bloqueoTotal, visualstudiocode, instalar_lamp… To add a new capability, just create a playbook here.

3. The mapping in config.yaml

The logical names used by the interface are resolved to real files in:

ansible:
  grupo_aula: "aula"
  playbooks:
    acender: "acenderAula"
    bloqueo: "bloqueoTotal"
    # add yours here: logical_name: "file_name_without_extension"

How to run a playbook

Manually (the whole classroom):

$ ansible-playbook -i hosts playbooks/visualstudiocode.yaml

Only on some computers (with --limit):

$ ansible-playbook -i hosts playbooks/visualstudiocode.yaml --limit tux01.local,tux02.local

Examples

Example 1 — Install a simple program (GIMP) on the whole classroom

---
- name: Install GIMP on the whole classroom
  hosts: aula
  become: yes
  tasks:
    - name: Install the gimp package
      apt:
        name: gimp
        state: present
        update_cache: yes

Example 2 — Install several packages at once

---
- name: Programming tools
  hosts: aula
  become: yes
  tasks:
    - name: Install packages
      apt:
        name:
          - python3-pip
          - git
          - build-essential
        state: present
        update_cache: yes

Example 3 — Install from an external repository (VS Code, already included)

---
- name: Install Visual Studio Code
  hosts: aula
  become: yes
  tasks:
    - name: Import Microsoft's GPG key
      apt_key:
        url: https://packages.microsoft.com/keys/microsoft.asc
        state: present
    - name: Add the repository
      apt_repository:
        repo: "deb [arch=amd64] https://packages.microsoft.com/repos/code stable main"
        state: present
    - name: Install code
      apt: { name: code, state: present, update_cache: yes }

Example 4 — Configure the computers (copy a configuration file)

---
- name: Distribute a common wallpaper
  hosts: aula
  become: yes
  tasks:
    - name: Copy the image to the computer
      copy:
        src: /opt/piztu/recursos/fondo.png
        dest: /usr/share/backgrounds/aula.png
        mode: "0644"

Example 5 — Change a system option (enable NumLock, already included)

---
- name: Enable NumLock at startup
  hosts: aula
  become: yes
  tasks:
    - name: Install numlockx
      apt: { name: numlockx, state: present }
    - name: Enable NumLock
      command: numlockx on

Example 6 — Uninstall a program

---
- name: Remove games
  hosts: aula
  become: yes
  tasks:
    - name: Remove gnome-mines
      apt:
        name: gnome-mines
        state: absent

Integrating a new playbook into the Piztu interface

  1. Save your .yaml in playbooks/ (e.g. playbooks/instalar_gimp.yaml).
  2. Give it a logical name in config.yaml:
    ansible:
      playbooks:
        instalar_gimp: "instalar_gimp"
  3. Call it from the interface with the executar_comando event (action instalar_gimp), and Piztu launches it against the whole aula group automatically.

You can also always run it manually with ansible-playbook -i hosts playbooks/..., without going through the interface.

Scroll to Top