17 KiB
Linux Template VM Setup Piano di implementazione
Status: pianificato non ancora implementato. Vedi TODO.md §6.1 (P2). Distro scelta: Ubuntu 24.04 LTS (cloud image, cloud-init). Approccio simmetrico a Windows.
Architettura: tre script + modulo transport
| Script / Modulo | Dove gira | Ruolo |
|---|---|---|
template/Deploy-LinuxBuild2404.ps1 |
Host (PS) | Crea VM da cloud image VMDK, genera seed ISO cloud-init, avvia, aspetta SSH |
template/Prepare-LinuxBuild2404.ps1 |
Host (PS) | Copia + esegue setup via SSH, valida stato, prende snapshot |
template/Setup-LinuxBuild2404.sh |
Guest (Bash) | Installa toolchain CI, dirs, hardening, gate finale |
scripts/_Transport.psm1 |
Host (PS) | Interfaccia comune WinRM/SSH per Invoke-CIJob e script CI |
Perche tre script separati (non tutto-in-uno): cloud-init copre solo il bootstrap OS (utente, SSH key, pacchetti base). Il toolchain CI e le validazioni per step sono piu leggibili e manutenibili in un secondo script dedicato identico alla divisione Deploy/Setup/Prepare di Windows.
Specifiche VM
| Parametro | Valore |
|---|---|
| OS | Ubuntu 24.04 LTS (cloud image, non ISO installer) |
| Immagine base | ubuntu-24.04-server-cloudimg-amd64.vmdk |
| Download | https://cloud-images.ubuntu.com/noble/current/ |
| vCPU | 4 |
| RAM | 4096 MB |
| Disco | 40 GB thin (resize del cloud VMDK) |
| NIC | VMnet8 (NAT) vmxnet3 diretto (driver nativo kernel) |
| VMX path | F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx |
| Snapshot name | BaseClean-Linux |
Differenza chiave da Windows: l'immagine di partenza e gia installata (cloud VMDK, ~600 MB). Nessuna fase di installazione OS cloud-init provvede al bootstrap al primo boot in 30-60 secondi. La NIC non richiede lo swap e1000e vmxnet3 perche il kernel Linux ha il driver vmxnet3 nativo.
Prerequisiti host
- SSH key CI dedicata generare una volta sola (no passphrase):
New-Item -ItemType Directory -Force F:\CI\keys | Out-Null ssh-keygen -t ed25519 -f F:\CI\keys\ci_linux -N '""' -C 'ci-linux-runner' # Risultato: F:\CI\keys\ci_linux (privata) + F:\CI\keys\ci_linux.pub (pubblica) - OpenSSH client verificato presente sull'host (default su Windows 11):
Get-WindowsCapability -Online -Name OpenSSH.Client* | Select-Object State # Atteso: State = Installed F:\CI\Templates\LinuxBuild2404\creata (Setup-Host.ps1 o manuale)F:\CI\ISO\creata (il VMDK viene scaricato automaticamente da Deploy se mancante)
Fase A Deploy-LinuxBuild2404.ps1
Script host-side. Produce una VM pronta con cloud-init completato e SSH raggiungibile. Non richiede installazione OS parte dal cloud VMDK pre-built.
-
Step 1 Validate prerequisites
vmrun.exepresente nel path atteso- SSH key
F:\CI\keys\ci_linux.pubpresente - Cartella destinazione VMX non gia occupata (o
-Forceper sovrascrivere) - (il VMDK viene gestito in Step 1b — nessun prerequisito manuale)
-
Step 1b Download cloud VMDK se assente (
F:\CI\ISO\come cache locale)$VmdkUrl = 'https://cloud-images.ubuntu.com/noble/current/ubuntu-24.04-server-cloudimg-amd64.vmdk' $VmdkPath = 'F:\CI\ISO\ubuntu-24.04-server-cloudimg-amd64.vmdk' if (-not (Test-Path $VmdkPath)) { Write-Host "[Deploy] VMDK non trovato, avvio download..." New-Item -ItemType Directory -Force F:\CI\ISO | Out-Null $tmp = "$VmdkPath.part" try { Invoke-WebRequest -Uri $VmdkUrl -OutFile $tmp -UseBasicParsing Move-Item $tmp $VmdkPath Write-Host "[Deploy] Download completato: $VmdkPath" } catch { Remove-Item $tmp -ErrorAction SilentlyContinue throw "[Deploy] Download VMDK fallito: $_" } } else { Write-Host "[Deploy] VMDK trovato in cache: $VmdkPath" }- Usa
Invoke-WebRequest(nativo PowerShell, no dipendenze esterne) - Scrittura atomica: file
.partdurante download, rinomina solo a completamento - In caso di errore: il file
.partviene rimosso, l'eccezione termina lo script - Parametro opzionale
-VmdkUrlper sovrascrivere l'URL (es. mirror locale)
- Usa
-
Step 2 Genera cloud-init user-data + meta-data (inline, no template esterno)
meta-data:instance-id: linuxbuild-001,local-hostname: ci-linux-templateuser-data(YAML):hostname: ci-linux-template,timezone: Europe/Romeusers: utenteci_build, shell/bin/bash,sudo: ALL=(ALL) NOPASSWD:ALL,ssh_authorized_keyscon contenuto dici_linux.pubpackages:[openssh-server, curl, ca-certificates, p7zip-full]package_update: trueruncmd:swapoff -a, commenta swap in/etc/fstab,sed PasswordAuthentication noin sshd_config,systemctl restart sshdpower_state:mode: rebootdopo primo provisioning
-
Step 3 Costruisce seed ISO nocloud via IMAPI2FS COM
- Due file:
user-data+meta-data(volume label:cidata) - Stesso codice COM gia usato in Deploy-WinBuild2025.ps1 Step 3
- Output:
F:\CI\Templates\LinuxBuild2404\cloud-init-seed.iso
- Due file:
-
Step 4 Copia e ridimensiona cloud VMDK
- Copia
ubuntu-24.04-server-cloudimg-amd64.vmdkLinuxBuild2404.vmdk - Ridimensiona a 40 GB:
vmware-vdiskmanager -x 40GB LinuxBuild2404.vmdk
- Copia
-
Step 5 Genera .vmx
guestOS = "ubuntu-64", BIOS (cloud image Ubuntu compatibile entrambi; BIOS piu semplice per lab)- NIC:
vmxnet3, VMnet8 - Disco:
LinuxBuild2404.vmdk(scsi0:0) - CD-ROM secondario:
cloud-init-seed.iso(connesso) - Nessun USB controller, nessuna sound card
memsize = 4096,numvcpus = 4
-
Step 6 Power on (
vmrun start nogui) -
Step 7 Polling SSH port 22 fino a ready
Test-NetConnection -ComputerName $IP -Port 22ogni 10 secondi- Timeout: 5 minuti (cloud-init + reboot finale)
- IP rilevato via
vmrun getGuestIPAddress
open-vm-tools e pre-installato nell'Ubuntu 24.04 cloud image.
vmrun getGuestIPAddressfunziona senza installazione aggiuntiva. -
Step 8 Verifica cloud-init completato
ssh -i F:\CI\keys\ci_linux -o StrictHostKeyChecking=accept-new ` -o ConnectTimeout=5 ci_build@$IP ` "test -f /var/lib/cloud/instance/boot-finished && echo OK" # Atteso: OK -
Step 9 Rimuove seed ISO dal VMX
- Setta
ide1:0.present = "FALSE"nel VMX - Evita che linked clone ricevano il seed ISO e ri-eseguano cloud-init
- Setta
-
Step 10 Print summary (VMX path, IP, SSH fingerprint)
Fase B Prepare-LinuxBuild2404.ps1
Script host-side. Copia il setup script, lo esegue via SSH, valida stato, prende snapshot.
Equivalente di Prepare-WinBuild2025.ps1 con SSH al posto di WinRM.
-
Step 1 Pre-flight
- VMX presente; se VM spenta, avvia con
vmrun start nogui - SSH key
F:\CI\keys\ci_linuxpresente ssh.exeescp.exenel PATH host- TCP/22 raggiungibile (
Test-NetConnection)
- VMX presente; se VM spenta, avvia con
-
Step 2 Auto-detect IP via
vmrun getGuestIPAddress $VMXPath- Se
-VMIPAddresse fornito esplicitamente, salta il rilevamento automatico
- Se
-
Step 3 Aggiungi host key a known_hosts
ssh -i F:\CI\keys\ci_linux -o StrictHostKeyChecking=accept-new ` ci_build@$IP "echo connected" | Out-NullSolo al primo run; idempotente se gia presente.
-
Step 4 Copia Setup-LinuxBuild2404.sh in VM
scp -i F:\CI\keys\ci_linux ` "$PSScriptRoot\Setup-LinuxBuild2404.sh" ` "ci_build@${IP}:/tmp/Setup-LinuxBuild2404.sh"Valida: confronta size locale vs remota via
ssh ... stat -c %s /tmp/... -
Step 5 Esegui setup script nel guest
ssh -i F:\CI\keys\ci_linux ci_build@$IP ` "chmod +x /tmp/Setup-LinuxBuild2404.sh && sudo /tmp/Setup-LinuxBuild2404.sh" # Cattura exit code; != 0 => abort con errore leggibileFlag opzionali passabili:
--skip-update,--dotnet,--mingw -
Step 6 Post-setup remote validation (batch via singola sessione SSH)
systemctl is-active ssh=activeid ci_buildcontienesudosudo -n trueexit 0 (passwordless sudo)which gcc g++ clang cmake python3 git 7ztutti trovatitest -d /opt/ci/build -a -d /opt/ci/output -a -d /opt/ci/scriptsexit 0swapon --showoutput vuoto (swap disabilitato)grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config
-
Step 7 Shutdown VM
& $vmrun stop $VMXPath soft # Polling vmrun list fino a VM non piu presente -
Step 8 Snapshot BaseClean-Linux
& $vmrun snapshot $VMXPath 'BaseClean-Linux' -
Final Print summary (VMX, snapshot name, toolchain versions rilevate)
Fase C Setup-LinuxBuild2404.sh
Script guest-side (Bash). Installazione toolchain CI e hardening.
Eseguito da Prepare via SSH come ci_build con sudo.
Header: #!/usr/bin/env bash + set -euo pipefail
Helper assert_step(): stampa [OK] [Step N] desc su successo, exit 1 su fallimento.
-
Step 1 apt update + upgrade (saltabile con
--skip-update)sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -qq -
Step 2 Toolchain build essentials
sudo apt-get install -y -qq \ build-essential gcc g++ clang \ make cmake ninja-build \ pkg-config autoconf automake libtool- assert:
command -v gcc,command -v clang,command -v cmake
- assert:
-
Step 3 Python
sudo apt-get install -y -qq python3 python3-pip python3-venv sudo ln -sf /usr/bin/python3 /usr/local/bin/python- assert:
python3 --version,pip3 --version
- assert:
-
Step 4 Tier-1 Toolchain (speculare a §6.6 Windows: Git + 7-Zip)
sudo apt-get install -y -qq git p7zip-full curl wget ca-certificates- assert:
command -v git,command -v 7z
- assert:
-
Step 4b .NET SDK (opzionale, flag
--dotnet)curl -fsSL https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.sh \ | sudo bash -s -- --channel 10.0 --install-dir /usr/local/dotnet sudo ln -sf /usr/local/dotnet/dotnet /usr/local/bin/dotnet- assert:
dotnet --version
- assert:
-
Step 4c mingw-w64 (opzionale, flag
--mingwcross-compile per Windows)sudo apt-get install -y -qq mingw-w64- assert:
command -v x86_64-w64-mingw32-gcc
- assert:
-
Step 5 CI directories
sudo mkdir -p /opt/ci/{build,output,scripts,cache} sudo chown -R ci_build:ci_build /opt/ci- assert:
test -d /opt/ci/build,test -d /opt/ci/output,test -d /opt/ci/scripts
- assert:
-
Step 6 SSH hardening (PasswordAuth off gia impostato da cloud-init, ri-validato)
sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config sudo systemctl restart sshd- assert:
grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config
- assert:
-
Step 7 Disabilita swap permanente
sudo swapoff -a sudo sed -i '/ swap / s/^/#/' /etc/fstab- assert:
swapon --showoutput vuoto
- assert:
-
Step 8 Disabilita apt auto-update (no lock durante build)
sudo systemctl mask apt-daily.service apt-daily-upgrade.service \ apt-daily.timer apt-daily-upgrade.timer sudo apt-get remove -y unattended-upgrades 2>/dev/null || true -
Step 9 Cleanup pre-snapshot
sudo apt-get clean sudo rm -rf /var/lib/apt/lists/* sudo journalctl --vacuum-time=1d sudo rm -rf /tmp/* /var/tmp/* history -c cat /dev/null > ~/.bash_history -
Final Gate pre-snapshot (exit 1 se qualcosa manca)
- Ogni tool richiesto raggiungibile con
command -v /opt/ci/{build,output,scripts}esistenti con ownerci_buildswapon --showvuotosshdattivoPasswordAuthentication noin sshd_config- Nessun installer residuo in
/tmp
- Ogni tool richiesto raggiungibile con
Fase D Adattamento script CI
-
scripts/_Transport.psm1nuovo modulo con interfaccia comune WinRM/SSH:function Invoke-RemoteCommand { param($Target, $Command, [ValidateSet('WinRM','SSH')] $Transport, ...) } function Copy-RemoteItem { param($Source, $Dest, $Target, $Direction, $Transport, ...) } function Test-RemoteReady { param($Target, $TimeoutSec, $Transport, ...) } -
scripts/Invoke-CIJob.ps1aggiungere parametro-GuestOS Windows|Linux- Auto-detect da VMX
guestOSfield se non fornito - Branch su transport (WinRM vs SSH) in ogni fase
- Auto-detect da VMX
-
scripts/Wait-VMReady.ps1aggiungere-Transport SSH- Probe:
Test-NetConnection -Port 22+ssh -o ConnectTimeout=5 ... "echo ok"
- Probe:
-
scripts/Invoke-RemoteBuild.ps1branch SSH+scp per Linux- Transfer:
scpinvece diCopy-Item -ToSession - Build:
ssh ... "cd /opt/ci/build && $BuildCommand"
- Transfer:
-
scripts/Get-BuildArtifacts.ps1branchscpper Linuxscp -r ci_build@$IP:/opt/ci/output/* $LocalArtifactDir\
-
scripts/New-BuildVM.ps1gia OS-agnostic (vmrun clone)- Verificare che
-SnapshotName BaseClean-Linuxfunzioni correttamente
- Verificare che
-
scripts/Remove-BuildVM.ps1gia OS-agnostic, nessuna modifica prevista
Fase E Runner e workflow Gitea
-
Label
linux-buildaggiunta al runner inrunner/config.yaml:labels: - 'windows-build:host' - 'linux-build:host' -
Variabile d'ambiente
GITEA_CI_LINUX_TEMPLATE_PATHnel servizio act_runner:F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx -
Workflow matrix di esempio (
gitea/workflow-example.ymlaggiornato):strategy: matrix: target: [windows, linux] runs-on: ${{ matrix.target }}-build
Fase F Test e2e
-
Smoke test linked clone + SSH ready:
.\scripts\New-BuildVM.ps1 -JobId 'linux-smoke-001' ` -TemplatePath 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx' ` -SnapshotName 'BaseClean-Linux' -
Build test comando reale nella VM:
.\scripts\Invoke-CIJob.ps1 -JobId 'linux-e2e-001' -GuestOS Linux ` -RepoUrl 'ssh://gitea-ci/Simone/<repo>.git' -Branch 'main' ` -TemplatePath 'F:\CI\Templates\LinuxBuild2404\LinuxBuild2404.vmx' ` -BuildCommand 'make -C /opt/ci/build all' ` -GuestArtifactSource '/opt/ci/output' -
Cleanup linked clone rimosso dopo build (
Remove-BuildVM.ps1) -
Matrix build run parallela Windows + Linux sullo stesso push
Differenze da Windows riepilogo
| Aspetto | Windows | Linux |
|---|---|---|
| Immagine di partenza | ISO installer (Deploy ~60-90 min unattended) | Cloud VMDK pre-built (boot + cloud-init ~60 s) |
| Provisioning unattended | autounattend.xml (Windows Setup) |
cloud-init user-data (seed ISO nocloud) |
| Transport host VM | WinRM HTTPS/5986 + PSSession | ssh.exe + scp.exe (built-in Windows 11) |
| NIC strategia | e1000e install vmxnet3 swap post-Tools | vmxnet3 diretto (driver nativo kernel) |
| Setup script | .ps1 (PowerShell, via WinRM) |
.sh (Bash, via SSH) |
| Rilevamento IP | vmrun getGuestIPAddress (VMware Tools) |
vmrun getGuestIPAddress (open-vm-tools) |
| Wait completamento | polling flag file via vmrun copyFileFromGuestToHost |
polling SSH + boot-finished cloud-init |
| CI dirs | C:\CI\{build,output,scripts} |
/opt/ci/{build,output,scripts,cache} |
| Snapshot name | BaseClean |
BaseClean-Linux |
Riferimenti
- ARCHITECTURE.md diagramma componenti (aggiornare dopo implementazione)
- CI-FLOW.md flusso pipeline (aggiornare Step 0 prerequisites)
- HOST-SETUP.md Setup-Host.ps1 (aggiungere step generazione SSH key)
- TODO.md §6.1 tracking implementazione