- HOST-SETUP.md: bootstrap macchina host (Setup-Host.ps1) - WINDOWS-TEMPLATE-SETUP.md: provisioning template Windows con Prepare + Setup-TemplateVM - LINUX-TEMPLATE-SETUP.md: bozza TODO template Linux (non implementato)
14 KiB
Linux Template VM Setup — DRAFT / TODO
Status: bozza. Non implementato. Vedi TODO.md §6.1 (P2). Documento di pianificazione per estendere il sistema CI con build su Linux, in parallelo al template Windows già operativo.
Obiettivo
Aggiungere supporto a build su Linux per:
- Compilazione cross-platform (es. versione Linux di plugin C/C++, build check con GCC/Clang)
- Test su distro Linux per progetti che lo richiedono
- Build matrix
[windows, linux]nei workflow Gitea
Architettura simmetrica al template Windows: VM template → snapshot BaseClean-Linux →
linked clone per ogni job → cleanup automatico.
Decisioni di design (da validare)
Distro
| Opzione | Pro | Contro |
|---|---|---|
| Ubuntu 24.04 LTS | Toolchain recente, supporto LTS fino al 2029, cloud-init ottimo | Snap default (lento per CI) |
| Debian 12 | Stabile, leggero, no snap | Toolchain meno recente |
| Rocky Linux 9 / Alma 9 | RHEL-compat, glibc moderno, dnf | Meno comune in workflow CI tipici |
Scelta proposta: Ubuntu 24.04 LTS minimal. Rationale: maggior parità con runner GitHub
ufficiali (ubuntu-latest mappa a 22.04/24.04), toolchain recente out-of-box, cloud-init
maturo per provisioning automatico.
Transport host → VM
| Opzione | Pro | Contro |
|---|---|---|
| SSH (chiave pubblica) | Standard Linux, supporto nativo OpenSSH su Win11/Server 2025 | Diversa API rispetto WinRM (PSSession) |
| WinRM su Linux (PSCore) | Codice script unificato | Setup complesso, non standard, fragile |
Scelta proposta: SSH key-based con ssh.exe + scp.exe (built-in Windows 10+) o
modulo Posh-SSH. WinRM su Linux non è production-ready.
Layer di astrazione
Aggiungere scripts/_Transport.psm1 con interfaccia comune:
# Pseudo-API
function Invoke-RemoteCommand {
param($Target, $ScriptBlock, $Args, [ValidateSet('WinRM','SSH')] $Transport)
}
function Copy-RemoteItem {
param($Source, $Destination, $Target, $Direction, $Transport)
}
function Test-RemoteReady {
param($Target, $TimeoutSec, $Transport)
}
Implementazioni:
- WinRM wrapper:
New-PSSession+Invoke-Command+Copy-Item -ToSession - SSH wrapper:
ssh.exe+scp.execon-i $keyfile -o StrictHostKeyChecking=accept-new
Invoke-CIJob.ps1 riceve -GuestOS Windows|Linux (o auto-detect dal VMX guestOS),
sceglie transport.
Specifiche VM proposte
| Parametro | Valore |
|---|---|
| OS | Ubuntu Server 24.04 LTS minimal |
| vCPU | 4 |
| RAM | 4096 MB (4 GB) — meno di Windows, footprint Linux più snello |
| Disco | 40 GB thin |
| NIC | VMnet8 (NAT) — internet per apt |
| VMX path | F:\CI\Templates\LinuxBuild\LinuxBuild.vmx |
| ISO | ubuntu-24.04.x-live-server-amd64.iso (in F:\CI\ISO\) |
| Snapshot name | BaseClean-Linux |
TODO — Implementazione
Pre-requisiti host
- OpenSSH client verificato presente su host (default Win11/Server 2025)
powershell Get-WindowsCapability -Online -Name OpenSSH.Client* - Genera SSH key dedicata per CI (no passphrase, separata da chiavi utente):
powershell ssh-keygen -t ed25519 -f F:\CI\keys\ci_linux -N '""' -C 'ci-linux-runner' - Aggiungere a
Setup-Host.ps1uno step opzionale-GenerateLinuxCIKeyche crea la chiave e la archivia con permessi corretti (F:\CI\keys\con ACL ristretta)
Fase A — Crea VM e installa Ubuntu
- Crea nuova VM in VMware Workstation (4 vCPU, 4 GB RAM, 40 GB thin)
- NIC: VMnet8 (NAT)
- Boot da ISO Ubuntu Server 24.04 LTS minimal
- Durante install scegli:
- Minimal install (no extra packages)
- OpenSSH server: Yes
- Username:
ci_build - Hostname:
ci-linux-template - LVM: opzionale (non necessario per template)
- Annota IP DHCP (
ip a)
Fase B — Provisioning iniziale (manuale, una volta)
Dentro la VM, come ci_build:
-
Disabilita swap permanente (overhead I/O su NVMe condivisa):
sudo swapoff -a sudo sed -i '/ swap / s/^/#/' /etc/fstab -
Disabilita servizi non necessari (snap, motd-news, ecc.):
sudo systemctl disable --now snapd.service snapd.socket snapd.seeded.service 2>/dev/null sudo systemctl disable --now motd-news.timer 2>/dev/null sudo systemctl disable --now apt-daily.timer apt-daily-upgrade.timerRationale: snap e timer apt rallentano boot e mangiano CPU su VM efimere.
-
Sudo passwordless per
ci_build(parità con WinRM admin senza prompt UAC):echo 'ci_build ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/90-ci_build sudo chmod 440 /etc/sudoers.d/90-ci_build -
Authorized SSH key dell'host CI:
mkdir -p ~/.ssh && chmod 700 ~/.ssh # Incolla la chiave pubblica generata su host (F:\CI\keys\ci_linux.pub) echo 'ssh-ed25519 AAAA... ci-linux-runner' >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys -
SSH hardening per template (ma non così stretto da bloccare CI):
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config sudo systemctl restart sshd
Fase C — Setup-LinuxTemplateVM.sh (script equivalente a Setup-TemplateVM.ps1)
Da creare: template/Setup-LinuxTemplateVM.sh con set -euo pipefail + assert_step() helper.
-
Helper
assert_step(throw on fail, log su success):assert_step() { local step="$1"; local desc="$2"; shift 2 if "$@" >/dev/null 2>&1; then echo " [OK] [$step] $desc" else echo " [FAIL] [$step] $desc" >&2; exit 1 fi } -
Step 1 —
apt update+ upgradesudo DEBIAN_FRONTEND=noninteractive apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -qq assert_step 'apt' 'no errors' true -
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 \ git curl wget ca-certificates \ python3 python3-pip python3-venv \ unzip zip xz-utils assert_step 'toolchain' 'gcc presente' command -v gcc assert_step 'toolchain' 'clang presente' command -v clang assert_step 'toolchain' 'cmake presente' command -v cmake assert_step 'toolchain' 'python3 presente' command -v python3 -
Step 3 — Toolchain extra opzionale
- mingw-w64 se serve cross-compile per Windows:
sudo apt-get install -y mingw-w64 - .NET SDK (per parità Windows): script
dotnet-install.shcon channel pinned - Node.js se workflow lo richiede: nvm o nodesource repo
- mingw-w64 se serve cross-compile per Windows:
-
Step 4 — CI working directories
sudo mkdir -p /opt/ci/{build,output,scripts,cache} sudo chown -R ci_build:ci_build /opt/ci assert_step 'dirs' 'tutte presenti' test -d /opt/ci/build -a -d /opt/ci/output -
Step 5 — Disabilita auto-update apt (no surprise reboot/lock):
sudo apt-get remove -y unattended-upgrades 2>/dev/null sudo systemctl mask apt-daily.service apt-daily-upgrade.service -
Step 6 — 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 # Zero free space (riduce dim VMDK dopo compact, opzionale) # sudo dd if=/dev/zero of=/zero bs=1M; sudo rm /zero -
Step 7 — Final pre-snapshot validation
- SSH server abilitato e in ascolto su 22
sudopasswordless funzionante perci_build- Tutti i tool elencati (
gcc --version,cmake --version, ecc.) ritornano exit 0 /opt/ci/{build,output,scripts}esistono con owner corretto- No leftover
/tmp/*, history vuota
Fase D — Prepare-LinuxTemplateSetup.ps1 (orchestratore host-side)
Equivalente di Prepare-TemplateSetup.ps1 per Linux. Usa SSH invece di WinRM.
-
Pre-flight host:
- SSH key esiste (
F:\CI\keys\ci_linux) ssh.exeescp.exeraggiungibili- IP target risponde a
Test-NetConnection -Port 22
- SSH key esiste (
-
Copia script in VM:
scp -i F:\CI\keys\ci_linux -o StrictHostKeyChecking=accept-new ` template\Setup-LinuxTemplateVM.sh ci_build@${VMIPAddress}:/tmp/ -
Esegui script in VM:
ssh -i F:\CI\keys\ci_linux ci_build@${VMIPAddress} ` "chmod +x /tmp/Setup-LinuxTemplateVM.sh && sudo /tmp/Setup-LinuxTemplateVM.sh"Cattura stdout + exit code, parse
[OK]/[FAIL]lines. -
Post-setup remote validation (parità Windows): query SSH per state checks:
systemctl is-active ssh= activeid ci_buildritorna gruppo + sudogcc --version,cmake --version,python3 --versionexit 0test -d /opt/ci/buildexit 0
Fase E — Snapshot
- Solo se Prepare exit 0 → power off VM:
sudo shutdown -h now - Take snapshot in VMware Workstation:
BaseClean-Linux(case-sensitive)
Fase F — Adattamento script CI
scripts/_Transport.psm1(nuovo modulo) con interfaccia comunescripts/Invoke-CIJob.ps1— aggiungere-GuestOS Windows|Linux, branching su transportscripts/Wait-VMReady.ps1— supporto SSH probe (Test-NetConnection -Port 22+ssh -o ConnectTimeout=5 ...)scripts/Invoke-RemoteBuild.ps1— branch SSH+scp per Linuxscripts/Get-BuildArtifacts.ps1—scpper Linux invece diCopy-Item -FromSessionscripts/New-BuildVM.ps1— already OS-agnostic (vmrun clone), verificare cheBaseClean-Linuxsia parametrizzabilescripts/Remove-BuildVM.ps1— already OS-agnostic
Fase G — Workflow Gitea
-
Registrare label
linux-buildsul runner (oppure secondo runner dedicato):# runner/config.yaml — aggiungere a labels esistenti labels: - 'windows-build:host' - 'linux-build:host' -
Workflow matrix:
jobs: build: strategy: matrix: target: [windows, linux] runs-on: ${{ matrix.target }}-build steps: - uses: actions/checkout@v4 - run: pwsh -File scripts/Invoke-CIJob.ps1 -GuestOS ${{ matrix.target }}
Fase H — Test e2e
-
Smoke test clone + SSH ready:
.\scripts\New-BuildVM.ps1 -JobId 'linux-smoke' -SnapshotName 'BaseClean-Linux' .\scripts\Wait-VMReady.ps1 -JobId 'linux-smoke' -Transport SSH .\scripts\Remove-BuildVM.ps1 -JobId 'linux-smoke' -
Build reale: scegliere repo con build Linux nativo (es.
cmakebased) e eseguire job e2e viaInvoke-CIJob.ps1 -GuestOS Linux -
Confronto artifact: build dello stesso repo target Windows vs Linux, verifica che entrambi vengano raccolti in
F:\CI\Artifacts\<jobId>\
Differenze chiave rispetto al template Windows
| Aspetto | Windows | Linux |
|---|---|---|
| Transport | WinRM HTTP/5985 + Basic | SSH/22 + ed25519 key |
| Auth fluid | ci_build admin + UAC off + LATFP=1 |
ci_build + sudoers NOPASSWD |
| Trasferimento file | Copy-Item -ToSession |
scp o rsync |
| Esecuzione remota | Invoke-Command -Session |
ssh user@host 'cmd' |
| AV/Firewall disable | Defender + Win Firewall off | ufw inattivo (default), no AV |
| Update package | Windows Update (COM API + sched task) | apt-get update && upgrade non-interactive |
| Toolchain | VS Build Tools 2026 + .NET SDK | gcc/g++/clang + cmake (+ .NET SDK opt) |
| Snapshot name | BaseClean |
BaseClean-Linux |
| Footprint VM | 6 GB RAM, 80 GB disk | 4 GB RAM, 40 GB disk |
| Boot time | ~30-60 s post-clone | ~10-20 s post-clone (atteso) |
Backlog correlato (TODO.md)
- §6.1 [P2] Linux Build VM — entry parent
- §6.4 [P3] Build matrix
[windows, linux]nel workflow - §6.3 [P3] Multi-host runner federation (se 4 VM Linux + 4 Windows non bastano)
- §5.2 [P2] Modulo
_Transport.psm1condiviso (prerequisito architetturale)
Domande aperte
- .NET SDK su Linux — sempre installato o solo se workflow lo richiede? Decisione: installare se workload richiede parità di build. Default off, opt-in via flag.
- Image size — Ubuntu minimal + toolchain ≈ 5 GB. Compact post-snapshot per ridurre footprint VMDK?
Decisione: sì,
dd if=/dev/zero+vmware-vdiskmanager -k(manuale, una tantum). - Pre-warm pool Linux — boot Linux è veloce, beneficio minore. Decisione: implementare solo se profile dimostra > 30% overhead.
- Cloud-init vs script manuale — cloud-init richiede ISO seed o NoCloud datasource. Più pulito ma overhead di setup. Decisione: script bash diretto (parità con flusso Windows). Cloud-init valutabile in v2.