Add unified implementation plan for Phase A and Phase B in Markdown format

- Create a new document `plans/implementation-plan-A-B.md` that consolidates the implementation plans for the Python rewrite (Phase A) and the migration to Linux Mint (Phase B).
- The document includes detailed sections such as executive summary, checklist, prerequisites, step-by-step activities, architectural hooks for future phases, risk matrix, and references.
- Ensure the plan is self-contained, adhering to specified structure and style guidelines, and does not introduce new technologies or modify existing files.
This commit is contained in:
2026-05-13 10:49:10 +02:00
parent 081f7e1d16
commit 770ac1edf8
6 changed files with 1683 additions and 522 deletions
+177 -179
View File
@@ -1,216 +1,214 @@
# Idea 2 — Adattare il sistema a girare su host Linux (Mint)
# Fase B — Migrazione host su Linux Mint
> Stato: **proposta / valutazione**.
> Target host: Linux Mint (kernel ≥ 6.x, su hardware compatibile con
> virtualizzazione hardware; KVM/Intel VT-x presenti su i9-10900X).
> **Stato**: piano esecutivo (parte committed della roadmap).
> Prerequisito: [Fase A](idea-1-python-rewrite.md) completata.
> Vedi [overview](ideas-overview.md).
> Hypervisor scelto: **VMware Workstation Pro Linux** (zero conversione template).
---
## 1. Obiettivo
Spostare l'host CI/CD da Windows 11 + VMware Workstation Pro a Linux Mint,
mantenendo:
Spostare l'host CI/CD da Windows 11 + Workstation Pro a **Linux Mint** +
**Workstation Pro Linux**, mantenendo:
- act_runner / Gitea (identici, già cross-platform — `act_runner` ha build Linux)
- workflow YAML invariati
- template VM Windows e Linux operative come build target
- artifact layout su filesystem locale
- act_runner / Gitea (binario Linux ufficiale)
- workflow YAML invariati (path generalizzati via env vars introdotte in Fase A)
- template VM Windows e Linux **identici** (stessi `.vmx`, `.vmdk`, snapshot)
- artifact layout (cambia solo la radice: `F:\CI\``/var/lib/ci/`)
- transport WinRM/SSH ai guest (pypsrp + paramiko già cross-platform da Fase A)
Cambia: hypervisor, transport layer di management, percorsi, eseguibili
amministrativi, gestione credenziali.
Cambia: OS host, service manager, credential store, percorsi, ownership filesystem.
---
## 2. Fattibilità
## 2. Decisione hypervisor: perché Workstation Pro Linux
### 2.1 Bivio strategico: quale hypervisor su Linux?
Confronto sintetico (decisione presa, non più aperta):
| Opzione | Pro | Contro | Verdetto |
| ----------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------- |
| **A. VMware Workstation Pro Linux** | Comando `vmrun` identico (binario `/usr/bin/vmrun`, **senza estensione `.exe`**); VMX dei template riutilizzabili 1:1 (zero conversione); guest tools invariati; dal 2024 free per uso personale e commerciale (Broadcom). | Roadmap di lungo periodo incerta dopo acquisizione Broadcom; dipendenza da binari proprietari su un OS open source. Richiede aggiornare i default hardcoded del wrapper `Resolve-VmrunPath` (`C:\Program Files (x86)\...\vmrun.exe``/usr/bin/vmrun`). | **Path a basso attrito** se si vuole minimizzare il rischio di porting (zero conversione template, zero rewrite di `_Common.psm1` oltre al path). |
| **B. KVM + libvirt + QEMU** | Open source, supportato nativamente da Linux Mint; tooling solido (`virsh`, `virt-install`, `virt-clone`); cloud-init friendly. | Conversione VMDK→qcow2 obbligatoria (`qemu-img convert`); riconfigurare guest Windows (driver virtio); riscrivere completamente lo strato vmrun. | **Raccomandata** per il lungo periodo. |
| C. VirtualBox | Cross-platform, simile a Workstation. | Performance inferiore a KVM; snapshot meno robusti; meno usato in CI. | Sconsigliata. |
| D. Proxmox VE | UI di management, API REST. | È un OS dedicato, non gira "sopra" Linux Mint. | Vedi Idea 3 (è simile a ESXi). |
**Le sezioni seguenti assumono Opzione B (KVM)** salvo dove indicato — è
lo scenario di porting più impegnativo e quindi quello da pianificare in
dettaglio. Se si sceglie A (Workstation Pro su Linux), la maggior parte del
tooling resta invariato: cambiano solo path (`F:\CI\``/var/lib/ci/`),
service manager (Windows Service → systemd), credential store e shell
(PS 5.1 → `pwsh` 7 o Python — vedi Idea 1).
### 2.2 Mappa di adattamento (assumendo Idea 1 già completata o in corso)
| Componente attuale | Equivalente Linux + KVM |
| ------------------------------------------------------ | ------------------------------------------------------------------ |
| `vmrun clone -snapshot=BaseClean ... linked` | `virsh snapshot-create` + `virt-clone --reflink` (qcow2 CoW) |
| `vmrun start <vmx>` | `virsh start <domain>` |
| `vmrun stop <vmx> hard` | `virsh destroy <domain>` |
| `vmrun deleteVM` | `virsh undefine <domain> --remove-all-storage` |
| File `.vmx` | Domain XML libvirt (definizione VM) |
| `WinBuild2025.vmdk` | `winbuild2025.qcow2` (base) + overlay qcow2 per ogni clone |
| `F:\CI\BuildVMs\` | `/var/lib/ci/build-vms/` (o pool storage libvirt dedicato) |
| `F:\CI\Artifacts\` | `/var/lib/ci/artifacts/` |
| `F:\CI\Templates\` | `/var/lib/ci/templates/` |
| `F:\CI\keys\ci_linux` | `/etc/ci/keys/ci_linux` (perms `600`, owner `ci-runner`) |
| Credential Manager `BuildVMGuest` | `secret-tool` (libsecret/GNOME Keyring) o file `.env` cifrato (`age`/`sops`) |
| WinRM HTTPS verso guest Windows | Identico (lato guest non cambia nulla) |
| SSH verso guest Linux | Identico |
| act_runner come Windows Service | `systemd unit` `act-runner.service` |
| Task Scheduler (`Register-CIScheduledTasks.ps1`) | `systemd timers` (`*.timer` + `*.service`) |
| PowerShell 5.1 | PowerShell 7 (`pwsh`) o **Python** (vedi Idea 1) |
| `vmnet8` (NAT 192.168.79.0/24) | `default` libvirt network (NAT 192.168.122.0/24) o bridge dedicato |
### 2.3 Conversione dei template VM (lavoro una-tantum)
#### Template Windows (WinBuild2025/2022)
1. Spegnere VM su Workstation, esportare `.vmx` + `.vmdk`.
2. Convertire: `qemu-img convert -O qcow2 WinBuild2025.vmdk winbuild2025.qcow2`.
3. Iniettare driver **virtio** (network, storage) nel guest Windows **prima**
della conversione (offline injection via `virt-v2v` oppure boot manuale
con ISO `virtio-win.iso` e installazione driver).
4. Importare con `virt-install --import --disk path=winbuild2025.qcow2,bus=virtio --os-variant=win2k25`.
5. Validare WinRM accessibile da host Linux (`Test-WSMan` equivalente con
`pwsh` o `pypsrp`).
6. Spegnere, creare snapshot di base: `virsh snapshot-create-as winbuild2025-template BaseClean`.
#### Template Linux (LinuxBuild2404)
1. Esportare e convertire VMDK → qcow2 (più semplice, driver virtio già presenti).
2. Importare con `virt-install --import ...`.
3. Già usa SSH + chiave: nessun cambio lato transport.
4. Snapshot `BaseClean-Linux`.
#### Linked clone su KVM
- `qemu-img create -f qcow2 -b /var/lib/ci/templates/winbuild2025.qcow2 -F qcow2 /var/lib/ci/build-vms/<jobid>.qcow2`
- Crea overlay CoW (equivalente di linked clone Workstation).
- Performance migliore se il filesystem è XFS con `reflink=1` o BTRFS.
### 2.4 Permessi e utenti
- Utente di servizio `ci-runner` (uid dedicato), membro di `libvirt` e `kvm`.
- act_runner gira come `ci-runner` via systemd (`User=ci-runner`).
- Sudoers limitati per operazioni privilegiate (es. `virsh net-start`).
- Storage pool libvirt con ownership corretta (`/var/lib/ci`).
### 2.5 Networking
- Bridge `br0` se serve raggiungibilità diretta dei guest dal host Gitea
remoto, oppure NAT (default libvirt) + DHCP statico via libvirt
dnsmasq se Gitea sta sulla stessa LAN.
- Replicare la convenzione "1 IP per job concorrente" già in uso.
### 2.6 Rischi specifici
| Rischio | Severità | Mitigazione |
| --------------------------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------- |
| Guest Windows non parte dopo conversione (driver virtio mancanti) | Alta | Iniezione driver prima della conversione, oppure boot in safe mode + install. |
| Performance I/O dei clone qcow2 inferiore a VMware linked clone in alcuni scenari | Media | Filesystem CoW (BTRFS / XFS reflink) + cache=none + aio=native su disco. |
| `vmrun` workflow / convenzioni codificate in `AGENTS.md` errori #9 #10 non più applicabili | Bassa | Documentare nuovo set di "errori frequenti KVM" (es. virtio drivers, SELinux). |
| Linux Mint kernel non sempre allineato al supporto VMware Workstation se si sceglie A | Media | Solo se si va opzione A: vincolarsi a kernel LTS testato. |
| Burn-in concorrente saturazione I/O diversa su qcow2 vs VMDK | Media | Ripetere `Test-CapacityBurnIn` su nuovo host prima del go-live. |
| WinRM HTTPS da host Linux verso guest Windows ha cipher mismatch occasionali | Bassa | Usare `pypsrp` con `auth='credssp'` o `auth='negotiate'`; testato in lab. |
| Conversione VMDK + sysprep del Windows template può rompere attivazione / licenza | Media | Validare licenza Windows e tooling unattended con la nuova HW signature. |
### 2.7 Vincoli che spariscono / che restano
**Spariscono**:
- Limitazioni PS 5.1 (`AGENTS.md` tabella PS7+) — su Linux si usa `pwsh` 7 o Python.
- Necessità di Credential Manager con bug noti sotto SYSTEM account.
- `autounattend.xml` solo per refresh del template Windows (operazione rara).
- Errori #9 (snapshot con `.vmem`) e #10 (`getGuestIPAddress` bloccante)
sono specifici di vmrun — non più applicabili.
**Restano / si trasformano**:
- Necessità di gestire snapshot in stato "powered off".
- IP collision per machine-id identico nei clone Linux (#11): identico
comportamento sotto KVM con dnsmasq DHCP.
- Errore #12 (stderr nativa + `$ErrorActionPreference='Stop'`) sparisce
se si esce da PowerShell, altrimenti resta.
| Opzione | Verdetto |
| ---------------------------------- | -------------------------------------------------------------------- |
| **VMware Workstation Pro Linux** | **SCELTA.** `vmrun` identico, VMX template riutilizzabili 1:1, free per uso personale e commerciale dal 2024. Plumbing-only port. |
| KVM + libvirt | Rimandato. Richiederebbe conversione VMDK→qcow2, virtio injection nei guest Windows, rewrite backend hypervisor. Resta come piano B se Broadcom dismette Workstation. |
| VirtualBox | Scartato. Performance/snapshot inferiori. |
---
## 3. Stima volumi / sforzo (relativa)
## 3. Mappa di adattamento
| Area | Indicatori dimensione | Complessità |
| ------------------------------------------------------------------- | ------------------------------- | ----------- |
| Conversione template Windows → qcow2 + virtio | 2 VM (2025, 2022) | Alta |
| Conversione template Linux → qcow2 | 1 VM | Bassa |
| Riscrittura `_Common.psm1` → wrapper `virsh`/`libvirt` | ~300 righe | Media |
| Riscrittura `_Transport.psm1` (WinRM) | ~240 righe | Bassa |
| Adattamento `New-BuildVM` / `Remove-BuildVM` / `Invoke-CIJob` | ~2.000 righe | Media |
| Riscrittura `Setup-Host.ps1` → script bash + systemd | ~400 righe | Media |
| `Register-CIScheduledTasks.ps1` → systemd `.timer` units | 6 task → 6 timer | Bassa |
| Adattamento workflow YAML (path Windows → POSIX) | 5 file | Bassa |
| Documentazione (HOST-SETUP.md, AGENTS.md, BEST-PRACTICES.md) | ~5 file md | Media |
| Validazione e2e: smoke + section 3.3 + capacity burn-in | piano test esistente | Alta |
Sequenza obbligata:
1. Decidere hypervisor (A vs B).
2. Convertire template Linux (più semplice, fa da PoC).
3. Convertire un template Windows e validare WinRM da Linux.
4. Riscrittura tooling (idealmente in Python — vedi Idea 1).
5. Migrazione storage `F:\CI\``/var/lib/ci/`.
6. Switch act_runner.
| Componente attuale | Equivalente Linux + Workstation Pro |
| --------------------------------------------------- | ------------------------------------------------------------ |
| `vmrun.exe` (`C:\Program Files (x86)\...`) | `/usr/bin/vmrun` (binario senza `.exe`, installato dal package Workstation) |
| File `.vmx` / `.vmdk` | **identici, copiati così come sono** |
| Snapshot `BaseClean` / `BaseClean-Linux` | preservati nella copia |
| `F:\CI\BuildVMs\` | `/var/lib/ci/build-vms/` |
| `F:\CI\Artifacts\` | `/var/lib/ci/artifacts/` |
| `F:\CI\Templates\` | `/var/lib/ci/templates/` |
| `F:\CI\keys\ci_linux` | `/etc/ci/keys/ci_linux` (perms `600`, owner `ci-runner`) |
| Credential Manager (`BuildVMGuest`, `GiteaPAT`) | `secret-tool` / GNOME Keyring / KWallet (backend `keyring`) |
| WinRM HTTPS verso guest Windows | identico (pypsrp parla con WinRM da Linux senza modifiche) |
| SSH verso guest Linux | identico (paramiko) |
| act_runner come Windows Service | systemd unit `act-runner.service` |
| Task Scheduler (`Register-CIScheduledTasks.ps1`) | systemd `*.timer` + `*.service` units |
| PowerShell 5.1 | `pwsh` 7 (solo per ricostruire template, raro) |
| `vmnet8` NAT (`192.168.79.0/24`) | `vmnet8` NAT su Workstation Pro Linux (stesso concetto, IP range configurabile) |
---
## 4. Pro / Contro
## 4. Strategia di migrazione
### Pro
### Step B1 — Setup host Linux Mint in parallelo (no impatto produzione)
- Elimina i vincoli PS 5.1 (tabella in `AGENTS.md`).
- Stack open source completo (no licenze VMware Workstation se si va KVM).
- `systemd` + `journalctl` per service management e log centralizzati.
- Filesystem CoW (BTRFS/XFS reflink) → clone disco ~istantanei, equivalente
o migliore di linked clone Workstation.
- Linux Mint ha buon supporto desktop per debug interattivo del runner.
- Disaccoppia dal futuro incerto di VMware Workstation (Broadcom).
- Installazione Linux Mint LTS + aggiornamenti
- Installazione VMware Workstation Pro per Linux (bundle ufficiale Broadcom)
- Verifica `vmrun` con una VM di test (clone, start, stop)
- Configurazione `vmnet8` NAT range coerente o equivalente
- Creazione utente di servizio `ci-runner` (uid dedicato)
- Creazione storage layout `/var/lib/ci/{build-vms,artifacts,templates,keys}`
con ownership `ci-runner:ci-runner` (mode 750)
- Installazione Python 3.11+ + venv in `/opt/ci/venv/` con `pip install -e .`
del package `ci_orchestrator` portato in Fase A
### Contro
Validazione: `python -m ci_orchestrator --help` funziona da utente `ci-runner`.
- Migrazione "tutta o niente" del host: non si può avere CI/CD attivo su
Win e su Linux in parallelo se il template/storage layout è condiviso.
- Conversione template Windows è il passaggio più rischioso (virtio,
attivazione, eventuale re-provisioning toolchain).
- Curva di apprendimento libvirt / virsh / domain XML.
- Tutta la documentazione e `AGENTS.md` da riscrivere.
- Test plan completo da rieseguire (smoke, e2e, burn-in).
### Step B2 — Trasferimento template VM
- Spegnere i template Workstation sull'host Windows (devono essere
fully powered-off — vedi `AGENTS.md` errore #9)
- Copia bit-by-bit di `F:\CI\Templates\``/var/lib/ci/templates/`
(`scp -r` o `rsync`)
- Aprire i `.vmx` su Workstation Linux per registrarli (`vmrun start ... nogui`
con stop immediato, oppure `vmrun -T ws snapshot list`) — risolverà
eventuali path interni se Workstation li chiede
- Verifica snapshot presenti: `vmrun listSnapshots <vmx>` deve mostrare
`BaseClean` / `BaseClean-Linux`
- Smoke test manuale: clone linked + start + WinRM/SSH dal host Linux
### Step B3 — Trasferimento credenziali e chiavi
- Copia chiave SSH guest Linux: `F:\CI\keys\ci_linux*``/etc/ci/keys/`
(mode 600, owner `ci-runner`)
- Re-store delle credenziali guest Windows nel keyring Linux:
`secret-tool store --label='BuildVMGuest' service ci target BuildVMGuest`
- Re-store Gitea PAT: `secret-tool store --label='GiteaPAT' service ci target GiteaPAT`
- Verifica via Python: `keyring.get_credential('BuildVMGuest', None)` non None
### Step B4 — Setup act_runner come systemd service
- Download act_runner Linux binary (versione allineata a v1.0.2 o successiva)
- Registrazione runner verso Gitea con label `windows-build:host` e
`linux-build:host` (stesse label di oggi → workflow non cambiano)
- File unit `/etc/systemd/system/act-runner.service`:
- `User=ci-runner`
- `WorkingDirectory=/var/lib/ci/runner`
- `Environment=PYTHONIOENCODING=utf-8`
- env vars `CI_*` per il config Python
- `systemctl enable --now act-runner.service`
- Validazione: `journalctl -u act-runner -f` mostra connessione a Gitea OK
### Step B5 — Conversione scheduled tasks → systemd timers
`Register-CIScheduledTasks.ps1` definisce N task periodici. Per ognuno
creare:
- `/etc/systemd/system/ci-<task>.service` (oneshot, chiama
`python -m ci_orchestrator <cmd>`)
- `/etc/systemd/system/ci-<task>.timer` (`OnCalendar=...` equivalente)
- `systemctl enable --now ci-<task>.timer`
Task tipici da convertire:
- `cleanup-orphaned-vms` (ogni ora)
- `retention-policy` (giornaliero)
- `watch-disk-space` (ogni 15 min)
- `watch-runner-health` (ogni 5 min)
- `backup-template` (settimanale)
### Step B6 — Cutover
Finestra di manutenzione concordata:
1. Stop act_runner sull'host Windows (`Stop-Service actions-runner`)
2. Rsync incrementale finale degli artifact recenti:
`F:\CI\Artifacts\``/var/lib/ci/artifacts/`
3. Verificare nessun job in coda lato Gitea
4. Avviare act_runner Linux (`systemctl start act-runner`)
5. Trigger manuale di un workflow di smoke test
6. Trigger del workflow matrix `build-nsInnoUnp.yml` (Win + Linux build)
Se PASS → cutover confermato. Se FAIL → rollback (riavvio runner Windows,
nessun dato è stato distrutto).
### Step B7 — Capacity burn-in sul nuovo host
Eseguire `Test-CapacityBurnIn` (versione Python) con N=4 concorrenti × R=10
round, sia per template Windows che Linux. Confronto tempi vs baseline
Windows host pre-migrazione (aspettativa: paragonabili, eventuali differenze
vanno indagate ma non sono blocker se entro ±20%).
### Step B8 — Decommissioning host Windows (opzionale)
Dopo 1-2 settimane di stabilità sul nuovo host:
- Backup finale di `F:\CI\` su archivio
- Spegnimento runner Windows (lasciato installato per un mese come
rollback option)
- Riallocazione hardware
---
## 5. Sinergia con altre idee
## 5. Adattamenti al codice Python (residui dopo Fase A)
- **Idea 1 (Python)**: forte prerequisito. PS 7 su Linux è possibile, ma
Python è più idiomatico per `libvirt` (binding `libvirt-python`) e
per riusare `paramiko` / `pypsrp` cross-platform.
- **Idea 3 (ESXi)**: parzialmente alternativa. Se si va su ESXi, l'host CI
resta comunque una macchina di management (può essere Linux Mint con
Python + `pyVmomi`, oppure restare Windows). Il "dove gira l'host" e
"dove girano le VM" si disaccoppiano.
Se Fase A ha rispettato le regole di §2 di [idea-1-python-rewrite.md](idea-1-python-rewrite.md),
il codice **non cambia**. Modifiche residue attese:
- `config.example.toml`: aggiungere sezione `[paths.linux]` con default
`/var/lib/ci/...` (la sezione `[paths.windows]` resta per chi ricostruisce
template da Win)
- `runner/config.yaml`: path env vars aggiornati a POSIX
- Eventuali test pytest che assumevano `Path('F:\\CI')` → usare fixture
parametrizzata
- Workflow `lint.yml`: rimuovere o relegare a job opzionale la parte PSSA
(utile solo se si tocca ancora codice PS dei template)
---
## 6. Decision checklist
## 6. Rischi specifici Fase B
Procedere **solo se** almeno 2 dei seguenti sono veri:
- [ ] Il vincolo Windows host è un problema concreto (licenze, policy aziendale, preferenza team).
- [ ] Si è disposti a investire una settimana piena di test di conversione VMDK→qcow2.
- [ ] Si è già completata (o si è disposti a fare in parallelo) l'Idea 1.
- [ ] Si vuole rimuovere la dipendenza commerciale da VMware Workstation.
| Rischio | Severità | Mitigazione |
| -------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------- |
| `vmrun` su Workstation Linux ha differenze sottili nel parsing output `list` / `getGuestIPAddress` | Media | Test del modulo `vmrun.py` su Linux durante Step B1; eventuali fix dietro feature flag. |
| Performance I/O linked clone su filesystem ext4 vs NTFS | Bassa | Misurare con burn-in (Step B7). Eventualmente XFS o BTRFS con CoW per il dataset template. |
| `vmnet8` NAT range configurato diversamente su Linux: IP collision con altri host LAN | Media | Allineare il range a quello attuale Windows (`192.168.79.0/24`) in `vmware-vmnet.conf`. |
| WinRM HTTPS self-signed: pypsrp da Linux può negoziare TLS 1.2 con cipher non supportati dal Windows guest | Media | Già testato in Fase A (lo stesso codice gira anche da Windows host). Validare con smoke test prima del cutover. |
| Permessi su `/var/lib/ci/build-vms/`: vmrun gira come `ci-runner` ma deve scrivere VMDK CoW | Media | ACL POSIX: `setfacl -d -m u:ci-runner:rwX` sulla directory. Test in Step B1. |
| `secret-tool` headless: act_runner come systemd service non ha sessione D-Bus per accedere al keyring | Alta | Usare backend `keyring` file-based + `age`/`sops` (vault file) oppure `keyring.backends.SecretService` con D-Bus user@.service. Decidere in Step B3 con PoC. |
| Errore #11 `AGENTS.md` (machine-id Linux clone) | Bassa | Identico comportamento, fix identico (reset machine-id pre-snapshot). Già documentato. |
| Errore #12 `AGENTS.md` (stderr nativa + `'Stop'`) | N/A | Sparisce: il codice non è più PowerShell. |
---
## 7. Path alternativo "minimo": dual-host
## 7. Path alternativo "dual-host" (se la Fase B si blocca)
Se non si vuole migrare ma solo "supportare anche Linux Mint", una via meno
invasiva:
- Mantenere host Windows come primario.
- Aggiungere un **secondo runner** Linux Mint che usa solo `linux-build` jobs
(KVM o Workstation Linux), label `linux-build:host-mint`.
- Workflow esistenti restano invariati; nuovi workflow possono selezionare il
runner secondario per test sperimentali.
- Stima: ~1/3 dello sforzo della migrazione completa, ma codebase divisa
in due (PS Win + qualche script Linux ad hoc) — debito tecnico crescente.
Se durante la migrazione si scopre un blocker grave (es. WinRM da Linux
non funzionante affidabilmente verso il template Windows specifico), si
può ripiegare su:
Questa via ha senso solo come **PoC temporaneo** prima di una migrazione completa.
- mantenere host Windows per i job `windows-build:host`
- usare host Linux Mint solo per `linux-build:host` (label dedicata)
- runner doppio registrato verso Gitea
Costo: codebase divisa in due ambienti, maggiore overhead operativo.
**Soluzione di emergenza, non target finale.**
---
## 8. Definizione di "fatto" (Fase B)
- [ ] act_runner gira come systemd service `act-runner.service` su Linux Mint
- [ ] Tutti i template VM (`WinBuild2025`, `WinBuild2022`, `LinuxBuild2404`)
operativi dal nuovo host con snapshot integri
- [ ] Workflow `build-nsInnoUnp.yml` (matrix Win+Linux) PASS dal nuovo host
- [ ] Burn-in capacity 4 job concorrenti PASS, tempi entro ±20% del baseline
- [ ] Storage migrato a `/var/lib/ci/`, host Windows in stand-by come rollback
- [ ] Tutti i timer systemd attivi e schedulati
- [ ] Credenziali guest accessibili da `ci-runner` headless
- [ ] `README.md`, `AGENTS.md`, `docs/HOST-SETUP.md` aggiornati per host Linux
- [ ] Almeno 1 settimana di esercizio in produzione senza incidenti