</>
AcademyPC
Home Corsi & Risorse
🔧 ISTITUTO TECNICO INFORMATICO — LABORATORIO RASPBERRY PI 5

Guida CompletaProgetti Didattici

Ogni passaggio spiegato nel dettaglio. Nulla lasciato al caso. Dalla configurazione iniziale del sistema operativo fino ai progetti avanzati di AI, IoT e cybersecurity.

Raspberry Pi 5 – 8GB RAM
SSD NVMe 1TB (M.2 HAT+)
Case con raffreddamento attivo
Alimentatore ufficiale 27W USB-C
Raspberry Pi OS Bookworm 64-bit
Rete LAN scolastica
⚙️

Setup Iniziale del Sistema

Configurazione completa di Raspberry Pi OS Bookworm 64-bit prima di qualsiasi progetto
PREREQUISITO ⏱ 30-45 min
⚠️
Esegui questo setup PRIMA di qualsiasi progetto. Un sistema configurato correttamente eviterà la maggior parte dei problemi durante i laboratori.
1

Flashare Raspberry Pi OS sul SSD

Operazione da eseguire su un PC, prima di accendere il Raspberry

Scarica Raspberry Pi Imager da https://www.raspberrypi.com/software/ e installalo sul tuo PC Windows/Mac/Linux.

Collega il SSD NVMe al PC tramite un adattatore USB-to-M.2 e segui questi passi nell'Imager:

  • Seleziona dispositivo: Raspberry Pi 5
  • Seleziona OS: Raspberry Pi OS (other) → Raspberry Pi OS Lite (64-bit) — senza desktop, più leggero per un server
  • Seleziona storage: il tuo SSD NVMe
  • Clicca l'icona ⚙️ Impostazioni avanzate prima di scrivere
ℹ️
Nelle impostazioni avanzate configura: hostname (es. raspberry-lab), utente (es. pi), password sicura, SSH abilitato, WiFi se necessario. In questo modo il Raspberry si avvia già configurato senza bisogno di monitor/tastiera.

Dopo aver scritto l'immagine, inserisci il SSD nel Raspberry Pi 5 tramite l'HAT+ NVMe ufficiale.

2

Primo accesso via SSH

Collegarsi al Raspberry dalla rete senza monitor né tastiera

Accendi il Raspberry Pi 5 e attendi 60 secondi per il boot completo. Poi trova l'IP assegnato dal router:

bash — dal tuo PC (Linux/Mac)
# Scansiona la rete per trovare il Raspberry (sostituisci 192.168.1 con la tua subnet)
nmap -sn 192.168.1.0/24 | grep -A1 "Raspberry"

# Oppure, se conosci il suo hostname:
ping raspberry-lab.local

# Una volta trovato l'IP, connettiti via SSH:
ssh pi@192.168.1.X

# Windows: usa PuTTY oppure il terminale di Windows 11
# Inserisci la password che hai scelto durante la configurazione
Se vedi il prompt pi@raspberry-lab:~$ sei connesso correttamente.
3

Aggiornare completamente il sistema

Fondamentale prima di qualsiasi installazione

bash — aggiornamento sistema
# Aggiorna la lista dei pacchetti disponibili dai repository
sudo apt update

# Aggiorna tutti i pacchetti installati all'ultima versione disponibile
sudo apt upgrade -y

# Aggiorna anche i pacchetti del firmware e del kernel
sudo apt full-upgrade -y

# Rimuovi pacchetti obsoleti non più necessari
sudo apt autoremove -y

# Pulisci la cache locale dei pacchetti scaricati
sudo apt autoclean

# Riavvia il sistema (necessario dopo aggiornamenti del kernel)
sudo reboot

Attendi il riavvio (circa 30 secondi) e riconnettiti via SSH.

4

Impostare un IP statico sulla rete scolastica

Indispensabile: il server deve avere sempre lo stesso IP

Se il Raspberry cambia IP ad ogni avvio, tutti i link e le configurazioni smetteranno di funzionare. Imposta un IP fisso:

bash — configura IP statico con nmcli
# Mostra le connessioni di rete attive e il nome dell'interfaccia
nmcli connection show

# Di solito la connessione ethernet si chiama "Wired connection 1"
# Imposta IP statico (adatta i valori alla tua rete scolastica)
sudo nmcli connection modify "Wired connection 1" \
  ipv4.addresses 192.168.1.200/24 \
  ipv4.gateway 192.168.1.1 \
  ipv4.dns "8.8.8.8,8.8.4.4" \
  ipv4.method manual

# Applica le modifiche riavviando la connessione
sudo nmcli connection down "Wired connection 1"
sudo nmcli connection up "Wired connection 1"

# Verifica il nuovo IP assegnato
ip addr show eth0
⚠️
Scegli un IP fuori dal range DHCP del router scolastico (es. se il DHCP assegna da .100 a .200, usa .201 o superiore) per evitare conflitti di IP.
5

Installare i pacchetti di base necessari

Tool essenziali per tutti i progetti

bash — pacchetti essenziali
# Installa tutti i tool essenziali in una sola riga
sudo apt install -y \
  curl wget git nano htop \
  net-tools nmap ufw fail2ban \
  python3 python3-pip python3-venv \
  ca-certificates gnupg lsb-release \
  unzip zip tree jq

# Verifica le versioni installate
python3 --version   # es: Python 3.11.x
git --version       # es: git version 2.39.x
curl --version      # es: curl 7.88.x
6

Configurare il firewall UFW

Sicurezza base: blocca tutto tranne ciò che serve

bash — configurazione firewall
# Imposta la policy di default: blocca tutto il traffico in entrata
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Permetti SSH (porta 22) — FONDAMENTALE: fallo PRIMA di attivare UFW
sudo ufw allow 22/tcp

# Permetti HTTP e HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Attiva il firewall (rispondo "y" alla conferma)
sudo ufw enable

# Controlla lo stato e le regole attive
sudo ufw status verbose
🚨
ATTENZIONE: Aggiungi SEMPRE la regola SSH (porta 22) PRIMA di attivare UFW. Altrimenti perdi l'accesso remoto al Raspberry.

Quando installi nuovi servizi, ricorda di aprire la porta corrispondente con sudo ufw allow PORTA/tcp.

☁️

Cloud della Classe con Nextcloud

Server cloud privato per condivisione file, compiti, calendari e collaborazione
⭐ INTERMEDIO ⏱ 2-3 ore Docker · Nginx · MariaDB
📌 Obiettivi Didattici
  • Capire la differenza tra cloud pubblico (Google Drive) e cloud privato self-hosted
  • Comprendere l'architettura a layer: proxy → applicazione → database → storage
  • Gestire utenti, gruppi e permessi su un server Linux reale
  • Imparare i concetti fondamentali di Docker: immagini, container, volumi, reti
  • Configurare un reverse proxy Nginx per esporre servizi web
🖥 Browser Studenti (porta 80/443)
↓ richiesta HTTP/HTTPS
⚡ Nginx – Reverse Proxy gestisce SSL e routing
↓ forwarda a porta interna 8080
📦 Container: Nextcloud applicazione PHP
🗄 Container: MariaDB database
⚡ Container: Redis cache sessioni
↓ Volume Docker montato
💾 SSD NVMe – Dati Persistenti
1

Installare Docker Engine e Docker Compose

La piattaforma di containerizzazione su cui girerà Nextcloud

Docker permette di isolare ogni applicazione in un "container" con tutte le sue dipendenze. Installiamo la versione ufficiale (non quella dei repository Debian che è più vecchia):

bash — installazione Docker
# Rimuovi eventuali versioni vecchie di Docker
sudo apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null

# Aggiungi la chiave GPG ufficiale di Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Aggiungi il repository Docker ai sorgenti apt
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Aggiorna i repository e installa Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

# Aggiungi l'utente corrente al gruppo docker (evita sudo ogni volta)
sudo usermod -aG docker $USER

# Applica il cambio di gruppo SUBITO (senza riavviare la sessione SSH)
newgrp docker

# Verifica le versioni installate
docker --version
docker compose version

# Verifica che il servizio Docker sia attivo
sudo systemctl status docker
Test finale: docker run hello-world — deve stampare "Hello from Docker!" senza errori.
2

Preparare le directory e i file di configurazione

Creare la struttura di cartelle per Nextcloud con dati persistenti

bash — struttura directory
# Crea la cartella principale del progetto
mkdir -p ~/nextcloud
cd ~/nextcloud

# Crea le directory che verranno montate come volumi Docker
mkdir -p data/nextcloud   # file di Nextcloud (config, app)
mkdir -p data/mariadb     # database MariaDB
mkdir -p data/userfiles   # file caricati dagli utenti

# Crea il file per le variabili d'ambiente (password separate dal compose)
nano .env

Inserisci nel file .env queste variabili (modifica le password!):

.env — variabili d'ambiente
# === PASSWORD DATABASE ===
MYSQL_ROOT_PASSWORD=RootPassSicura2024!
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud_user
MYSQL_PASSWORD=NcDbPass2024!

# === ADMIN NEXTCLOUD ===
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=AdminPass2024!

# === DOMINIO (usa l'IP del Raspberry se non hai un dominio)
NEXTCLOUD_TRUSTED_DOMAINS=192.168.1.200
⚠️
Il file .env contiene password. Non condividerlo mai. Aggiungilo a .gitignore se usi Git.
3

Creare il file docker-compose.yml

Il file che descrive tutta l'architettura: Nextcloud + MariaDB + Redis

bash — crea il file compose
nano ~/nextcloud/docker-compose.yml
yaml — docker-compose.yml (contenuto completo)
version: '3.8'

services:

  # === DATABASE MariaDB ===
  db:
    image: mariadb:10.11
    container_name: nextcloud-db
    restart: always
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      # I dati del DB vengono salvati qui sul SSD (persistono anche se il container si riavvia)
      - ./data/mariadb:/var/lib/mysql
    networks:
      - nextcloud-net
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  # === CACHE REDIS ===
  redis:
    image: redis:7-alpine
    container_name: nextcloud-redis
    restart: always
    command: redis-server --requirepass nextcloudredis123
    networks:
      - nextcloud-net

  # === APPLICAZIONE NEXTCLOUD ===
  nextcloud:
    image: nextcloud:28-apache
    container_name: nextcloud-app
    restart: always
    ports:
      - "8080:80"   # espone Nextcloud sulla porta 8080 del Raspberry
    environment:
      MYSQL_HOST: db
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      REDIS_HOST: redis
      REDIS_HOST_PASSWORD: nextcloudredis123
      NEXTCLOUD_ADMIN_USER: ${NEXTCLOUD_ADMIN_USER}
      NEXTCLOUD_ADMIN_PASSWORD: ${NEXTCLOUD_ADMIN_PASSWORD}
      NEXTCLOUD_TRUSTED_DOMAINS: ${NEXTCLOUD_TRUSTED_DOMAINS}
      PHP_MEMORY_LIMIT: 512M
      PHP_UPLOAD_LIMIT: 2G
    volumes:
      - ./data/nextcloud:/var/www/html          # core di Nextcloud
      - ./data/userfiles:/var/www/html/data     # file degli utenti
    networks:
      - nextcloud-net
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

networks:
  nextcloud-net:
    driver: bridge
4

Avviare i container e verificare

Primo avvio: Docker scaricherà le immagini (~600MB totali)

bash — avvio e verifica
# Vai nella cartella del progetto
cd ~/nextcloud

# Avvia tutto in background (-d = detached mode)
docker compose up -d

# Osserva i log in tempo reale (Ctrl+C per uscire senza fermare i container)
docker compose logs -f

# Controlla che tutti e 3 i container siano "Up"
docker compose ps

# Controlla lo stato dettagliato
docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"

Il primo avvio richiede 2-5 minuti mentre Nextcloud inizializza il database. Poi apri il browser:

Accesso: http://192.168.1.200:8080 — Effettua login con le credenziali admin definite nel file .env

Se la pagina non si apre, controlla i log con docker compose logs nextcloud per vedere gli errori.

5

Configurare Nginx come Reverse Proxy (porta 80)

Per accedere senza specificare la porta :8080

bash — installa e configura Nginx
# Installa Nginx
sudo apt install -y nginx

# Crea il file di configurazione per Nextcloud
sudo nano /etc/nginx/sites-available/nextcloud
nginx — configurazione virtual host
server {
    listen 80;
    server_name 192.168.1.200;  # o il tuo dominio

    # Aumenta la dimensione massima dei file caricabili
    client_max_body_size 2G;

    # Header di sicurezza
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer" always;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Timeout per upload file grandi
        proxy_connect_timeout 300;
        proxy_send_timeout 300;
        proxy_read_timeout 300;

        # Disabilita il buffering per i download
        proxy_buffering off;
    }
}
bash — attiva il sito
# Abilita il sito creando un link simbolico
sudo ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/

# Rimuovi il sito di default di Nginx
sudo rm -f /etc/nginx/sites-enabled/default

# Testa la configurazione (deve rispondere "syntax is ok")
sudo nginx -t

# Applica la configurazione
sudo systemctl reload nginx

# Apri la porta 80 nel firewall
sudo ufw allow 80/tcp
Ora Nextcloud è accessibile su http://192.168.1.200 senza specificare la porta!
6

Creare account per ogni studente via riga di comando

Automazione: creare 25+ account in pochi secondi con uno script

bash — crea gruppo e utenti singoli
# Crea un gruppo per gli studenti della classe docker exec -u www-data nextcloud-app \ php occ group:add studenti_4A # Crea un singolo utente (ripeti per ogni studente) docker exec -u www-data nextcloud-app \ php occ user:add \ --display-name="Mario Rossi" \ --group="studenti_4A" \ --password-from-env \ mario.rossi \ <<< "Password123!" # Verifica la lista utenti docker exec -u www-data nextcloud-app php occ user:list

Per creare tutti gli utenti della classe in una volta sola, usa questo script:

bash — script crea_utenti.sh
#!/bin/bash # Lista studenti: "username:NomeCompleto" declare -a STUDENTI=( "mario.rossi:Mario Rossi" "giulia.bianchi:Giulia Bianchi" "luca.ferrari:Luca Ferrari" "anna.romano:Anna Romano" "marco.conti:Marco Conti" ) GRUPPO="studenti_4A" PASSWORD_DEFAULT="Cambiam1!" for entry in "${STUDENTI[@]}"; do USERNAME="${entry%%:*}" NOME="${entry#*:}" echo "Creo utente: $USERNAME ($NOME)" docker exec -u www-data nextcloud-app \ php occ user:add \ --display-name="$NOME" \ --group="$GRUPPO" \ --password-from-env \ "$USERNAME" <<< "$PASSWORD_DEFAULT" done echo "✅ Tutti gli utenti creati!"
bash — esegui lo script
chmod +x crea_utenti.sh bash crea_utenti.sh
🎓 Attività Dettagliate per Studenti
  • Accedere con le proprie credenziali e cambiare la password di default
  • Caricare un file di testo con la propria relazione nella cartella "Compiti → Settimana_01"
  • Creare una cartella condivisa "Progetto Gruppo" e condividerla con 3 compagni specificando i permessi (solo lettura vs modifica)
  • Configurare il calendario condiviso della classe: ogni studente aggiunge 2 scadenze future
  • Installare il client Nextcloud Desktop sul PC del laboratorio e sincronizzare i file
  • Avanzato: analizza la struttura del filesystem di Nextcloud — dove vengono salvati i file? (./data/userfiles/)
🔧 Troubleshooting Comune
ProblemaCausa probabileSoluzione
Pagina bianca o errore 502Container Nextcloud non ancora prontodocker compose logs nextcloud — attendi init
"Trusted domain" errorIP non aggiunto ai trusted domainAggiungi IP in .env e ricrea il container
Upload fallisce su file grandiLimite PHP o NginxVerifica client_max_body_size in Nginx
Database connection errorMariaDB non ancora prontoAttendi healthcheck o docker compose restart nextcloud
🤖

Server AI Locale per la Classe

Modello linguistico privato (LLM) accessibile da tutta la rete scolastica, senza internet
⭐⭐ INTERMEDIO+ ⏱ 1-2 ore + download modello Ollama · Open WebUI · Docker
📌 Obiettivi Didattici
  • Capire cosa sono i modelli LLM (Large Language Models) e come funzionano internamente
  • Distinguere tra AI cloud (ChatGPT = dati su server esterni) e AI locale (tutto rimane in aula)
  • Valutare criticamente le risposte dell'AI: correttezza, allucinazioni, limiti
  • Comprendere il concetto di quantizzazione dei modelli (4-bit, 8-bit) per fitting in RAM
  • Usare l'AI come strumento di studio per informatica, programmazione e sistemi
🖥 Browser Studenti (qualsiasi PC della rete)
↓ HTTP porta 3000
🌐 Open WebUI — Interfaccia chat (Docker) simile a ChatGPT
↓ REST API porta 11434
⚙️ Ollama — Runtime LLM gestisce i modelli
↓ inferenza locale in RAM
🧠 Modello AI (Mistral 7B o Llama3) ~4GB su SSD
📊 Confronto Modelli — Scegli in base alle esigenze
ModelloDimensioneRAM necessariaVelocità su RPi5Qualità risposteUso consigliato
llama3.2:3b~2 GB4 GB⚡ Veloce (~3 tok/s)⭐⭐⭐Demo, esercizi veloci
mistral:7b~4 GB6 GB🐢 Media (~1.5 tok/s)⭐⭐⭐⭐Uso quotidiano classe
phi3:mini~2.3 GB4 GB⚡ Veloce (~2.5 tok/s)⭐⭐⭐⭐Codice e ragionamento
gemma2:9b~5.4 GB7 GB🐢 Lenta (~1 tok/s)⭐⭐⭐⭐⭐Risposte più accurate
1

Installare Ollama

Il runtime che gestisce ed esegue i modelli AI localmente

Ollama è compatibile con ARM64 (architettura del Raspberry Pi 5) dalla versione 0.1.17 in poi. Installiamo l'ultima versione:

bash — installazione Ollama
# Scarica ed esegui lo script di installazione ufficiale
curl -fsSL https://ollama.com/install.sh | sh

# Lo script installa Ollama come servizio systemd
# Verifica che il servizio sia partito
sudo systemctl status ollama

# Verifica che risponda sulla porta 11434
curl http://localhost:11434
# Risposta attesa: "Ollama is running"

# Controlla la versione installata
ollama --version
ℹ️
Ollama di default ascolta solo su localhost. Lo configureremo al passo 3 per renderlo accessibile da tutta la rete.
2

Scaricare il modello AI

Il download richiede 2-4 GB e diversi minuti — pianifica in anticipo

Consiglio: scarica il modello durante la notte o prima della lezione.

bash — download e test modello
# Scarica Mistral 7B (raccomandato per il laboratorio — buona qualità)
ollama pull mistral

# Oppure Llama3.2 3B (più veloce, consuma meno RAM)
ollama pull llama3.2:3b

# Vedi tutti i modelli scaricati con la loro dimensione
ollama list

# Test rapido: esegui il modello nel terminale
# Scrivi una domanda e premi Invio — Ctrl+D per uscire
ollama run mistral "Spiega il subnetting in 3 righe"

# Controlla quanta RAM sta usando durante l'inferenza
watch -n 1 free -h
⚠️
Durante l'inferenza il Raspberry Pi 5 userà 5-7 GB di RAM. Con 8 GB totali rimane sufficiente spazio per il sistema operativo.
3

Configurare Ollama per l'accesso dalla rete

Di default Ollama blocca connessioni esterne — va abilitato esplicitamente

bash — modifica configurazione systemd
# Crea un override per il servizio systemd di Ollama
sudo mkdir -p /etc/systemd/system/ollama.service.d
sudo nano /etc/systemd/system/ollama.service.d/override.conf

Inserisci questo contenuto nel file:

ini — override.conf
[Service]
# Ascolta su tutte le interfacce di rete (non solo localhost)
Environment="OLLAMA_HOST=0.0.0.0:11434"
# Numero massimo di richieste parallele (una per studente)
Environment="OLLAMA_NUM_PARALLEL=2"
# Mantieni il modello in RAM per 10 minuti dopo l'uso
Environment="OLLAMA_KEEP_ALIVE=10m"
bash — applica e apri firewall
# Ricarica la configurazione systemd
sudo systemctl daemon-reload

# Riavvia Ollama con le nuove impostazioni
sudo systemctl restart ollama

# Apri la porta nel firewall per la rete locale
sudo ufw allow from 192.168.1.0/24 to any port 11434

# Verifica che Ollama risponda da un altro PC della rete:
curl http://192.168.1.200:11434/api/tags
4

Installare Open WebUI — Interfaccia grafica per gli studenti

Un'interfaccia web simile a ChatGPT, accessibile da browser

bash — installa Open WebUI via Docker
# Crea la cartella dati per Open WebUI mkdir -p ~/open-webui-data # Avvia il container Open WebUI docker run -d \ --name open-webui \ --restart always \ --network host \ -v ~/open-webui-data:/app/backend/data \ -e OLLAMA_BASE_URL=http://127.0.0.1:11434 \ -e WEBUI_AUTH=true \ -e WEBUI_NAME="AI Scolastica" \ ghcr.io/open-webui/open-webui:main # Segui i log durante l'avvio (attendi messaggio "Application startup complete") docker logs -f open-webui # Apri la porta 3000 nel firewall sudo ufw allow 3000/tcp
Accesso: http://192.168.1.200:3000
Il primo utente che si registra diventa automaticamente amministratore. Registrati tu come docente per primo!
5

Configurare limiti per gli studenti (pannello admin)

Gestire l'accesso e prevenire abusi

Accedi come admin a Open WebUI → Impostazioni → Admin Panel e configura:

  • Disabilita la registrazione pubblica: Enable New Sign Ups → OFF
  • Crea account manualmente per ogni studente dal pannello utenti
  • Imposta il modello di default per tutti gli utenti
  • Abilita la cronologia conversazioni (utile per il docente per le verifiche)
bash — crea utente via API Open WebUI
# Prima ottieni il token admin (effettuando login) TOKEN=$(curl -s -X POST http://localhost:3000/api/v1/auths/signin \ -H "Content-Type: application/json" \ -d '{"email":"admin@scuola.it","password":"AdminPass"}' | jq -r '.token') # Crea un utente studente curl -s -X POST http://localhost:3000/api/v1/auths/signup \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TOKEN" \ -d '{ "name": "Mario Rossi", "email": "mario.rossi@studenti.it", "password": "PasswordStudente1!", "role": "user" }'
🎓 Attività Dettagliate per Studenti
  • Chiedere al modello di spiegare il subnetting con un esempio su una rete /26 — verificare matematicamente se la risposta è corretta
  • Generare uno script Python che calcola tutte le sottoreti di un indirizzo dato — testarlo nel terminale
  • Testare le "allucinazioni": chiedi all'AI una data storica inventata e osserva come risponde
  • Confronta le risposte di Mistral vs Llama3 alla stessa domanda tecnica: quale è più preciso?
  • Crea un "system prompt" che trasforma l'AI in un tutor di reti che risponde solo con esempi pratici
  • Avanzato: usa l'API REST di Ollama da Python per inviare domande programmaticamente
🌐

Server Web Apache per gli Studenti

Ogni studente pubblica il proprio sito web reale su un server condiviso
⭐ BASE ⏱ 1-2 ore Apache2 · HTML/CSS · Linux users
1

Installare e configurare Apache2

Il web server più usato al mondo

bash — installazione Apache
# Installa Apache2
sudo apt install -y apache2

# Avvialo e abilita l'avvio automatico al boot
sudo systemctl start apache2
sudo systemctl enable apache2

# Controlla che sia in esecuzione
sudo systemctl status apache2

# Apri la porta 80 nel firewall (già aperta se hai fatto il progetto 1)
sudo ufw allow 80/tcp

# Test: deve rispondere con "It works!" (pagina di default Apache)
curl http://localhost
# Oppure apri il browser su http://192.168.1.200

# Abilita i moduli Apache necessari
sudo a2enmod rewrite   # URL rewriting
sudo a2enmod headers   # gestione header HTTP
sudo a2enmod userdir   # cartelle utente (~utente)
sudo systemctl restart apache2
2

Creare utenti Linux e struttura directory per ogni studente

Ogni studente ha la sua cartella web isolata con i propri permessi

bash — script crea_studenti_web.sh
#!/bin/bash # Lista degli studenti (modifica con i nomi reali) declare -a STUDENTI=("mario.rossi" "giulia.bianchi" "luca.ferrari" "anna.romano") WEB_ROOT="/var/www/html" PASS_DEFAULT="Scuola2024!" for STUDENTE in "${STUDENTI[@]}"; do echo "▶ Configuro studente: $STUDENTE" # Crea utente Linux se non esiste già if ! id "$STUDENTE" &>/dev/null; then sudo useradd -m -s /bin/bash "$STUDENTE" echo "$STUDENTE:$PASS_DEFAULT" | sudo chpasswd echo " ✓ Utente Linux creato" fi # Crea la cartella web dello studente sudo mkdir -p "$WEB_ROOT/$STUDENTE" # Crea una pagina HTML di benvenuto sudo tee "$WEB_ROOT/$STUDENTE/index.html" > /dev/null << HTML <!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <title>Sito di $STUDENTE</title> <style>body{font-family:sans-serif;max-width:800px;margin:40px auto;padding:20px}</style> </head> <body> <h1>Benvenuto nel sito di $STUDENTE</h1> <p>Questo sito è in costruzione...</p> </body> </html> HTML # Imposta permessi: studente proprietario, Apache può leggere sudo chown -R "$STUDENTE":www-data "$WEB_ROOT/$STUDENTE" sudo chmod -R 755 "$WEB_ROOT/$STUDENTE" echo " ✓ Sito disponibile su: http://192.168.1.200/$STUDENTE" done echo "" echo "✅ Configurazione completata!"
bash — esegui lo script
chmod +x crea_studenti_web.sh sudo bash crea_studenti_web.sh
3

Configurare un Virtual Host per ogni studente (sottodominio)

Per accedere con URL tipo mario.lab.local invece di /mario.rossi

Prima configura il DNS locale nel router scolastico per risolvere *.lab.local all'IP del Raspberry. Poi crea i virtual host:

bash — script crea virtual host
#!/bin/bash declare -a STUDENTI=("mario.rossi" "giulia.bianchi" "luca.ferrari") WEB_ROOT="/var/www/html" for STUDENTE in "${STUDENTI[@]}"; do NOME_BREVE="${STUDENTE%%.*}" # es: "mario" da "mario.rossi" CONF_FILE="/etc/apache2/sites-available/${STUDENTE}.conf" sudo tee "$CONF_FILE" > /dev/null << APACHE <VirtualHost *:80> ServerName ${NOME_BREVE}.lab.local DocumentRoot ${WEB_ROOT}/${STUDENTE} <Directory ${WEB_ROOT}/${STUDENTE}> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog \${APACHE_LOG_DIR}/${STUDENTE}_error.log CustomLog \${APACHE_LOG_DIR}/${STUDENTE}_access.log combined </VirtualHost> APACHE sudo a2ensite "${STUDENTE}.conf" echo "✓ Virtual host creato: http://${NOME_BREVE}.lab.local" done sudo systemctl reload apache2
4

Permettere agli studenti di caricare i propri file via SCP/SFTP

Gli studenti caricano i file HTML/CSS dal loro PC direttamente sul server

Ogni studente può caricare i propri file HTML usando SCP (dalla riga di comando) o un client SFTP grafico come FileZilla:

bash — caricare file dal PC dello studente
# Comandi da eseguire SUL PC DELLO STUDENTE (non sul Raspberry) # Carica un singolo file HTML scp index.html mario.rossi@192.168.1.200:/var/www/html/mario.rossi/ # Carica una cartella intera (con CSS, immagini, etc.) scp -r ./mio-sito/* mario.rossi@192.168.1.200:/var/www/html/mario.rossi/ # Verifica il sito subito dopo: apri il browser su # http://192.168.1.200/mario.rossi
ℹ️
Con FileZilla: File → Gestione siti → Nuovo sito → Protocollo SFTP, host 192.168.1.200, porta 22, utente mario.rossi, password quella assegnata. Poi trascina i file nella cartella di destra.
5

Analizzare i log di Apache

Capire chi accede al sito, quando e come

bash — analisi log Apache
# Vedi le ultime 20 richieste HTTP ricevute dal server sudo tail -20 /var/log/apache2/access.log # Monitora le richieste in tempo reale (aggiorna mentre navighi) sudo tail -f /var/log/apache2/access.log # Conta quante richieste ha ricevuto ogni sito studente sudo awk '{print $7}' /var/log/apache2/access.log | \ grep -oP '^/[^/]+' | sort | uniq -c | sort -rn | head -10 # Vedi gli IP che hanno visitato il sito sudo awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -rn # Controlla gli errori (404 = pagina non trovata, 500 = errore server) sudo tail -20 /var/log/apache2/error.log
🎓 Attività Dettagliate per Studenti
  • Creare un sito web personale con: pagina home, pagina "Chi sono", pagina "Progetti" — tutto collegato con nav bar
  • Aggiungere CSS esterno (file separato), immagini e font Google Fonts
  • Analizzare il proprio log di accesso: quante visite ha ricevuto il tuo sito? Da quali IP?
  • Creare una pagina HTML con un form (anche solo grafico, senza backend) per esercitarsi con i tag
  • Avanzato: aggiungi PHP al sito — crea una pagina che mostra l'ora del server con <?php echo date('H:i:s'); ?>
  • Avanzato: configura HTTPS con certificato auto-firmato per il tuo virtual host
🔀

Laboratorio di Rete Simulata

Router, switch, VLAN e analisi traffico con GNS3 e Wireshark
⭐⭐ INTERMEDIO ⏱ 2-3 ore setup + esercizi GNS3 · Wireshark · Docker · VyOS
📌 Obiettivi Didattici
  • Progettare e implementare topologie di rete con router e switch virtuali
  • Configurare il subnetting: calcolare subnet mask, indirizzi di rete, broadcast, host range
  • Configurare il routing statico e capire perché non scala (poi confrontare con OSPF)
  • Analizzare il traffico di rete con Wireshark: ARP, ICMP, TCP, DNS a livello di byte
  • Creare e isolare VLAN su uno switch Layer 2
1

Installare GNS3 Server sul Raspberry Pi

Il server GNS3 gira sul Raspberry, i client si connettono dai PC degli studenti

bash — installazione GNS3 Server
# Installa le dipendenze per GNS3
sudo apt install -y \
  python3-pip python3-venv \
  qemu-kvm \
  libvirt-daemon-system \
  bridge-utils \
  ubridge \
  wireshark \
  tshark

# Installa GNS3 server via pip in un virtualenv isolato
python3 -m venv ~/gns3-venv
source ~/gns3-venv/bin/activate
pip install gns3-server gns3-webclient

# Aggiungi l'utente al gruppo necessario per cattura pacchetti
sudo usermod -aG wireshark $USER
sudo usermod -aG kvm $USER
sudo usermod -aG ubridge $USER

# Applica i gruppi (richiede logout/login o riavvio)
sudo reboot
⚠️
GNS3 su Raspberry Pi 5 supporta topologie fino a ~6 dispositivi. Per classi grandi considera di installare GNS3 VM su un PC con VMware/VirtualBox e usare il Raspberry come macchina ausiliaria.
2

Creare il servizio systemd per GNS3

GNS3 deve avviarsi automaticamente e rimanere sempre disponibile

bash — crea servizio systemd
sudo nano /etc/systemd/system/gns3.service
ini — gns3.service
[Unit] Description=GNS3 Network Emulator Server After=network.target [Service] Type=simple User=pi WorkingDirectory=/home/pi ExecStart=/home/pi/gns3-venv/bin/gns3server \ --host 0.0.0.0 \ --port 3080 \ --log /var/log/gns3.log Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target
bash — attiva il servizio
sudo systemctl daemon-reload sudo systemctl enable gns3 sudo systemctl start gns3 sudo systemctl status gns3 # Apri la porta nel firewall sudo ufw allow 3080/tcp # Verifica accesso curl http://localhost:3080/v2/version
3

Installare GNS3 Client sui PC degli Studenti

Il client grafico si installa su ogni PC del laboratorio e si connette al server Raspberry

  • Scarica GNS3 da https://www.gns3.com/software/download per Windows
  • Durante l'installazione scegli "Run appliances on a remote server"
  • Alla prima apertura: Edit → Preferences → Server → Remote server
  • Imposta Host: 192.168.1.200, Port: 3080
  • Testa la connessione — deve comparire il nome del server
ℹ️
Alternativamente, usa la GNS3 Web Interface direttamente nel browser: http://192.168.1.200:3080 — nessuna installazione necessaria sui client.
4

Creare la prima topologia: 2 PC + 1 Router

La topologia base per capire il routing IP

topologia — schema e configurazione
Topologia: PC1 (192.168.1.10/24) ──── eth0 ──── R1 ──── eth1 ──── PC2 (10.0.0.10/24) (192.168.1.1/24) (10.0.0.1/24) Configurazione R1 (router VyOS o Cisco IOL): # Configura interfaccia verso PC1 configure set interfaces ethernet eth0 address 192.168.1.1/24 set interfaces ethernet eth1 address 10.0.0.1/24 commit save exit Su PC1 — imposta IP e gateway: ip addr add 192.168.1.10/24 dev eth0 ip route add default via 192.168.1.1 Su PC2 — imposta IP e gateway: ip addr add 10.0.0.10/24 dev eth0 ip route add default via 10.0.0.1 Test connettività: PC1> ping 10.0.0.10 # deve rispondere PC1> ping 10.0.0.1 # gateway del router
5

Analizzare il traffico con Wireshark

Catturare e decodificare i pacchetti di rete a livello di byte

bash — cattura con tshark (riga di comando)
# Cattura tutti i pacchetti ICMP (ping) sull'interfaccia eth0 sudo tshark -i eth0 -f "icmp" # Cattura e salva su file per analisi in Wireshark GUI sudo tshark -i eth0 -w /tmp/cattura.pcap # Analizza un file .pcap già catturato tshark -r /tmp/cattura.pcap # Filtra solo i pacchetti ARP (risoluzione IP→MAC) sudo tshark -i eth0 -f "arp" -V | head -50 # Filtra per IP sorgente specifico sudo tshark -i eth0 -Y "ip.src == 192.168.1.10"

In GNS3, clicca con il tasto destro su un cavo e scegli "Start Capture" per aprire Wireshark automaticamente su quel link.

🎓 Esercizi Pratici Graduati
  • Base: Configura una topologia 2-router, imposta routing statico su entrambi, verifica il ping end-to-end
  • Base: Cattura un ARP request/reply con Wireshark e identifica MAC address sorgente/destinazione
  • Medio: Topologia 3-router in linea (A-B-C): configura routing statico su tutti e 3 e verifica che A raggiunga C
  • Medio: Crea 2 VLAN (VLAN 10 e VLAN 20) su uno switch managed e verifica che i dispositivi su VLAN diverse non si "vedano"
  • Avanzato: Configura OSPF tra 3 router e analizza i pacchetti "Hello" che i router si scambiano per trovare i vicini
  • Sfida: simulare un traceroute e spiegare ogni hop — perché il TTL decrementato di 1 rivela i router intermedi?
📷

Videosorveglianza AI con Rilevamento Persone

Computer vision in tempo reale con Frigate NVR e TensorFlow Lite sull'edge
⭐⭐ INTERMEDIO ⏱ 2-3 ore Frigate · TensorFlow Lite · Docker · OpenCV
📌 Obiettivi Didattici
  • Capire come funziona l'object detection: bounding box, confidence score, classi
  • Comprendere l'edge AI: l'inferenza avviene localmente sul dispositivo, senza cloud
  • Analizzare le implicazioni etiche e legali della videosorveglianza AI (GDPR)
  • Capire come ottimizzare modelli per hardware limitato (quantizzazione TFLite)
1

Collegare e testare la webcam USB

Verifica che il sistema riconosca la webcam prima di installare Frigate

bash — verifica e test webcam
# Installa tool per gestione V4L (Video4Linux) sudo apt install -y v4l-utils ffmpeg # Lista tutti i dispositivi video riconosciuti dal sistema ls /dev/video* # Dovresti vedere /dev/video0 (e magari /dev/video1) # Ottieni informazioni dettagliate sulla webcam v4l2-ctl --device /dev/video0 --all # Elenca le risoluzioni supportate dalla webcam v4l2-ctl --device /dev/video0 --list-formats-ext # Cattura 5 secondi di video per test (crea un file test.mp4) ffmpeg -f v4l2 -i /dev/video0 -t 5 -vf scale=640:480 /tmp/test.mp4 # Scarica il file sul tuo PC per visualizzarlo # scp pi@192.168.1.200:/tmp/test.mp4 .
2

Creare la configurazione di Frigate

Il file config.yml definisce le telecamere e i parametri di rilevamento

bash — crea struttura directory
# Crea le directory necessarie per Frigate mkdir -p ~/frigate/config mkdir -p ~/frigate/storage # Crea il file di configurazione principale nano ~/frigate/config/config.yml
yaml — config.yml Frigate (completo)
# Disabilita MQTT (per semplicità nel laboratorio) mqtt: enabled: False # Configurazione del detector AI (usa CPU con TFLite) detectors: cpu_detector: type: cpu num_threads: 3 # usa 3 dei 4 core del RPi5 # Definizione della telecamera cameras: webcam_aula: ffmpeg: inputs: - path: /dev/video0 input_args: preset-usb-webcam # preset ottimizzato per USB roles: - detect # questa stream viene analizzata dall'AI - record # questa stream viene registrata # Parametri di rilevamento detect: enabled: True width: 640 # risoluzione per l'AI (bassa = più veloce) height: 480 fps: 5 # frame al secondo analizzati (5 = equilibrio) # Oggetti da rilevare e soglia minima di confidenza objects: track: - person # rileva persone - cat # rileva gatti (per divertimento) filters: person: min_score: 0.5 # ignora rilevamenti < 50% confidenza threshold: 0.7 # soglia per contare come "rilevato" min_area: 5000 # ignora oggetti molto piccoli # Registrazione clip quando viene rilevata una persona record: enabled: True retain: days: 1 # mantieni le registrazioni per 1 giorno events: retain: default: 10 # mantieni 10 secondi prima/dopo ogni evento # Salva snapshot JPG per ogni rilevamento snapshots: enabled: True retain: default: 7 # mantieni snapshot per 7 giorni # Directory dove salvare le registrazioni record: storage: /media/frigate
3

Avviare Frigate con Docker

Il container ha accesso privilegiato alla webcam e alla GPU (se disponibile)

bash — avvio container Frigate
# Crea directory per la storage dei video mkdir -p ~/frigate/storage docker run -d \ --name frigate \ --restart unless-stopped \ --privileged \ --shm-size=256m \ --mount type=bind,source=~/frigate/config,target=/config \ --mount type=bind,source=~/frigate/storage,target=/media/frigate \ --device /dev/video0 \ -e TZ=Europe/Rome \ -p 5000:5000 \ -p 8554:8554 \ ghcr.io/blakeblackshear/frigate:stable-standard-arm64 # Segui i log durante l'avvio (importante: verifica che la webcam venga trovata) docker logs -f frigate # Apri la porta nel firewall sudo ufw allow 5000/tcp
Dashboard: http://192.168.1.200:5000 — Vedrai la telecamera in diretta con i bounding box dei rilevamenti in tempo reale.
4

Monitorare le prestazioni del sistema durante l'inferenza

Capire il costo computazionale dell'AI in tempo reale

bash — monitoring risorse
# Monitora CPU, RAM e temperatura in tempo reale watch -n 1 'echo "=== CPU ===" && top -bn1 | head -5 && \ echo "=== RAM ===" && free -h && \ echo "=== TEMP ===" && vcgencmd measure_temp' # Temperatura del processore (non superare 80°C) vcgencmd measure_temp # Statistiche Frigate via API curl -s http://localhost:5000/api/stats | python3 -m json.tool
⚠️
L'inferenza AI a 5 FPS porta il Raspberry Pi 5 al 70-80% di CPU. Il case con raffreddamento attivo è fondamentale. Se la temperatura supera 85°C, riduci gli FPS nel config a 3.
🎓 Attività e Discussioni per Studenti
  • Analizza la dashboard di Frigate: conta i rilevamenti per ora — ci sono pattern? (es. più rilevamenti durante la ricreazione?)
  • Modifica min_score da 0.5 a 0.9 — quanti falsi positivi spariscono? Quanti rilevamenti reali si perdono?
  • Misura la latenza dell'AI: quanto tempo passa tra il tuo movimento e l'apparizione del bounding box?
  • Dibattito etico: questo sistema in una vera scuola viola la privacy degli studenti? Quali regole GDPR si applicano? Chi deve dare il consenso?
  • Avanzato: scrivi un script Python che interroga l'API di Frigate e invia una notifica email quando viene rilevata una persona fuori orario
🏠

Smart Home Didattica con Home Assistant

Domotica reale: sensori, automazioni, MQTT e dashboard interattiva
⭐⭐ INTERMEDIO ⏱ 2-4 ore Home Assistant · MQTT · Python · Node-RED
📌 Obiettivi Didattici
  • Comprendere il modello publish/subscribe di MQTT e perché è ideale per IoT
  • Leggere e interpretare dati da sensori fisici (temperatura, umidità, movimento)
  • Creare automazioni basate su condizioni: "SE temperatura > 25°C ALLORA invia notifica"
  • Progettare una dashboard professionale per la visualizzazione dati in tempo reale
  • Capire i protocolli IoT: MQTT, Zigbee, Z-Wave, WiFi — differenze e casi d'uso
1

Installare Home Assistant Container

La piattaforma open-source per la domotica più usata al mondo

bash — installazione Home Assistant
# Crea directory configurazione mkdir -p ~/homeassistant/config # Avvia Home Assistant Container docker run -d \ --name homeassistant \ --restart unless-stopped \ --privileged \ --network host \ -e TZ=Europe/Rome \ -v ~/homeassistant/config:/config \ ghcr.io/home-assistant/home-assistant:stable # Segui i log — il primo avvio richiede 2-3 minuti docker logs -f homeassistant # Apri la porta nel firewall sudo ufw allow 8123/tcp
Accesso: http://192.168.1.200:8123 — Segui la procedura guidata per creare l'account amministratore e configurare la posizione geografica.
2

Installare e configurare Mosquitto MQTT Broker

Il "postino" che riceve e distribuisce i messaggi tra sensori e Home Assistant

MQTT usa il modello publish/subscribe: i sensori pubblicano dati su "topic", Home Assistant si iscrive ai topic per riceverli.

bash — installazione e configurazione Mosquitto
# Installa Mosquitto broker sudo apt install -y mosquitto mosquitto-clients # Crea file di configurazione sudo tee /etc/mosquitto/conf.d/lab.conf << EOF # Ascolta su tutte le interfacce listener 1883 # Richiedi autenticazione allow_anonymous false password_file /etc/mosquitto/passwd EOF # Crea utente MQTT per Home Assistant sudo mosquitto_passwd -c /etc/mosquitto/passwd homeassistant # Inserisci la password quando richiesto: MqttHA2024! # Crea utente MQTT per i sensori/studenti sudo mosquitto_passwd /etc/mosquitto/passwd sensori # Password: MqttSensori2024! # Riavvia Mosquitto sudo systemctl restart mosquitto sudo systemctl enable mosquitto sudo systemctl status mosquitto # Apri porta nel firewall sudo ufw allow 1883/tcp # Test: pubblica un messaggio dal terminale mosquitto_pub -h localhost -u sensori -P MqttSensori2024! \ -t "aula/temperatura" -m "22.5" # Test: ascolta tutti i messaggi (apri un secondo terminale) mosquitto_sub -h localhost -u homeassistant -P MqttHA2024! \ -t "#" -v
3

Collegare MQTT a Home Assistant

Configurare l'integrazione MQTT in Home Assistant per ricevere i dati dei sensori

  • Apri Home Assistant → Impostazioni → Dispositivi e Servizi → Aggiungi Integrazione
  • Cerca e seleziona MQTT
  • Inserisci: Broker = localhost, Porta = 1883, Username = homeassistant, Password = MqttHA2024!
  • Clicca "Invia" — deve apparire la conferma di connessione riuscita

Ora aggiungi i sensori nel file di configurazione di Home Assistant:

bash — modifica configuration.yaml
# Apri il file di configurazione principale nano ~/homeassistant/config/configuration.yaml
yaml — configuration.yaml (aggiunta sensori MQTT)
mqtt: sensor: - name: "Temperatura Aula" state_topic: "aula/temperatura" unit_of_measurement: "°C" device_class: temperature value_template: "{{ value | float }}" expire_after: 120 # considera scaduto dopo 2 minuti senza aggiornamenti - name: "Umidità Aula" state_topic: "aula/umidita" unit_of_measurement: "%" device_class: humidity value_template: "{{ value | float }}" - name: "CO2 Aula" state_topic: "aula/co2" unit_of_measurement: "ppm" device_class: carbon_dioxide binary_sensor: - name: "Movimento Corridoio" state_topic: "scuola/movimento/corridoio" payload_on: "ON" payload_off: "OFF" device_class: motion
bash — ricarica la configurazione
# Controlla la sintassi prima di applicare docker exec homeassistant python3 -m homeassistant --script check_config -c /config # Riavvia Home Assistant per applicare le modifiche docker restart homeassistant
4

Creare un sensore simulato con Python

Script che simula un sensore IoT reale pubblicando dati ogni 10 secondi

bash — installa libreria MQTT per Python
pip3 install paho-mqtt
python — sensore_aula.py (completo)
#!/usr/bin/env python3 """ Sensore IoT simulato per il laboratorio didattico. Pubblica temperatura, umidità e CO2 via MQTT ogni 10 secondi. """ import paho.mqtt.client as mqtt import random import time import json from datetime import datetime # === CONFIGURAZIONE === BROKER_HOST = "localhost" # IP del Raspberry BROKER_PORT = 1883 USERNAME = "sensori" PASSWORD = "MqttSensori2024!" # Valori base del sensore (simulano un ambiente reale) temp_base = 21.0 # temperatura base in gradi Celsius umid_base = 55.0 # umidità base in percentuale co2_base = 800 # CO2 base in ppm (parti per milione) def on_connect(client, userdata, flags, rc): if rc == 0: print(f"✅ Connesso al broker MQTT su {BROKER_HOST}:{BROKER_PORT}") else: print(f"❌ Connessione fallita con codice: {rc}") def on_publish(client, userdata, mid): pass # callback chiamata dopo ogni publish riuscito # Crea il client MQTT client = mqtt.Client(client_id="sensore_aula_01") client.username_pw_set(USERNAME, PASSWORD) client.on_connect = on_connect client.on_publish = on_publish # Connettiti al broker client.connect(BROKER_HOST, BROKER_PORT, keepalive=60) client.loop_start() # thread in background per mantenere la connessione print("🌡 Sensore aula avviato. Premi Ctrl+C per fermare.") print("-" * 50) try: while True: # Genera valori con piccole variazioni casuali (simulano un sensore reale) temperatura = round(temp_base + random.uniform(-2.0, 2.0), 1) umidita = round(umid_base + random.uniform(-5.0, 5.0), 1) co2 = int(co2_base + random.uniform(-100, 200)) # Simula aumento CO2 durante l'ora di lezione ora = datetime.now().hour if 8 <= ora <= 13: co2 += 200 # più persone in classe = più CO2 timestamp = datetime.now().strftime("%H:%M:%S") print(f"[{timestamp}] 🌡 {temperatura}°C | 💧 {umidita}% | 🌬 {co2} ppm") # Pubblica ogni valore su un topic separato client.publish("aula/temperatura", str(temperatura), qos=1) client.publish("aula/umidita", str(umidita), qos=1) client.publish("aula/co2", str(co2), qos=1) # Pubblica anche un JSON con tutti i dati insieme payload = json.dumps({ "temperatura": temperatura, "umidita": umidita, "co2": co2, "timestamp": datetime.now().isoformat() }) client.publish("aula/dati_completi", payload, qos=1) time.sleep(10) # aspetta 10 secondi prima del prossimo invio except KeyboardInterrupt: print("\n⏹ Sensore fermato.") client.loop_stop() client.disconnect()
bash — avvia il sensore in background
# Esegui in background con nohup (rimane attivo dopo logout SSH) nohup python3 sensore_aula.py > /tmp/sensore.log 2>&1 & echo "PID del processo: $!" # Vedi i log del sensore tail -f /tmp/sensore.log # Per fermarlo: trova il PID e killalo ps aux | grep sensore_aula.py kill <PID>
5

Creare automazioni e dashboard in Home Assistant

Automazioni: "SE condizione ALLORA azione". Dashboard: visualizzazione dati live

Creare un'automazione via interfaccia grafica:

  • Home Assistant → Impostazioni → Automazioni → Crea Automazione → Inizia da zero
  • Trigger: Stato di un'entità → seleziona "Temperatura Aula" → supera 25°C
  • Azione: Chiama un servizio → notify.persistent_notification → messaggio "🌡 Temperatura alta in aula!"
yaml — automazione in YAML (alternativa al GUI)
alias: "Avviso Temperatura Alta" description: "Notifica quando la temperatura supera 25°C" trigger: - platform: numeric_state entity_id: sensor.temperatura_aula above: 25 for: minutes: 2 # deve restare alta per 2 minuti (evita falsi allarmi) condition: [] action: - service: notify.persistent_notification data: title: "⚠️ Temperatura elevata" message: > La temperatura in aula è {{ states('sensor.temperatura_aula') }}°C. Considera di aprire le finestre. - service: logbook.log data: name: "Temperatura Aula" message: "Superata soglia 25°C" mode: single

Dashboard: Home Assistant → Overview → Modifica Dashboard → Aggiungi Scheda → scegli "Grafico Storico" o "Indicatore" per ogni sensore.

🎓 Attività Dettagliate per Studenti
  • Modifica lo script Python per aggiungere un sensore di luminosità simulato (lux) — aggiungi il topic e la card in Home Assistant
  • Crea un'automazione "CO2 Alert": se CO2 > 1200ppm manda una notifica (livello non salubre per l'apprendimento)
  • Progetta la dashboard della "smart classroom" con almeno 4 sensori diversi usando grafico storico, indicatori e card personalizzate
  • Registra i dati per 30 minuti e analizza: la CO2 aumenta durante la lezione? Cosa suggerisce?
  • Avanzato: installa Node-RED tramite Docker e crea un flusso visuale che legge da MQTT e scrive su un foglio Google Sheets
🔐

Laboratorio Cybersecurity

Analisi vulnerabilità, penetration testing etico in rete isolata, hardening dei sistemi
⭐⭐⭐ AVANZATO ⏱ 3-4 ore + esercizi Nmap · DVWA · Metasploit · Fail2ban · UFW
🚨
AVVISO LEGALE IMPORTANTE: Tutte le attività di questo laboratorio devono essere eseguite esclusivamente su sistemi di proprietà del laboratorio scolastico e su reti completamente isolate da internet. Eseguire scansioni o attacchi su sistemi non autorizzati è un reato penale ai sensi dell'art. 615-ter del Codice Penale italiano. Questo laboratorio ha scopo puramente didattico.
📌 Obiettivi Didattici
  • Comprendere le categorie OWASP Top 10: le 10 vulnerabilità web più critiche
  • Eseguire una scansione di rete con Nmap e interpretare correttamente i risultati
  • Testare vulnerabilità SQL Injection, XSS e CSRF in ambiente sicuro (DVWA)
  • Configurare tecniche di hardening: firewall, fail2ban, SSH sicuro, aggiornamenti automatici
  • Analizzare i log di sistema per identificare tentativi di intrusione
1

Creare la rete isolata con Docker

Tutti gli attacchi avvengono in una rete virtuale senza accesso a internet

bash — rete isolata
# Crea una rete Docker completamente isolata (--internal = nessun accesso esterno) docker network create \ --driver bridge \ --internal \ --subnet 10.10.10.0/24 \ --gateway 10.10.10.1 \ lab-cybersec # Verifica che la rete sia stata creata docker network inspect lab-cybersec | python3 -m json.tool # Lista tutte le reti Docker docker network ls
2

Installare i target vulnerabili

DVWA e Metasploitable 2: applicazioni intenzionalmente vulnerabili per l'apprendimento

bash — avvia DVWA (web app vulnerabile)
# DVWA = Damn Vulnerable Web Application # Contiene SQL Injection, XSS, CSRF, File Upload, ecc. docker run -d \ --name dvwa \ --network lab-cybersec \ --ip 10.10.10.10 \ -p 8888:80 \ ghcr.io/digininja/dvwa:latest # Aspetta che il container si avvii (circa 30 secondi) sleep 30 # Verifica che sia in esecuzione docker logs dvwa | tail -5
DVWA: http://192.168.1.200:8888 — Login: admin / password
Prima di iniziare: Setup/Reset DB → Create/Reset Database. Poi: DVWA Security → imposta livello "Low" per i primi esercizi.
3

Installare e usare Nmap per la scansione di rete

Il tool di network scanning più usato dai professionisti della sicurezza

bash — nmap: dalla base all'avanzato
# Installa Nmap sudo apt install -y nmap ===== LIVELLO BASE ===== # 1. Scansione host discovery: quali dispositivi sono attivi in rete? # (Invia solo ping, non scansiona porte) sudo nmap -sn 192.168.1.0/24 # 2. Scansione rapida delle 100 porte più comuni su un host sudo nmap -F 192.168.1.200 ===== LIVELLO INTERMEDIO ===== # 3. Scansione completa con rilevamento versioni servizi # -sV = versione servizi, -O = sistema operativo sudo nmap -sV -O 192.168.1.200 # 4. Scansione SYN (più veloce e stealth) # Invia solo SYN, non completa il 3-way handshake sudo nmap -sS 192.168.1.200 # 5. Scansione di tutte e 65535 le porte sudo nmap -p- 192.168.1.200 ===== LIVELLO AVANZATO ===== # 6. Scansione aggressiva con script NSE (Nmap Scripting Engine) # -A = OS + versioni + traceroute + script sudo nmap -A 192.168.1.200 # 7. Usa script NSE per rilevare vulnerabilità HTTP sudo nmap --script=http-vuln* 192.168.1.200 # 8. Salva l'output in tutti i formati per report sudo nmap -sV -O 192.168.1.200 -oA /tmp/scansione_lab
4

Esercizi SQL Injection su DVWA

Capire come funziona l'attacco SQL Injection più comune

Vai in DVWA → SQL Injection → Security Level: Low. Il campo "User ID" è vulnerabile.

sql — esercizi SQL Injection progressivi
LIVELLO 1 — Verifica se il campo è vulnerabile: Input: 1' # Se compare un errore SQL, il campo è vulnerabile! # Errore tipo: "You have an error in your SQL syntax..." LIVELLO 2 — Bypass dell'autenticazione: Input: 1' OR '1'='1 # Restituisce TUTTI gli utenti invece di uno solo # La query diventa: WHERE id='1' OR '1'='1' (sempre vera!) LIVELLO 3 — Scopri il numero di colonne con ORDER BY: Input: 1' ORDER BY 1-- Input: 1' ORDER BY 2-- Input: 1' ORDER BY 3-- # se errore, ci sono solo 2 colonne LIVELLO 4 — UNION per estrarre dati dal DB: Input: 1' UNION SELECT user(), database()-- - # Restituisce: utente MySQL e nome del database! LIVELLO 5 — Lista tutte le tabelle del database: Input: 1' UNION SELECT table_name, NULL FROM information_schema.tables WHERE table_schema=database()-- - LIVELLO 6 — Estrai utenti e password hash: Input: 1' UNION SELECT user, password FROM users-- - # Le password sono in MD5 — già questo è grave!
💡
Dopo ogni attacco discuti: Come si previene? Risposta: Prepared Statements (query parametrizzate). Esempio in PHP: $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?")
5

Esercizi XSS (Cross-Site Scripting) su DVWA

Capire come iniettare codice JavaScript malevolo in pagine web

Vai in DVWA → XSS (Reflected) → Security Level: Low.

html — payload XSS progressivi
LIVELLO 1 — XSS base: inietta un alert popup Input nel campo "What's your name": <script>alert('XSS vulnerabile!')</script> LIVELLO 2 — Ruba il cookie di sessione (simulazione) <script>alert('Cookie: ' + document.cookie)</script> # In un attacco reale, il cookie verrebbe inviato a un server esterno LIVELLO 3 — Modifica il contenuto della pagina (DOM) <script>document.body.innerHTML = '<h1>Sito hackerato!</h1>'</script> LIVELLO 4 — Redirect a sito esterno (phishing) <script>window.location='https://www.google.it'</script>
💡
Prevenzione XSS: Sempre usare output encoding — in PHP: htmlspecialchars($input, ENT_QUOTES) converte <script> in &lt;script&gt; che il browser non esegue.
6

Hardening del sistema — Tecniche di difesa reali

Configurare il Raspberry come server sicuro per la produzione

bash — hardening SSH
# Fai un backup prima di modificare sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak # Modifica la configurazione SSH sudo nano /etc/ssh/sshd_config # Modifica/aggiungi queste righe: Port 2222 # cambia la porta default (meno attacchi automatici) PermitRootLogin no # disabilita login diretto come root MaxAuthTries 3 # massimo 3 tentativi di password PasswordAuthentication yes # keep yes per il lab (in prod: no + chiavi SSH) LoginGraceTime 30 # 30 secondi per autenticarsi X11Forwarding no # disabilita X11 forwarding (non necessario) AllowUsers pi # solo l'utente pi può fare SSH # Riavvia SSH dopo le modifiche sudo systemctl restart sshd # Aggiorna la regola UFW per la nuova porta SSH sudo ufw allow 2222/tcp sudo ufw delete allow 22/tcp
bash — configurazione Fail2ban
# Installa Fail2ban (blocca IP dopo tentativi falliti) sudo apt install -y fail2ban # Crea configurazione personalizzata (non modificare il file .conf originale) sudo tee /etc/fail2ban/jail.local << EOF [DEFAULT] bantime = 3600 # blocca l'IP per 1 ora findtime = 600 # finestra di 10 minuti per contare i fallimenti maxretry = 5 # blocca dopo 5 tentativi falliti [sshd] enabled = true port = 2222 # porta SSH che hai configurato logpath = %(sshd_log)s maxretry = 3 # per SSH ancora più restrittivo [apache-auth] enabled = true [nginx-http-auth] enabled = true EOF # Avvia e abilita Fail2ban sudo systemctl enable fail2ban sudo systemctl restart fail2ban # Controlla lo stato delle "prigioni" attive sudo fail2ban-client status # Controlla lo stato della jail SSH sudo fail2ban-client status sshd # Sblocca un IP bloccato per errore # sudo fail2ban-client set sshd unbanip 192.168.1.X
bash — analisi log per tentativi di intrusione
# Vedi tutti i tentativi di login SSH falliti sudo grep "Failed password" /var/log/auth.log | tail -20 # Conta i tentativi falliti per IP (chi attacca di più?) sudo grep "Failed password" /var/log/auth.log | \ awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10 # Vedi i login riusciti sudo grep "Accepted" /var/log/auth.log | tail -10 # Monitor in tempo reale dei log di autenticazione sudo tail -f /var/log/auth.log | grep --line-buffered "Failed\|Accepted\|Invalid"
🎓 Attività Dettagliate per Studenti
  • Scansiona la rete del laboratorio con Nmap e crea un report professionale: quanti host attivi, quali porte aperte, quali servizi identificati
  • Completa tutti e 6 i livelli di SQL Injection su DVWA (Low → Medium → High) e documenta le differenze nelle tecniche difensive
  • Esegui gli esercizi XSS Reflected e XSS Stored su DVWA — qual è la differenza? Quale è più pericoloso e perché?
  • Configura Fail2ban e simulalo: esegui 6 tentativi SSH falliti di fila — il tuo IP viene bloccato?
  • Analizza i log auth.log: quanti tentativi falliti ci sono? Da quanti IP diversi? Probabilmente ci sono già scanner automatici!
  • Avanzato: installa Metasploit Framework e usa il modulo scanner/http/http_version per rilevare le versioni dei web server in rete
  • Presentazione finale: ogni studente sceglie una vulnerabilità OWASP Top 10, la dimostra su DVWA e spiega come si previene in produzione
📅

Piano Didattico Annuale

Percorso progressivo strutturato per sviluppare competenze complete durante l'anno scolastico
Settembre — Novembre · Primo Periodo

🌐 Fondamenti Server e Linux

  • Setup completo Raspberry Pi OS
  • Comandi Linux essenziali e gestione file
  • Utenti, gruppi e permessi su Linux
  • Web Server Apache — Progetto 3
  • Cloud Nextcloud — Progetto 1
  • Introduzione a Docker e container
  • Configurazione Firewall UFW
Dicembre — Marzo · Secondo Periodo

🔀 Reti, Protocolli e AI

  • Subnetting e indirizzamento IP
  • Simulazione reti con GNS3 — Progetto 4
  • Analisi traffico con Wireshark
  • Routing statico e OSPF
  • Server AI Locale Ollama — Progetto 2
  • Modelli LLM e prompt engineering
  • Containerizzazione avanzata con Docker Compose
Aprile — Giugno · Terzo Periodo

🚀 Progetti Avanzati a Scelta

  • Smart Home IoT — Progetto 6
  • oppure: Cybersecurity Lab — Progetto 7
  • oppure: Videosorveglianza AI — Progetto 5
  • Progetto finale integrativo di gruppo
  • Documentazione tecnica del progetto
  • Presentazione finale alla classe
🗃 Checklist Pre-Laboratorio per il Docente
  • Raspberry Pi 5 acceso e raggiungibile via SSH all'IP statico configurato
  • Docker in esecuzione: docker ps mostra i container attivi del giorno
  • Firewall attivo con le porte corrette aperte: sudo ufw status
  • Spazio su disco sufficiente: df -h / (almeno 50GB liberi)
  • RAM disponibile: free -h (almeno 2GB liberi senza carico)
  • Temperatura del processore: vcgencmd measure_temp (sotto 60°C a riposo)
  • Backup della configurazione Docker Compose e file .env in luogo sicuro
🔄 Comandi di Manutenzione Settimanale
bash — manutenzione settimanale
# Aggiorna il sistema operativo
sudo apt update && sudo apt upgrade -y && sudo apt autoremove -y

# Aggiorna tutte le immagini Docker all'ultima versione
docker images | awk 'NR>1 {print $1":"$2}' | xargs -I {} docker pull {}

# Riavvia tutti i container con le nuove immagini
cd ~/nextcloud && docker compose pull && docker compose up -d

# Controlla lo spazio su disco usato da Docker
docker system df

# Rimuovi immagini e container inutilizzati (libera spazio)
docker system prune -f

# Controlla la temperatura
vcgencmd measure_temp

# Controlla Fail2ban
sudo fail2ban-client status sshd