Vai al contenuto principale

#tutorial

Not only can you create powerful masks quickly in darktable, you can also reuse them in multiple modules, saving time and allowing you to apply differ

Altro...

Not only can you create powerful masks quickly in darktable, you can also reuse them in multiple modules, saving time and allowing you to apply different types of changes (e.g. exposure, color, or detail) to the same masked area. Let's look at some examples of how to reuse masks below:
https://avidandrew.com/reusing-masks.html

#photography #tutorial #opensource #artwithopensource #foss #fossart #canon #darktable #camera #linux #software #freesoftware #ford #car #classicCar

Reusing Masks on Multiple Modules in Darktable

#opensource #linux #freesoftware #software #tutorial #photography #darktable #camera #car #canon #artwithopensource #foss #classiccar #ford #fossart

0 0 1

Nginx e TLS: come ridurre TTFB e latenza con le impostazioni giuste

Il TTFB non dipende solo dall’applicazione: quanto costa davvero l’handshake TLSQuando un sito HTTPS risponde lentamente, il riflesso condizionato di

Altro...

Il TTFB non dipende solo dall’applicazione: quanto costa davvero l’handshake TLSQuando un sito HTTPS risponde lentamente, il riflesso condizionato di ogni sistemista è guardare al backend: query lente, cache assente, un’applicazione #PHP o .NET che non scala. Ma prima ancora che la richiesta arrivi al codice applicativo, il client e il server devono completare un handshake TLS, negoziare un protocollo, verificare un certificato ed eventualmente riprendere una sessione precedente. Ognuno di questi passaggi ha un costo in millisecondi, e su siti ad alto traffico o con molte connessioni “fredde” (nuovi visitatori, CDN edge miss, mobile su rete instabile) quel costo si somma in modo tutt’altro che trascurabile.

La buona notizia è che gran parte di questo overhead è governato da una manciata di direttive #Nginx che, se lasciate ai valori di default, non sono ottimizzate per la latenza. In questo articolo vediamo come intervenire in modo mirato su HTTP/2, HTTP/3, cache di sessione TLS, versioni del protocollo, cipher suite e OCSP stapling, con un occhio a cosa è davvero cambiato nel panorama TLS nel 2026 rispetto a configurazioni “storiche” che circolano ancora in molte guide.

HTTP/2 e HTTP/3: come attivarli correttamenteSu Nginx recente (1.25.1 e successivi) il supporto HTTP/2 non si attiva più come parametro del blocco listen, ma con una direttiva dedicata. La sintassi legacy listen 443 ssl http2; è deprecata e in alcune build genera un warning in fase di reload:

listen 443 ssl;
http2 on;Per chi vuole spingersi oltre, HTTP/3 (basato su QUIC, quindi su UDP anziché TCP) è supportato nativamente da Nginx 1.25.0 in poi:

listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic reuseport;
listen [::]:443 quic reuseport;
http2 on;
add_header Alt-Svc 'h3=":443"; ma=86400';L’header Alt-Svc non è opzionale: senza di esso il #browser non ha modo di sapere che il server parla anche HTTP/3, e continuerà a usare HTTP/2 anche se QUIC è configurato correttamente sul lato server. Va inoltre ricordato che molte reti aziendali e alcuni provider filtrano il traffico UDP sulla porta 443, quindi HTTP/3 va sempre trattato come miglioramento progressivo e non come sostituto esclusivo di HTTP/2.

Session cache e session ticket: evitare handshake completiOgni handshake TLS completo comporta uno scambio di chiavi asimmetrico, che è l’operazione più costosa dell’intero processo. La cache di sessione permette a un client che si riconnette di saltare questo passaggio:

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets on;Una cache condivisa da 10 MB memorizza circa 4.000 sessioni: per un sito a traffico medio è più che sufficiente, ma su cluster con più worker o più nodi Nginx dietro un load balancer va dimensionata in base al numero di client unici attesi nella finestra di ssl_session_timeout. Un dettaglio spesso trascurato: da Nginx 1.23.2 la gestione delle chiavi dei session ticket è stata migliorata, ma se si opera un’infrastruttura con più server dietro lo stesso load balancer, le chiavi di ticket vanno sincronizzate tra i nodi (tipicamente con ssl_session_ticket_key e un file condiviso via configuration management), altrimenti il beneficio della ripresa di sessione si perde ogni volta che il client finisce su un nodo diverso da quello dell’handshake iniziale.

Versioni del protocollo: perché TLS 1.3 non è solo “più sicuro”La direttiva sulle versioni supportate resta relativamente semplice:

ssl_protocols TLSv1.2 TLSv1.3;Il punto tecnico interessante è che TLS 1.3 non porta solo benefici di sicurezza (rimozione di cipher obsoleti, forward secrecy obbligatoria), ma anche di #performance pura: riduce l’handshake a un singolo round trip contro i due richiesti da TLS 1.2, e supporta la ripresa di sessione tramite un meccanismo (0-RTT/PSK) che rende le riconnessioni ancora più rapide. Per un client con RTT di rete di 80-100ms verso il server — scenario comune per utenti mobile o geograficamente distanti dal datacenter — il risparmio di un intero round trip si traduce direttamente in TTFB più basso.

Mantenere TLS 1.2 come fallback resta comunque prudente per compatibilità con client legacy (alcune librerie HTTP embedded, dispositivi #IoT, versioni datate di Android). Limitarsi al solo TLS 1.3 va considerato solo per ambienti controllati, come API interne o servizi machine-to-machine dove si conoscono con certezza i client.

Cipher suite: meno è meglio, con TLS 1.3Su TLS 1.2 la scelta delle cipher suite ha ancora impatto pratico:

ssl_prefer_server_ciphers off;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';Da notare l’impostazione ssl_prefer_server_ciphers off: con TLS 1.3 e i client moderni, lasciare che sia il client a scegliere la cipher (in base a cosa è accelerato via hardware sul suo dispositivo, ad esempio AES-NI vs ChaCha20 su mobile) è generalmente più efficiente che imporre l’ordine lato server.

Con TLS 1.3, però, le cipher suite sono fissate dal protocollo stesso: mantenere una lunga stringa ssl_ciphers personalizzata e una direttiva ssl_ecdh_curve manuale non porta quasi nessun beneficio aggiuntivo per le connessioni che negoziano TLS 1.3, e serve solo a coprire il fallback su TLS 1.2. Molte configurazioni “best practice” che circolano online sono più complesse del necessario proprio perché non tengono conto di questo aspetto.

OCSP stapling: un capitolo da riscrivere nel 2026Fino a poco tempo fa, l’OCSP stapling era una delle ottimizzazioni TLS più raccomandate: invece di far verificare al browser lo stato di revoca del certificato con una richiesta separata al CA, il server allega (“stapla”) una risposta OCSP firmata direttamente durante l’handshake, risparmiando un round trip:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/full_chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;Questo è un punto su cui molti sistemisti non sono ancora allineati: Let’s Encrypt ha dismesso il supporto OCSP nell’agosto 2025, passando esclusivamente a CRL (Certificate Revocation List) a corto ciclo di vita per la verifica di revoca. Se i certificati del vostro dominio provengono da Let’s Encrypt, le direttive sopra sono di fatto inerti: Nginx proverà a fare stapling ma non otterrà risposte valide, e conviene rimuoverle per tenere la configurazione pulita e i log privi di errori di risoluzione OCSP inutili. Se invece usate un CA diverso che continua a supportare OCSP, le direttive restano valide e utili.

Buffer TLS: un’ottimizzazione minore ma misurabilessl_buffer_size 4k;Il valore di default di Nginx per il buffer di invio TLS è 16k, pensato per massimizzare il throughput su trasferimenti di grandi dimensioni. Per il traffico HTTP tipico — pagine HTML, chiamate API, asset di dimensioni moderate — un buffer più piccolo (4k) riduce la quantità di dati che devono essere cifrati e trasmessi prima che il client possa iniziare a processare la risposta, con un guadagno tipico nell’ordine di 30-50ms sul TTFB. È un’ottimizzazione minore rispetto a HTTP/2 o al session caching, ma essendo a costo zero (nessun trade-off di sicurezza) vale la pena applicarla su siti dove il TTFB è una metrica critica.

Configurazione completa di riferimentoserver {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;

ssl_certificate     /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets on;
ssl_buffer_size 4k;

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" always;
add_header X-Frame-Options SAMEORIGIN always;
add_header X-Content-Type-Options nosniff always;

}Da personalizzare rimuovendo il blocco OCSP se il certificato proviene da Let’s Encrypt, e aggiungendo i blocchi listen ... quic reuseport; e l’header Alt-Svc se si vuole abilitare anche HTTP/3.

Cosa aspettarsi (e cosa no) da questa ottimizzazioneVale la pena essere chiari sui limiti: il tuning TLS non risolve un’applicazione lenta. Se il backend impiega 800ms per generare una risposta, risparmiare 50ms sull’handshake è un’ottimizzazione marginale rispetto al problema reale. Dove il tuning TLS fa davvero la differenza è nel ridurre l’overhead fisso presente su ogni richiesta HTTPS, in particolare per le connessioni “fredde” e per utenti con RTT di rete elevato — scenari in cui il costo dell’handshake può facilmente superare il tempo di elaborazione lato server. Caching applicativo, ottimizzazione del backend e CDN restano le leve principali per le performance complessive, ma un livello TLS ben configurato è la base su cui tutte le altre ottimizzazioni si appoggiano, ed è spesso trascurata proprio perché “funziona già” con i valori di default.

Articolo ispirato e approfondito a partire da: Nginx tuning tips: HTTPS/TLS – Turbocharge TTFB/Latency, LinuxBlog.io.

#howto #tutorial #nginx #tlsssl

0 0 1

Il filesystem /proc su Linux: la guida completa per il troubleshooting da sistemista

Ogni sistemista #Linux, prima o poi, si trova davanti a una domanda che top o free non riescono a risolvere del tutto: perché questo processo consuma

Altro...

Ogni sistemista #Linux, prima o poi, si trova davanti a una domanda che top o free non riescono a risolvere del tutto: perché questo processo consuma tanta memoria? Perché una porta risulta occupata ma netstat non mostra nulla? Perché un servizio continua a scrivere su un file che, in teoria, è stato cancellato? La risposta, quasi sempre, si trova in un posto che molti amministratori conoscono solo superficialmente: /proc.

/proc non è una directory come le altre. È un filesystem virtuale, di tipo procfs, generato e mantenuto interamente dal #kernel in memoria: non un singolo byte dei suoi contenuti risiede su disco. È, di fatto, una finestra live sullo stato interno del kernel, esposta attraverso strumenti che ogni sistemista già conosce: cat, grep, awk. Comandi come free, ps, top e iostat non fanno altro che leggere e formattare i dati che /proc mette a disposizione: imparare a leggerlo direttamente significa avere accesso alle stesse informazioni, ma senza filtri, e con la possibilità di combinarle in modi che nessun tool preconfezionato offre.

La struttura: due mondi in una directory/proc contiene sostanzialmente due categorie di contenuti. Da un lato le directory numerate, una per ogni processo in esecuzione (/proc/1234/, dove 1234 è il PID), che espongono lo stato specifico di quel processo. Dall’altro i file di sistema globali, come /proc/meminfo o /proc/cpuinfo, che riflettono lo stato del kernel nel suo complesso, indipendentemente da quale processo li legga.

I file di sistema che contano davvero/proc/cpuinfo e /proc/stat/proc/cpuinfo elenca i core logici della #CPU con modello, velocità di clock, dimensione della cache e i flag di supporto per estensioni come vmx (virtualizzazione hardware), aes e avx2. Un one-liner molto usato per contare le CPU logiche disponibili è:

grep -c '^processor' /proc/cpuinfo/proc/stat, invece, espone i contatori di tempo CPU aggregati e per singolo core, suddivisi in colonne: user, nice, system, idle, iowait, irq, softirq. Su un server sotto carico I/O-intensivo, tenere d’occhio la colonna iowait nel tempo è spesso più diagnostico di qualunque dashboard grafica, perché permette di isolare il momento esatto in cui la CPU comincia ad attendere lo storage invece di lavorare.

/proc/meminfo: oltre a “free”/proc/meminfo è la fonte dati grezza dietro al comando free, ma contiene molti più campi di quelli che free mostra normalmente. Due meritano attenzione particolare: MemAvailable, che indica la memoria realmente disponibile per nuovi processi tenendo conto della cache riclamabile (a differenza di MemFree, che è quasi sempre un numero fuorviante), e Dirty, che riporta quanta memoria contiene dati modificati ancora in attesa di essere scritti su disco — un valore che cresce pericolosamente su sistemi con storage lento e scritture intense.

Per un monitoraggio in tempo reale della pressione di memoria, questo comando è estremamente utile in fase di troubleshooting:

watch -n1 'grep -E "MemAvailable|Dirty|Writeback|SwapFree" /proc/meminfo'/proc/diskstats, /proc/loadavg, /proc/net//proc/diskstats fornisce le statistiche I/O per dispositivo — letture, scritture, settori trasferiti, tempo speso in operazioni — ed è la fonte dietro iostat. /proc/loadavg espone le tre celebri medie di carico a 1, 5 e 15 minuti, mentre /proc/uptime riporta i secondi trascorsi dal boot e il tempo cumulativo di inattività della CPU.

La sottodirectory /proc/net/ merita un capitolo a sé: /proc/net/dev contiene i contatori di byte e pacchetti per ogni interfaccia di rete, /proc/net/tcp e tcp6 elencano tutte le connessioni TCP attive in formato esadecimale, /proc/net/sockstat riassume l’utilizzo dei socket a livello di sistema, e /proc/net/snmp espone contatori SNMP utili per individuare retransmit e fallimenti di connessione anomali.

Il mondo per-processo: /proc/PID/Qui si trova la parte più preziosa per il debugging quotidiano. Alcuni file chiave:

/proc/PID/cmdline — il comando esatto con cui il processo è stato lanciato, con gli argomenti delimitati da byte null.

/proc/PID/status — un riepilogo leggibile con UID, GID, utilizzo di memoria e numero di thread. Il campo VmRSS indica la memoria residente effettivamente occupata, mentre VmSwap segnala se (e quanto) il processo è finito in #swap.

/proc/PID/fd/ — una directory di symlink, uno per ogni file descriptor aperto dal processo. È la base dati su cui si appoggia lsof. Contare i descrittori aperti è semplice: ls /proc/12345/fd | wc -l.

/proc/PID/io — la contabilità I/O del processo, con read_bytes e write_bytes che riflettono i dati effettivamente passati al layer di storage.

/proc/PID/maps e /proc/PID/smaps — le regioni di memoria mappate dal processo (codice, stack, heap, librerie condivise). smaps va oltre e fornisce, per ogni regione, i dettagli su RSS, PSS e swap.

/proc/PID/environ — le variabili d’ambiente al momento del lancio, anch’esse delimitate da byte null.

/proc/PID/cwd e /proc/PID/exe — symlink rispettivamente alla directory di lavoro corrente e all’eseguibile su disco. Sono fondamentali per identificare binari che sono stati cancellati o sostituiti mentre il processo era ancora in esecuzione (un classico segnale da cercare dopo un aggiornamento di sicurezza mal gestito).

/proc/PID/oom_score e oom_score_adj — il punteggio che l’OOM killer del kernel #usa per decidere quale processo terminare per primo in caso di esaurimento memoria. oom_score_adj, con un range da -1000 a 1000, permette di proteggere o “sacrificare” volontariamente un processo specifico.

Due scorciatoie tornano utili spesso: /proc/self/ punta sempre al processo che sta effettuando la lettura, mentre /proc/$$/ punta alla shell corrente all’interno di uno script.

Casi pratici di troubleshootingTrovare quale processo ha in ascolto una determinata porta (qui la porta 443/0x01BB su #IPv6), senza usare ss o lsof:

inode=$(awk '$2 ~ /:01BB$/ {print $10; exit}' /proc/net/tcp6)
ls -l /proc/*/fd/ 2>/dev/null | grep "socket:[$inode]"Individuare processi che tengono aperti file già cancellati — una causa classica di dischi che risultano pieni pur senza file visibili, perché lo #spazio non viene liberato finché il file descriptor resta aperto:

find /proc/*/fd -ls 2>/dev/null | grep '(deleted)'Ispezionare i contatori di interrupt per CPU, utile per diagnosticare squilibri di IRQ affinity su macchine multi-core:

cat /proc/interrupts | head -20/proc/sys e il tuning via sysctlSotto /proc/sys/ si trovano i file scrivibili che espongono i tunable del kernel — la stessa interfaccia usata da sysctl. Ad esempio, per modificare a caldo la propensione del kernel allo swap:

echo 10 | sudo tee /proc/sys/vm/swappinessTra i tunable più comuni: vm.swappiness (0-200, propensione allo swap), net.ipv4.ip_forward (abilitazione dell’IP forwarding), net.core.somaxconn (backlog massimo per i socket in ascolto) e fs.file-max (limite di file descriptor a livello di sistema). Ricordiamo che le modifiche fatte così sono volatili: per renderle permanenti serve intervenire su /etc/sysctl.conf o su un file in /etc/sysctl.d/.

/proc dentro i containerUn punto che genera spesso confusione: /proc è namespace-aware. Dentro un #container Docker, la directory mostra il namespace PID del container, non quello dell’host — il PID 1 visto dall’interno è l’entrypoint del container, non l’init dell’host. Attenzione però: campi come quelli di /proc/meminfo o /proc/stat spesso riflettono ancora i totali dell’host e non i limiti imposti dai cgroup al container, un dettaglio che ha tratto in inganno più di un tool di monitoring scritto ingenuamente.

/proc contro /sys: quando usare cosa/sys (sysfs) è il filesystem virtuale complementare a /proc, ma orientato al modello dei dispositivi del kernel: driver, bus, block device, gestione dell’energia. Un esempio tipico è /sys/devices/system/cpu/cpu0/cpufreq/, che espone i parametri di scaling della frequenza per singolo core. La regola pratica: /proc per processi e stato del kernel a livello di sistema, /sys per configurazione e stato dei dispositivi hardware.

ConclusioneConoscere /proc non è un esercizio accademico: è uno degli strumenti diagnostici più potenti a disposizione di un sistemista Linux, proprio perché sta sotto ogni tool di monitoring che si finisce per usare quotidianamente. Quando top, free o netstat non bastano — o semplicemente non sono installati sulla macchina compromessa o minimale su cui ci si trova a lavorare — sapere leggere direttamente /proc/meminfo, /proc/PID/status o /proc/net/tcp fa la differenza tra un troubleshooting rapido e ore perse a indovinare. Vale la pena tenere a portata di mano, come riferimento minimo, i file /proc/meminfo, /proc/cpuinfo, /proc/stat, /proc/net/dev e la struttura di /proc/PID/: coprono la stragrande maggioranza dei casi reali di debugging su sistemi in produzione.

Fonte originale: A Guide to Linux /proc Filesystem, LinuxBlog.io

#linux #guide #howto #tutorial

0 0 1

PHP-FPM in produzione: perché pm static batte dynamic e come calcolare pm.max_children

Chi gestisce uno stack LEMP o #LAMP in produzione conosce bene il dilemma: #PHP-FPM va lasciato “respirare” con un process manager dinamico, oppure co

Altro...

Chi gestisce uno stack LEMP o #LAMP in produzione conosce bene il dilemma: #PHP-FPM va lasciato “respirare” con un process manager dinamico, oppure conviene bloccare tutto su un numero fisso di worker? La risposta non è scontata, e sbagliarla ha un costo diretto in latenza durante i picchi di traffico. Vediamo perché, per molti carichi di lavoro, pm static è la scelta più solida — e come calcolare i parametri giusti senza affidarsi a numeri presi a caso da qualche post su Stack Overflow.

I tre process manager di PHP-FPMPHP-FPM gestisce i processi worker attraverso la direttiva pm nel file di pool (tipicamente /etc/php/8.x/fpm/pool.d/www.conf), che può assumere tre valori:

dynamic: il numero di processi figlio oscilla tra pm.min_spare_servers e pm.max_spare_servers, fino al tetto di pm.max_children. È il default su molte distribuzioni ed è pensato per bilanciare consumo di RAM e capacità di risposta.

ondemand: i processi vengono creati solo quando arriva una richiesta e vengono terminati dopo pm.process_idle_timeout secondi di inattività. Nessun worker “a riposo” occupa memoria, ma ogni nuovo processo comporta un fork che ha un costo in latenza.

static: il numero di worker è fissato esattamente a pm.max_children, tutti avviati all’avvio del servizio e mai terminati. Nessun fork a runtime, nessuna sorpresa.

La differenza pratica tra dynamic/ondemand e static si vede sotto carico: ogni volta che PHP-FPM deve forkare un nuovo processo per rispondere a un picco di richieste, quel fork costa tempo di #CPU e, sotto pressione, può accodare le richieste in ingresso nel socket backlog. Su un server che serve traffico costante e prevedibile, questo overhead è puro spreco.

Perché “dynamic” può ingannareIl process manager dinamico sembra la scelta “intelligente” perché si adatta al carico. In realtà introduce una variabile in più proprio nei momenti in cui non la vorresti: durante un picco di traffico, quando i worker spare non bastano più, PHP-FPM deve forkarne di nuovi mentre il sistema è già sotto stress. Il risultato è un aumento di latenza percepibile negli access log, spesso confuso con un problema del database o del codice applicativo quando in realtà è il process manager stesso a introdurre il collo di bottiglia.

Quando usare pm staticLa regola pratica è semplice: se il server ha traffico sostenuto e memoria sufficiente per tenere tutti i worker sempre attivi, static è la scelta giusta. Se invece si gestiscono più pool PHP-FPM su un host condiviso con memoria limitata (tipico di ambienti multi-tenant o hosting condiviso), ondemand resta preferibile perché libera RAM quando il traffico cala.

; /etc/php/8.3/fpm/pool.d/www.conf
pm = static
pm.max_children = 40
pm.max_requests = 1000
Da notare pm.max_requests: anche in modalità static conviene non lasciarlo a 0 (illimitato). Un valore alto — 1000 richieste è un buon punto di partenza — fa sì che ogni worker venga riciclato periodicamente, mitigando eventuali memory leak nelle librerie PHP senza introdurre l’overhead di respawn continui tipico della modalità dinamica.

Come calcolare pm.max_children senza indovinareIl valore corretto di pm.max_children dipende da quanta RAM è disponibile e da quanta ne consuma mediamente un singolo worker PHP-FPM — un dato che varia moltissimo in base al framework (un’app Symfony con Doctrine pesa parecchio di più di uno script #WordPress minimale).

Per misurare il consumo medio reale dei worker già in esecuzione:

ps --no-headers -o rss -C php-fpm8.3 | awk '{ sum += $1; n++ } END { print sum/n/1024 " MB" }'Questo comando interroga la RSS (Resident Set Size) di tutti i processi php-fpm attivi e ne calcola la media in MB. Con quel numero in mano, la formula diventa:

pm.max_children = (RAM dedicata a PHP-FPM in MB) / (RSS medio per worker in MB)Ad esempio, su un server con 6 GB di RAM riservati al pool PHP-FPM e worker che consumano in media 60 MB ciascuno:

6000 MB / 60 MB ≈ 100 workerÈ fondamentale non allocare a PHP-FPM tutta la RAM disponibile sulla macchina: bisogna lasciare margine per il sistema operativo, il #web server (#Nginx o Apache in front-end), la cache degli oggetti (Redis/Memcached) e, se presente sullo stesso host, il database. Una regola prudente è dedicare a PHP-FPM non più del 60-70% della RAM totale su un server dedicato al solo stack web.

Monitoraggio continuo, non solo calcolo una tantumIl consumo medio per worker cambia nel tempo — un deploy che introduce una libreria pesante, una query N+1 che gonfia il footprint di memoria, o semplicemente un aumento del traffico su endpoint più complessi. Vale la pena schedulare periodicamente il comando ps sopra (ad esempio via cron con output su un file di log, oppure integrandolo in un dashboard di monitoring come Netdata o Prometheus con node_exporter) per verificare che il valore di pm.max_children resti coerente con la realtà, invece di scoprirlo durante un incidente in produzione.

Un altro segnale da tenere d’occhio è il log di PHP-FPM stesso: se compaiono righe del tipo

WARNING: [pool www] server reached pm.max_children setting (40), consider raising itsignifica che il tetto è stato raggiunto e le richieste in eccesso stanno finendo in coda sul socket, con conseguente aumento del tempo di risposta. È il segnale più diretto per capire se il dimensionamento fatto a tavolino regge davvero sotto carico reale.

ConclusioneNon esiste un process manager “giusto” in assoluto: la scelta dipende dal profilo di traffico e dalla disponibilità di memoria. Ma per la maggior parte dei server di produzione con traffico prevedibile e risorse dedicate, pm static abbinato a un pm.max_children calcolato sul consumo reale di RSS — e non copiato da un #tutorial generico — elimina una fonte di latenza spesso invisibile finché non arriva il picco di traffico che la rende evidente. Vale la pena rivedere la configurazione dei propri pool PHP-FPM con questo approccio, misurando prima di decidere.

Fonte: LinuxBlog.io — PHP-FPM tuning: Using ‘pm static’ for max performance

#linux #guide #howto #tutorial #performance #php

0 0 1

Agent Plugins 1.0: lo standard che rende portabili skill e server MCP tra VS Code, Copilot CLI e SDK

Il problema che Agent Plugins 1.0 prova a risolvereChi lavora quotidianamente con #GitHub #Copilot conosce bene la frammentazione degli ultimi due ann

Altro...

Il problema che Agent Plugins 1.0 prova a risolvereChi lavora quotidianamente con #GitHub #Copilot conosce bene la frammentazione degli ultimi due anni: skill scritte per VS Code che non funzionano su Copilot CLI, configurazioni #MCP duplicate tra client diversi, agenti custom da ricostruire da zero ogni volta che si cambia strumento. Con Agent Plugins 1.0, annunciato a metà agosto 2026, GitHub prova a chiudere questa frammentazione introducendo uno standard aperto — non un formato proprietario — per pacchettizzare skill e server MCP in un plugin installabile una sola volta e utilizzabile su più superfici: VS Code, Copilot CLI, Copilot SDK, l’app Copilot e il coding agent #cloud.

È un cambio di prospettiva interessante anche per chi non #usa Copilot come strumento principale: la specifica Agent Plugins non è un’invenzione isolata, ma converge con formati simili già visti in altri ecosistemi (Claude, OpenPlugin), e questo la rende rilevante per chiunque costruisca strumenti per agenti AI, non solo per i team Microsoft/GitHub.

Anatomia di un Agent PluginUn plugin conforme allo standard 1.0 è una directory con una struttura riconoscibile. Il file centrale è plugin.json, che dichiara esplicitamente lo schema a cui aderisce:

{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "my-dev-tools",
"description": "Utility per lo sviluppo React",
"version": "1.2.0"
}I soli campi obbligatori sono $schema e name; tutto il resto (version, description, author, homepage, repository, license, keywords) è opzionale ma consigliato per la pubblicazione su un marketplace.

Attorno al manifest, la struttura tipica di un plugin più completo è questa:

my-testing-plugin/
plugin.json # Metadati del plugin
skills/
test-runner/
SKILL.md # Istruzioni della skill
run-tests.sh # Script di supporto
agents/
test-reviewer.agent.md # Agente custom (client-specific)
hooks/
hooks.json # Configurazione hook (client-specific)
scripts/
validate-tests.sh
.mcp.json # Definizione dei server MCPLa distinzione più importante per chi progetta un plugin è tra componenti portabili e componenti client-specific:

Portabili (parte dello standard 1.0): server MCP (integrazioni con tool esterni) e skill, cioè istruzioni, script e risorse caricate on-demand dall’agente.

Client-specific (solo VS Code, ad esempio): agenti custom con personalità e configurazione tool dedicata, hook che eseguono comandi shell in punti precisi del ciclo di vita dell’agente, e slash command richiamabili in chat con /.

Questa separazione è la vera innovazione pratica: uno stesso plugin può portare le sue skill e i suoi server MCP ovunque, mentre le personalizzazioni specifiche di un client restano lì dove hanno senso, senza rompere la compatibilità altrove.

Configurare i server MCP dentro un pluginI server MCP si dichiarano in .mcp.json (o mcp.json), con variabili d’ambiente che il runtime dell’agente risolve automaticamente al momento del caricamento:

{
"mcpServers": {
"plugin-database": {
"command": "${PLUGIN_ROOT}/servers/db-server",
"args": ["--config", "${PLUGIN_ROOT}/config.json"],
"env": {
"DB_PATH": "${PLUGIN_ROOT}/data"
}
}
}
}La variabile ${PLUGIN_ROOT} punta sempre alla directory del plugin installato, indipendentemente da dove l’utente finale lo abbia scaricato — un dettaglio che elimina un’intera classe di bug legati a percorsi assoluti hardcoded nei plugin distribuiti da terze parti.

Hook: automazioni sul ciclo di vita dell’agentePer i client che supportano questa estensione (il formato è compatibile con la sintassi già nota da Claude), gli hook permettono di agganciare comandi shell a eventi specifici, ad esempio dopo l’uso di un tool:

{
"hooks": {
"PostToolUse": [
{
"type": "command",
"command": "${PLUGIN_ROOT}/scripts/format.sh"
}
]
}
}Un caso d’uso concreto: formattare automaticamente il codice generato dall’agente subito dopo ogni modifica a un file, senza dover ricordare di lanciare il linter manualmente.

Migrare un plugin Copilot esistenteChi ha già plugin Copilot “vecchio formato” non deve riscrivere nulla da zero. GitHub descrive un percorso di migrazione minimo:

Aggiungere il campo $schema al plugin.json esistente, puntandolo allo schema Agent Plugins 1.0.

Mantenere le skill dove sono già, sotto skills/.

Spostare i file specifici di Copilot (agenti, comandi, regole, hook, canvas) dentro una directory dedicata com.github.copilot/, così da separarli chiaramente dalla parte portabile.

I plugin GitHub Copilot esistenti restano comunque supportati senza obbligo di migrazione: è un aggiornamento incrementale, non un breaking change forzato.

Governance aziendale: managed-settings.jsonPer i team enterprise, probabilmente l’aspetto più rilevante non è la portabilità in sé ma il controllo centralizzato che ne deriva. Il file managed-settings.json permette di definire una baseline aziendale su cosa è installabile:

{
"extraKnownMarketplaces": {
"company-tools": {
"source": { "source": "github", "repo": "vostra-org/plugin-marketplace" }
}
},
"enabledPlugins": {
"code-formatter@company-tools": true
}
}Tre leve principali:

enabledPlugins — installa automaticamente o blocca esplicitamente plugin specifici per tutti gli utenti gestiti.

extraKnownMarketplaces — aggiunge marketplace interni oltre a quelli pubblici di default.

strictKnownMarketplaces — se attivato, limita l’installazione ai soli marketplace esplicitamente autorizzati, impedendo l’uso di sorgenti non gestite.

Le impostazioni enterprise agiscono come baseline additiva: i team possono comunque aggiungere plugin approvati sopra la configurazione centrale, senza però poter aggirare i blocchi imposti a livello organizzativo. Per chi gestisce flotte di sviluppatori con policy di sicurezza stringenti, è la differenza tra “confidare che ognuno installi solo cose sicure” e avere un controllo verificabile.

Dove si installano i pluginIl canale di scoperta di default è l’Awesome Copilot marketplace, disponibile fin da subito in VS Code, Copilot CLI e nell’app Copilot. Per plugin locali o in sviluppo, VS Code offre una registrazione esplicita via impostazioni:

"chat.pluginLocations": {
"/percorso/al/mio-plugin": true,
"/percorso/a/un-altro-plugin": false
}Un dettaglio utile in fase di debug: se un plugin non viene rilevato, vale la pena controllare che chat.plugins.enabled sia attivo, che il nome nel manifest sia in kebab-case (obbligatorio per lo standard 1.0), e — per problemi di installazione persistenti — ripulire la cache locale in ~/.config/Code/agentPlugins/ su #Linux.

ConclusioneAgent Plugins 1.0 non introduce funzionalità radicalmente nuove rispetto a quello che skill e server MCP già facevano singolarmente: il suo valore è nella standardizzazione del confezionamento e nella governance che ne deriva. Per un team che sviluppa strumenti interni per i propri agenti AI — che siano skill per il debug, integrazioni con sistemi proprietari via MCP, o automazioni sul ciclo di vita dell’agente — poter scrivere il plugin una sola volta e vederlo funzionare su CLI, editor e SDK senza riscritture è un risparmio di manutenzione concreto, non solo un dettaglio architetturale. Vale la pena tenerlo d’occhio anche per chi non usa Copilot: essendo uno standard aperto, è probabile che altri agent tool ne adottino la compatibilità nei prossimi mesi.

Fonte: Agent Plugins 1.0 in VS Code, Copilot CLI, and the Copilot app — GitHub Changelog

#vscode #howto #tutorial #net #copilot

0 0 1

DNS su Linux: la guida completa a resolv.conf, systemd-resolved e troubleshooting con dig e getent

Perché la risoluzione DNS su Linux è più complicata di quanto sembriChiunque amministri server #Linux prima o poi si scontra con il fastidioso “Tempor

Altro...

Perché la risoluzione DNS su Linux è più complicata di quanto sembriChiunque amministri server #Linux prima o poi si scontra con il fastidioso “Temporary failure in name resolution” o con un #DNS che risolve alcuni domini e non altri. La causa quasi sempre non è il DNS in sé, ma la catena di componenti che sta tra un comando come curl e la vera query verso un nameserver: /etc/nsswitch.conf, /etc/resolv.conf, e — sulle distribuzioni moderne — systemd-resolved o #NetworkManager che gestiscono tutto al posto nostro, spesso silenziosamente.

In questo articolo ricostruiamo l’intera catena di risoluzione dei nomi su Linux, i comandi giusti per ispezionarla e un metodo pratico per isolare il problema in pochi minuti, invece di procedere per tentativi.

L’ordine di risoluzione: nsswitch.confIl primo file da guardare non è resolv.conf, ma /etc/nsswitch.conf. La riga che interessa è quella che inizia con hosts:, tipicamente:

hosts: files dns myhostnameQuesto significa che il sistema consulta prima /etc/hosts (voce files), poi il DNS, e infine risolve il proprio hostname locale. Se un dominio dovrebbe risolvere correttamente ma non lo fa, e in /etc/hosts c’è una voce residua o sbagliata, il DNS non c’#entra affatto: la query non arriva nemmeno a un resolver.

Chi gestisce davvero /etc/resolv.confSulle distribuzioni Linux di qualche anno fa, /etc/resolv.conf era un file statico che si editava a mano. Da #Ubuntu 18.04 in poi, e su gran parte delle distribuzioni moderne (Fedora, molte immagini #cloud di Debian/RHEL), quel file è generato dinamicamente — modificarlo a mano spesso non produce alcun effetto persistente, perché viene sovrascritto al prossimo evento di rete.

Il modo più veloce per capire chi ha il controllo è guardare cosa punta il file:

ls -la /etc/resolv.confSe è un file regolare, probabilmente la configurazione è statica.

Se è un symlink verso /run/systemd/resolve/stub-resolv.conf, il sistema #usa #systemd-resolved.

Se punta a /run/NetworkManager/resolv.conf, è NetworkManager a gestire il DNS.

Sapere quale dei due componenti è “al comando” evita l’errore più comune: editare resolv.conf a mano, vederlo funzionare per pochi secondi, e poi ritrovarsi la modifica cancellata al riavvio dell’interfaccia di rete.

Il formato di resolv.confnameserver 1.1.1.1
nameserver 8.8.8.8
search example.com
options ndots:5Alcuni dettagli spesso ignorati ma rilevanti in produzione:

nameserver — Linux ne considera al massimo tre; gli altri vengono ignorati.

search — suffisso di dominio aggiunto automaticamente a hostname “corti” (senza punti o con pochi punti).

options ndots:5 — controlla quando un nome viene considerato “già qualificato” e quando invece riceve il suffisso di search. È un parametro che in ambienti #Kubernetes causa non pochi grattacapi, perché una query con pochi punti può generare fino a 5 lookup DNS prima di andare a buon fine.

systemd-resolved: il resolver locale che (quasi) nessuno vedeSulla maggior parte delle distribuzioni moderne, le query DNS delle applicazioni non vanno direttamente a #Internet: passano per un listener locale su 127.0.0.53:53, gestito da systemd-resolved, che si occupa di caching e — dove configurato — di DNSSEC. Lo strumento per interagirci è resolvectl.

Stato completo per interfaccia

resolvectl status

Query esplicita tramite systemd-resolved

resolvectl query esempio.it

Svuotare la cache (utile dopo un cambio DNS o un test)

sudo resolvectl flush-caches

Statistiche su cache hit/miss

resolvectl statisticsPer impostare server DNS validi per l’intero sistema, indipendentemente dall’interfaccia attiva, si edita /etc/systemd/resolved.conf:

[Resolve]
DNS=1.1.1.1 1.0.0.1
FallbackDNS=8.8.8.8 8.8.4.4e si riavvia il servizio:

sudo systemctl restart systemd-resolveddig, getent e la differenza che fa risparmiare ore di debugIl tool principale per interrogare direttamente un server DNS è dig (pacchetto dnsutils su Debian/Ubuntu, bind-utils su Fedora/RHEL):

dig esempio.it
dig @8.8.8.8 esempio.it # interroga un resolver specifico
dig esempio.it MX # record di posta
dig esempio.it AAAA # IPv6
dig esempio.it NS # nameserver autoritativi
dig -x 104.21.1.1 # reverse lookup
dig +short esempio.it # output compatto
dig +trace esempio.it # ricostruisce l'intera catena, dai root server in giù
dig +dnssec esempio.it # verifica la firma DNSSECIl punto chiave, spesso sottovalutato: dig ignora completamente /etc/nsswitch.conf e /etc/hosts. Parla direttamente con un server DNS. Questo lo rende perfetto per isolare i problemi, ma pericoloso se usato come unico strumento diagnostico: dig può funzionare perfettamente mentre l’applicazione continua a fallire, perché il problema è nel percorso NSS (Name Service Switch), non nel DNS.

Per replicare esattamente quello che fa un’applicazione, si usa getent:

getent hosts esempio.itSe dig funziona ma getent no, il problema non è di rete: è nella configurazione NSS, in /etc/hosts, o nel modulo myhostname. È una distinzione che vale la pena memorizzare, perché sposta immediatamente l’indagine nella direzione giusta.

Un metodo, non solo comandi: la checklist di troubleshootingDi fronte a un errore di risoluzione, seguire un ordine preciso evita di girare a vuoto:

Controllare che /etc/resolv.conf contenga un nameserver valido e capire chi lo gestisce (ls -la).

Verificare che /etc/nsswitch.conf includa dns nella riga hosts.

Testare un resolver pubblico direttamente: dig @1.1.1.1 google.com. Se funziona, la rete verso l’esterno è a posto.

Testare il resolver locale: dig google.com. Se qui fallisce ma il passo precedente no, il problema è nella configurazione locale (systemd-resolved, NetworkManager, o un resolver aziendale irraggiungibile).

Controllare lo stato del servizio: systemctl status systemd-resolved.

Guardare gli assegnamenti DNS per interfaccia con resolvectl status — particolarmente utile in scenari con VPN e split-DNS.

Svuotare la cache con resolvectl flush-caches se si sospettano record stale.

Confrontare dig e getent: se divergono, il problema è nel percorso NSS.

Per fallimenti persistenti e inspiegabili, dig +trace ricostruisce l’intera catena di delega dai root server fino all’autoritativo, rivelando problemi come delegazioni NS rotte o glue record mancanti.

Split-DNS e VPN: un caso che confonde moltiCon una VPN aziendale attiva, resolvectl status mostra a quale interfaccia è associato ciascun dominio DNS. Se il dominio associato al link VPN è ~., quell’interfaccia diventa la route DNS predefinita per tutte le query. Se invece è qualcosa come ~interna.azienda.it, solo le query per quel dominio specifico vengono instradate sul tunnel — le altre continuano a passare per il resolver pubblico. Non riconoscere questa differenza è una causa frequente di “il sito interno non si risolve, ma internet funziona” o viceversa.

Fissare un DNS statico senza che venga sovrascrittoSu sistemi gestiti da NetworkManager, il modo corretto non è editare resolv.conf ma dire a NetworkManager di non sovrascrivere le impostazioni manuali:

nmcli con mod "Wired connection 1" ipv4.dns "1.1.1.1 8.8.8.8"
nmcli con mod "Wired connection 1" ipv4.ignore-auto-dns yes
nmcli con up "Wired connection 1"Su sistemi con systemd-resolved, la via pulita è impostare DNS= e FallbackDNS= in resolved.conf, come visto sopra. Solo come ultima risorsa — ad esempio su container minimali senza questi servizi — ha senso rendere resolv.conf immutabile:

sudo chattr +i /etc/resolv.conf # blocca il file
sudo chattr -i /etc/resolv.conf # sblocca per un aggiornamento futuroQuale resolver sceglierePer server in produzione, affidarsi al solo router di casa/ufficio è rischioso: se il router si blocca o si riavvia, cade anche la risoluzione DNS di tutti i servizi a valle. Tra i resolver pubblici più usati in ambito professionale: Cloudflare (1.1.1.1 / 1.0.0.1, orientato a bassa latenza e privacy), Google (8.8.8.8 / 8.8.4.4, rete anycast molto ridondata) e Quad9 (9.9.9.9, che filtra domini noti per malware già a livello di resolver).

ConclusioneLa risoluzione DNS su Linux non è un singolo componente ma una catena — NSS, resolv.conf, systemd-resolved o NetworkManager, e infine il resolver remoto. La maggior parte dei problemi “misteriosi” si risolve rapidamente se si segue la catena nell’ordine giusto invece di riavviare servizi a caso. Tenere a mente la differenza tra dig (parla direttamente col DNS) e getent (replica il percorso reale delle applicazioni) è probabilmente il singolo accorgimento che fa risparmiare più tempo in debug.

Fonte: Linux Nameservers and DNS Resolution — LinuxBlog.io

#linux #howto #tutorial #dns

0 0 1

WebMCP: come i siti web espongono strumenti agli agenti AI, spiegato con Cloudflare Browser Run

Il problema degli agenti AI che “guardano” il browserChi ha provato a far navigare un agente AI su un sito #web sa quanto sia fragile il paradigma att

Altro...

Il problema degli agenti AI che “guardano” il browserChi ha provato a far navigare un agente AI su un sito #web sa quanto sia fragile il paradigma attuale: screenshot della pagina, #analisi visiva per capire dove cliccare, simulazione del click, nuovo screenshot per verificare cosa è successo, e via così ad ogni passaggio. Funziona, ma è lento, costoso in token e si rompe alla prima modifica del layout o al primo elemento che carica in ritardo. È lo stesso problema che affligge da anni gli script di web scraping tradizionali, solo applicato ad agenti che devono anche “capire” cosa stanno guardando.

WebMCP (Web Model Context Protocol) nasce per rovesciare questo approccio: invece di far indovinare all’agente dove cliccare, è il sito stesso a dichiarare quali azioni sono disponibili, con che parametri, e come invocarle direttamente in codice. #Cloudflare ha da poco reso disponibile il supporto sperimentale a WebMCP nella sua piattaforma #Browser Run, un’occasione utile per capire come funziona davvero questo standard ancora in bozza.

Cos’è WebMCP e chi lo sta sviluppandoLa proposta iniziale è stata pubblicata nell’agosto 2025 da ingegneri di Microsoft e #Google, e oggi è portata avanti principalmente dal team #Chrome come bozza sperimentale — non è ancora uno standard web consolidato, ma è già implementabile e testabile in Chrome beta. L’idea centrale è una nuova API del browser, navigator.modelContext, che qualsiasi pagina web può usare per registrare “tool” strutturati, nello stesso spirito del Model Context Protocol usato da Claude e altri assistenti per esporre funzionalità a un LLM — solo che qui il “server” #MCP è JavaScript in esecuzione lato pagina, e l’host è il browser stesso.

navigator.modelContext.registerTool({
name: "scroll_to_section",
description: "Scorre la pagina fino a una sezione specifica",
inputSchema: {
type: "object",
properties: { id: { type: "string" } },
required: ["id"]
},
async execute({ id }) {
document.getElementById(String(id))?.scrollIntoView({ behavior: "smooth" });
return "ok";
}
});Un agente che visita la pagina può interrogare l’elenco dei tool disponibili in un dato momento — che cambia dinamicamente in base allo stato della pagina — ed eseguirli con parametri tipizzati, invece di simulare interazioni DOM.

Provarlo con Cloudflare Browser RunCloudflare ha aggiunto un pool sperimentale di sessioni browser con Chrome beta (dove WebMCP è disponibile) alla sua piattaforma Browser Run, separato dal pool di produzione che resta su Chrome stabile. Per avviare una sessione di test basta la CLI wrangler:

assicurarsi di avere l'ultima versione di wrangler

npm i -g wrangler@latest

creare una sessione browser "lab" con keep-alive di 5 minuti

wrangler browser create --lab --keepAlive 300Dalla console DevTools della sessione si può interrogare direttamente l’elenco dei tool esposti da un sito che implementa WebMCP (Cloudflare fornisce come demo pubblica una finta catena di hotel):

navigator.modelContextTesting.listTools();
// [
// { "name": "view_hotel", "description": "...", "inputSchema": "..." },
// { "name": "search_location", "description": "...", "inputSchema": "..." },
// { "name": "lookup_amenity", "description": "...", "inputSchema": "..." }
// ]Eseguire un tool è altrettanto diretto:

await navigator.modelContextTesting.executeTool(
"search_location",
JSON.stringify({ query: "Paris" })
);Un dettaglio interessante per chi progetta flussi che coinvolgono azioni sensibili (pagamenti, prenotazioni, conferme): la specifica prevede nativamente lo human-in-the-loop. Un tool come complete_booking può sospendere l’esecuzione in attesa che l’utente confermi manualmente un’azione nell’interfaccia, prima di restituire il risultato all’agente.

Collegare un agente AI realePer far interagire un vero agente con siti WebMCP, Cloudflare consiglia di appoggiarsi a Chrome DevTools MCP, configurabile in client come Claude Code o Cursor puntando al WebSocket endpoint della sessione lab:

{
"browser-rendering-cdp": {
"command": [
"npx", "-y", "chrome-devtools-mcp@latest",
"--wsEndpoint=wss://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/browser-rendering/devtools/browser?keep_alive=600000&lab=true",
"--wsHeaders={"Authorization":"Bearer <CLOUDFLARE_API_TOKEN>"}"
]
}
}Il parametro lab=true è ciò che instrada la connessione verso una sessione con WebMCP abilitato invece che verso il pool di produzione standard.

Il lato server: esporre i tool di un Worker al browserPer chi già costruisce agenti su Cloudflare Workers usando McpAgent, il pacchetto agents include un adapter sperimentale, registerWebMcp, che fa da ponte tra i tool esposti da un server MCP remoto e il registro navigator.modelContext della pagina:

import { registerWebMcp } from "agents/experimental/webmcp";

const handle = await registerWebMcp({
url: "/mcp",
prefix: "remote.",
getHeaders: async () => ({ Authorization: Bearer ${await getToken()} })
});L’adapter scopre i tool del server (tools/list), li registra come shim locali il cui execute inoltra la chiamata al server via client.callTool(), e si mantiene sincronizzato ascoltando le notifiche tools/list_changed. Il risultato pratico è una separazione naturale: tutto ciò che riguarda il DOM (scorrimento, focus, clipboard, stato locale in Zustand o IndexedDB) resta tool in-page; tutto ciò che richiede storage durevole, credenziali segrete o chiamate a API di terze parti resta lato server, ma diventa comunque visibile e invocabile dall’AI del browser attraverso lo stesso registro.

Cosa considerare prima di adottarloVale la pena essere chiari sulla maturità dello standard: le API navigator.modelContext e navigator.modelContextTesting funzionano oggi solo in sessioni Chrome beta o “lab”, non in produzione stabile, e sia la specifica sia l’adapter di Cloudflare sono etichettati esplicitamente come sperimentali, soggetti a modifiche non retrocompatibili. Sul fronte sicurezza, esporre tool strutturati a un agente terzo significa anche esporre una superficie potenzialmente sfruttabile — collisioni di nomi tra tool silenziose, o un agente compromesso che invoca un tool con parametri malevoli, sono scenari da considerare al pari di qualsiasi altra API pubblica. Per chi sviluppa siti pensati per essere “agent-friendly” — e-commerce, prenotazioni, dashboard SaaS — è comunque il momento giusto per iniziare a sperimentare, prima che il pattern diventi lo standard de facto per l’interazione tra agenti AI e web.

ConclusioneWebMCP propone un cambio di paradigma sensato: far dichiarare alle applicazioni web le proprie capacità in modo strutturato, invece di costringere gli agenti AI a reverse-engineering visivo dell’interfaccia. Non è ancora pronto per la produzione, ma la direzione — supportata sia da Google sia da Microsoft, e ora testabile concretamente su Cloudflare Browser Run — merita di essere seguita da chi sviluppa applicazioni web che prima o poi dovranno “parlare” anche con un agente, non solo con un umano davanti a un browser.

Fonte: Cloudflare Browser Run Docs – WebMCP e Cloudflare Agents – WebMCP adapter

#ai #chrome #tutorial #web #mcp

0 0 1

Claude Code: le sessioni ora comunicano tra loro (ma non su Windows)

Con la versione 2.1.224, rilasciata la prima settimana di agosto 2026, Claude Code introduce la messaggistica tr

Altro...

Con la versione 2.1.224, rilasciata la prima settimana di agosto 2026, Claude Code introduce la messaggistica tra sessioni: due o più istanze del CLI, avviate in terminali diversi, possono ora scambiarsi messaggi di testo senza che sia l’utente a fare da tramite copiando e incollando contesto da un terminale all’altro. È una funzionalità pensata per chi lavora abitualmente con più sessioni parallele su worktree diversi dello stesso repository, e merita attenzione anche solo per capire come configurarla in modo sicuro in un contesto aziendale.

Il problema che risolveChi #usa Claude Code su progetti complessi finisce spesso per aprire più terminali: uno per il lavoro principale, uno per un hotfix urgente, uno per un refactoring in un worktree separato. Fino a v2.1.223 l’unico modo per far sapere a una sessione cosa stava succedendo in un’altra era manuale: copiare un riassunto, incollarlo, ripetere il contesto. La messaggistica cross-session automatizza esattamente questo passaggio.

Due strumenti nuovi: ListAgents e SendMessageClaude Code espone due tool interni che il modello usa autonomamente, senza che l’utente li invochi direttamente:

ListAgents individua le sessioni raggiungibili: subagent nella sessione corrente, altre sessioni locali sulla stessa macchina (incluse quelle in background) e sessioni remote se è attiva la Remote Control.

SendMessage consegna un messaggio di testo a una sessione specifica, identificata per nome.

Il messaggio non è mai la cronologia della conversazione né un file: è un testo che una Claude scrive per un’altra Claude. Per spostare davvero un intero contesto conversazionale tra terminali resta lo strumento giusto il resume di sessione, non la messaggistica.

Per vedere quali sessioni sono raggiungibili basta lanciare, in un terminale con Claude Code attivo:

/list-agentsIl comando elenca ogni sessione con il nome a cui risponde (derivato dalla cartella di lavoro, oppure impostato con /rename o il flag --name), utile per distinguere sessioni omonime che girano in directory diverse.

Come si usa in praticaNon si compone il messaggio a mano: si dice a Claude cosa si vuole che l’altra sessione sappia, ed è Claude a scrivere il riassunto effettivo. Due esempi di prompt tipici:

Chiedi alla sessione nell'altro terminale se la migrazione è terminataSpiega alla sessione che lavora sulle API di pagamento cosa abbiamo appena cambiatoNel secondo caso il contenuto esatto del messaggio varia: è Claude a decidere come riassumere il lavoro fatto. Quando il messaggio arriva, compare nella conversazione della sessione ricevente con il nome del mittente, e viene compattato in una riga Message from che si espande con Ctrl+O.

Dove viaggia il messaggioIl percorso dipende da dove gira la sessione di destinazione:

Stessa macchina: il messaggio passa attraverso un socket per-sessione, mai attraverso i server Anthropic. In questo caso sono possibili sia nuovi messaggi sia risposte.

Altra macchina dell’utente: il messaggio passa dai server Anthropic e arriva tramite la connessione Remote Control di quella macchina. Da qui è possibile solo rispondere, non avviare una conversazione.

Claude Code on the #web: stesso discorso, solo risposte.

Ogni sessione si registra su disco e apre un proprio “inbox socket”: due sessioni si trovano a vicenda solo se vedono lo stesso filesystem, il che significa che una sessione dentro un #container e una sull’host non possono raggiungersi, mentre due sessioni nello stesso container sì.

Controllo dei messaggi in arrivoPer un uso in ambienti con requisiti di governance, il parametro di configurazione rilevante è crossSessionInbound, impostabile su tre valori:

{
"crossSessionInbound": "accept"
}accept: ogni messaggio viene consegnato direttamente.

hold: Claude Code mostra un avviso ma non consegna nulla, finché l’utente non approva.

refuse: il messaggio viene scartato senza notifica al destinatario.

Quando non è impostato alcun valore, Claude Code decide messaggio per messaggio in base alla modalità di permessi delle due sessioni: se la sessione ricevente richiede conferma per i permessi, il messaggio viene consegnato; se la sessione ricevente salta le conferme (modalità bypassPermissions), il messaggio viene messo in attesa di approvazione, a meno che anche il mittente dichiari di essere in bypass.

Per richiedere sempre un’approvazione esplicita prima che un messaggio lasci la macchina locale, si può impostare:

{
"isolatePeerMachines": true
}Per disattivare del tutto la funzionalità a livello di organizzazione, nelle managed settings:

{
"permissions": {
"deny": ["SendMessage", "ListAgents"]
},
"crossSessionInbound": "refuse"
}Cosa una sessione remota non può fareUn messaggio in arrivo da un’altra sessione non equivale mai al consenso dell’utente: non può approvare un prompt di permesso in sospeso, non può modificare impostazioni di permessi o il file CLAUDE.md, ed eventuali comandi contenuti nel testo (ad esempio /compact) vengono trattati come testo normale, mai eseguiti. Se agire sul messaggio richiede un permesso che la sessione ricevente non ha, scatta comunque il prompt standard.

I limiti attualiLa limitazione più rilevante per chi lavora su #Windows: la messaggistica cross-session funziona su macOS e #Linux, inclusa una sessione Linux dentro WSL 2, ma non su Windows nativo. È inoltre assente su Amazon Bedrock, Claude Platform su #AWS, #Google #Cloud Agent Platform e Microsoft Foundry. Restano infine due limiti strutturali: i messaggi sono solo testo semplice (i protocolli strutturati degli agent team restano interni al team) e i loop di messaggi vengono limitati automaticamente, con un massimo di 50 messaggi accettati in attesa di lettura per sessione.

Quando ha senso usarlaLa documentazione ufficiale indica quattro casi d’uso principali: passare un finding da una sessione a un’altra dopo una scoperta rilevante, coordinare worktree paralleli sullo stesso repository, far riportare lo stato di un’operazione lunga (una migrazione, una suite di test) alla sessione che la sta monitorando, e rispondere a messaggi arrivati da sessioni su altre macchine o dal web. Per chi lavora già con più terminali aperti sullo stesso progetto, è una funzione che elimina una frizione reale, a patto di capire bene i default di crossSessionInbound prima di usarla in un ambiente con permessi sensibili.

Fonte: documentazione ufficiale Claude Code – Cross-session messaging.

#ai #howto #tutorial #claudecode

0 0 1

Autenticazione SSH a chiave pubblica: la guida completa con ssh-keygen

Perché le password su SSH sono ormai un rischio da eliminareSe gestisci anche un solo server Linux esposto su Internet, i log di /var/log/auth.log te

Altro...

Perché le password su SSH sono ormai un rischio da eliminareSe gestisci anche un solo server Linux esposto su Internet, i log di /var/log/auth.log te lo confermano ogni giorno: bot e botnet tentano continuamente il login SSH via password, in modalità brute-force o credential stuffing. Una password, per quanto complessa, resta un segreto condiviso che può essere intercettato, indovinato o riutilizzato da un attaccante che l’ha ottenuta altrove. L’autenticazione a chiave pubblica elimina questo vettore alla radice: il server non conosce mai un segreto trasmissibile, ma verifica solo che il client possieda la chiave privata corrispondente a una chiave pubblica già autorizzata.

Questa guida copre il flusso completo: generazione della coppia di chiavi con ssh-keygen, distribuzione della chiave pubblica, gestione di host multipli con ~/.ssh/config, uso di ssh-agent e, infine, disattivazione sicura del login via password lato server.

Generare la coppia di chiavi con ssh-keygenIl primo passo è la scelta dell’algoritmo. Nel 2026 la raccomandazione per la quasi totalità degli scenari è Ed25519: chiavi più corte di RSA, generazione e verifica più veloci, sicurezza equivalente (o superiore) a RSA 3072/4096 bit. OpenSSH genera Ed25519 come default da ssh-keygen 9.5 (fine 2023), ma vale la pena specificarlo esplicitamente per chiarezza e portabilità degli script:

ssh-keygen -t ed25519 -C "nome@host-o-scopo-della-chiave"Il comando chiede dove salvare la chiave (default ~/.ssh/id_ed25519) e una passphrase. Imposta sempre una passphrase: senza, chiunque copi il file della chiave privata (backup non cifrato, laptop rubato, snapshot di VM) ottiene accesso diretto ai sistemi target. Se devi supportare dispositivi legacy che non gestiscono Ed25519 (raro, ma capita con apparati di rete datati), usa RSA a 4096 bit come alternativa:

ssh-keygen -t rsa -b 4096 -C "nome@host-o-scopo-della-chiave"Un’opzione spesso sottovalutata è l’uso di chiavi FIDO2/hardware, dove il materiale crittografico non lascia mai una security key fisica (es. YubiKey):

ssh-keygen -t ed25519-sk -C "chiave-hardware"Per ambienti con requisiti di compliance elevati o accessi amministrativi privilegiati, vale la pena valutarla: anche in caso di compromissione totale della workstation, la chiave privata resta inaccessibile senza il dispositivo fisico.

Distribuire la chiave pubblicaIl modo più rapido è ssh-copy-id, che si occupa di creare (se assente) la directory ~/.ssh sul server remoto, con permessi corretti, e di appendere la chiave pubblica a authorized_keys:

ssh-copy-id -i ~/.ssh/id_ed25519.pub utente@serverSe ssh-copy-id non è disponibile (ad esempio da un client Windows senza WSL), il metodo manuale equivalente è:

cat ~/.ssh/id_ed25519.pub | ssh utente@server
"mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"I permessi contano davvero: OpenSSH lato server rifiuta silenziosamente authorized_keys se la directory .ssh è scrivibile da altri utenti o se il file ha permessi troppo aperti. Se il login a chiave “non funziona” senza errori evidenti, controlla sempre chmod 700 ~/.ssh e chmod 600 ~/.ssh/authorized_keys prima di cercare altrove.

Gestire host multipli con ~/.ssh/configChi amministra decine di server trae grande beneficio da un file di configurazione client centralizzato. Invece di ricordare chiave, utente e porta per ogni host, definisci alias in ~/.ssh/config:

Host prod-web01
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/id_ed25519_prod
IdentitiesOnly yes

Host *.interno.lan
User admin
IdentityFile ~/.ssh/id_ed25519_lan
ForwardAgent noDa quel momento ssh prod-web01 basta e avanza. L’opzione IdentitiesOnly yes è importante quando gestisci più chiavi: senza di essa, il client SSH può offrire al server tutte le identità disponibili nell’agent, esaurendo il numero massimo di tentativi consentiti (MaxAuthTries) prima di arrivare a quella corretta.

ssh-agent: passphrase una sola volta per sessioneCon una passphrase impostata (come dovrebbe essere sempre), digitarla a ogni connessione è scomodo. ssh-agent mantiene la chiave decifrata in memoria per la durata della sessione:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519Sulla maggior parte delle distribuzioni desktop l’agent è già integrato con il session manager. Evita ForwardAgent yes indiscriminato: l’agent forwarding espone la tua chiave in memoria a qualunque processo con privilegi root sul server intermedio, un rischio concreto se quel server non è pienamente fidato. Se ti serve saltare attraverso un bastion host, preferisci ProxyJump:

Host bastion
HostName bastion.example.com
User jump

Host target-interno
HostName 10.0.5.20
User admin
ProxyJump bastionDisabilitare l’autenticazione a password lato serverSolo dopo aver verificato che il login a chiave funziona correttamente (testalo in una sessione separata prima di chiudere quella attuale), disattiva la password lato server. Sulle distribuzioni moderne (Debian/Ubuntu recenti), il modo più pulito è un drop-in dedicato, che viene caricato prima del file principale e quindi vince sui default:

sudo mkdir -p /etc/ssh/sshd_config.d
sudo tee /etc/ssh/sshd_config.d/00-disable-password-auth.conf <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
sudo sshd -t && sudo systemctl reload sshdsshd -t valida la sintassi prima del reload: un errore di battitura in questo file può tagliarti fuori dal server se non hai un accesso alternativo (console cloud, iDRAC/iLO, ecc.). PermitRootLogin prohibit-password è la scelta consigliata rispetto a no secco: mantiene comunque disponibile il root via chiave per operazioni di emergenza, ma blocca il tentativo via password.

Checklist finale per un hardening solidoUna chiave dedicata per servizio/scopo (deploy, amministrazione, CI/CD), non un’unica chiave riutilizzata ovunque.

Passphrase sempre presente sulle chiavi memorizzate su disco non cifrato.

Audit periodico di authorized_keys su ogni server: rimuovi le chiavi di chi ha lasciato il team o non necessita più di accesso.

AuthorizedKeysCommand con backend centralizzato (Vault, LDAP) se gestisci decine di server e vuoi evitare la distribuzione manuale delle chiavi.

Fail2ban o equivalente comunque attivo, come difesa in profondità anche a password disabilitate.

ConclusioneIl passaggio da password a chiavi SSH richiede pochi minuti per server, ma elimina una delle superfici di attacco più sfruttate contro sistemi Linux esposti. La combinazione di Ed25519, ~/.ssh/config ben strutturato e password disabilitate lato server è oggi lo standard minimo per qualunque infrastruttura, piccola o grande che sia.

Fonte: LinuxBlog.io.

#sicurezza #linux #howto #tutorial

0 0 0

Troubleshooting Windows: perché partire dall’evidenza e non dal comando di riparazione

Il problema non è la mancanza di strumenti, è l’ordine in cui si usanoWindows include più utility diagnostiche di quante un amministratore ne userà ma

Altro...

Il problema non è la mancanza di strumenti, è l’ordine in cui si usanoWindows include più utility diagnostiche di quante un amministratore ne userà mai tutte. Eppure la causa più comune di sessioni di troubleshooting infruttuose non è l’ignoranza dei tool, ma la sequenza sbagliata: si parte da un comando di riparazione (sfc /scannow, un reset di Windows Update, un DISM al buio) prima ancora di aver capito quale sottosistema sta effettivamente fallendo. Il risultato è tempo perso, evidenze diagnostiche distrutte dal riavvio, e spesso la causa radice che resta lì, pronta a ripresentarsi la settimana successiva.

Vale la pena fermarsi a formalizzare un metodo, perché è quello che separa un troubleshooting efficace da un’accozzaglia di tentativi casuali. Di seguito un processo in cinque passi, seguito da una rassegna degli strumenti chiave e da una tabella sintesi sintomo → strumento che può diventare un riferimento rapido da tenere a portata di mano durante un incidente.

Un processo ripetibile prima di toccare qualsiasi comandoLa maggior parte delle sessioni di troubleshooting falliscono prima ancora che venga lanciato il primo comando. Un amministratore vede un errore, prova un comando di riparazione che conosce, riavvia, e scopre che il problema originale è ancora lì. Un approccio più solido richiede di rallentare abbastanza da stabilire una baseline:

Confermare o riprodurre il problema: è cronico o è stato un episodio isolato?

Registrare il sintomo esatto: messaggio di errore, orario, utente coinvolto, dispositivo, modifiche recenti.

Raccogliere le evidenze dal sistema più probabilmente coinvolto.

Applicare una modifica alla volta, partendo dall’opzione meno invasiva.

Verificare il risultato e documentare cosa è effettivamente cambiato.

Un esempio concreto: se Windows Update fallisce con un errore generico, la tentazione è resettare tutti i componenti di aggiornamento in blocco. Il primo passo corretto è invece capire in quale fase è avvenuto il fallimento — scan, download, staging, installazione o riavvio — perché questa distinzione determina se bisogna guardare i log di Windows Update, i log di servicing, lo stato del disco, la configurazione delle policy o la connettività di rete.

Event Viewer: il primo posto dove cercare quando c’è un timestampEvent Viewer è il punto di partenza quando il sintomo ha un orario preciso: un crash applicativo, un riavvio inatteso, un servizio che si ferma, un problema di driver, un’installazione fallita. Si parte dai Windows Logs, filtrando Application, System e Setup per eventi Critical, Error e Warning nell’intorno temporale del problema, per poi individuare l’event source, l’event ID, il modulo che genera il fault, il nome del servizio o del driver coinvolto.

Il criterio per separare il segnale dal rumore è la ripetibilità: un warning isolato di ieri è quasi sempre rumore; un errore che compare sistematicamente ogni volta che si apre una determinata applicazione è un segnale affidabile. Le evidenze diagnostiche più utili sono quelle correlate nel tempo e riproducibili, non gli eventi isolati.

SFC prima, DISM solo se SFC non bastaSystem File Checker (SFC) è uno strumento di riparazione mirato per i file di sistema protetti. Si usa quando una feature nativa di Windows si comporta in modo anomalo, un componente integrato non parte, oppure Event Viewer punta a file del sistema operativo mancanti o corrotti:

sfc /scannowSFC è utile perché verifica e sostituisce i file protetti senza richiedere una reinstallazione, ma dipende dal component store locale come sorgente di riparazione. Se quello store è danneggiato, SFC può segnalare corruzione trovata ma non riparabile del tutto. A quel punto il passo successivo è DISM, non ripetere SFC all’infinito sperando in un risultato diverso.

Deployment Image Servicing and Management (DISM) opera a livello di image e component store, uno strato sotto SFC. Va usato quando SFC non riesce a completare le riparazioni, quando l’installazione di Windows Update o di una feature fallisce ripetutamente, o quando il problema è a livello di servicing. Il comando di riparazione online più comune:

DISM /Online /Cleanup-Image /RestoreHealthIn ambienti enterprise, DISM può aver bisogno di una sorgente di riparazione affidabile — supporto di installazione, un’immagine montata, o una posizione di contenuto gestita — soprattutto quando gli endpoint non possono scaricare i contenuti di riparazione da Windows Update. Dopo che DISM completa con successo, conviene rilanciare SFC, così i file protetti possono essere riparati da un component store ormai sano.

Windows Update: capire in quale fase fallisce prima di resettare tuttoIl troubleshooting di Windows Update deve partire dall’identificazione della fase fallita. Un fallimento nello scan suggerisce problemi di policy, rete, proxy o sorgente di aggiornamento. Un fallimento nel download indica problemi di connettività, disponibilità dei contenuti o cache. Un fallimento nell’installazione punta spesso allo servicing stack, al component store, allo spazio su disco, a un riavvio pendente o a un driver in conflitto.

Sulle versioni moderne di Windows, Windows Update si basa su dati Event Tracing for Windows (ETW) piuttosto che scrivere un semplice log testuale in continuo. Per generare un log leggibile quando serve un dettaglio più approfondito lato client, si usa PowerShell:

Get-WindowsUpdateLogVale anche controllare Event Viewer nei log operativi del client di Windows Update e il Setup log per gli eventi di installazione. Se lo stesso pacchetto KB fallisce ripetutamente, conviene verificare se l’aggiornamento è applicabile, se esiste un aggiornamento che lo sostituisce, e da quale sorgente il dispositivo riceve gli update — Windows Update diretto, Microsoft Update, WSUS, oppure una piattaforma di gestione come Intune o Configuration Manager.

Un reset completo di Windows Update dovrebbe essere un passo tardivo, non il primo. Resettare i servizi e svuotare le cache può sbloccare client incastrati, ma distrugge anche evidenze utili. Meglio catturare prima il codice di errore, i log e la cronologia degli aggiornamenti.

“La rete non funziona” è quasi sempre DNS o configurazioneI sintomi di rete richiedono un punto di partenza diverso, perché gli utenti spesso descrivono come “la rete è giù” un problema che in realtà è DNS, routing, autenticazione, policy del firewall o un singolo endpoint applicativo che non risponde. È corretto partire dalla configurazione TCP/IP locale prima di testare i servizi remoti.

Un errore comune tra amministratori meno esperti è dare per scontato che “il ping non risponde” equivalga a “la rete è giù”. In ambienti enterprise questa assunzione è spesso sbagliata: molti sistemi sono configurati per ignorare le richieste ICMP pur continuando a erogare regolarmente il servizio previsto. Un firewall può bloccare ICMP, una policy di sicurezza può disabilitare le risposte, un servizio cloud può non rispondere mai al ping. La domanda giusta non è se un dispositivo risponde al ping, ma se il servizio richiesto è effettivamente raggiungibile: bisogna sempre testare ciò che l’utente sta effettivamente cercando di usare, con strumenti come ipconfig, nslookup e tracert mirati sul servizio specifico.

Tabella di riferimento rapido: sintomo → strumentoSintomoPartire daPerchéApp che va in crash o si chiude inaspettatamenteEvent Viewer, poi Reliability MonitorIdentifica moduli in fault, errori applicativi e pattern di modifiche recentiWindows Update fallisce ripetutamenteLog di Windows Update, Setup log, DISMSepara i fallimenti di scan, download, installazione e servicingFeature di Windows mancanti o instabiliSFC, poi DISM se SFC non riparaRipara i file di sistema protetti e il component store sottostanteUtenti non raggiungono risorse di reteipconfig, ping, nslookup, tracertValida configurazione locale, raggiungibilità, DNS e routing in ordineLe performance degradano improvvisamenteTask Manager, Resource Monitor, Event ViewerCorrela la pressione sulle risorse con servizi, driver ed erroriReliability Monitor merita una menzione a parte perché offre una vista a timeline di crash applicativi, fallimenti di Windows, installazioni di driver ed eventi di aggiornamento. È meno dettagliato di Event Viewer, ma resta eccellente per individuare rapidamente cosa è cambiato immediatamente prima che iniziasse un problema ricorrente.

Costruire il proprio toolkit di troubleshootingPer un professionista IT, l’abilità di troubleshooting più preziosa non è memorizzare comandi, ma sapere quale fonte di evidenza fidarsi per una determinata classe di problema. Event Viewer dice cosa Windows ha registrato; Reliability Monitor mostra quando i problemi sono iniziati. Una checklist pratica da seguire durante un incidente:

Registrare sintomi esatti, orario, dispositivo, utente e modifiche recenti.

Controllare i log più rilevanti prima di applicare riparazioni ad ampio raggio.

Eseguire i comandi di riparazione da un terminale elevato e catturarne l’output.

Cambiare una variabile alla volta, per sapere con certezza cosa ha risolto il problema.

Verificare dal punto di vista dell’utente, non solo dalla console amministrativa.

Questa disciplina previene due errori tipici: eseguire riparazioni distruttive troppo presto, e dichiarare vittoria prima di aver verificato il flusso di lavoro reale. Se un utente non riesce ad aprire una condivisione di rete, un ping riuscito non è il traguardo: il traguardo è l’utente che apre la condivisione, accede ai file attesi e conferma che il problema non si ripresenta.

ConclusioneLa differenza tra una sessione di troubleshooting produttiva e una frustrante raramente sta nella conoscenza di comandi avanzati. Sta nel partire dal sintomo invece che dal comando, chiedersi quale evidenza confermerebbe o smentirebbe la causa più probabile, e solo a quel punto scegliere lo strumento che fornisce quell’evidenza nel modo più veloce. È questa disciplina che trasforma una collezione di utility in un vero toolkit diagnostico.

Fonte: Critical Windows Troubleshooting Tools: Stop Wasting Time on the Wrong Fixes, Petri IT Knowledgebase

#powershell #windows #guide #howto #tutorial

0 0 0

Diagnosticare lo swap su Linux con smem: USS, PSS, RSS e il ruolo di vm.swappiness nei cgroup v2

Un server con RAM libera che continua a usare swap è uno degli scenari più fraintesi nella diagnostica Linux. La reazione istintiva è quasi sempre la

Altro...

Un server con RAM libera che continua a usare swap è uno degli scenari più fraintesi nella diagnostica Linux. La reazione istintiva è quasi sempre la stessa: aumentare la RAM o disattivare lo swap. Nessuna delle due è la risposta giusta se prima non sai quale processo sta finendo su disco e perché. Lo strumento più adatto a rispondere a questa domanda è smem, un tool di reporting che calcola l’uso di memoria proporzionale per processo, swap incluso — una cosa che top e ps da soli non fanno.

Perché il kernel usa lo swap anche con RAM liberaLinux è progettato per usare tutta la RAM disponibile, spesso per la cache dei file. Quando il kernel decide che alcune pagine di memoria non vengono accedute da un po’, può spostarle su swap anche se c’è ancora RAM libera: è un comportamento intenzionale, non un guasto. Il parametro che governa questa aggressività è vm.swappiness, un valore da 0 a 200 che esprime quanto il kernel preferisce recuperare pagine di cache file rispetto a spostare pagine anonime su swap.

Un dettaglio poco noto e rilevante da kernel 5.8 in poi: con i cgroup v2, vm.swappiness=0 non significa più “non spostare mai nulla su swap”. Continua a indicare una forte preferenza per liberare cache file, ma il kernel spingerà comunque pagine anonime su swap se è vicino all’OOM. Prima di intervenire su questo parametro, però, il primo passo resta capire chi sta effettivamente consumando swap.

Installare smemNon è quasi mai preinstallato, ma è nei repository delle principali distribuzioni:

RHEL / CentOS / AlmaLinux / Fedora

dnf install smem

Debian / Ubuntu

apt install smemUSS, PSS e RSS: la differenza che conta davveroLa ragione per cui smem è più utile di un ps aux --sort=-rss al volo sta nelle metriche che espone. ps e top mostrano principalmente RSS, che sovrastima sistematicamente l’uso di memoria perché conta anche le pagine condivise tra processi (librerie, memoria mappata) come se appartenessero interamente a ciascun processo.

RSS (Resident Set Size): memoria fisica occupata dal processo, incluse le pagine condivise con altri processi — per questo tende a sovrastimare.

USS (Unique Set Size): memoria usata esclusivamente da quel processo, senza nulla di condiviso. È quanta memoria verrebbe effettivamente liberata se il processo terminasse.

PSS (Proportional Set Size): somma la USS più una quota proporzionale della memoria condivisa, distribuita tra tutti i processi che la usano. È la metrica più realistica per capire “quanta memoria sta davvero consumando il sistema per questo processo”, perché sommando i PSS di tutti i processi non conti la stessa pagina condivisa più volte.

Su un web server con decine di processi PHP-FPM o worker Nginx che condividono le stesse librerie, la differenza tra RSS e PSS può essere enorme: sommare tutti gli RSS ti dà un numero fantasioso, sommare i PSS ti avvicina al reale consumo di RAM del sistema.

Uso di base: chi sta consumando swapIl comando principale per la diagnosi dello swap ordina i processi per swap decrescente:

smem -rs swapOutput tipico (troncato):

PID User Command Swap USS PSS RSS
28986 mysql /usr/sbin/mysqld --daemoniz 476372 10963864 10963932 10965112
29152 root /usr/sbin/rsyslogd -n 371424 3956 17475 43352
31423 root /opt/fluent-bit/bin/fluent- 22508 26612 26739 29100In questo esempio è immediato vedere che mysqld e rsyslogd sono i responsabili principali dello swap, non un generico “sistema pieno”. Questo è già un’informazione azionabile: invece di aggiungere RAM alla cieca, sai su quale servizio intervenire.

Per una vista più visuale, smem genera anche grafici a torta per utente o processo, utile per presentare rapidamente la distribuzione dei consumi:

smem --pie name -s rss(richiede matplotlib installato per generare l’immagine).

Cosa fare dopo aver identificato il colpevoleUna volta isolato il processo, la strada tipica è duplice: da un lato tuning applicativo del servizio (per MySQL, rivedere innodb_buffer_pool_size e le connessioni aperte; per rsyslog, verificare codeon accumulo di code su disco lento), dall’altro una revisione più conservativa di vm.swappiness:

sysctl vm.swappiness=1
echo 'vm.swappiness=1' >> /etc/sysctl.confUn valore basso (1-10) dice al kernel di preferire fortemente la RAM e ricorrere allo swap solo come ultima risorsa, comportamento adatto alla maggior parte dei carichi di hosting: il default di 60 è pensato per un uso desktop generico ed è piuttosto aggressivo per un server.

Se il servizio gira in un cgroup (container, systemd slice)Su sistemi che orchestrano i workload con cgroup v2 — container Docker/Podman, unit systemd con MemoryMax=, pod Kubernetes — la vecchia intuizione su swap e RAM va integrata con un secondo livello di controllo: memory.swap.max. Questo parametro è un limite massimo di swap utilizzabile dal cgroup: se il cgroup raggiunge quel tetto, la memoria anonima al suo interno smette di essere spostata su swap, indipendentemente da cosa dice vm.swappiness a livello di kernel. Non è pensato per gestire quanto swap viene usato durante il funzionamento normale, ma come argine per evitare che un singolo cgroup saturi lo swap dell’intero host.

Una pratica ragionevole quando si dimensionano i limiti di un cgroup è impostare memory.high attorno al 10-20% sotto memory.max, per dare al kernel margine di reclaim prima di colpire il limite duro, e aggiungere un 20-30% al di sopra del picco di utilizzo reale dell’applicazione quando si calcola memory.max, per tenere conto della page cache che nei cgroup v2 conta comunque contro il totale di memoria assegnato.

Conclusionesmem è uno strumento leggero ma preciso per rispondere a una domanda che free, top o vmstat lasciano aperta: non solo “quanto swap sto usando”, ma “chi lo sta usando e quanto pesa davvero, al netto della memoria condivisa”. Su un server che sembra inspiegabilmente lento nonostante RAM apparentemente disponibile, è spesso il primo strumento da tirare fuori prima di toccare vm.swappiness, aggiungere RAM o — peggio — disattivare lo swap del tutto, cosa che su Linux tende a peggiorare le cose sotto pressione di memoria invece di risolverle.

Fonte originale: Diagnosing Swap Usage with smem on Linux, LinuxBlog.io

Copertina: diagnosi dello swap su Linux con smem, USS PSS RSS Copertina: diagnosi dello swap su Linux con smem, USS PSS RSS

#linux #guide #howto #tutorial #performance #swap #sysadmin

0 0 0

Podman: l’alternativa a Docker che ogni sysadmin Linux dovrebbe conoscere

Per anni Docker è stato il default indiscusso quando si parlava di container su Linux. Ma l’architettura basata su un daemon centrale che gira come ro

Altro...

Per anni Docker è stato il default indiscusso quando si parlava di container su Linux. Ma l’architettura basata su un daemon centrale che gira come root ha sempre lasciato sul tavolo un problema di superficie d’attacco: se qualcuno compromette dockerd, ha di fatto accesso root all’intero host. Podman nasce proprio per chiudere questo gap, offrendo un motore container daemonless, compatibile con le immagini OCI e con la CLI Docker, che si integra in modo molto più nativo con systemd e con il modello di permessi di Linux.

Vediamo come installarlo, come si differenzia realmente da Docker oltre gli slogan, e come portarlo in produzione con systemd e le Quadlet, che sono probabilmente la ragione migliore per prenderlo sul serio.

Cos’è Podman, in praticaPodman (da Pod Manager) è un motore container open source senza demone centrale. Ogni container gira come processo figlio dell’utente che lo ha avviato, non come figlio di un servizio di sistema con privilegi elevati. Questo significa che è possibile eseguire container completamente rootless, senza mai invocare sudo, riducendo drasticamente cosa un container compromesso può effettivamente toccare sull’host.

Sotto il cofano Podman usa gli stessi runtime OCI di Docker e parla lo stesso formato immagine, quindi la stragrande maggioranza dei comandi Docker funziona invariata sostituendo semplicemente il nome del binario (o creando un alias docker=podman, oppure installando il pacchetto podman-docker che fa da shim trasparente).

Un concetto che Docker non ha nativamente è quello di pod: gruppi di uno o più container che condividono rete e storage, concettualmente vicini ai pod di Kubernetes. Comodo quando si vogliono far girare insieme più container che devono comunicare come se fossero sulla stessa macchina.

Installazione# Debian/Ubuntu (Debian 11+, Ubuntu 20.10+)
sudo apt-get update
sudo apt-get -y install podman

Fedora/CentOS/RHEL 8+

sudo dnf -y install podman

openSUSE

sudo zypper install podman

Arch/Manjaro

sudo pacman -S podmanVerifica dell’installazione:

podman --version
podman info
podman run hello-worldSe l’ultimo comando restituisce il messaggio di benvenuto di Podman, l’installazione è a posto.

Uso quotidiano: i comandi non cambiano quasi nullaShell interattiva dentro un container Ubuntu:

podman run -it ubuntu bashServizio in background, con Nginx esposto sulla porta 8080 dell’host:

podman run -d --name web -p 8080:80 nginx
podman psIl resto della CLI ricalca Docker praticamente 1:1: podman pull, podman images, podman stop/start, podman rm/rmi. Dietro le quinte, podman build è in realtà un wrapper attorno a Buildah, mentre lo spostamento di immagini tra registry passa per Skopeo: strumenti separati che Podman orchestra per te, senza che serva conoscerli nel dettaglio per l’uso base.

Dove Docker e Podman divergono davveroLa compatibilità è alta ma non totale, e i problemi emergono quasi sempre dal modello rootless. Il caso più comune sono i bind mount: poiché i container rootless usano user namespace e mapping subuid/subgid, una directory montata dall’host non sempre ha la proprietà che il container si aspetta. Su sistemi con SELinux attivo serve anche il suffisso :z o :Z per far ri-etichettare correttamente i file:

podman run -v /host/path:/container/path:Z myimage:z minuscolo condivide il volume tra più container, :Z maiuscolo lo rende privato per un singolo container. Se serve far coincidere esattamente la proprietà con quella dell’host, l’opzione --uidmap permette un controllo fine, oppure si può far girare il container in modalità rootful per replicare il comportamento di Docker.

Altri attriti da conoscere prima di migrare: l’accesso GPU da container rootless è limitato (NVIDIA richiede nvidia-container-toolkit e setup CDI, con i container da ricreare a ogni aggiornamento driver), e i Docker secrets insieme ad alcune configurazioni di rete non hanno una corrispondenza 1:1. Niente di bloccante, ma va testato prima di assumere che la migrazione sia un semplice “find and replace”.

Container come servizi systemd: le QuadletQuesto è probabilmente il motivo migliore per scegliere Podman in un contesto server. Invece di lasciare un demone in background a gestire lo stato dei container, si delega tutto a systemd, che diventa responsabile di avvio, riavvio e supervisione, esattamente come per qualsiasi altro servizio di sistema.

Il meccanismo si chiama Quadlet: un file dichiarativo con estensione .container che Podman traduce automaticamente in una unit systemd. Per un servizio utente rootless, il file va in ~/.config/containers/systemd/. Esempio minimo per Nginx:

[Container]
ContainerName=web
Image=docker.io/library/nginx:latest
PublishPort=8080:80

[Install]
WantedBy=default.targetAttivazione:

systemctl --user daemon-reload
systemctl --user start webDa questo momento il container è gestito da systemd come un servizio qualsiasi: si riavvia in caso di crash, si integra con i log di journald, si può abilitare al boot. Aggiungendo l’etichetta AutoUpdate=registry a un container, inoltre, podman auto-update può controllare periodicamente nuove versioni dell’immagine e riavviare il servizio in automatico, senza bisogno di Watchtower o strumenti equivalenti.

Migrare da Docker ComposeChi ha un’infrastruttura basata su Compose ha due strade percorribili. La prima è continuare a usare Compose così com’è: il binario standalone docker compose può puntare al socket di Podman senza toccare i file docker-compose.yml esistenti:

systemctl --user enable --now podman.socketLa seconda è convertire i file Compose in Quadlet, così che sia systemd a gestire tutto nativamente. Scrivere le unit a mano è tedioso, quindi conviene usare podlet, un tool che legge un docker-compose.yml e genera i file Quadlet corrispondenti. C’è una curva di apprendimento, ma è comunque più veloce che partire da zero.

Docker resta rilevanteNonostante i vantaggi di Podman, Docker non sta scomparendo. L’ecosistema attorno a Docker (Compose, Swarm, e tutta la tooling che si integra con esso, inclusi molti sistemi CI/CD già configurati per il socket Docker) resta enorme, e non tutte le piattaforme gestiscono bene le peculiarità rootless di Podman. Se un team è già standardizzato su Docker, spesso ha più senso restare sull’esistente piuttosto che affrontare una migrazione per un guadagno marginale.

Dove Podman convince davvero è quando si parte da zero: setup più sicuro per default, nessun demone da tenere sotto controllo, integrazione diretta con systemd per la gestione del ciclo di vita dei servizi.

ConclusionePodman è un motore container completo, compatibile con Docker, che funziona senza demone e senza bisogno di privilegi root. Per l’uso quotidiano è quasi un drop-in replacement: si installa dal repository della distribuzione, si usano gli stessi comandi (o si crea l’alias docker=podman), e si ottengono benefici di sicurezza concreti senza dover reimparare nulla. I limiti di compatibilità, soprattutto su bind mount, GPU e secrets, vanno conosciuti e testati prima di una migrazione in produzione, ma per chi sta impostando nuovi ambienti containerizzati su Linux, specialmente se pensa di gestirli con systemd e Quadlet, vale decisamente la pena valutarlo.

Fonte originale: Hayden James, “Docker Alternative: Podman on Linux”, LinuxBlog.io.

#linux #container #devops #docker #guide #howto #podman #tutorial

0 0 0

C# 15 introduce le union: basta OneOf e Results per modellare i tipi (.NET 11 Preview 6)

Da anni gli sviluppatori C# aspettano un modo nativo per dire “questo valore è esattamente uno tra questi tipi, e nient’altro”, con il compilatore in

Altro...

Da anni gli sviluppatori C# aspettano un modo nativo per dire “questo valore è esattamente uno tra questi tipi, e nient’altro”, con il compilatore in grado di garantirlo. In assenza di un supporto di linguaggio, la community si è arrangiata con pattern come Results<T> di ASP.NET Core Minimal API o con librerie come OneOf. Funzionano, ma con un limite strutturale: se aggiungi un quarto caso possibile a una funzione che prima ne restituiva tre, nessuno ti avvisa che uno switch a valle non gestisce il nuovo tipo. Manca l’esaustività, che è poi il punto centrale delle discriminated union.

Con .NET 11 Preview 6 (rilasciata il 14 luglio 2026) e C# 15, questa lacuna si chiude: arriva la parola chiave union, insieme a un intero pacchetto di funzionalità correlate (conversioni implicite, pattern matching esaustivo, gestione della nullabilità) che rendono i union type un cittadino di prima classe del linguaggio.

La sintassi: dichiarare un union typeLa forma più semplice è la union declaration, una sintassi compatta che genera automaticamente uno struct:

public union Pet(Cat, Dog, Bird);Questa singola riga dice al compilatore che un Pet è esattamente un Cat, un Dog o un Bird, e nient’altro. Sotto il cofano, il compilatore genera uno struct che implementa l’interfaccia System.Runtime.CompilerServices.IUnion e conserva il valore effettivo in una proprietà Value di tipo object?.

I union generici sono immediatamente utili per modellare risultati di operazioni che possono fallire, un caso d’uso ricorrentissimo in codice di produzione:

public union Result<TSuccess, TError>(TSuccess, TError);

Result<User, Error> Register(string username)
{
if (string.IsNullOrEmpty(username))
return new Error("Username cannot be empty");

return new User(username);

}Da notare l’ultima riga: nessun wrapping esplicito, nessuna chiamata a un factory method. Il valore User o Error viene convertito implicitamente in Result<User, Error> grazie alle union conversion generate automaticamente per ogni case type.

Pattern matching esaustivo, finalmenteIl vero salto di qualità è nel matching. Se dimentichi un caso in uno switch su un union type, il compilatore te lo dice:

string Describe(Pet pet) => pet switch
{
Dog d => d.Name,
Cat c => c.Name,
// CS8509: switch expression does not handle all
// possible values of its input type (Bird)
};Aggiungendo il caso mancante, l’avviso scompare, e non serve più il classico _ => throw new InvalidOperationException("unreachable") per zittire il compilatore:

string Describe(Pet pet) => pet switch
{
Dog d => d.Name,
Cat c => c.Name,
Bird b => b.Name,
};Il punto interessante è che questa esaustività è dinamica: se in futuro aggiungi un nuovo case type al union (per esempio un quarto animale), ogni switch esistente che non lo gestisce si illumina di un warning. Per chi ha inseguito bug di produzione causati da un case dimenticato in un evento di dominio, è un cambiamento non da poco.

I pattern si applicano direttamente al union, senza bisogno di accedere manualmente a .Value: il compilatore effettua l’unwrapping in automatico, anche negli if pattern classici:

if (pet is Dog d)
{
Console.WriteLine(d.Name);
}Gestione del nullIl valore di default di un union type ha Value == null, ed è possibile intercettarlo esplicitamente con il pattern null:

string Describe(Pet pet) => pet switch
{
null => "nessun animale",
Dog d => d.Name,
Cat c => c.Name,
Bird b => b.Name,
};La necessità o meno del ramo null dipende dal fatto che il parametro o il campo union-typed sia nullable: l’analisi di nullabilità del compilatore guida correttamente questi casi, in coerenza con le annotazioni #nullable enable già in uso nella maggior parte delle codebase moderne.

Un caso pratico: modellare eventi di dominioI union type diventano davvero interessanti quando li si combina con i record per il domain modeling, per esempio in un sistema di elaborazione ordini con eventi distinti:

public record OrderPlaced(Guid OrderId, decimal Total);
public record OrderShipped(Guid OrderId, string TrackingNumber);
public record OrderCancelled(Guid OrderId, string Reason);
public union OrderEvent(OrderPlaced, OrderShipped, OrderCancelled);

string Summarize(OrderEvent evt) => evt switch
{
OrderPlaced p => $"Ordine {p.OrderId} piazzato per {p.Total:C}",
OrderShipped s => $"Ordine {s.OrderId} spedito, tracking: {s.TrackingNumber}",
OrderCancelled c => $"Ordine {c.OrderId} annullato: {c.Reason}",
};Quando tra tre mesi qualcuno aggiungerà OrderRefunded al union, ogni handler che non lo gestisce lancerà un warning in fase di compilazione, invece di fallire silenziosamente in produzione. È il compilatore che fa da revisore di esaustività al posto tuo.

I union possono anche esporre metodi e proprietà calcolate (ma non campi d’istanza), utile per incapsulare logica di conversione:

public union Length(Meters, Feet)
{
public double TotalMeters => this switch
{
Meters m => m.Value,
Feet f => f.Value * 0.3048,
_ => throw new InvalidOperationException(),
};
}Union personalizzati con l’attributo [Union]La parola chiave union genera sempre uno struct. Se per motivi di identità, ereditarietà o layout di memoria serve un tipo reference, è possibile costruire un union personalizzato applicando direttamente l’attributo System.Runtime.CompilerServices.UnionAttribute e implementando l’interfaccia IUnion:

[System.Runtime.CompilerServices.Union]
public class Shape : System.Runtime.CompilerServices.IUnion
{
private readonly object? _value;
public Shape(Circle value) { _value = value; }
public Shape(Rectangle value) { _value = value; }
public object? Value => _value;
}Nella grande maggioranza dei casi, però, la sintassi union compatta copre già ogni esigenza pratica: l’approccio con attributo è pensato per scenari con requisiti specifici che lo struct generato non può soddisfare.

Come provarlo oggiI union type sono attualmente in preview. Per sperimentarli serve l’SDK .NET 11 Preview e questa configurazione nel file di progetto:

ConclusioniF# ha le discriminated union fin dalle origini, e la richiesta di un equivalente in C# (csharplang issue #113) è aperta da anni. Con l’arrivo dei union type, non ogni problema di modellazione richiede più una gerarchia di classi: per rappresentare “uno tra un insieme chiuso di tipi”, ora esiste un costrutto di linguaggio dedicato, con conversioni implicite, pattern matching esaustivo e un’ottima integrazione con i record esistenti. Per chi lavora ogni giorno con API che possono restituire risultati eterogenei, o con event sourcing e domain modeling, è una delle novità più concrete della prossima versione di C#.

Fonte: .NET Blog, C# language reference proposal: Unions e Maarten Balliauw.

#c #guide #tutorial #net

0 0 0

Nmap su Linux: la guida pratica a scanning e discovery di rete per sistemisti

Chi amministra server Linux prima o poi si trova a dover rispondere a una domanda apparentemente semplice: “cosa è realmente esposto su questa macchin

Altro...

Chi amministra server Linux prima o poi si trova a dover rispondere a una domanda apparentemente semplice: “cosa è realmente esposto su questa macchina, e su questa rete?” La risposta corretta non arriva mai da un elenco di regole firewall letto a memoria, ma da una verifica attiva. Nmap (Network Mapper) resta lo strumento di riferimento per questo tipo di verifica: open source, nato nel 1997, ancora oggi il punto di partenza per audit di sicurezza, mappatura di reti e troubleshooting di connettività.

In questo articolo vediamo un percorso pratico per usare nmap in scenari reali di amministrazione sistemi: dalla discovery degli host alla scansione delle porte, fino agli script NSE per individuare vulnerabilità e configurazioni deboli.

Nota importante: esegui scansioni solo su reti e host di tua proprietà o per cui hai autorizzazione esplicita. La scansione non autorizzata può costituire reato in molte giurisdizioni, Italia compresa (accesso abusivo a sistema informatico, art. 615-ter c.p.).

InstallazioneNmap è disponibile nei repository di tutte le distribuzioni principali:

Debian/Ubuntu

sudo apt install nmap

Fedora/RHEL/CentOS

sudo dnf install nmap

Arch/Manjaro

sudo pacman -S nmap

Verifica

nmap --versionHost discovery: chi è vivo sulla reteIl primo passo in qualsiasi audit è capire quali host rispondono. Per questo si usa la scansione “ping”, che salta completamente il controllo delle porte:

nmap -sn 192.168.1.0/24Su una rete locale nmap non si limita all’ICMP: usa il protocollo ARP, molto più veloce e capace di scovare anche dispositivi che ignorano i normali ping. Su reti instradate, invece, combina richieste ICMP echo, TCP SYN sulla porta 443, TCP ACK sulla porta 80 e timestamp ICMP. Il risultato è un inventario rapido e silenzioso di ciò che è realmente connesso, utile ad esempio quando serve scoprire quale indirizzo IP il DHCP ha assegnato a un nuovo dispositivo.

Scansione delle porteUna volta identificati gli host attivi, il passo successivo è capire quali servizi espongono. Senza opzioni, nmap scansiona le 1.000 porte TCP più comuni e non richiede privilegi root:

nmap 192.168.1.10Da root, il tipo di scansione predefinito diventa la SYN scan (o “stealth scan”), più veloce perché non completa mai l’handshake TCP a tre vie e lascia meno tracce nei log applicativi:

sudo nmap -sS 192.168.1.10Le 1.000 porte di default lasciano fuori parecchio. Un’istanza MySQL su una porta non standard, o un demone SSH spostato sulla 2222, restano invisibili. Per una copertura completa:

sudo nmap -sS -p- 192.168.1.10 # tutte le 65.535 porte
sudo nmap -p 22,80,443,3306 192.168.1.10 # porte specifiche
sudo nmap -p 1-1024 192.168.1.10 # un intervalloVa tenuto d’occhio anche l’UDP, spesso trascurato ma sede di servizi critici come DNS (53), SNMP (161) e NTP (123):

sudo nmap -sU -p 53,161,123 192.168.1.1Le scansioni UDP sono più lente perché una porta chiusa non sempre genera una risposta esplicita: conviene limitare l’intervallo di porte o armarsi di pazienza.

Version detection e OS fingerprintingSapere che la porta 22 è aperta è utile. Sapere che dietro c’è OpenSSH 8.9p1 lo è molto di più, soprattutto per intercettare versioni obsolete durante un audit di sicurezza:

sudo nmap -sV 192.168.1.10

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.6
80/tcp open http nginx 1.24.0
3306/tcp open mysql MySQL 8.0.35Con --version-intensity (da 0 a 9, default 7) si regola quanto nmap insiste nel probing: abbassarlo a 2-3 velocizza la scansione senza perdere molta precisione sui servizi comuni.

Per un’ipotesi sul sistema operativo, tramite fingerprinting dello stack TCP/IP, serve almeno una porta aperta e una chiusa:

sudo nmap -O 192.168.1.10Su macchine virtuali o stack TCP personalizzati la stima può essere imprecisa, ma resta un segnale utile per separare rapidamente server Linux, macchine Windows e dispositivi embedded su uno stesso segmento di rete.

Per un quadro completo in un colpo solo (OS detection, version detection, script scanning e traceroute) c’è la scansione aggressiva:

sudo nmap -A 192.168.1.10Genera molto traffico: da evitare su reti di produzione senza una finestra di manutenzione concordata.

Nmap Scripting Engine (NSE): oltre il semplice port scanLa vera potenza di nmap emerge con NSE, il motore di scripting che esegue controlli automatizzati sugli host scoperti: dalla ricerca di vulnerabilità note alla verifica di configurazioni deboli. Gli script risiedono in /usr/share/nmap/scripts/ e sono organizzati in categorie (default, auth, vuln, discovery, intrusive, safe).

Vulnerabilità note (categoria più invasiva, usarla con criterio)

sudo nmap --script=vuln 192.168.1.10

Accesso FTP anonimo

sudo nmap --script=ftp-anon -p 21 192.168.1.10

Header HTTP (spesso rivelano versioni software o debug info)

sudo nmap --script=http-headers -p 80,443 192.168.1.10

Open relay SMTP

sudo nmap --script=smtp-open-relay -p 25 192.168.1.20Un controllo rapido su porta 80/443 con http-headers capita spesso di far emergere header con versioni software esposte inutilmente: una correzione da cinque minuti che chiude una falla di information disclosure.

Output e automazionePer qualsiasi verifica che vada oltre il controllo estemporaneo, conviene salvare i risultati:

sudo nmap -sV 192.168.1.0/24 -oA scan_resultsIl flag -oA genera contemporaneamente output normale (.nmap), XML (.xml, utile per l’integrazione con altri strumenti e dashboard) e formato “grepable” (.gnmap), comodo per il parsing rapido da shell.

Combinazioni utili nel lavoro quotidiano# Solo porte effettivamente aperte, timing aggressivo su rete affidabile
sudo nmap -sS -T4 --open 192.168.1.10

Tutti i server SSH su una subnet

sudo nmap -p 22 --open -sV 192.168.1.0/24

Verifica che MySQL non sia esposto inutilmente

sudo nmap -p 3306 --open 192.168.1.0/24

Discovery + version scan solo sugli host realmente attivi

sudo nmap -sn 192.168.1.0/24 -oG - | grep "Up" | awk '{print $2}' | sudo nmap -sV -iL -MySQL esposto senza motivo è uno degli errori di configurazione più comuni e più pericolosi: una scansione mirata come quella sopra richiede due secondi e può intercettare il problema prima che lo trovi qualcun altro.

Nmap ha inoltre sei template di timing, da T0 (paranoico, lentissimo) a T5 (aggressivo): T3 è il default bilanciato, T4 va bene su reti locali affidabili, mentre su VPN o collegamenti lenti conviene scendere a T2 per evitare falsi negativi dovuti a pacchetti persi.

Porte filtrate: un segnale, non un fastidioNmap distingue tre stati: open, closed e filtered. Quest’ultimo indica che un firewall o un packet filter sta bloccando silenziosamente la sonda. Se compaiono molte porte filtrate su un server che non ti aspetti sia protetto da firewall, vale la pena indagare: potrebbe essere ufw, firewalld, un ruleset nftables o un security group del provider cloud. In ogni caso, è un’indicazione da non ignorare, e lo stesso principio vale per i probe di version detection e OS fingerprinting, che un firewall può alterare o azzerare.

ConclusioneNmap non si impara in un pomeriggio, ma i comandi visti coprono la maggior parte del lavoro quotidiano di un sistemista: discovery degli host, scansione delle porte, identificazione di servizi e versioni, script NSE per approfondire, e output strutturato per automazione o revisione successiva. La sequenza tipica è semplice: si parte con -sn per la discovery, si aggiunge -sV quando servono i dettagli sui servizi, e si porta NSE in campo quando serve scavare più a fondo. Timing prudente in produzione, aggressivo nel proprio lab: è una distinzione che vale la pena interiorizzare prima di lanciare la prima scansione su un ambiente che non si controlla del tutto.

Fonte originale: Hayden James, “nmap on Linux: Guide to Network Scanning and Discovery”, LinuxBlog.io.

#sicurezza #linux #guide #howto #tutorial #networking #nmap

0 0 0

Fail2ban su Linux: come configurarlo per bloccare davvero gli attacchi brute-force

Perché ogni server esposto a Internet ha bisogno di Fail2banBasta controllare i log di autenticazione di un qualunque server Linux raggiungibile da In

Altro...

Perché ogni server esposto a Internet ha bisogno di Fail2banBasta controllare i log di autenticazione di un qualunque server Linux raggiungibile da Internet per rendersi conto di un fatto scomodo: nel giro di poche ore compaiono centinaia di tentativi di accesso falliti su SSH, pannelli web o form di login. Non è un attacco mirato: sono scanner automatici che perlustrano di continuo intere sottoreti, alla ricerca di credenziali deboli o servizi mal configurati. Ignorare questo rumore di fondo non è un’opzione, ma bloccare manualmente ogni IP sospetto è impraticabile.

Fail2ban risolve il problema analizzando i log in tempo reale e bannando automaticamente, tramite il firewall, gli indirizzi IP che superano una soglia di tentativi falliti in una finestra temporale configurabile. È uno strumento maturo, leggero, presente nei repository di tutte le principali distribuzioni, ma la configurazione di default lascia molto sul tavolo: un bantime di 10 minuti, tanto per fare un esempio, è quasi inutile contro un attaccante automatizzato che può semplicemente aspettare e riprovare.

In questa guida vediamo come installare, configurare e soprattutto tunare Fail2ban per ottenere una protezione reale, con particolare attenzione agli scenari più comuni su un server di produzione: SSH, Nginx, firewall moderni basati su nftables e persistenza dei ban tra un reboot e l’altro.

I tre concetti chiave: filter, jail, actionPrima di mettere mano alla configurazione conviene avere chiaro il modello concettuale di Fail2ban, perché tutta la configurazione ruota attorno a tre elementi:

Filter: un insieme di espressioni regolari che individuano le righe di log corrispondenti a un tentativo di accesso fallito.

Jail: combina un filtro con il percorso del log da monitorare, le soglie di attivazione e l’azione da eseguire al superamento della soglia.

Action: cosa succede quando la soglia viene superata. Nella maggior parte dei casi è una regola firewall, ma può includere anche l’invio di una notifica via email.

Fail2ban include già filtri e jail pronti per decine di servizi (SSH, Apache, Nginx, Postfix, Dovecot…). Nella pratica quotidiana ci si limita ad abilitare le jail utili e a regolare qualche parametro.

InstallazioneFail2ban è disponibile nei repository ufficiali di tutte le distribuzioni principali.

Debian/Ubuntu:

sudo apt update
sudo apt install fail2banFedora / RHEL 9+ / Rocky / AlmaLinux:

sudo dnf install fail2banArch Linux:

sudo pacman -S fail2banAbilitiamo e avviamo il servizio, poi verifichiamo lo stato:

sudo systemctl enable --now fail2ban
sudo systemctl status fail2banSe lo stato non riporta active (running), i log vanno controllati con sudo journalctl -u fail2ban -n 50.

Configurare Fail2ban nel modo correttoUn errore comune è modificare direttamente /etc/fail2ban/jail.conf: questo file viene sovrascritto a ogni aggiornamento del pacchetto, con conseguente perdita delle personalizzazioni. L’approccio corretto è creare un file dedicato dentro jail.d/:

sudo nano /etc/fail2ban/jail.d/custom.confIn alternativa si può copiare il file di default in jail.local, che ha priorità sui valori in jail.conf:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localLa sezione [DEFAULT]Nella sezione [DEFAULT] si impostano i valori applicati a tutte le jail, salvo override specifico:

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1bantime: durata del ban. Il default (spesso 10 minuti) è troppo permissivo: 1 ora è un buon punto di partenza, e per attaccanti persistenti si può salire a 24h o 1w. Il valore -1 produce un ban permanente, da usare con cautela.

findtime: la finestra temporale in cui vengono contati i fallimenti.

maxretry: numero di tentativi falliti prima del ban. 5 è ragionevole per SSH, si può scendere a 3 per una postura più aggressiva.

ignoreip: gli IP che non verranno mai bannati. È fondamentale aggiungere qui il proprio IP prima di abilitare qualsiasi jail: restare fuori dal proprio server per un ban accidentale è un classico errore da evitare.

Se il server ha un indirizzo IPv6 pubblico, va incluso anche quello: alcuni filtri più datati intercettano solo IPv4, quindi conviene verificare che le jail catturino correttamente entrambi i protocolli.

La jail SSHÈ la jail più importante per la maggior parte dei server. In jail.local o in un nuovo file /etc/fail2ban/jail.d/sshd.conf:

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3
bantime = 1hSe SSH è stato spostato su una porta non standard (buona pratica consigliata), va aggiornata la riga port. Sui sistemi basati su systemd, %(sshd_log)s punta automaticamente al journal; sui sistemi più datati che usano /var/log/auth.log o /var/log/secure, Fail2ban gestisce la differenza tramite il parametro backend. Dopo ogni modifica alla configurazione:

sudo fail2ban-client reloadJail per NginxI server web attirano un tipo diverso di abuso: scanner di URL 404, bruteforcer su form di login, bot che generano richieste inutili.

[nginx-http-auth]
enabled = true
logpath = %(nginx_error_log)s
maxretry = 3

[nginx-limit-req]
enabled = true
logpath = %(nginx_error_log)s
maxretry = 10La jail nginx-limit-req intercetta i client che superano i limit_req configurati in Nginx: è una combinazione efficace se il server web è già stato ottimizzato per gestire traffico elevato. Se Fail2ban segnala che un percorso di log non esiste, va impostato esplicitamente, ad esempio logpath = /var/log/nginx/error.log.

Verificare jail e ban attiviIl comando fail2ban-client è lo strumento principale per monitorare la situazione. Elenco delle jail attive:

sudo fail2ban-client statusDettaglio di una jail specifica, comprensivo di IP attualmente bannati:

sudo fail2ban-client status sshdPer bannare o sbannare manualmente un IP:

sudo fail2ban-client set sshd banip 203.0.113.99
sudo fail2ban-client set sshd unbanip 203.0.113.99Il comando unbanip è quello da tenere a portata di mano nel caso in cui ci si banni da soli per errore, prima di aver aggiunto il proprio IP a ignoreip.

Ban incrementali con la jail recidiveUna delle funzionalità meno conosciute ma più efficaci di Fail2ban è la jail recidive, che monitora il log interno di Fail2ban stesso e applica ban molto più lunghi agli IP che, dopo la scadenza di un primo ban, tornano a fare bruteforcing.

[recidive]
enabled = true
logpath = /var/log/fail2ban.log
action = %(action_mwl)s
bantime = 1w
findtime = 1d
maxretry = 5Con questa configurazione, un IP bannato 5 volte in un giorno riceve un ban di una settimana: è l’equivalente più vicino a una blocklist persistente senza dover integrare feed di threat intelligence esterni. Su sistemi che scrivono solo sul journal, va impostato backend = systemd nella jail recidive, oppure va verificato che Fail2ban stia scrivendo un log tradizionale.

Testare i filtri prima di attivarliPrima di abilitare una jail, conviene verificare che il regex del filtro corrisponda davvero alle righe di log presenti sul sistema:

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.confL’output riporta gli IP individuati e il numero di righe che hanno fatto match. Un filtro che non intercetta nulla non protegge nulla: questo comando è indispensabile soprattutto quando si scrive un filtro personalizzato per un’applicazione custom, dentro /etc/fail2ban/filter.d/:

/etc/fail2ban/filter.d/myapp-auth.conf

[Definition]
failregex = ^<HOST> .* "POST /login" 401
ignoreregex =Il tag <HOST> è obbligatorio: Fail2ban lo sostituisce con un’espressione regolare che cattura l’indirizzo IP da bannare. Un pattern troppo generico rischia di bannare traffico legittimo, quindi va sempre validato con fail2ban-regex prima di collegarlo a una jail attiva.

nftables, firewalld e persistenza dei banSu Debian 12+ e Ubuntu 22.04+, nftables è il backend firewall di default. L’azione di ban predefinita di Fail2ban usa ancora iptables, che nella maggior parte delle installazioni funziona tramite il layer di compatibilità iptables-nft. Se invece si usa nftables puro, l’azione va impostata esplicitamente:

banaction = nftables-multiport
banaction_allports = nftables-allportsSu RHEL, Fedora e Rocky, dove firewalld è lo standard, va usata l’azione corrispondente:

banaction = firewallcmd-rich-rules
banaction_allports = firewallcmd-allportsPer default, i ban sono mantenuti in memoria e vengono persi a ogni riavvio. Per farli sopravvivere ai reboot va abilitato il database SQLite (su molte distribuzioni recenti è già attivo di default):

dbfile = /var/lib/fail2ban/fail2ban.sqlite3
dbpurgeage = 7dUna configurazione di partenza completaEcco un file /etc/fail2ban/jail.d/custom.conf che copre i casi d’uso più comuni su un server Linux tipico, da usare come punto di partenza:

[DEFAULT]
bantime = 2h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
dbpurgeage = 7d

[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3
bantime = 6h

[nginx-http-auth]
enabled = true
logpath = %(nginx_error_log)s
maxretry = 4

[nginx-limit-req]
enabled = true
logpath = %(nginx_error_log)s
maxretry = 10

[recidive]
enabled = true
logpath = /var/log/fail2ban.log
bantime = 1w
findtime = 1d
maxretry = 5sudo fail2ban-client reload
sudo fail2ban-client statusCosa Fail2ban non risolveFail2ban è uno strumento reattivo, non preventivo: banna un IP solo dopo che ha già effettuato diversi tentativi. Non copre, da solo, alcuni scenari:

attacchi bruteforce distribuiti su migliaia di IP diversi, ciascuno con uno o due tentativi soltanto;

exploit zero-day che non generano righe di log riconoscibili;

attacchi a livello applicativo che non producono un fallimento di autenticazione tracciabile.

Per una protezione a più livelli, Fail2ban va affiancato all’autenticazione SSH tramite chiavi (disabilitando del tutto l’autenticazione via password), a un firewall configurato correttamente e a una revisione periodica dei log. Un’attenzione particolare va riservata ai server dietro Cloudflare o un altro reverse proxy: senza ripristinare l’IP originale del visitatore (tramite mod_remoteip su Apache o real_ip_module su Nginx), Fail2ban finirebbe per bannare gli IP del proxy stesso invece degli attaccanti reali.

Comandi da tenere sempre a portata di manosudo fail2ban-client status — elenco di tutte le jail attive

sudo fail2ban-client status sshd — stato dettagliato di una jail

sudo fail2ban-client set sshd banip 1.2.3.4 — ban manuale di un IP

sudo fail2ban-client set sshd unbanip 1.2.3.4 — rimozione manuale di un ban

sudo fail2ban-client reload — ricarica la configurazione dopo una modifica

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf — test di un filtro

sudo tail -f /var/log/fail2ban.log — monitoraggio dei ban in tempo reale

ConclusioneFail2ban resta uno degli strumenti che meritano un posto fisso su ogni server Linux esposto a Internet: l’installazione richiede pochi minuti e già con una configurazione minima riduce in modo drastico il rumore generato da scanner SSH e probe automatizzati sui servizi web. La differenza reale, però, la fanno tre accorgimenti spesso trascurati: impostare un bantime ragionevole (il default di 10 minuti è quasi inutile), aggiungere sempre il proprio IP a ignoreip prima di abilitare le jail, e attivare la jail recidive per penalizzare chi insiste. Da soli, questi tre passaggi fanno la differenza tra un’installazione di default e una protezione che funziona davvero.

Fonte: Fail2ban on Linux: Protect Your Server from Brute-Force Attacks, LinuxBlog.io

#sicurezza #linux #howto #tutorial

0 0 0

Nginx e TLS nel 2026: le tecniche aggiornate per ridurre TTFB e latenza HTTPS

Nel 2026 quasi tutto il traffico web viaggia in HTTPS, ma quanto di quella cifratura sta ancora costando millisecondi inutili al vostro Time To First

Altro...

Nel 2026 quasi tutto il traffico web viaggia in HTTPS, ma quanto di quella cifratura sta ancora costando millisecondi inutili al vostro Time To First Byte? Molte configurazioni Nginx che giravano perfettamente nel 2020 oggi trascinano direttive deprecate, parametri OCSP che non fanno più nulla e cipher suite che TLS 1.3 ignora comunque. Vale la pena rimettere mano al blocco ssl_* del vostro server, non per inseguire un punteggio più alto su SSL Labs, ma perché ogni handshake più corto si moltiplica per il numero di visitatori.

Va detto subito, con onestà: il tuning TLS non salva un backend lento. Se il TTFB del vostro sito è dominato da query al database, cache fredda o un’applicazione PHP/.NET che impiega 800ms a costruire la pagina, ottimizzare l’handshake sposta l’ago di qualche decina di millisecondi. Ma è ottimizzazione a costo quasi zero, che si somma a tutto il resto: cache, CDN, query tuning. Va fatta bene una volta e poi dimenticata.

HTTP/2 e HTTP/3: la sintassi è cambiataSe la vostra configurazione risale a qualche anno fa, probabilmente avete ancora questa riga:

listen 443 ssl http2;Funziona ancora, ma da Nginx 1.25.1 il parametro http2 sulla direttiva listen è deprecato: lanciando nginx -t su una build recente comparirà un warning esplicito. La forma corretta separa i due concetti:

listen 443 ssl;
http2 on;La direttiva http2 attiva il protocollo per l’intero server block, il che è più pulito che ripeterlo su ogni riga listen. Se gestite una flotta di server dietro un load balancer, verificate che tutte le istanze montino Nginx 1.25.1 o superiore prima di effettuare lo switch: una versione più vecchia non riconosce http2 on; e si rifiuta di avviarsi.

Attivare HTTP/3 con QUIC senza compilare nullaFino a poco tempo fa, abilitare HTTP/3 su Nginx significava patchare e ricompilare da sorgente contro una libreria TLS con supporto QUIC: un esercizio che pochi sistemisti volevano affrontare in produzione. Quell’epoca è finita. Il supporto nativo a QUIC e HTTP/3 è arrivato nel mainline Nginx a partire dalla 1.25.0 ed è ormai maturo nel branch stable, quindi sulle distribuzioni recenti o sul repository ufficiale Nginx non serve più compilare nulla a mano.

Va detto che, nonostante l’entusiasmo degli anni scorsi, l’adozione reale di HTTP/3 procede più lentamente del previsto: a metà 2026 HTTP/2 serve poco più della metà delle richieste globali mentre HTTP/3 si attesta intorno al 21%, con un plateau che dura da diversi mesi. Parte del motivo è strutturale: un browser passa a HTTP/3 solo dopo aver scoperto il supporto tramite un header Alt-Svc o un record DNS, quindi molte prime visite non negoziano mai QUIC. Vale comunque la pena abilitarlo: sposta il trasporto su UDP ed elimina l’head-of-line blocking di TCP, un vantaggio concreto su connessioni mobili lente o con perdita di pacchetti.

Su Nginx 1.25.0 o superiore con supporto QUIC integrato, un server block tipico è:

server {
listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic reuseport;
listen [::]:443 quic reuseport;

http2 on;

ssl_certificate     /path/to/your/certificate.pem;
ssl_certificate_key /path/to/your/key.pem;

# Annuncia HTTP/3 ai client che arrivano via HTTP/1.1 o HTTP/2
add_header Alt-Svc 'h3=":443"; ma=86400';

# ... resto della configurazione del server

}Attenzione a reuseport: va specificato una sola volta per combinazione IP/porta. Se gestite più server block sullo stesso indirizzo, mettete reuseport solo sul blocco predefinito e usate listen 443 quic; sugli altri, altrimenti Nginx si rifiuta di partire.

L’header Alt-Svc è il dettaglio che quasi tutti dimenticano: senza di esso i browser non hanno modo di sapere che il server parla HTTP/3 e restano su HTTP/2. Dopo la modifica, testate e ricaricate:

nginx -t
nginx -s reloadPer verificare rapidamente da riga di comando quale protocollo state effettivamente servendo:

curl --http2 -I https://vostrodominio.it/
curl --http3 -I https://vostrodominio.it/Session cache e session ticket: il vero risparmio sull’handshakeCon HTTPS, invece di una singola andata e ritorno, la connessione richiede un handshake aggiuntivo. Attivare la cache delle sessioni TLS riduce questo costo per le connessioni ripetute:

ssl_session_cache shared:SSL:10m; # circa 40.000 sessioni
ssl_session_timeout 1d; # tempo di riutilizzo della sessioneSui session ticket la raccomandazione è cambiata rispetto a qualche anno fa. Un tempo si consigliava di disabilitarli perché la rotazione della chiave di cifratura non era gestita correttamente da Nginx. Da Nginx 1.23.2 in poi la gestione delle chiavi per la ripresa stateless delle sessioni è molto migliorata, quindi salvo casi particolari conviene tenerli attivi:

ssl_session_tickets on;Unica eccezione: se gestite più server Nginx dietro un bilanciatore senza sincronizzare le chiavi dei ticket tra le istanze, la ripresa della sessione si rompe silenziosamente e perdete il beneficio. In quel caso, sincronizzate le chiavi o disabilitate i ticket su tutta la flotta in modo coerente.

Quali versioni TLS tenere attiveTLS 1.0 e 1.1 sono obsoleti, bloccati da ogni browser moderno e vietati dallo standard PCI DSS: vanno disattivati ovunque, senza eccezioni. La vera decisione riguarda invece TLS 1.2 e 1.3.

Per la maggior parte dei siti pubblici, la scelta corretta è tenere entrambi attivi:

ssl_protocols TLSv1.2 TLSv1.3;È TLS 1.3 a fare la differenza sul TTFB: riduce l’handshake a un singolo round trip e supporta la ripresa di sessione, quindi i visitatori che tornano si connettono più rapidamente. TLS 1.2 resta come fallback per client più datati e, su un sito pubblico normale, non costa nulla lasciarlo attivo.

Passate a TLS 1.3 soltanto se controllate i client che si connettono: un’API interna, un backend applicativo, un servizio dove sapete con certezza che nessun client datato deve collegarsi:

ssl_protocols TLSv1.3;Disabilitare TLS 1.2 su un sito pubblico è il tipo di modifica che sembra pulita in un file di configurazione e poi silenziosamente taglia fuori una fetta di traffico reale. Senza un motivo specifico, lasciatelo acceso.

OCSP stapling: cosa è cambiato con Let’s EncryptL’OCSP stapling permette a Nginx di allegare all’handshake una prova firmata dalla CA della validità del certificato, evitando che il client debba interrogare direttamente il servizio OCSP. La configurazione classica resta questa:

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/full_chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;Ma qui c’è un cambiamento importante da conoscere se usate Let’s Encrypt: il 6 agosto 2025 Let’s Encrypt ha terminato il supporto OCSP e spento i propri responder. I certificati che emette oggi non hanno più un URL OCSP, ma un URL CRL al suo posto. Senza un responder da interrogare, ssl_stapling on; non fa più nulla sui certificati Let’s Encrypt e Nginx registra nei log un warning "ssl_stapling" ignored, no OCSP responder URL.

Il bilancio onesto nel 2026 è questo: se la vostra CA pubblica ancora un URL OCSP, lo stapling resta un piccolo vantaggio innocuo e potete tenerlo attivo. Se siete su Let’s Encrypt, le direttive sopra sono ormai inerti e potete rimuoverle per tenere puliti configurazione e log. È parte di uno spostamento più ampio del settore verso CRL e certificati a vita breve.

Buffer SSL più piccolo per ridurre il TTFBIl parametro ssl_buffer_size imposta la dimensione del buffer usato per inviare dati via HTTPS. Il valore predefinito è 16k, pensato per risposte di grandi dimensioni, ma per minimizzare il TTFB conviene spesso un valore più piccolo:

ssl_buffer_size 4k;Il risparmio tipico è di 30-50 millisecondi sul TTFB, variabile a seconda del carico e delle dimensioni medie delle risposte servite.

Configurazione completa consigliata per il 2026http2 on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets on;
ssl_buffer_size 4k;

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header X-Frame-Options sameorigin;
add_header X-Content-Type-Options nosniff;Da notare: con TLS 1.3 le cipher suite sono fissate dal protocollo stesso, quindi una lunga stringa ssl_ciphers personalizzata e una direttiva ssl_ecdh_curve manuale non portano quasi nessun beneficio. I cipher elencati sopra si applicano soltanto alle connessioni TLS 1.2, e ssl_prefer_server_ciphers va disattivato perché i client moderni scelgono in modo sensato per conto proprio. Piuttosto che ottimizzare a mano all’infinito, generate una configurazione aggiornata con il Mozilla SSL Configuration Generator e incollate solo le parti che vi servono.

Se avete ancora in configurazione una riga X-Xss-Protection "1; mode=block", rimuovetela: l’XSS auditor del browser che controllava è stato eliminato da tutti i browser principali, e in alcuni casi quell’header può addirittura introdurre vulnerabilità invece di prevenirle. Una Content-Security-Policy è il sostituto moderno.

ConclusioneNessuna di queste modifiche, presa singolarmente, trasformerà le prestazioni del vostro sito. Ma insieme costituiscono un livello di ottimizzazione a costo pressoché nullo che qualsiasi sistemista dovrebbe verificare almeno una volta l’anno, specialmente dopo un major upgrade di Nginx o un rinnovo dell’infrastruttura dei certificati. Testate sempre con nginx -t prima di ricaricare, verificate il risultato con SSL Labs e con l’ispezione della colonna Protocol negli strumenti di sviluppo del browser, e ricordate che il vero collo di bottiglia, nella maggior parte dei casi, resta ciò che succede dopo l’handshake: cache, query e tempo di generazione della risposta.

Fonte: Nginx tuning tips: HTTPS/TLS – Turbocharge TTFB/Latency, LinuxBlog.io (Hayden James).

#sicurezza #linux #tutorial #performance #nginx #tlsssl

0 0 0

Swap attivo con RAM libera? Ecco come scoprire il processo colpevole con smem su Linux

Perché il tuo server usa swap con RAM libera (e come scoprire chi è il colpevole con smem)Capita spesso: un server ha 32 o 64 GB di RAM, il carico è t

Altro...

Perché il tuo server usa swap con RAM libera (e come scoprire chi è il colpevole con smem)Capita spesso: un server ha 32 o 64 GB di RAM, il carico è tutto sommato modesto, eppure free -h mostra qualche centinaio di MB o addirittura qualche GB in swap. Il riflesso istintivo di molti sistemisti è colpevolizzare la RAM insufficiente e chiedere un upgrade. Nella maggior parte dei casi, però, il problema non è la quantità di memoria disponibile, ma quali processi stanno finendo in swap e perché. Per rispondere serve uno strumento che guardi dentro ai singoli processi, non solo ai numeri aggregati: smem.

Perché Linux usa lo swap anche con RAM liberaIl kernel Linux non tratta la RAM come una risorsa da tenere il più vuota possibile: la usa aggressivamente per la page cache, per velocizzare I/O su file e librerie. Quando il kernel individua pagine di memoria che non vengono acquisite/toccate da tempo, può decidere di spostarle in swap per liberare RAM fisica da destinare alla cache, anche se tecnicamente c’è ancora memoria “libera” disponibile. Questo comportamento è regolato dal parametro vm.swappiness (0-100, con default storicamente a 60 su molte distribuzioni), che indica al kernel quanto è propenso a scambiare memoria anonima verso lo swap piuttosto che liberare pagine di cache.

Il punto chiave: prima di toccare vm.swappiness alla cieca, bisogna sapere chi sta effettivamente occupando swap. Un valore aggregato come quello di free non lo dice. Serve la vista per processo.

smem: memoria proporzionale, non solo RSSTool classici come top o ps mostrano RSS (Resident Set Size), che però ha un difetto noto: se due processi condividono le stesse pagine di memoria (librerie condivise, memoria mappata), quella memoria viene contata per intero in ognuno dei due, gonfiando artificialmente i numeri quando si sommano i processi.

smem risolve il problema calcolando anche:

USS (Unique Set Size): memoria usata esclusivamente da quel processo, non condivisa con nessun altro — utile per capire quanto libereresti davvero uccidendo il processo

PSS (Proportional Set Size): memoria condivisa divisa proporzionalmente tra i processi che la usano — la metrica più corretta per sommare l’uso reale di memoria di un sistema senza doppi conteggi

Swap: quanta memoria di quello specifico processo è stata spostata su disco

Installazionesmem non è quasi mai preinstallato, ma è nei repository di tutte le principali distribuzioni:

RHEL / CentOS / AlmaLinux / Fedora

dnf install smem

Debian / Ubuntu

apt install smemUso pratico: trovare chi consuma swapIl comando base per ordinare i processi per swap consumato:

smem -rs swapOutput tipico (troncato):

PID User Command Swap USS PSS RSS
28986 mysql /usr/sbin/mysqld --daemon 476372 10963864 10963932 10965112
29152 root /usr/sbin/rsyslogd -n 371424 3956 17475 43352
31423 root /opt/fluent-bit/bin/fluent 22508 26612 26739 29100Da un output così è immediato capire che mysqld e rsyslogd sono i principali responsabili dell’uso di swap su questo host, e non un generico “poca RAM”. Da qui l’indagine si sposta su quel servizio specifico: per MySQL, ad esempio, tipicamente significa rivedere innodb_buffer_pool_size rispetto alla RAM totale disponibile, o verificare connessioni/thread che allocano memoria inutilmente.

Alcune varianti utili del comando:

Ordina per USS (memoria realmente esclusiva del processo)

smem -rs uss

Filtra per utente

smem -u

Vista grafica a torta per RSS (richiede matplotlib)

smem --pie name -s rssDalla diagnosi al tuningUna volta identificati i servizi che finiscono in swap, ci sono due strade complementari:

Agire sul servizio: ridimensionare i buffer/pool applicativi (buffer pool di MySQL, heap JVM, cache applicative) in base alla RAM effettivamente disponibile, invece di lasciare valori di default pensati per macchine generiche.

Agire sul kernel, solo dopo aver capito il quadro reale: ridurre vm.swappiness per rendere il kernel meno aggressivo nello spostare memoria anonima in swap:

sysctl vm.swappiness=1
echo 'vm.swappiness=1' >> /etc/sysctl.confDa notare che vm.swappiness=0 non disabilita completamente lo swap su kernel recenti (dal 3.5 in poi il comportamento è cambiato rispetto alle versioni più vecchie), mentre valori molto bassi come 1 riducono drasticamente la propensione allo swap mantenendo comunque una valvola di sicurezza in caso di pressione di memoria reale. Su un database server dedicato, dove si preferisce quasi sempre tenere i dati “caldi” in RAM piuttosto che liberare cache, è una delle prime ottimizzazioni da considerare.

ConclusioneVedere swap attivo su un server con RAM apparentemente libera non è di per sé un allarme: è il comportamento normale di un kernel che ottimizza l’uso della cache. Il problema comincia quando lo swap coinvolge processi critici per la latenza, come un database o un servizio applicativo, degradando le performance in modo silenzioso. smem -rs swap è il primo comando da lanciare in questi casi: in pochi secondi isola il processo responsabile, distingue la memoria condivisa da quella esclusiva, e trasforma un sintomo generico (“il server è lento”) in un’azione concreta di tuning, sul servizio o sul kernel.

Fonte: LinuxBlog.io, “Diagnosing Swap Usage with smem on Linux”.

#linux #howto #tutorial #performance #swap

0 0 0