15 ottobre 2026 · aggiornato il 3 novembre 2026 · 13 min lettura
Sul mio pve ci sono 5 container LXC, tre accesi e due spenti, e una VM spenta, e dopo un po' di uso si vede quali impostazioni di Proxmox LXC contano davvero: cores impostato sempre, unprivileged lasciato attivo, nesting e keyctl attivati con criterio e backup=1 su ogni volume che vuoi ritrovare nel backup. Questa guida segue quell'ordine, dalla creazione al ripristino.
Cosa distingue un container LXC da una VM
Un container LXC su Proxmox condivide il kernel dell'host, mentre una VM ne ha uno proprio. Per questo il container parte in pochi istanti, occupa poca memoria e si salva con vzdump senza strumenti esterni, ma isola meno. Secondo la documentazione Proxmox, il kernel condiviso espone una superficie d'attacco, e le VM offrono un isolamento migliore.
La scelta fra le due strade ha già un post suo, VM vs LXC su Proxmox: quando scegliere, e qui non la ripeto. Parto dal presupposto che tu abbia deciso per il container e voglia configurarlo bene. La documentazione ufficiale dà una sola indicazione: per i casi che chiedono il massimo isolamento e la migrazione a caldo, nidificare i container dentro una VM QEMU resta una pratica raccomandata.
I container del mio lab sono servizi fidati e personali: un server Git, un gestore di password, un servizio di statistiche web, un ambiente di prova e un server di gioco. Per questo carico di lavoro il compromesso è accettabile. Per servizi esposti a utenti che non controlli, la valutazione cambia.
Creare il container dall'interfaccia web e dal template
Un container nasce da un template, cioè un'immagine di sistema già pronta che Proxmox scarica sul tuo storage. Dall'interfaccia web scarichi il template dallo storage, scegli Create CT in alto a destra e compili la procedura guidata schermata per schermata.
Apri lo storage che contiene i template, quindi la sezione CT Templates, e scarica il template della distribuzione che preferisci con il pulsante Templates.
Premi Create CT e nella scheda General imposta ID, nome host e password di root o chiave SSH. Lascia attiva la casella Unprivileged container.
Vaultwarden self-hosted in homelab: 7,4 MiB di RAM e zero compromessi
Vaultwarden self-hosted homelab: setup completo su Proxmox LXC con Caddy HTTPS, admin panel sigillato e backup testato. Sette decisioni motivate.
Nella scheda Template scegli quello appena scaricato.
Nella scheda Disks indica lo storage e la dimensione del disco di root.
Nella scheda CPU imposta il numero di core, in Memory la RAM e lo swap, in Network il bridge e l'indirizzo IP.
Controlla il riepilogo in Confirm e conferma.
La casella Unprivileged è attiva di default: la documentazione di pct dice che alla creazione il valore predefinito è 1. Non c'è motivo di toglierla per un servizio normale.
Creare il container da riga di comando con pct
Il comando pct fa dalla shell dell'host tutto ciò che fa l'interfaccia, ed è più comodo quando devi ricreare container simili o documentare cosa hai fatto. La sequenza è: aggiornare l'elenco dei template, scaricarne uno, creare il container.
bash
# Sul nodo Proxmox, come root
pveam update
pveam available --section system
pveam download <storage-template> <nome-template>
# Container come il 106 (Forgejo): 2 core, 1 GB di RAM, disco da 16 GB
pct create 106 <storage-template>:vztmpl/<nome-template> \
--hostname forgejo \
--cores 2 \
--memory 1024 \
--rootfs <storage-dischi>:16 \
--unprivileged 1 \
--features nesting=1 \
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
--onboot 1
pct start 106
I segnaposto da sostituire: <storage-template> è lo storage dove tieni i template, <nome-template> il nome del file mostrato da pveam available, <storage-dischi> lo storage dove vive il disco di root. La memoria è in megabyte e la dimensione del rootfs in gigabyte. Se metti una password o una chiave SSH con l'opzione apposita, evita di lasciarla nella cronologia della shell: preferisci la chiave pubblica.
Per l'indirizzo statico sostituisci ip=dhcp con ip=<indirizzo>/<prefisso>,gw=<gateway>. Se l'utente non è root o lo storage non è condiviso, le opzioni non cambiano: cambia solo dove il comando pesca il template.
Risorse: core, RAM, disco e mount point
Il valore da impostare per primo è cores, perché per impostazione predefinita un container può usare tutti i core disponibili dell'host, come dice la pagina del manuale di pct. Gli altri parametri hanno un ruolo diverso e vanno tenuti distinti.
cores — quanti core vedono e possono usare i processi del container
cpulimit — limite al tempo CPU complessivo, con default 0 (nessun limite)
cpuunits — peso relativo nella spartizione della CPU fra container, con default 100 su cgroup v2
memory — RAM in megabyte, con default 512
swap — swap in megabyte, con default 512
La differenza fra cores e cpulimit è la fonte della trappola che segue. In un vecchio thread del forum Proxmox, del 2017 e riferito alla versione 4, un membro dello staff di Proxmox spiega che cpulimit limita le prestazioni ma non riduce il numero di core assegnati. Non ho riverificato quel comportamento sulla versione che uso oggi: il dato è quindi un motivo per impostare cores esplicitamente, senza affidarsi a cpulimit.
Sul mio pve oggi ci sono questi container: il 106 con Forgejo (2 core, 1 GB di RAM, disco da 16 GB), il 131 con Vaultwarden in Docker dietro Caddy (1 core, 1 GB, 8 GB), il 140 con PostHog in Docker (10 core, 16 GB, 64 GB), il 110 con un Ubuntu di staging acceso solo per le prove e il 104 con il server Minecraft GTNH, spento. Le dimensioni sono state scelte a mano per ciascun servizio, e quelle di PostHog seguono i requisiti dichiarati dal produttore: secondo la pagina del self-hosting di PostHog, serve l'equivalente di una VM con 4 vCPU, 16 GB di RAM e più di 30 GB di spazio, e per le istanze self-hosted non c'è supporto clienti. Il 140 ha più core del minimo: 10 contro 4.
La prima trappola: i core visibili al worker di PostHog
Il worker di PostHog apre un processo per ogni core che vede nel container. Il meccanismo preciso non l'ho trovato in nessuna fonte ufficiale, quindi lo presento come osservazione diretta e non come regola documentata. La conseguenza pratica è che cores non è soltanto un limite per l'host: è anche il numero da cui un'applicazione dimensiona i propri processi.
Se non imposti cores, il container vede tutti i core dell'host e un software che ne apre uno per core ne apre troppi, e il consumo di RAM cresce con il numero di processi. La verifica richiede un comando solo:
bash
# Dal nodo Proxmox: quanti core vede il container 140
pct exec 140 -- nproc
# Per impostarli, a caldo o a freddo secondo il caso
pct set 140 --cores 10
Il valore di nproc dentro il container è il numero che il software legge. Verificalo dopo ogni modifica di cores, e prima di avviare servizi che dimensionano i processi sui core.
Mount point e disco extra
Oltre al disco di root puoi aggiungere altri volumi, detti mount point. Il caso del mio lab è il 104: il mondo del server Minecraft sta su un mount point da 24 GB, separato dal sistema. La pagina Backup and Restore dice che i mount point oltre al disco di root non sono inclusi nei backup per impostazione predefinita, e che si includono con l'opzione Backup. Funziona solo per i volumi gestiti dallo storage di Proxmox: bind mount e device mount non vengono mai salvati.
bash
# Aggiunge al container 104 un volume da 24 GB, incluso nei backup
pct set 104 -mp0 <storage-dischi>:24,mp=/srv/mondo,backup=1
<storage-dischi> è lo storage del volume e /srv/mondo il percorso dentro il container. Senza backup=1 il mondo di gioco resterebbe fuori da ogni backup, mentre il disco di sistema verrebbe salvato: è il tipo di dimenticanza che si scopre soltanto al momento del ripristino. Sul 104 l'opzione è attiva, quindi il mondo entra in ogni backup del container.
Unprivileged, nesting e keyctl: cosa attivare e quando
Un container unprivileged mappa il root del container su un utente senza privilegi dell'host. La wiki sui container non privilegiati descrive la mappatura degli UID: in genere root (uid 0) diventa l'uid 100000, l'uid 1 diventa 100001 e così via. Se il processo evade dal container, sull'host non ha i privilegi di root.
Sul mio pve tutti i container sono unprivileged con nesting=1. L'opzione keyctl=1 la attivo solo dove gira Docker, cioè sul 131 e sul 140. La documentazione di pct descrive il nesting come l'esposizione di procfs e sysfs per consentire container annidati. Che keyctl serva a Docker nei container unprivileged non l'ho letto nel testo ufficiale: il vincolo viene da un thread del forum che cita la documentazione, e la riga di configurazione che funziona è questa:
bash
# Container con Docker: unprivileged, nesting e keyctl
pct set 131 --features keyctl=1,nesting=1
Il nesting ha un costo: espone /proc e /sys dell'host al container, e le fonti sono divise su Docker dentro LXC. Un ex dipendente di Proxmox sul forum consiglia una VM per utenti non fidati, mentre un blog di un'azienda di servizi lo definisce "the worst of both worlds" perché gli accorgimenti necessari riducono l'isolamento. Le due posizioni concordano su un punto: il rischio dipende da chi usa il servizio.
Per i volumi condivisi in unprivileged, come una cartella NFS o un bind mount, servono mapping di UID e GID e le voci in /etc/subuid e /etc/subgid: la procedura sta nella stessa wiki, e la lascio lì.
Accesso al container e rete
Per entrare in un container hai tre strade, da quella che serve soltanto da emergenza a quella di tutti i giorni. La console dall'interfaccia web funziona anche con la rete rotta. Dalla shell dell'host pct enter apre una shell di root nel container, e pct exec esegue un singolo comando senza entrare. Per l'uso quotidiano il tuo accesso resta SSH, con la chiave pubblica.
bash
pct enter 106 # shell dentro il container
pct exec 106 -- systemctl status <servizio>
pct console 106 # console, esce con Ctrl+a q
<servizio> è l'unità systemd da controllare. Per la rete, il --net0 della creazione collega il container al bridge dell'host: con ip=dhcp l'indirizzo arriva dal tuo server DHCP, con un indirizzo statico lo decidi tu. Per un servizio a cui altri fanno riferimento, come Forgejo, l'indirizzo fisso o la prenotazione DHCP evita che cambi.
Per l'avvio ordinato, onboot ha default 0 e startup definisce l'ordine, con lo spegnimento nell'ordine inverso. Nel mio lab onboot=1 ce l'hanno solo i servizi che devono esserci sempre (Forgejo, Vaultwarden, PostHog): il 110 di staging ha l'avvio automatico spento e parte solo per le prove, e lo stesso vale per il 104 di Minecraft, che oggi è fermo.
Backup con vzdump su NFS
Il backup nativo dei container è vzdump, e funziona anche per gli LXC senza software aggiuntivo. Sul mio pve un job in Datacenter, sezione Backup, parte ogni notte alle 03:00 e scrive sullo storage NFS del NAS: modalità snapshot, compressione zstd, i container 106, 131 e 140 più la VM, e tiene gli ultimi cinque backup (keep-last=5). Il 104 ha un backup programmato a parte, sospeso finché il server resta spento, e lo staging non ha bisogno di backup: si ricrea dalla produzione. Secondo la pagina Backup and Restore i job sono salvati in /etc/pve/jobs.cfg, li esegue pvescheduler e gli orari usano la sintassi dei calendari di systemd.
Le dimensioni dei backup di una notte, sul mio NAS: Forgejo 1,10 GB, Vaultwarden 563 MB, PostHog 13,99 GB. PostHog pesa più di tutti gli altri, e il suo disco da 64 GB è anche il più grande; i tempi di un ripristino dipendono dalla dimensione del backup.
Per i container la documentazione elenca tre modalità: stop, suspend e snapshot. In modalità suspend vzdump usa rsync due volte e richiede spazio temporaneo, e con destinazione NFS o CIFS conviene puntare --tmpdir su un filesystem locale, perché la pagina parla di un miglioramento delle prestazioni di molte volte. La modalità snapshot richiede uno storage che gestisca gli snapshot. La compressione può essere lzo, gzip o zstd, e zstd è la più veloce perché usa più thread.
bash
# Backup manuale del container 106 sullo storage NFS
vzdump 106 --storage <storage-nfs> --mode snapshot --compress zstd
# Variante in modalità suspend con cartella temporanea locale
vzdump 106 --storage <storage-nfs> --mode suspend --tmpdir <cartella-locale>
# Conserva soltanto gli ultimi backup, nel job o da riga di comando
vzdump 106 --storage <storage-nfs> --prune-backups keep-daily=<n>,keep-weekly=<n>
I segnaposto: <storage-nfs> è lo storage NFS configurato in Proxmox, <cartella-locale> una directory su un disco locale con spazio sufficiente, <n> quanti backup giornalieri e settimanali vuoi conservare. La retention si regola con prune-backups, che accetta keep-last, keep-daily, keep-weekly e keep-monthly. Un job saltato perché l'host era spento non viene recuperato, salvo l'opzione Repeat missed.
C'è un limite da conoscere se pensi a strumenti di terzi: Veeam e NAKIVO fanno il backup delle VM di Proxmox, non dei container. Per Veeam lo dice la documentazione; per NAKIVO, che mi ha dato una licenza gratuita per blogger, la pagina sul backup di Proxmox parla solo di VM e template. L'ho provato ad aprile 2026: la procedura di backup non elencava nessun container, l'agente per le macchine fisiche installato dentro un LXC unprivileged non ha mai finito di censire i dischi, e NAKIVO mi ha confermato che i container non sono supportati. Per gli LXC la via resta vzdump, oppure Proxmox Backup Server: il confronto fra i tre è in Il miglior backup per Proxmox nel 2026.
La seconda trappola: /proc/uptime e l'avvio dei processi
Dentro un container /proc/uptime riporta il tempo di attività del container e non quello dell'host, mentre l'avvio dei processi è contato dal boot dell'host. È un'osservazione mia e i due numeri non coincidono, quindi un uptime letto nel container non basta a dire da quando gira un servizio.
Le fonti lo spiegano in parte. Proxmox usa LXCFS per dare ai container un /proc su misura, come dice la wiki sui Linux Container, e il README di LXCFS spiega che file come /proc/cpuinfo, /proc/meminfo, /proc/stat e /proc/uptime sono resi consapevoli del container: l'uptime dice da quanto gira il container, non l'host. L'avvio di ogni processo invece il kernel lo conta dal boot del sistema, come riporta la pagina di manuale di proc, e il kernel di un container è quello dell'host. Non ho seguito questo percorso riga per riga sulla mia versione di Proxmox, ma spiega lo scarto che vedo.
La regola pratica è dunque non ricavare l'età di un servizio da uptime e metriche lette dentro il container. Per sapere quando è ripartito, usa lo stato dell'unità (systemctl status) o l'orario nei log, che non dipendono da quale file ha letto il tempo di avvio. Per chi gestisce una flotta di container, in azienda o a casa, la stessa cautela vale per qualunque strumento di monitoraggio che calcola le durate dai contatori del kernel.