Files
local-ci-cd-system/docs/LINUX-TEMPLATE-SETUP.md
T
Simone 68cde01c9d security(sprint1): §1.1/1.3/1.4 — WinRM HTTPS/5986, SHA256 pinning infra, IP regex per-octet
§1.4 — Replace loose IP ValidatePattern with per-octet regex in 4 scripts
  (Invoke-CIJob, Invoke-RemoteBuild, Get-BuildArtifacts, Wait-VMReady)

§1.1 — Migrate all WinRM connections from HTTP/5985 to HTTPS/5986
  - Deploy post-install.ps1: remove AllowUnencrypted=true; self-signed cert + HTTPS listener
    already present; firewall rule restricted to 192.168.79.0/24
  - Setup-WinBuild2025.ps1: assert AllowUnencrypted=false
  - Prepare-WinBuild2025.ps1: preflight uses TCP/5986; Test-WSMan -UseSSL -Port 5986;
    New-PSSession -UseSSL -Port 5986; host AllowUnencrypted save/restore removed (not needed for HTTPS)
  - Invoke-RemoteBuild, Get-BuildArtifacts: New-PSSession -UseSSL -Port 5986 -Authentication Basic
  - Wait-VMReady: New-WSManSessionOption + Test-WSMan -Port 5986 -UseSSL
  - Validate-DeployState, Validate-SetupState: Invoke-Command -UseSSL -Port 5986,
    AllowUnencrypted check → false; AllowUnencrypted host-side removed from both
  - Docs: PLAN, README, ARCHITECTURE, BEST-PRACTICES, HOST-SETUP, WINDOWS-TEMPLATE-SETUP,
    LINUX-TEMPLATE-SETUP, TODO updated

§1.3 — SHA256 hash pinning infrastructure
  - Assert-Hash function + $script:Hashes hashtable added to Setup-WinBuild2025.ps1
  - Assert-Hash called after dotnet-install.ps1, python installer, vs_buildtools.exe downloads
  - Hashes initialized to '' (warn-skip); must be filled before next snapshot refresh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 14:46:41 +02:00

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.exe con -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.ps1 uno step opzionale -GenerateLinuxCIKey che 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.timer
    

    Rationale: 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-WinBuild2025.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 + upgrade

    sudo 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.sh con channel pinned
    • Node.js se workflow lo richiede: nvm o nodesource repo
  • 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
    • sudo passwordless funzionante per ci_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-WinBuild2025.ps1 per Linux. Usa SSH invece di WinRM.

  • Pre-flight host:

    • SSH key esiste (F:\CI\keys\ci_linux)
    • ssh.exe e scp.exe raggiungibili
    • IP target risponde a Test-NetConnection -Port 22
  • 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 = active
    • id ci_build ritorna gruppo + sudo
    • gcc --version, cmake --version, python3 --version exit 0
    • test -d /opt/ci/build exit 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 comune
  • scripts/Invoke-CIJob.ps1 — aggiungere -GuestOS Windows|Linux, branching su transport
  • scripts/Wait-VMReady.ps1 — supporto SSH probe (Test-NetConnection -Port 22 + ssh -o ConnectTimeout=5 ...)
  • scripts/Invoke-RemoteBuild.ps1 — branch SSH+scp per Linux
  • scripts/Get-BuildArtifacts.ps1scp per Linux invece di Copy-Item -FromSession
  • scripts/New-BuildVM.ps1 — already OS-agnostic (vmrun clone), verificare che BaseClean-Linux sia parametrizzabile
  • scripts/Remove-BuildVM.ps1 — already OS-agnostic

Fase G — Workflow Gitea

  • Registrare label linux-build sul 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. cmake based) e eseguire job e2e via Invoke-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 HTTPS/5986 + Basic (-SkipCACheck) 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.psm1 condiviso (prerequisito architetturale)

Domande aperte

  1. .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.
  2. 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).
  3. Pre-warm pool Linux — boot Linux è veloce, beneficio minore. Decisione: implementare solo se profile dimostra > 30% overhead.
  4. 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.