{"id":50393187,"url":"https://github.com/ninuxorg/ansible-ninux-openwrt","last_synced_at":"2026-06-01T21:00:41.051Z","repository":{"id":361282330,"uuid":"1250673858","full_name":"ninuxorg/ansible-ninux-openwrt","owner":"ninuxorg","description":"Automated OpenWrt firmware build system for Ninux mesh network nodes — Ansible role + Jenkins pipeline with multi-target, multi-VPN and Captive Portal variants","archived":false,"fork":false,"pushed_at":"2026-05-29T22:31:34.000Z","size":64,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T00:14:00.510Z","etag":null,"topics":["ansible","captive-portal","firmware","jenkins","mesh-network","ninux","openwisp","openwrt","wireguard","zerotier"],"latest_commit_sha":null,"homepage":"http://ninux.org","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ninuxorg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-26T21:33:17.000Z","updated_at":"2026-05-29T22:31:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ninuxorg/ansible-ninux-openwrt","commit_stats":null,"previous_names":["ninuxorg/ansible-ninux-openwrt"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ninuxorg/ansible-ninux-openwrt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninuxorg%2Fansible-ninux-openwrt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninuxorg%2Fansible-ninux-openwrt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninuxorg%2Fansible-ninux-openwrt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninuxorg%2Fansible-ninux-openwrt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ninuxorg","download_url":"https://codeload.github.com/ninuxorg/ansible-ninux-openwrt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninuxorg%2Fansible-ninux-openwrt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33707328,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","captive-portal","firmware","jenkins","mesh-network","ninux","openwisp","openwrt","wireguard","zerotier"],"created_at":"2026-05-30T19:30:38.066Z","updated_at":"2026-05-30T19:30:38.584Z","avatar_url":"https://github.com/ninuxorg.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ansible-ninux-openwrt\n\nSistema di build automatizzato per firmware **OpenWrt** per i nodi della rete mesh [Ninux](http://ninux.org).\n\n\n---\n\n## Indice\n\n1. [Struttura del repo](#struttura-del-repo)\n2. [Configurazione rapida](#configurazione-rapida)\n3. [Installazione Jenkins su Debian Trixie](#installazione-jenkins-su-debian-trixie)\n4. [Configurazione Jenkins](#configurazione-jenkins)\n5. [Configurazione del build](#configurazione-del-build)\n6. [Aggiungere device e organizzazioni](#aggiungere-device-e-organizzazioni)\n7. [Uso da riga di comando](#uso-da-riga-di-comando)\n8. [Performance e ottimizzazioni](#performance-e-ottimizzazioni)\n9. [OpenWISP Firmware Upgrader](#openwisp-firmware-upgrader)\n10. [Struttura dei firmware prodotti](#struttura-dei-firmware-prodotti)\n11. [Troubleshooting](#troubleshooting)\n\n---\n\n## Struttura del repo\n\n```\nansible-ninux-openwrt/\n│\n├── config/                              \u003c- CONFIGURAZIONE (modifica qui)\n│   ├── build.yml                        \u003c- Tutte le variabili di build\n│   ├── base.config                      \u003c- Pacchetti comuni a tutti i target\n│   ├── chilli.ext                       \u003c- Estensione Captive Portal\n│   ├── zerotier.ext                     \u003c- Estensione ZeroTier VPN\n│   ├── wireguard.ext                    \u003c- Estensione WireGuard VPN\n│   ├── organizations/\n│   │   └── \u003corg\u003e/\n│   │       └── \u003cdevice\u003e.config          \u003c- Config per device\n│   └── root_files/\n│       └── \u003corg\u003e/                       \u003c- Overlay filesystem per org\n│           └── etc/\n│               ├── config/\n│               └── uci-defaults/\n│\n├── setup/\n│   └── install-jenkins.sh              \u003c- Script autoinstall (Debian Trixie)\n│\n├── inventory/\n│   ├── hosts.yml                        \u003c- Build host (localhost)\n│   ├── vault.yml.example               \u003c- Template credenziali cifrate\n│   └── group_vars/build_hosts.yml\n│\n├── playbooks/\n│   ├── build_all.yml                    \u003c- Build tutti i device (varianti parallele)\n│   ├── build_firmware.yml              \u003c- Build singolo device\n│   ├── build_matrix.yml                \u003c- Build matrice personalizzata\n│   ├── build_parallel.yml              \u003c- Build parallela tra device\n│   ├── cleanup.yml                     \u003c- Pulizia manuale disco\n│   └── _build_device_variants.yml      \u003c- Helper interno\n│\n├── roles/ninux_build_openwrt/\n│   ├── defaults/main.yml               \u003c- Default variabili ruolo\n│   └── tasks/\n│       ├── main.yml\n│       ├── deps.yml                    \u003c- apt install dipendenze\n│       ├── prepare.yml                 \u003c- Directory, ccache, tmpfs\n│       ├── clone_ninux.yml             \u003c- Copia config/ sul build host\n│       ├── clone_openwrt.yml           \u003c- Clone/aggiorna OpenWrt\n│       ├── rootfiles.yml               \u003c- Overlay filesystem\n│       ├── feeds.yml                   \u003c- feeds.conf + update + install\n│       ├── dotconfig.yml               \u003c- Assembla .config\n│       ├── build.yml                   \u003c- make download + make -jN\n│       ├── artifacts.yml               \u003c- Copia firmware output/ e NFS\n│       └── openwisp_upload.yml         \u003c- Upload OpenWISP (opzionale)\n│\n├── Jenkinsfile\n├── ansible.cfg\n└── .gitignore\n```\n\n**Il file principale da modificare e' `config/build.yml`** — contiene tutte le variabili con commenti esplicativi.\n\n---\n\n## Configurazione rapida\n\n```bash\n# 1. Clona il repo\ngit clone https://github.com/ninuxorg/ansible-ninux-openwrt.git\ncd ansible-ninux-openwrt\n\n# 2. Modifica la configurazione\nnano config/build.yml\n\n# 3. Verifica i device disponibili\nls config/organizations/basilicata/\n\n# 4. Lancia la build\nansible-playbook playbooks/build_all.yml\n```\n\n---\n\n## Installazione Jenkins su Debian Trixie\n\n### Requisiti hardware consigliati (LXC Proxmox)\n\n| Risorsa | Minimo | Consigliato |\n|---------|--------|-------------|\n| CPU     | 4 core | 12 core     |\n| RAM     | 8 GB   | 24 GB       |\n| Disco   | 80 GB  | 200 GB      |\n\n\u003e **Nota Proxmox LXC**: il container deve avere `nesting=1` abilitato\n\u003e per permettere il mount di tmpfs. In `/etc/pve/lxc/\u003cCTID\u003e.conf`:\n\u003e ```\n\u003e features: nesting=1\n\u003e ```\n\u003e Dopo: `pct restart \u003cCTID\u003e`\n\n### Installazione automatica (consigliata)\n\n```bash\n# Clona il repo\ngit clone https://github.com/ninuxorg/ansible-ninux-openwrt.git\ncd ansible-ninux-openwrt\n\n# Esegui lo script come root\nsudo ./setup/install-jenkins.sh\n\n# Con vault password per OpenWISP (opzionale)\nsudo ./setup/install-jenkins.sh --vault-pass \"mia-password-segreta\"\n\n# Solo dipendenze, Jenkins gia' installato\nsudo ./setup/install-jenkins.sh --skip-jenkins\n```\n\nLo script installa e configura automaticamente:\n\n- Java 21 (OpenJDK)\n- Ansible (via pipx, metodo consigliato su Trixie)\n- Jenkins LTS con chiave GPG 2026\n- Tutte le dipendenze build OpenWrt\n- ccache persistente in `/var/cache/openwrt-ccache`\n- tmpfs in `/mnt/openwrt-tmpfs` (8G, montato al boot via fstab)\n- Permessi sudo per l'utente `jenkins`\n\n### Installazione manuale passo per passo\n\n#### 1. Java 21\n\n```bash\napt-get update\napt-get install -y fontconfig openjdk-21-jre\njava -version\n```\n\n#### 2. Ansible\n\n```bash\napt-get install -y pipx\npipx install --include-deps ansible\npipx ensurepath\nsource ~/.bashrc\nansible --version\n```\n\n#### 3. Jenkins LTS\n\n```bash\n# Chiave GPG aggiornata (dicembre 2025)\nmkdir -p /etc/apt/keyrings\ncurl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2026.key \\\n  -o /etc/apt/keyrings/jenkins-keyring.asc\n\necho \"deb [signed-by=/etc/apt/keyrings/jenkins-keyring.asc] \\\n  https://pkg.jenkins.io/debian-stable binary/\" \\\n  \u003e /etc/apt/sources.list.d/jenkins.list\n\napt-get update\napt-get install -y jenkins\nsystemctl enable --now jenkins\n\n# Password iniziale\ncat /var/lib/jenkins/secrets/initialAdminPassword\n```\n\n#### 4. Dipendenze build OpenWrt\n\n```bash\napt-get install -y \\\n  build-essential ccache time git subversion g++ bash make \\\n  libssl-dev patch libncurses-dev zlib1g-dev gawk flex gettext \\\n  wget unzip xz-utils python3 python3-distutils-extra \\\n  rsync curl libsnmp-dev liblzma-dev libpam0g-dev cpio\n```\n\n#### 5. ccache persistente\n\n```bash\nmkdir -p /var/cache/openwrt-ccache\nchmod 777 /var/cache/openwrt-ccache\nchown jenkins:jenkins /var/cache/openwrt-ccache\n```\n\n#### 6. tmpfs\n\n```bash\nmkdir -p /mnt/openwrt-tmpfs\necho \"tmpfs /mnt/openwrt-tmpfs tmpfs defaults,size=8G,mode=0777 0 0\" \u003e\u003e /etc/fstab\nmount /mnt/openwrt-tmpfs\ndf -h /mnt/openwrt-tmpfs\n```\n\n#### 7. sudo per jenkins\n\n```bash\ncat \u003e /etc/sudoers.d/jenkins-openwrt \u003c\u003c 'EOF'\njenkins ALL=(ALL) NOPASSWD: /bin/mount\njenkins ALL=(ALL) NOPASSWD: /bin/umount\njenkins ALL=(ALL) NOPASSWD: /usr/bin/apt-get\njenkins ALL=(ALL) NOPASSWD: /usr/bin/apt\nEOF\nchmod 440 /etc/sudoers.d/jenkins-openwrt\n```\n\n---\n\n## Configurazione Jenkins\n\n### 1. Primo accesso\n\n1. Apri `http://\u003cIP-SERVER\u003e:8080`\n2. Inserisci la password iniziale: `cat /var/lib/jenkins/secrets/initialAdminPassword`\n3. Scegli **\"Install suggested plugins\"**\n4. Crea l'utente amministratore\n\n### 2. Plugin aggiuntivi richiesti\n\nVai in **Manage Jenkins → Plugins → Available plugins**:\n\n| Plugin | Note |\n|--------|------|\n| **Ansible** | Integrazione Ansible |\n| **Timestamper** | Timestamp nei log di build |\n| **Build Timeout** | Timeout per build lunghe |\n| **Workspace Cleanup** | Pulizia workspace post-build |\n\nPipeline e Git sono gia' inclusi nei plugin suggeriti.\n\n### 3. Configurazione Ansible in Jenkins\n\n**Manage Jenkins → Tools → Ansible installations**:\n\n- Name: `ansible`\n- Install automatically: **no**\n- Path to ansible executables directory: `/root/.local/bin`\n\n### 4. Creazione del job Pipeline\n\n1. **New Item** → nome `NinuxOpenwrt` → tipo **Pipeline** → OK\n2. Tab **General**:\n   - Spunta **\"Do not allow concurrent builds\"**\n   - Build Timeout: **240 minuti**\n3. Tab **Pipeline**:\n   - Definition: **Pipeline script from SCM**\n   - SCM: **Git**\n   - Repository URL: `https://github.com/mikysal78/ansible-ninux-openwrt.git`\n   - Branch Specifier: `*/main`\n   - Script Path: `Jenkinsfile`\n4. **Save** → **Build with Parameters** per il primo lancio\n\n### 5. Parametri del job\n\n| Parametro | Default | Descrizione |\n|-----------|---------|-------------|\n| `OPENWRT_ORG` | `basilicata` | Organizzazione Ninux |\n| `OPENWRT_VERSION` | `v25.12.4` | Tag OpenWrt |\n| `VPN_VARIANTS` | `ALL` | `ALL` / `NO` / `ZeroTier` / `WireGuard` / `DualVPN` |\n| `CAPTIVE_PORTAL_VARIANTS` | false | Compila anche varianti con CP |\n| `SKIP_DEPS` | false | Salta `apt install` (dopo il primo run) |\n| `TMPFS_ENABLED` | true | RAM disk per `tmp/` (+30% velocita') |\n| `TMPFS_SIZE` | `8G` | Dimensione tmpfs |\n| `CCACHE_DIR` | `/var/cache/openwrt-ccache` | ccache persistente |\n| `CCACHE_SIZE` | `20G` | Dimensione massima ccache |\n| `OPENWISP_UPLOAD` | false | Upload su OpenWISP |\n| `OPENWISP_TRIGGER_UPGRADE` | false | Avvia batch upgrade OpenWISP |\n| `OPENWISP_URL` | `` | URL istanza OpenWISP |\n\n### 6. Vault password per OpenWISP\n\n```bash\n# Sul server Jenkins\necho \"mia-password-vault\" \u003e /var/lib/jenkins/.vault_pass\nchmod 600 /var/lib/jenkins/.vault_pass\nchown jenkins:jenkins /var/lib/jenkins/.vault_pass\n\n# Crea il vault con credenziali\ncp inventory/vault.yml.example inventory/vault.yml\nnano inventory/vault.yml\nansible-vault encrypt inventory/vault.yml \\\n  --vault-password-file /var/lib/jenkins/.vault_pass\n```\n\n---\n\n## Configurazione del build\n\n**Modifica `config/build.yml`** per personalizzare la build.\n\nSezioni principali:\n\n```yaml\n# --- Versione e org ---\nopenwrt_version: \"v25.12.4\"\nopenwrt_org: \"basilicata\"\n\n# --- Varianti da compilare ---\nopenwrt_vpn_variants: [NO, ZeroTier, WireGuard, DualVPN]\nopenwrt_cp_variants: false\n\n# --- Dove salvare i firmware ---\nopenwrt_nfs_dir: \"/mnt/nfs-firmware\"\n\n# --- Performance ---\nopenwrt_ccache_dir: \"/var/cache/openwrt-ccache\"\nopenwrt_ccache_maxsize: \"20G\"\nopenwrt_tmpfs_enabled: true\nopenwrt_tmpfs_size: \"8G\"\n\n# --- OpenWISP (disabilitato di default) ---\nopenwisp_upload_enabled: false\nopenwisp_url: \"\"\nopenwisp_org_id: \"\"\n```\n\nLe variabili in `config/build.yml` sovrascrivono i default del ruolo.\nOverride ulteriore a runtime: `-e variabile=valore`.\n\n---\n\n## Aggiungere device e organizzazioni\n\n### Nuovo device\n\n```bash\n# 1. Genera il .config con OpenWrt menuconfig\ncd /path/to/openwrt-src\nmake menuconfig   # seleziona target e salva\ncp .config /repo/config/organizations/basilicata/nome_device.config\n\n# 2. Verifica che il file sia stato aggiunto\nls config/organizations/basilicata/\n\n# 3. Commita\ngit add config/organizations/basilicata/nome_device.config\ngit commit -m \"feat: aggiungi device nome_device\"\n```\n\nIl nome del file senza `.config` e' il valore di `openwrt_target`.\nL'autodiscovery lo includera' automaticamente nella prossima build.\n\n### Nuova organizzazione\n\n```bash\nmkdir -p config/organizations/roma\nmkdir -p config/root_files/roma/etc/{config,uci-defaults}\n\n# Parti dai config esistenti\ncp config/organizations/basilicata/*.config config/organizations/roma/\n\n# Personalizza root_files\ncp -r config/root_files/basilicata/. config/root_files/roma/\n\n# Build per la nuova org\nansible-playbook playbooks/build_all.yml -e openwrt_org=roma\n```\n\n---\n\n## Uso da riga di comando\n\n```bash\n# Tutti i device, tutte le varianti VPN\nansible-playbook playbooks/build_all.yml\n\n# Con Captive Portal (2x build per device)\nansible-playbook playbooks/build_all.yml -e openwrt_cp_variants=true\n\n# Solo alcune varianti VPN\nansible-playbook playbooks/build_all.yml \\\n  -e '{\"openwrt_vpn_variants\": [\"NO\", \"ZeroTier\"]}'\n\n# Singolo device, tutte le varianti\nansible-playbook playbooks/build_firmware.yml \\\n  -e openwrt_target=glinet_gl-mt300n-v2\n\n# Singola variante specifica\nansible-playbook playbooks/build_firmware.yml \\\n  -e openwrt_target=glinet_gl-mt300n-v2 \\\n  -e '{\"openwrt_vpn_variants\": [\"ZeroTier\"]}' \\\n  -e openwrt_captive_portal=true\n\n# Solo installazione dipendenze\nansible-playbook playbooks/build_all.yml --tags deps\n\n# Solo build (dipendenze gia' installate)\nansible-playbook playbooks/build_all.yml --skip-tags deps\n\n# Pulizia disco\nansible-playbook playbooks/cleanup.yml                        # solo temporanei\nansible-playbook playbooks/cleanup.yml -e cleanup_full=true  # tutto\nansible-playbook playbooks/cleanup.yml -e cleanup_output=true # solo output/\n```\n\n---\n\n## Performance e ottimizzazioni\n\n### Strategia di build\n\n```\nDevice 1\n  ├── VPN=NO        ─┐\n  ├── VPN=ZeroTier   ├─ parallelo (async, condividono toolchain)\n  ├── VPN=WireGuard  │\n  └── VPN=DualVPN   ─┘\n  → pulizia staging_dir/build_dir\nDevice 2\n  └── (idem)\n...\nPost: pulizia totale + smonta tmpfs + stats ccache\n```\n\nLe varianti dello stesso device condividono la toolchain gia' compilata\ne ricompilano solo i pacchetti che differiscono (pochi MB),\nquindi il parallelo e' efficiente senza moltiplicare RAM/disco.\n\n### Impatto stimato su 12 CPU / 24 GB RAM\n\n| Ottimizzazione | Guadagno |\n|----------------|----------|\n| `make -j14` (nproc+2) | baseline |\n| ccache (dalla 2a build) | **-70%** tempo |\n| ccache SLOPPINESS | hit rate piu' alto |\n| tmpfs per `tmp/` | **-30%** I/O |\n| 4 varianti in parallelo | **-60%** per device |\n\n### Proxmox LXC e tmpfs\n\n```bash\n# Host Proxmox\necho \"features: nesting=1\" \u003e\u003e /etc/pve/lxc/\u003cCTID\u003e.conf\npct restart \u003cCTID\u003e\n```\n\n---\n\n## OpenWISP Firmware Upgrader\n\n### Configurazione\n\nIn `config/build.yml`:\n\n```yaml\nopenwisp_upload_enabled: true\nopenwisp_url: \"https://openwisp.ninux.org\"\nopenwisp_org_slug: \"basilicata\"\nopenwisp_org_id: \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nopenwisp_trigger_upgrade: false   # true = avvia upgrade automatico\n```\n\nCredenziali in `inventory/vault.yml`:\n\n```bash\ncp inventory/vault.yml.example inventory/vault.yml\n# Modifica: openwisp_username e openwisp_password\nansible-vault encrypt inventory/vault.yml \\\n  --vault-password-file /var/lib/jenkins/.vault_pass\n```\n\n### Flusso\n\n```\nBuild → artifacts.yml → openwisp_upload.yml\n  1. Login → token Bearer\n  2. Cerca/crea Category (org + device)\n  3. Crea Build (versione-target-VPN-CP)\n  4. Carica sysupgrade + factory\n  5. (opzionale) Batch upgrade\n```\n\n---\n\n## Struttura dei firmware prodotti\n\n```\noutput/                              \u003c- file finali per Jenkins artifacts\n└── v25.12.4/\n    └── basilicata/\n        ├── Standard/\n        │   ├── VPN-NO/glinet_gl-mt300n-v2/\n        │   ├── VPN-ZeroTier/glinet_gl-mt300n-v2/\n        │   ├── VPN-WireGuard/glinet_gl-mt300n-v2/\n        │   └── VPN-DualVPN/glinet_gl-mt300n-v2/\n        └── CaptivePortal/\n            └── VPN-*/...\n\n/mnt/nfs-firmware/                   \u003c- bin/targets/ completo\n└── v25.12.4/basilicata/Standard/VPN-ZeroTier/glinet_gl-mt300n-v2/\n    ├── openwrt-*-sysupgrade.bin\n    ├── openwrt-*-factory.bin\n    ├── sha256sums\n    └── ...\n```\n\n---\n\n## Troubleshooting\n\n### `openwrt_work_dir is undefined`\n\nAssicurati di usare i playbook da `playbooks/` — caricano `config/build.yml`\ntramite `vars_files`. Non richiamare il ruolo direttamente senza caricare le variabili.\n\n### `chown failed: Operation not permitted` su NFS\n\nI task non usano `owner` sulle directory NFS. Se persiste, verifica che\nil server NFS esporti con `no_root_squash` o adatta i permessi lato server.\n\n### `libncurses5 not available`\n\nPacchetto rimosso da Debian 13+. Usa `libncurses-dev` (gia' nel repo).\nAggiorna `openwrt_build_deps` in `config/build.yml` se hai un'installazione vecchia.\n\n### Jenkins: `git tool does not exist`\n\n**Manage Jenkins → Tools → Git installations**:\n- Name: `Default`\n- Path: `git`\n\n### Jenkins: timeout su build lunghe\n\nIn **Manage Jenkins → Configure System** imposta Build Timeout a 240+ minuti.\n\n### ccache hit rate basso\n\n```bash\nCCACHE_DIR=/var/cache/openwrt-ccache ccache --show-stats\n```\n\nHit rate sotto 50% dopo la seconda build: controlla che `CCACHE_DIR`\nsia lo stesso tra i job e che `nesting=1` sia attivo (per tmpfs).\n\n### tmpfs: `mount: permission denied` in LXC\n\nAbilita `nesting=1` nella config Proxmox del container (vedi sezione Performance).\n\n### Log di build per variante fallita\n\n```bash\n# In locale\nfind build/ -name \"log-*.log\" | xargs ls -lt | head -10\n\n# In Jenkins\nfind /var/lib/jenkins/workspace/NinuxOpenwrt/build -name \"log-*.log\" \\\n  | xargs ls -lt | head -5\n```\n\n---\n\n## Licenza\n\nGPL-3.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fninuxorg%2Fansible-ninux-openwrt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fninuxorg%2Fansible-ninux-openwrt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fninuxorg%2Fansible-ninux-openwrt/lists"}