<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DebianItalia on DebianItalia - download ISO, mirror e repository Debian</title><link>https://debianitalia.it/</link><description>Recent content in DebianItalia on DebianItalia - download ISO, mirror e repository Debian</description><generator>Hugo</generator><language>it</language><lastBuildDate>Mon, 16 Mar 2026 00:10:00 +0100</lastBuildDate><atom:link href="https://debianitalia.it/index.xml" rel="self" type="application/rss+xml"/><item><title>FTP anonimo con vsftpd: porta 21</title><link>https://debianitalia.it/wiki/how-to/vsftpd-ftp-anonimo-port-forwarding/</link><pubDate>Mon, 16 Mar 2026 00:10:00 +0100</pubDate><guid>https://debianitalia.it/wiki/how-to/vsftpd-ftp-anonimo-port-forwarding/</guid><description>&lt;p&gt;Se ti serve un server FTP pubblico e semplice da usare, &lt;code&gt;vsftpd&lt;/code&gt; resta una scelta stabile e leggera.
In questa guida configuriamo un FTP &lt;strong&gt;anonimo&lt;/strong&gt; su Debian e apriamo la porta &lt;strong&gt;21&lt;/strong&gt; dal router in modo corretto.&lt;/p&gt;
&lt;h2 id="1-requisiti-e-note-importanti"&gt;&lt;strong&gt;1) Requisiti e note importanti&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Prima di iniziare:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;server Debian aggiornato&lt;/li&gt;
&lt;li&gt;accesso root o sudo&lt;/li&gt;
&lt;li&gt;IP locale statico sul server (es. &lt;code&gt;192.168.1.50&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;accesso al pannello del router&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nota sicurezza: FTP classico non cifra il traffico. Se devi trasferire dati sensibili, valuta SFTP o FTPS.&lt;/p&gt;</description></item><item><title>Chiavetta USB avviabile (Windows/Linux)</title><link>https://debianitalia.it/wiki/how-to/chiavetta-usb-guida/</link><pubDate>Sun, 15 Mar 2026 22:10:00 +0100</pubDate><guid>https://debianitalia.it/wiki/how-to/chiavetta-usb-guida/</guid><description>&lt;p&gt;Una chiavetta USB avviabile è indispensabile per installare sistemi operativi, fare recovery o ripristinare macchine che non partono.
In questa guida trovi un percorso completo, con i metodi più affidabili.&lt;/p&gt;
&lt;p&gt;Per scaricare la ISO usa sempre la sezione &lt;a href="https://debianitalia.it/downloads/"&gt;Downloads&lt;/a&gt; di DebianItalia.&lt;/p&gt;
&lt;h2 id="1-cosa-ti-serve"&gt;&lt;strong&gt;1) Cosa ti serve&lt;/strong&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;chiavetta USB da almeno 8 GB&lt;/li&gt;
&lt;li&gt;file ISO valido del sistema operativo&lt;/li&gt;
&lt;li&gt;PC con accesso a boot menu/BIOS&lt;/li&gt;
&lt;li&gt;tool di scrittura (Rufus, balenaEtcher, UNetbootin o equivalente)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="2-metodo-consigliato-su-windows-rufus"&gt;&lt;strong&gt;2) Metodo consigliato su Windows: Rufus&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Rufus è rapido e affidabile nella maggior parte dei casi.&lt;/p&gt;</description></item><item><title>Installare Debian 13: guida completa</title><link>https://debianitalia.it/wiki/how-to/installare-debian-guida/</link><pubDate>Sun, 15 Mar 2026 22:05:00 +0100</pubDate><guid>https://debianitalia.it/wiki/how-to/installare-debian-guida/</guid><description>&lt;p&gt;Installare Debian 13 non è difficile, ma fare i passaggi nell’ordine giusto evita errori e perdite di tempo.
Questa guida segue il flusso reale di installazione, con consigli pratici e impostazioni consigliate.&lt;/p&gt;
&lt;h2 id="1-prima-di-iniziare-requisiti-e-backup"&gt;&lt;strong&gt;1) Prima di iniziare: requisiti e backup&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Controlla di avere:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPU da almeno 1 GHz&lt;/li&gt;
&lt;li&gt;minimo 1 GB RAM (consigliati 2+ GB)&lt;/li&gt;
&lt;li&gt;almeno 10 GB liberi su disco (meglio 20+ GB)&lt;/li&gt;
&lt;li&gt;una chiavetta USB da 8 GB&lt;/li&gt;
&lt;li&gt;backup completo dei dati importanti&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Se devi ancora creare il supporto, usa la guida su &lt;a href="https://debianitalia.it/wiki/how-to/chiavetta-usb-guida/"&gt;chiavetta USB avviabile&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Guida introduttiva alla Wiki DebianItalia</title><link>https://debianitalia.it/wiki/hello-world/getting-started-debian-wiki/</link><pubDate>Sun, 15 Mar 2026 10:30:00 +0100</pubDate><guid>https://debianitalia.it/wiki/hello-world/getting-started-debian-wiki/</guid><description>&lt;p&gt;Benvenuto nella nuova sezione Wiki di DebianItalia.&lt;/p&gt;
&lt;p&gt;Questa area nasce per raccogliere guide tecniche chiare, affidabili e utili a tutta la community Debian.
L&amp;rsquo;obiettivo è condividere conoscenza pratica, migliorare il supporto tra utenti e creare nel tempo una base documentale sempre più completa.&lt;/p&gt;
&lt;p&gt;Se vuoi contribuire, puoi inviare le tue guide su temi come:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;installazione e configurazione di pacchetti&lt;/li&gt;
&lt;li&gt;desktop environment e ottimizzazioni&lt;/li&gt;
&lt;li&gt;librerie, strumenti di sviluppo e automazione&lt;/li&gt;
&lt;li&gt;troubleshooting e risoluzione problemi&lt;/li&gt;
&lt;li&gt;buone pratiche per server e sistemi desktop&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ogni contributo selezionato verrà pubblicato con autore, data, categorie e link di condivisione.&lt;/p&gt;</description></item><item><title>Downloads</title><link>https://debianitalia.it/downloads/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://debianitalia.it/downloads/</guid><description>&lt;h2 class="di-page-section-title"&gt;Uso rapido&lt;/h2&gt;
&lt;p class="di-muted"&gt;Scegli distribuzione e versione per ottenere il link diretto all'ISO, insieme ai comandi wget e curl già pronti da copiare. Il catalogo viene letto dal mirror e si aggiorna con le immagini disponibili, così passi subito al download senza cercare a mano l'URL&lt;/p&gt;
&lt;div class="di-box"&gt;
 &lt;div class="di-grid two"&gt;
 &lt;div&gt;
 &lt;label for="di-distro"&gt;&lt;strong&gt;Distribuzione&lt;/strong&gt;&lt;/label&gt;
 &lt;select id="di-distro"&gt;&lt;option value=""&gt;Seleziona distro&lt;/option&gt;&lt;/select&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;label for="di-version"&gt;&lt;strong&gt;Versione&lt;/strong&gt;&lt;/label&gt;
 &lt;select id="di-version" disabled&gt;&lt;option value=""&gt;Seleziona versione&lt;/option&gt;&lt;/select&gt;
 &lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;div id="di-result" class="di-box" style="display:none"&gt;
 &lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;a id="di-link" href="#" target="_blank" rel="noopener"&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;div class="di-copy-head"&gt;
 &lt;strong&gt;wget&lt;/strong&gt;
 &lt;button id="di-copy-wget" class="di-copy-btn" type="button"&gt;Copia&lt;/button&gt;
 &lt;/div&gt;
 &lt;textarea id="di-wget" rows="3" readonly&gt;&lt;/textarea&gt;
 &lt;div class="di-copy-head"&gt;
 &lt;strong&gt;curl&lt;/strong&gt;
 &lt;button id="di-copy-curl" class="di-copy-btn" type="button"&gt;Copia&lt;/button&gt;
 &lt;/div&gt;
 &lt;textarea id="di-curl" rows="3" readonly&gt;&lt;/textarea&gt;
&lt;/div&gt;
&lt;script&gt;
(function () {
 const distro = document.getElementById('di-distro');
 const version = document.getElementById('di-version');
 const box = document.getElementById('di-result');
 const link = document.getElementById('di-link');
 const wget = document.getElementById('di-wget');
 const curl = document.getElementById('di-curl');
 const copyWget = document.getElementById('di-copy-wget');
 const copyCurl = document.getElementById('di-copy-curl');
 let data = {};

 function cleanUrl(raw) {
 try {
 const u = new URL((raw || '').trim(), window.location.origin);
 if (u.protocol !== 'http:' &amp;&amp; u.protocol !== 'https:') return '';
 u.hash = '';
 return u.toString();
 } catch (_) {
 return '';
 }
 }

 function filenameFromUrl(raw) {
 try {
 const u = new URL(raw);
 const path = u.pathname.split('/').filter(Boolean).pop() || 'download.iso';
 return decodeURIComponent(path);
 } catch (_) {
 return 'download.iso';
 }
 }

 async function copyText(btn, text) {
 if (!text) return;
 try {
 await navigator.clipboard.writeText(text);
 const old = btn.textContent;
 btn.textContent = 'Copiato';
 setTimeout(function () { btn.textContent = old; }, 1100);
 } catch (_) {
 const ta = document.createElement('textarea');
 ta.value = text;
 ta.style.position = 'fixed';
 ta.style.left = '-9999px';
 document.body.appendChild(ta);
 ta.focus();
 ta.select();
 document.execCommand('copy');
 document.body.removeChild(ta);
 }
 }

 function populateDistro() {
 distro.innerHTML = '&lt;option value=""&gt;Seleziona distro&lt;/option&gt;';
 Object.keys(data).sort().forEach(name =&gt; {
 const o = document.createElement('option');
 o.value = name;
 o.textContent = name;
 distro.appendChild(o);
 });
 }

 async function loadIsos() {
 const endpoints = ['/api/isos', '/data/isos.json'];
 for (const ep of endpoints) {
 try {
 const res = await fetch(ep, { cache: 'no-store' });
 if (!res.ok) continue;
 const json = await res.json();
 if (json &amp;&amp; typeof json === 'object') {
 data = json;
 populateDistro();
 return;
 }
 } catch (_) {}
 }
 const o = document.createElement('option');
 o.value = '';
 o.textContent = 'Errore nel caricamento catalogo ISO';
 distro.appendChild(o);
 }

 distro.addEventListener('change', () =&gt; {
 version.innerHTML = '&lt;option value=""&gt;Seleziona versione&lt;/option&gt;';
 box.style.display = 'none';
 const entries = data[distro.value] || {};
 Object.entries(entries).forEach(([name, rawUrl]) =&gt; {
 const url = cleanUrl(rawUrl);
 if (!url) return;
 const o = document.createElement('option');
 o.value = url;
 o.textContent = name;
 version.appendChild(o);
 });
 version.disabled = version.options.length &lt;= 1;
 });

 version.addEventListener('change', () =&gt; {
 if (!version.value) {
 box.style.display = 'none';
 return;
 }
 const url = cleanUrl(version.value);
 if (!url) {
 box.style.display = 'none';
 return;
 }
 const file = filenameFromUrl(url);
 link.href = url;
 link.textContent = file;
 wget.value = `wget -O "${file}" "${url}"`;
 curl.value = `curl -L "${url}" -o "${file}"`;
 box.style.display = 'block';
 });

 copyWget.addEventListener('click', () =&gt; copyText(copyWget, wget.value));
 copyCurl.addEventListener('click', () =&gt; copyText(copyCurl, curl.value));
 loadIsos();
})();
&lt;/script&gt;</description></item><item><title>Links</title><link>https://debianitalia.it/links/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://debianitalia.it/links/</guid><description>&lt;ul&gt;
&lt;li&gt;🌐 &lt;a href="https://www.debian.org/"&gt;Sito ufficiale Debian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;📚 &lt;a href="https://www.debian.org/doc/"&gt;Documentazione Debian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;💾 &lt;a href="https://www.debian.org/distrib/netinst"&gt;Netinst ISO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;📀 &lt;a href="https://www.debian.org/CD/"&gt;Immagini complete&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;🧪 &lt;a href="https://www.debian.org/devel/debian-installer/"&gt;Testing installer images&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>News</title><link>https://debianitalia.it/news/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://debianitalia.it/news/</guid><description>&lt;h2 class="di-page-section-title"&gt;Ultime notizie&lt;/h2&gt;
&lt;p class="di-muted"&gt;Raccogliamo feed RSS da comunità Linux e Debian italiane per avere una panoramica rapida di aggiornamenti, guide e articoli utili. La lista si aggiorna automaticamente e deduplica le entry, così leggi solo gli elementi più rilevanti&lt;/p&gt;
&lt;div class="di-box"&gt;
 &lt;h4&gt;Latest entries&lt;/h4&gt;
 &lt;div id="news-status" class="di-muted"&gt;Caricamento feed in corso...&lt;/div&gt;
 &lt;div id="news-list"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
(function () {
 var feeds = [
 'https://www.ils.org/rss.xml',
 'https://www.ubuntu-it.org/news/feed',
 'https://www.intopic.it/rss/tecnologia/linux/',
 'https://www.miamammausalinux.org/feed/',
 'https://planet.linux.it/lug/rss.xml'
 ];
 var status = document.getElementById('news-status');
 var list = document.getElementById('news-list');

 function decodeEntities(input) {
 return (input || '')
 .replace(/&lt;!\[CDATA\[([\s\S]*?)\]\]&gt;/g, '$1')
 .replace(/&amp;#x([0-9a-f]+);/gi, function (_, h) { return String.fromCodePoint(parseInt(h, 16)); })
 .replace(/&amp;#([0-9]+);/g, function (_, d) { return String.fromCodePoint(parseInt(d, 10)); })
 .replace(/&amp;amp;/g, '&amp;')
 .replace(/&amp;lt;/g, '&lt;')
 .replace(/&amp;gt;/g, '&gt;')
 .replace(/&amp;quot;/g, '"')
 .replace(/&amp;#39;/g, "'");
 }

 function stripTags(raw) {
 return decodeEntities((raw || '').replace(/&lt;[^&gt;]+&gt;/g, ' '))
 .replace(/\]\]&gt;\s*$/g, '')
 .replace(/\s+/g, ' ')
 .trim();
 }

 function cleanLink(raw) {
 try {
 var u = new URL((raw || '').trim());
 if (u.protocol !== 'http:' &amp;&amp; u.protocol !== 'https:') return '';
 u.hash = '';
 return u.toString();
 } catch (_) {
 return '';
 }
 }

 function isNoisyTitle(text) {
 var t = (text || '').toLowerCase().trim();
 if (!t || t === 'untitled') return true;
 return t.indexOf(']]&gt;') !== -1 || t.indexOf('canali:') === 0 || t.indexOf('[ canali:') === 0 || t.indexOf('tags:') === 0;
 }

 function cleanDescriptionForTitle(text) {
 return stripTags(text || '')
 .replace(/\s*\|\s*canali\s*:.*$/i, '')
 .replace(/\s*canali\s*:.*$/i, '')
 .replace(/\s*tags\s*:.*$/i, '')
 .trim();
 }

 function looksLikeHostPathTitle(text) {
 return /^[a-z0-9.-]+\.[a-z]{2,}\s*\/\s*[a-z0-9._-]+$/i.test((text || '').trim());
 }

 function safeTitle(title, desc) {
 var t = stripTags(title || '');
 if (t &amp;&amp; !isNoisyTitle(t) &amp;&amp; !looksLikeHostPathTitle(t)) return t;
 var d = cleanDescriptionForTitle(desc || '');
 if (d &amp;&amp; !isNoisyTitle(d) &amp;&amp; !looksLikeHostPathTitle(d)) return d.length &gt; 140 ? d.slice(0, 137) + '...' : d;
 return '';
 }

 function dedupeSort(items) {
 var seen = {};
 return (items || [])
 .filter(function (x) {
 var k = (x &amp;&amp; x.link ? x.link : '') + '|' + (x &amp;&amp; x.title ? x.title : '');
 if (!k || seen[k]) return false;
 seen[k] = true;
 return true;
 })
 .sort(function (a, b) {
 var ta = new Date(a.pubDate || 0).getTime() || 0;
 var tb = new Date(b.pubDate || 0).getTime() || 0;
 return tb - ta;
 })
 .slice(0, 60);
 }

 function render(items, ok, total) {
 var rows = dedupeSort(items);
 status.textContent = 'Feeds online: ' + ok + '/' + total + ' | Entries: ' + rows.length;
 if (!rows.length) {
 list.innerHTML = '&lt;p class="di-muted"&gt;Nessuna entry disponibile al momento.&lt;/p&gt;</description></item><item><title>Packages</title><link>https://debianitalia.it/packages/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://debianitalia.it/packages/</guid><description>&lt;h2 class="di-page-section-title"&gt;Ricerca pacchetti&lt;/h2&gt;
&lt;p class="di-muted"&gt;Cerca i pacchetti Debian nel mirror italiano e controlla il lag del repository in tempo reale. La ricerca live ti aiuta a trovare velocemente nome, descrizione e versione, senza uscire dal portale&lt;/p&gt;
&lt;div class="di-box"&gt;
 &lt;h3&gt;Mirror Status&lt;/h3&gt;
 &lt;p id="mirror-status" class="di-muted"&gt;Caricamento stato mirror...&lt;/p&gt;
&lt;/div&gt;
&lt;div class="di-box di-grid"&gt;
 &lt;label for="pkg-q"&gt;&lt;strong&gt;Cerca pacchetto Debian&lt;/strong&gt;&lt;/label&gt;
 &lt;input id="pkg-q" type="text" placeholder="es. nginx, bash, coreutils" autocomplete="off"&gt;
 &lt;p id="pkg-status" class="di-muted"&gt;Digita almeno 2 caratteri per avviare la ricerca live.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="pkg-results-wrap" class="di-box" style="display:none"&gt;
 &lt;h4&gt;Risultati&lt;/h4&gt;
 &lt;p id="pkg-results-meta" class="di-muted"&gt;&lt;/p&gt;
 &lt;div id="pkg-results-list"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
(function () {
 const statusEl = document.getElementById('mirror-status');
 const qEl = document.getElementById('pkg-q');
 const pkgStatus = document.getElementById('pkg-status');
 const wrap = document.getElementById('pkg-results-wrap');
 const meta = document.getElementById('pkg-results-meta');
 const list = document.getElementById('pkg-results-list');

 let searchTimer = null;
 let requestSeq = 0;

 function esc(str) {
 return String(str || '')
 .replace(/&amp;/g, '&amp;amp;')
 .replace(/&lt;/g, '&amp;lt;')
 .replace(/&gt;/g, '&amp;gt;')
 .replace(/"/g, '&amp;quot;')
 .replace(/'/g, '&amp;#39;');
 }

 async function loadMirrorStatus() {
 try {
 const r = await fetch('/api/mirror-status', { cache: 'no-store' });
 if (r.ok) {
 const j = await r.json();
 const lag = Number(j.lag_min);
 if (Number.isFinite(lag) &amp;&amp; lag &gt;= 0) {
 statusEl.textContent = `Mirror deb.debianitalia.it: online, lag ${lag} min`;
 return;
 }
 }
 } catch (_) {}

 try {
 const r2 = await fetch('/data/mirror_status.json', { cache: 'no-store' });
 const j2 = await r2.json();
 const key = 'deb.debianitalia.it/debian_stable_Release';
 const lag = j2 &amp;&amp; j2.data &amp;&amp; j2.data[key] ? Number(j2.data[key].lag_min) : NaN;
 if (Number.isFinite(lag) &amp;&amp; lag &gt;= 0) {
 statusEl.textContent = `Mirror deb.debianitalia.it: online, lag ${lag} min`;
 } else {
 statusEl.textContent = 'Mirror deb.debianitalia.it: stato non disponibile';
 }
 } catch (_) {
 statusEl.textContent = 'Mirror deb.debianitalia.it: impossibile caricare lo stato';
 }
 }

 function renderResults(items) {
 if (!items || !items.length) {
 wrap.style.display = 'block';
 meta.textContent = 'Nessun risultato trovato.';
 list.innerHTML = '';
 return;
 }

 wrap.style.display = 'block';
 list.innerHTML = items.map(function (it) {
 const name = esc(it.name);
 const desc = esc(it.description || '');
 const version = esc(it.version || 'n/a');
 const suite = esc(it.suite || '');
 const section = esc(it.section || '');
 const link = esc(it.url || '');
 const line = ['version ' + version, suite, section].filter(Boolean).join(' | ');

 return (
 '&lt;article class="pkg-result-item"&gt;' +
 '&lt;h5&gt;&lt;a href="' + link + '" target="_blank" rel="noopener"&gt;' + name + '&lt;/a&gt;&lt;/h5&gt;' +
 '&lt;p class="pkg-result-desc"&gt;' + desc + '&lt;/p&gt;</description></item><item><title>Paste</title><link>https://debianitalia.it/paste/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://debianitalia.it/paste/</guid><description>&lt;h2 class="di-page-section-title"&gt;Editor rapido&lt;/h2&gt;
&lt;p class="di-muted"&gt;Usa il pastebin per scrivere o incollare note, snippet, log e comandi da condividere al volo. Il layout è minimale per arrivare subito all'azione: puoi copiare il testo, scaricare un file .txt o generare un link condivisibile in pochi secondi&lt;/p&gt;
&lt;div class="di-box" style="padding:0;overflow:hidden;"&gt;
 &lt;div style="background:#0b1f78;color:#dbe4ff;padding:8px 12px;font-family:monospace;"&gt;GNU nano 7.2 /paste.txt&lt;/div&gt;
 &lt;textarea id="nano-editor" style="width:100%;min-height:380px;border:0;padding:12px;font-family:monospace;resize:vertical;background:#1F1F1F;color:#ECECEC;line-height:1.35;"&gt;&lt;/textarea&gt;
 &lt;div id="nano-status" style="background:#2a2a2a;color:#d7d7d7;padding:6px 12px;font-family:monospace;"&gt;Ln 1, Col 1 | Chars 0&lt;/div&gt;
 &lt;/div&gt;
&lt;div class="di-box di-grid two"&gt;
 &lt;button id="nano-copy"&gt;Copy&lt;/button&gt;
 &lt;button id="nano-clear"&gt;Clear&lt;/button&gt;
 &lt;button id="nano-download"&gt;Download .txt&lt;/button&gt;
 &lt;button id="nano-share"&gt;Generate Share Link&lt;/button&gt;
&lt;/div&gt;
&lt;div id="nano-msg" class="di-muted" style="text-align:center;min-height:1.2rem;"&gt;&lt;/div&gt;
&lt;div id="nano-share-box" class="di-box" style="display:none;"&gt;
 &lt;label for="nano-link"&gt;&lt;strong&gt;Share Link&lt;/strong&gt;&lt;/label&gt;
 &lt;div class="di-share-link-row"&gt;
 &lt;input id="nano-link" type="text" readonly&gt;
 &lt;button id="nano-link-copy" type="button"&gt;Copy Link&lt;/button&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
(function () {
 var ta = document.getElementById('nano-editor');
 var st = document.getElementById('nano-status');
 var msg = document.getElementById('nano-msg');
 var shareBox = document.getElementById('nano-share-box');
 var link = document.getElementById('nano-link');
 var linkCopy = document.getElementById('nano-link-copy');

 function b64uEnc(str) {
 var bytes = new TextEncoder().encode(str);
 var bin = '';
 for (var i = 0; i &lt; bytes.length; i++) bin += String.fromCharCode(bytes[i]);
 return btoa(bin).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'');
 }
 function b64uDec(str) {
 var b64 = String(str || '').replace(/-/g,'+').replace(/_/g,'/');
 while (b64.length % 4) b64 += '=';
 var bin = atob(b64);
 var bytes = new Uint8Array(bin.length);
 for (var i = 0; i &lt; bin.length; i++) bytes[i] = bin.charCodeAt(i);
 return new TextDecoder().decode(bytes);
 }

 function updateStatus() {
 var v = ta.value;
 var p = ta.selectionStart || 0;
 var lines = v.slice(0,p).split('\n');
 var ln = lines.length;
 var col = lines[lines.length-1].length + 1;
 st.textContent = 'Ln ' + ln + ', Col ' + col + ' | Chars ' + v.length;
 }

 ta.addEventListener('input', updateStatus);
 ta.addEventListener('click', updateStatus);
 ta.addEventListener('keyup', updateStatus);

 ta.addEventListener('keydown', function (e) {
 if (e.key === 'Tab') {
 e.preventDefault();
 var s = ta.selectionStart;
 var epos = ta.selectionEnd;
 ta.value = ta.value.slice(0,s) + ' ' + ta.value.slice(epos);
 ta.selectionStart = ta.selectionEnd = s + 2;
 updateStatus();
 }
 });

 document.getElementById('nano-copy').addEventListener('click', async function () {
 try {
 await navigator.clipboard.writeText(ta.value);
 msg.textContent = 'Copied.';
 } catch (_) {
 msg.textContent = 'Copy failed.';
 }
 });

 document.getElementById('nano-clear').addEventListener('click', function () {
 ta.value = '';
 shareBox.style.display = 'none';
 msg.textContent = '';
 updateStatus();
 });

 document.getElementById('nano-download').addEventListener('click', function () {
 var blob = new Blob([ta.value], {type:'text/plain;charset=utf-8'});
 var a = document.createElement('a');
 a.href = URL.createObjectURL(blob);
 a.download = 'paste.txt';
 a.click();
 URL.revokeObjectURL(a.href);
 });

 document.getElementById('nano-share').addEventListener('click', async function () {
 var content = ta.value || '';
 if (!content.trim()) {
 msg.textContent = 'Write something before generating the share link.';
 return;
 }
 msg.textContent = 'Generating share link...';
 try {
 var r = await fetch('/api/paste', {
 method: 'POST',
 headers: { 'Content-Type': 'application/json' },
 body: JSON.stringify({ text: content, basePath: location.pathname })
 });
 var payload = await r.json().catch(function () { return {}; });
 if (!r.ok || !payload.ok || !payload.url) throw new Error(payload.error || payload.detail || ('HTTP ' + r.status));
 link.value = payload.url;
 shareBox.style.display = 'block';
 msg.textContent = 'Share link ready.';
 } catch (e) {
 msg.textContent = 'Share link error: ' + String(e.message || e);
 }
 });

 linkCopy.addEventListener('click', async function () {
 if (!link.value) return;
 try {
 await navigator.clipboard.writeText(link.value);
 msg.textContent = 'Share link copied.';
 } catch (_) {
 msg.textContent = 'Copy link failed.';
 }
 });

 var q = new URLSearchParams(location.search).get('p');
 var h = location.hash.indexOf('#p=') === 0 ? location.hash.slice(3) : '';
 var incoming = h || q || '';
 if (incoming) {
 try { ta.value = b64uDec(incoming); } catch (_) {}
 }
 updateStatus();
})();
&lt;/script&gt;</description></item><item><title>Repo</title><link>https://debianitalia.it/repo/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://debianitalia.it/repo/</guid><description>&lt;h2 class="di-page-section-title"&gt;Uso rapido&lt;/h2&gt;
&lt;p class="di-muted"&gt;Genera in pochi secondi il tuo &lt;em&gt;sources.list&lt;/em&gt; per il mirror italiano deb.debianitalia.it. Scegli il codename, seleziona i componenti che ti servono e copia il blocco APT già pronto, senza scrivere a mano indirizzi e suite del repository&lt;/p&gt;
&lt;div class="di-box di-grid two"&gt;
 &lt;div&gt;
 &lt;label for="repo-codename"&gt;&lt;strong&gt;Codename Debian&lt;/strong&gt;&lt;/label&gt;
 &lt;select id="repo-codename" class="repo-codename-select"&gt;
 &lt;option value="trixie"&gt;trixie (stable)&lt;/option&gt;
 &lt;option value="bookworm"&gt;bookworm (oldstable)&lt;/option&gt;
 &lt;option value="bullseye"&gt;bullseye (oldoldstable)&lt;/option&gt;
 &lt;option value="forky"&gt;forky (testing)&lt;/option&gt;
 &lt;option value="sid"&gt;sid (unstable)&lt;/option&gt;
 &lt;/select&gt;
 &lt;/div&gt;
 &lt;div&gt;
 &lt;label&gt;&lt;strong&gt;Componenti&lt;/strong&gt;&lt;/label&gt;
 &lt;div&gt;&lt;label&gt;&lt;input type="checkbox" class="repo-cmp" value="main" checked&gt; main&lt;/label&gt;&lt;/div&gt;
 &lt;div&gt;&lt;label&gt;&lt;input type="checkbox" class="repo-cmp" value="contrib" checked&gt; contrib&lt;/label&gt;&lt;/div&gt;
 &lt;div&gt;&lt;label&gt;&lt;input type="checkbox" class="repo-cmp" value="non-free"&gt; non-free&lt;/label&gt;&lt;/div&gt;
 &lt;div&gt;&lt;label&gt;&lt;input type="checkbox" class="repo-cmp" value="non-free-firmware"&gt; non-free-firmware&lt;/label&gt;&lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;div class="di-box" style="text-align:center;"&gt;
 &lt;button id="repo-generate"&gt;Genera sources.list&lt;/button&gt;
 &lt;button id="repo-copy" style="margin-left:8px;"&gt;Copia&lt;/button&gt;
 &lt;textarea id="repo-result" class="repo-result" rows="12" readonly&gt;&lt;/textarea&gt;
&lt;/div&gt;
&lt;script&gt;
(function () {
 var code = document.getElementById('repo-codename');
 var out = document.getElementById('repo-result');
 var btn = document.getElementById('repo-generate');
 var copyBtn = document.getElementById('repo-copy');

 function cmps() {
 return Array.prototype.slice.call(document.querySelectorAll('.repo-cmp:checked')).map(function(x){ return x.value; });
 }

 var hasSecurity = new Set(['trixie','bookworm','bullseye']);
 var hasUpdates = new Set(['trixie','bookworm','bullseye']);
 var hasBackports = new Set(['trixie']);

 btn.addEventListener('click', function () {
 var c = code.value;
 var selected = cmps();
 if (!selected.length) {
 out.value = 'Seleziona almeno un componente.';
 return;
 }
 var j = selected.join(' ');
 var lines = [];
 lines.push('## Debian ' + c + ' Main ##', '');
 lines.push('deb http://deb.debianitalia.it/debian ' + c + ' ' + j);
 lines.push('deb-src http://deb.debianitalia.it/debian ' + c + ' ' + j, '');

 if (hasSecurity.has(c)) {
 lines.push('## Debian ' + c + ' Security ##', '');
 lines.push('deb http://deb.debianitalia.it/debian-security ' + c + '-security ' + j);
 lines.push('deb-src http://deb.debianitalia.it/debian-security ' + c + '-security ' + j, '');
 }
 if (hasUpdates.has(c)) {
 lines.push('## Debian ' + c + ' Updates ##', '');
 lines.push('deb http://deb.debianitalia.it/debian ' + c + '-updates ' + j);
 lines.push('deb-src http://deb.debianitalia.it/debian ' + c + '-updates ' + j, '');
 }
 if (hasBackports.has(c)) {
 lines.push('## Debian ' + c + ' Backports ##', '');
 lines.push('deb http://deb.debianitalia.it/debian ' + c + '-backports ' + j);
 lines.push('deb-src http://deb.debianitalia.it/debian ' + c + '-backports ' + j, '');
 }

 out.value = lines.join('\n');
 });

 copyBtn.addEventListener('click', async function () {
 if (!out.value) return;
 try {
 await navigator.clipboard.writeText(out.value);
 copyBtn.textContent = 'Copiato';
 setTimeout(function(){ copyBtn.textContent = 'Copia'; }, 1200);
 } catch (_) {
 out.select();
 document.execCommand('copy');
 }
 });
})();
&lt;/script&gt;</description></item><item><title>Uploads</title><link>https://debianitalia.it/uploads/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://debianitalia.it/uploads/</guid><description>&lt;h2 class="di-page-section-title"&gt;Carica file&lt;/h2&gt;
&lt;p class="di-muted"&gt;Carica immagini, video, audio, documenti o codice e ottieni un link diretto da condividere. Il pannello mostra la coda, lo stato dell'upload e i risultati, così sai sempre cosa è stato inviato e dove si trova&lt;/p&gt;
&lt;div class="di-box di-grid di-upload-box"&gt;
 &lt;div class="di-upload-picker"&gt;
 &lt;input id="up-files" class="di-up-hidden" type="file" multiple&gt;
 &lt;label for="up-files" class="di-upload-select"&gt;[ Seleziona file ]&lt;/label&gt;
 &lt;div id="up-file-count" class="di-muted di-upload-count"&gt;&lt;/div&gt;
 &lt;/div&gt;
&lt;p&gt;&lt;button id="up-start" class="di-upload-start"&gt;Upload now&lt;/button&gt;&lt;/p&gt;
 &lt;div id="up-status" class="di-muted"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="up-details" style="display:none;"&gt;
 &lt;div class="di-box"&gt;
 &lt;h4&gt;File Queue&lt;/h4&gt;
 &lt;div id="up-queue"&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;div class="di-box"&gt;
 &lt;h4&gt;Upload Results&lt;/h4&gt;
 &lt;div id="up-results"&gt;&lt;/div&gt;
 &lt;/div&gt;
&lt;/div&gt;
&lt;div class="di-box di-supported-formats"&gt;
 &lt;h4&gt;Formati supportati&lt;/h4&gt;
 &lt;ul class="di-format-list"&gt;
 &lt;li&gt;&lt;strong&gt;Immagini:&lt;/strong&gt; &lt;code&gt;jpg jpeg png gif webp svg&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Video:&lt;/strong&gt; &lt;code&gt;mp4 webm ogv mov m4v&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Audio:&lt;/strong&gt; &lt;code&gt;mp3 wav ogg m4a flac&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Documenti / Testo / Codice:&lt;/strong&gt; &lt;code&gt;pdf txt md markdown csv tsv log json xml yaml yml ini conf cfg toml rtf tex c cpp h hpp java cs go rs swift kt kts dart sql graphql war ear so dll&lt;/code&gt;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Archivi:&lt;/strong&gt; &lt;code&gt;zip rar 7z gz bz2 xz zst lz lzma lz4 z tar tar.gz tar.bz2 tar.xz tar.lzma tar.lz4 tar.z&lt;/code&gt;&lt;/li&gt;
 &lt;/ul&gt;
&lt;/div&gt;
&lt;script&gt;
(function () {
 const endpoint = '/api/upload';
 const fileInput = document.getElementById('up-files');
 const fileCount = document.getElementById('up-file-count');
 const status = document.getElementById('up-status');
 const details = document.getElementById('up-details');
 const queue = document.getElementById('up-queue');
 const results = document.getElementById('up-results');
 const btn = document.getElementById('up-start');

 function human(n){
 const u=['B','KB','MB','GB']; let i=0; let v=n;
 while(v&gt;=1024 &amp;&amp; i&lt;u.length-1){v/=1024;i++;}
 return (v&gt;=10||i===0?Math.round(v):v.toFixed(1))+' '+u[i];
 }

 fileInput.addEventListener('change', () =&gt; {
 const files = Array.from(fileInput.files || []);
 if (!files.length) {
 fileCount.textContent = '';
 return;
 }
 fileCount.textContent = files.length === 1
 ? `${files[0].name} (${human(files[0].size)})`
 : `${files.length} file selezionati`;
 });

 btn.addEventListener('click', async () =&gt; {
 const files = Array.from(fileInput.files || []);
 if (!files.length) {
 status.textContent = 'Seleziona almeno un file.';
 details.style.display = 'none';
 return;
 }

 status.textContent = 'Upload in corso...';
 queue.innerHTML = files.map((f, i) =&gt; `${i + 1}. ${f.name} (${human(f.size)})`).join('&lt;br&gt;');

 const out = [];
 for (const f of files) {
 try {
 const fd = new FormData();
 fd.append('file', f, f.name);
 const r = await fetch(endpoint, { method:'POST', body: fd });
 const payload = await r.json().catch(() =&gt; ({}));
 if (!r.ok || !payload.ok || !payload.url) {
 throw new Error(payload.error || payload.detail || ('HTTP ' + r.status));
 }
 out.push(`${f.name}: &lt;a href="${payload.url}" target="_blank" rel="noopener"&gt;${payload.url}&lt;/a&gt;`);
 } catch (e) {
 out.push(`${f.name}: ERROR - ${String(e.message || e)}`);
 }
 }

 results.innerHTML = out.join('&lt;br&gt;');
 details.style.display = 'block';
 status.textContent = `Upload completato: ${files.length} file processati.`;
 });
})();
&lt;/script&gt;</description></item></channel></rss>