<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title><![CDATA[ Andrea Casarin ]]></title>
<description><![CDATA[ Practical insights on software engineering and system building. A digital craftsman&#x27;s journey through code, architecture, and measured results. ]]></description>
<link>https://www.andreacasarin.com</link>
<image>
    <url>https://www.andreacasarin.com/favicon.png</url>
    <title>Andrea Casarin</title>
    <link>https://www.andreacasarin.com</link>
</image>
<lastBuildDate>Thu, 07 Aug 2025 14:48:54 +0200</lastBuildDate>
<atom:link href="https://www.andreacasarin.com" rel="self" type="application/rss+xml"/>
<ttl>60</ttl>

    <item>
        <title><![CDATA[ Annotiquo, da web a nota in pochi secondi ]]></title>
        <description><![CDATA[ Annotiquo: estrazione contenuti da siti web e video YouTube, sintesi tramite intelligenza artificiale ed esportazione in markdown. Con 2 click. ]]></description>
        <link>https://www.andreacasarin.com/2025/07/30/annotiquo-da-web-a-nota-in-pochi-secondi.html/</link>
        <guid isPermaLink="false">688a4c416b9d09000165115a</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Wed, 30 Jul 2025 18:50:42 +0200</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2025/07/annotiquo-screenshot.jpg" medium="image"/>
        <content:encoded><![CDATA[ 
<!--kg-card-begin: html-->
<a href="https://www.producthunt.com/products/annotiquo?embed=true&utm_source=badge-featured&utm_medium=badge&utm_source=badge-annotiquo" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1000380&theme=light&t=1754384616638" alt="Annotiquo - Intelligent&#0032;content&#0032;extraction&#0032;and&#0032;summarization&#0032;with&#0032;AI | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<!--kg-card-end: html-->
<h2 id="introduzione-il-mio-processo-di-apprendimento">Introduzione: il mio processo di apprendimento</h2>
<p>Utilizzo <strong>Obsidian</strong> come centro della mia knowledge base, ma ho sempre trovato che prendere appunti da fonti online fosse un processo macchinoso. Articoli approfonditi, video tecnici e thread di discussione finivano spesso per diventare segnalibri dimenticati o note frammentarie, difficili da ritrovare e riutilizzare.</p>
<p>Lo scenario è familiare: trovo un articolo illuminante e vorrei integrarne i concetti chiave nel mio vault di Obsidian. Le opzioni più semplici, però, presentano diversi ostacoli:</p>
<ul>
<li><strong>Copia-incolla:</strong> Restituisce un testo con formattazione caotica, link interrotti ed elementi di layout superflui.</li>
<li><strong>Screenshot:</strong> Si perdono nel rullino fotografico dello smartphone, senza un contesto chiaro.</li>
<li><strong>Segnalibri:</strong> Dopo una settimana, il motivo per cui ho salvato quel link è già svanito.</li>
<li><strong>Appunti manuali:</strong> Interrompere la lettura, perdere la concentrazione e tentare di sintetizzare al volo è dispersivo e inefficiente.</li>
</ul>
<p>Lo stesso problema si ripresenta, amplificato, con i video di YouTube. Estrarre i concetti chiave da una conferenza o qualcosa di simile, richiede di:</p>
<ul>
<li>Riascoltare più volte passaggi specifici.</li>
<li>Trascrivere manualmente i punti salienti.</li>
<li>Riorganizzare le informazioni in un formato coerente.</li>
</ul>
<p>È un metodo frustrante che scoraggia l'apprendimento attivo.</p>
<h2 id="la-mia-soluzione-due-click-per-un-markdown-pulito">La  mia soluzione: due click per un markdown pulito</h2>
<p><strong>Annotiquo</strong> è un'estensione per Chrome progettata per risolvere questo specifico problema: estrarre il contenuto di una pagina web e convertirlo in Markdown pulito, pronto per essere archiviato.</p>
<p><strong>Come funziona:</strong></p>
<ol>
<li>Apri l'articolo o il video di tuo interesse.</li>
<li>Clicca sull'icona dell'estensione e seleziona "Copia Testo".</li>
<li>Incolla il contenuto direttamente in <strong>Obsidian</strong>: pulito, ben formattato e privo di distrazioni.</li>
</ol>
<p>Non sono richieste configurazioni complesse o registrazioni. L'estensione riconosce il tipo di contenuto e applica autonomamente il parser più adeguato.</p>
<h2 id="limpatto-sul-lavoro-quotidiano">L'impatto sul lavoro quotidiano</h2>
<p>L'adozione di questo strumento ha migliorato concretamente la mia gestione delle informazioni:</p>
<ul>
<li><strong>Per gli articoli:</strong> Il contenuto principale viene estratto senza barre laterali, pubblicità o menu. La formattazione Markdown si integra nativamente in Obsidian, preservando link e struttura.</li>
<li><strong>Per i video YouTube:</strong> L'estensione estrae automaticamente le trascrizioni (se disponibili), organizzandole con titolo, descrizione e metadati. In pochi secondi, puoi avere una versione testuale di una discussione di ore.</li>
<li><strong>Per thread e discussioni:</strong> Viene catturato solo il flusso principale della conversazione, mantenendo la struttura e i riferimenti essenziali.</li>
</ul>
<h2 id="levoluzione-dallestrazione-alla-sintesi-intelligente">L'Evoluzione: dall'estrazione alla sintesi intelligente</h2>
<p>Se inizialmente <strong>Annotiquo</strong> é nato come semplice strumento di estrazione, non appena completata questa parte ho subito notato una ovvia evoluzione: creare una sintesi dei contenuti estratti. La web app associata introduce proprio questa funzionalità: la <strong>estrarre i contenuti chiave tramite intelligenza artificiale</strong>.</p>
<p>Invece di archiviare un articolo tecnico di 3.000 parole, ora posso generare un riassunto di 300 parole che ne cattura i concetti fondamentali. Un video di un'ora può essere condensato in un estratto testuale di 5 minuti con i punti salienti.</p>
<p>Ovviamente questo ha un costo, ma con un sistema a crediti è tuto trasparente e flessibile: paghi solo per l'uso effettivo, senza canoni mensili che gravano anche nei periodi di inutilizzo. E in ogni caso é possibile gratuitamente estrarre il contenuto completo per gestirlo manualmente o con un altro strumento.</p>
<h2 id="risultati-concreti">Risultati concreti</h2>
<p>Dopo un paio di mesi di utilizzo quotidiano, sono soddisfatto. I benefici sono evidenti:</p>
<ul>
<li><strong>Knowledge base più ricca:</strong> La mia libreria di Obsidian si popola di note dense e strutturate.</li>
<li><strong>Ricerca più efficace:</strong> Posso confrontare e analizzare fonti diverse all'interno di un unico documento.</li>
<li><strong>Percorsi di apprendimento chiari:</strong> Video e articoli su uno stesso argomento si trasformano in una risorsa unificata e coerente.</li>
<li><strong>Minore attrito:</strong> È scomparsa l'esitazione nel decidere se "valga la pena prendere appunti".</li>
</ul>
<h2 id="a-chi-si-rivolge-annotiquo">A chi si rivolge Annotiquo?</h2>
<p>Ho sviluppato <strong>Annotiquo</strong> principalmente per risolvere un'esigenza personale, ma ho intuito presto che il problema é condiviso da molti. Se anche tu hai un workflow simile al mio, credo che questo strumento possa esserti estremamente utile.</p>
<p>Direi che profilo ideale è chi:</p>
<ul>
<li>Utilizza strumenti come <strong>Obsidian, Notion o Roam</strong> per il knowledge management.</li>
<li>Consuma regolarmente contenuti tecnici online (articoli, video, documentazione).</li>
<li>Desidera trasformare il consumo passivo di informazioni in apprendimento attivo.</li>
<li>Percepisce il divario tra "contenuto interessante" e "nota realmente utilizzabile".</li>
</ul>
<p>A differenza di altri strumenti che puntano a reinventare da zero il modo in cui prendi appunti, <strong>Annotiquo</strong> vuole essere a supporto del sistema che già utilizzi, eliminando gli attriti nel punto esatto in cui si creano.</p>
<p>Se ti riconosci in questa descrizione, ti invito a provare. Trovi tutto il necessario sul sito ufficiale: <strong><a href="https://annotiquo.com/?ref=andreacasarin.com">annotiquo.com</a></strong>:</p>
<ul>
<li>L'<strong>estensione per Chrome è gratuita</strong> e funziona anche offline.</li>
<li>Con l'iscrizione alla web app, riceverai <strong>10 crediti gratuiti</strong> per testare la sintesi con AI, senza alcun impegno.</li>
</ul>
<h2 id="continua">Continua</h2>
<p>Questo articolo è il <strong>primo di una serie dedicata al progetto</strong>. Il mese prossimo pubblicherò un'analisi più tecnica, in cui racconterò le scelte architetturali e le tecnologie dietro lo sviluppo di <strong>Annotiquo</strong>.</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Un Mese di Vibe Coding: Lezioni Pratiche da un Esperimento Reale ]]></title>
        <description><![CDATA[ Sviluppo full-AI per 30 giorni: successi, code creep, test ingannevoli e consigli pratici per sfruttare l’intelligenza artificiale senza farsi travolgere. ]]></description>
        <link>https://www.andreacasarin.com/2025/06/28/mese-vibe-coding-lezioni-pratiche-esperimento-reale.html/</link>
        <guid isPermaLink="false">685ea9836b9d090001651141</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 28 Jun 2025 15:31:56 +0200</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2025/06/vibe-coding.jpg" medium="image"/>
        <content:encoded><![CDATA[ <p>Questo mese ho deciso di buttarmi in un esperimento che avevo in mente da tempo: sviluppare un progetto intero usando principalmente l'AI come partner di coding. <strong>Spoiler:</strong> è stata un'esperienza affascinante, ma con qualche sorpresa che non mi aspettavo.</p>
<hr>
<h2 id="il-contesto-dellesperimento">Il contesto dell'esperimento</h2>
<p>L'idea era semplice: prendere un progetto di media complessità e vedere fino a che punto riuscivo a delegare il lavoro di sviluppo all'intelligenza artificiale. Non parliamo di semplici <em>snippet</em> di codice o refactoring minori, ma di <strong>architettura</strong>, <strong>implementazione di feature complete</strong> e <strong>debugging</strong>.</p>
<p>Il risultato? Un mese di lavoro intenso che mi ha fatto capire molte cose su come l'AI può (e non può) aiutarci nel nostro lavoro quotidiano.</p>
<hr>
<h2 id="la-regola-doro-specificit%C3%A0-estrema">La regola d'oro: specificità estrema</h2>
<p>La prima lezione, e probabilmente la più importante, è che con l'AI la <strong>vaghezza è il nemico numero uno</strong>. Se con un developer junior puoi permetterti di dire «implementa un sistema di autenticazione» e aspettarti che faccia le domande giuste, con l'AI questo approccio porta dritto al disastro.</p>
<p>Ogni feature va descritta come se stessi scrivendo documentazione per qualcuno che non ha mai visto il progetto. I <strong>Product Requirement Documents</strong> dettagliati non sono un lusso, ma una necessità. L'AI ha bisogno di sapere esattamente cosa fare, come farlo e — soprattutto — cosa <strong>non</strong> fare.</p>
<blockquote>
<p>Specificare cosa <strong>non</strong> vuoi è altrettanto importante quanto dire cosa vuoi: evita iniziative creative che poi dovrai sistemare a mano.</p>
</blockquote>
<hr>
<h2 id="il-paradosso-delle-tecnologie-popolari">Il paradosso delle tecnologie popolari</h2>
<p>L'AI performa molto meglio su stack mainstream e ben documentati. Ha senso: è stata addestrata su montagne di codice pubblico, tutorial e documentazione di <strong>React</strong>, <strong>Node.js</strong>, <strong>Python</strong> e simili.</p>
<p>Quando ho provato a usare librerie più di nicchia o pattern architetturali meno comuni, la qualità delle soluzioni proposte è calata drasticamente: API inventate, approcci teoricamente corretti ma impraticabili.</p>
<blockquote>
<p><strong>La lezione:</strong> se vuoi massimizzare l'efficacia dell'AI, punta su tecnologie con <strong>grandi community</strong> e <strong>documentazione abbondante</strong>. Non è il momento di sperimentare con quella nuova libreria <em>experimental</em> trovata su GitHub.</p>
</blockquote>
<hr>
<h2 id="debugging-dove-lai-mostra-i-limiti">Debugging: dove l'AI mostra i limiti</h2>
<p>Il debugging è stata l'area più frustrante. L'AI è bravissima a scrivere codice che <em>sembra</em> sensato, ma quando qualcosa va storto la sua capacità di analisi sistematica lascia a desiderare.</p>
<p>Spesso si fissa su una singola ipotesi e continua a proporre variazioni dello stesso approccio sbagliato. In questi casi conviene fermarsi, analizzare il problema da soli, e poi dare all'AI indicazioni <strong>molto specifiche</strong> su cosa cercare e dove.</p>
<blockquote>
<p><strong>Code Creep</strong>: Ogni ciclo di debug con l'AI — direi il <strong>99 %</strong> delle volte — si traduce nell'<strong>aggiunta di nuovo codice</strong>: patch, controlli extra, logging ridondante. Il risultato è un gonfiarsi costante della <em>codebase</em>, con effetti negativi su leggibilità e futura manutenzione. Tenere la situazione sotto controllo richiede <strong>refactoring frequenti</strong> e una <strong>sorveglianza umana costante</strong>.</p>
</blockquote>
<hr>
<h2 id="test-tra-copertura-e-soluzioni-apparenti">Test: tra copertura e soluzioni apparenti</h2>
<p>Di fronte a test falliti, l'AI spesso «risolve» il problema aggiungendo eccezioni, <em>mock</em> o log per mascherare l'errore invece di correggere il bug reale.</p>
<blockquote>
<p>Questo porta a un <strong>falso senso di sicurezza</strong>: i test passano, ma il difetto di fondo rimane.</p>
</blockquote>
<hr>
<h2 id="gestione-della-complessit%C3%A0-architetturale">Gestione della complessità architetturale</h2>
<p>Per singole funzioni o moduli isolati i risultati sono spesso eccellenti. Ma mantenere coerenza in un'intera applicazione è un'altra storia.</p>
<p>L'AI tende a <strong>ottimizzare localmente</strong> piuttosto che globalmente: crea funzioni perfette per il contesto immediato, che però introducono <strong>inconsistenze</strong> o <strong>duplicazioni</strong> altrove.</p>
<blockquote>
<p><strong>Soluzione:</strong> definire chiaramente pattern e convenzioni <em>prima</em> di iniziare, e richiamarli costantemente quando chiedi nuove implementazioni.</p>
</blockquote>
<hr>
<h2 id="velocit%C3%A0-vs-qualit%C3%A0-trovare-il-giusto-equilibrio">Velocità vs Qualità: trovare il giusto equilibrio</h2>
<p>La velocità di sviluppo con l'AI può essere impressionante, ma c'è un trade‑off importante: il codice generato funziona spesso al primo colpo, ma non sempre è <strong>quello che avresti scritto tu</strong>.</p>
<p>A volte mancano ottimizzazioni, altre la struttura non è ideale per future estensioni. Devi decidere quando accettare una soluzione «abbastanza buona» per procedere e quando invece investire tempo nel <strong>raffinare</strong> ciò che l'AI ha prodotto.</p>
<hr>
<h2 id="lessons-learned-e-prossimi-passi">Lessons learned e prossimi passi</h2>
<h3 id="dove-lai-brilla">Dove l'AI brilla</h3>
<ul>
<li>Boilerplate e setup iniziale di progetti</li>
<li>Implementazione di pattern ben consolidati</li>
<li>(Con supervisione) scrittura di test unitari</li>
<li>Refactoring di codice esistente</li>
</ul>
<h3 id="dove-serve-ancora-la-mano-umana">Dove serve ancora la mano umana</h3>
<ul>
<li>Decisioni architetturali complesse</li>
<li>Debugging di problemi non ovvi e prevenzione del <em>Code Creep</em></li>
<li>Ottimizzazioni di performance</li>
<li>Sicurezza, gestione degli errori <em>edge‑case</em> e reale copertura dei test</li>
</ul>
<hr>
<h2 id="conclusioni-pratiche">Conclusioni pratiche</h2>
<p>Se stai pensando di integrare l'AI nel tuo workflow di sviluppo, <strong>inizia gradualmente</strong>. Usala per accelerare le parti più meccaniche, ma mantieni sempre il controllo sulle decisioni architetturali critiche.</p>
<p>Investi tempo nella <strong>documentazione</strong>: più specifico sei nei prompt, migliori saranno i risultati. E ricorda: l'AI è uno strumento, non un sostituto del tuo giudizio da developer esperto.</p>
<p>Il progetto di cui parlo in questo articolo è online su <a href="https://annotiquo.com/?ref=andreacasarin.com">annotiquo.com</a>. L'estensione del browser è in fase di revisione, ma conto di pubblicarla a breve: l'ho creata principalmente perché ne avevo bisogno io, e spero possa tornare utile anche ad altri.</p>
<hr>
<p>Continuerò questo esperimento nei prossimi mesi, esplorando nuovi approcci e condividendo ciò che imparo, iscriviti alla newsletter se vuoi seguirmi in questo percorso. Nel frattempo, spero che queste riflessioni ti siano utili se decidi di provare qualcosa di simile nel tuo team.</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Mastering Generative AI Agents con RAG e LangChain – Cosa ho imparato davvero ]]></title>
        <description><![CDATA[ Ho seguito il corso di IBM su edX, &quot;Mastering Generative AI Agents with RAG and LangChain&quot; ecco cosa ho imparato davvero. ]]></description>
        <link>https://www.andreacasarin.com/2025/05/29/mastering-generative-ai-agents-con-rag-e-langchain.html/</link>
        <guid isPermaLink="false">6838c9516b9d090001651110</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Thu, 29 May 2025 22:59:54 +0200</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2025/05/langchain-rag-edx.jpg" medium="image"/>
        <content:encoded><![CDATA[ <h2 id="un-corso-per-orientarsi">Un corso per orientarsi</h2>
<p>Ho seguito il corso di IBM su edX, "Mastering Generative AI Agents with RAG and LangChain". È pensato per sviluppatori, data scientist e tech lead che vogliono capire come costruire applicazioni AI concrete, andando oltre la semplice chiamata a un'API come ChatGPT. Il corso è strutturato in moduli brevi, con un buon equilibrio tra spiegazioni teoriche, esempi pratici e laboratori interattivi. Non è pensato per chi parte da zero, ma è molto utile se hai già una base e vuoi mettere ordine tra strumenti, concetti e workflow.</p>
<h2 id="cosa-vuol-dire-usare-rag">Cosa vuol dire usare RAG</h2>
<p>RAG (Retrieval-Augmented Generation) è un'architettura che permette a un LLM di integrare informazioni esterne, aggiornabili e contestualizzate, al momento della generazione. Questo evita di dover riaddestrare il modello ogni volta che cambiano i dati. In pratica, il processo è diviso in due fasi:</p>
<ol>
<li><strong>Retrieval</strong>: una query dell’utente viene trasformata in un embedding e confrontata con un insieme di documenti indicizzati. Si recuperano quelli più rilevanti.</li>
<li><strong>Generation</strong>: i documenti recuperati vengono passati come contesto al modello, che genera una risposta più precisa e informata.</li>
</ol>
<p>Questo approccio consente di usare modelli generalisti (come GPT o LLaMA) per rispondere a domande su contesti molto specifici, ad esempio un manuale tecnico interno o una raccolta di policy aziendali.</p>
<h3 id="perch%C3%A9-%C3%A8-utile">Perché è utile</h3>
<p>Il vantaggio principale è la flessibilità: puoi aggiornare i dati in tempo reale senza dover modificare il modello. È anche più scalabile e meno costoso rispetto al fine-tuning. Tuttavia, la qualità delle risposte dipende molto da come segmenti i documenti, dalla qualità degli embedding e dalla struttura del database vettoriale.</p>
<h2 id="prompt-engineering-ancora-fondamentale">Prompt engineering: ancora fondamentale</h2>
<p>Anche se oggi abbiamo strumenti più sofisticati, il prompt resta il modo più immediato per guidare un LLM. Il corso dedica una sezione interessante al prompt engineering, mostrando diverse strategie:</p>
<ul>
<li>Prompt a zero, uno o pochi esempi (zero-shot, one-shot, few-shot)</li>
<li>Prompt strutturati con esempi guidati</li>
<li>Prompt chain-of-thought, che aiutano il modello a ragionare a passi</li>
<li>Tecniche di auto-verifica come la self-consistency</li>
</ul>
<p>Viene anche data attenzione agli strumenti che aiutano a creare prompt riutilizzabili e modulari, come i template di LangChain, e a testarne l’efficacia in contesti diversi.</p>
<h2 id="langchain-mettere-insieme-i-pezzi">LangChain: mettere insieme i pezzi</h2>
<p>LangChain è il framework open source che il corso usa per orchestrare modelli, prompt, retrieval, memoria e strumenti esterni. L’idea alla base è semplice: creare applicazioni AI componibili, in cui puoi collegare vari moduli (chains, tools, memory, agents) in modo flessibile.</p>
<p>Puoi ad esempio:</p>
<ul>
<li>Creare una catena di prompt che processano input passo dopo passo</li>
<li>Usare agenti per decidere in autonomia quale tool usare in base al contesto</li>
<li>Integrare chiamate a database, filesystem, API o plugin esterni</li>
</ul>
<p>LangChain è molto utile quando hai bisogno di costruire qualcosa di più articolato di una singola risposta testuale: ad esempio, un assistente con memoria, un sistema che interroga fonti strutturate o una pipeline che coinvolge più modelli.</p>
<h2 id="lavorare-con-i-documenti-la-pipeline-rag">Lavorare con i documenti: la pipeline RAG</h2>
<p>Una parte molto concreta del corso riguarda la gestione dei documenti: è qui che LangChain e RAG si incontrano davvero. Il flusso tipico è questo:</p>
<ol>
<li><strong>Caricamento</strong>: prendi documenti da fonti diverse (PDF, API, file locali...)</li>
<li><strong>Segmentazione</strong>: li dividi in porzioni più piccole, chiamate chunk</li>
<li><strong>Embedding</strong>: trasformi ogni chunk in un vettore numerico che rappresenta il suo significato</li>
<li><strong>Indicizzazione</strong>: salvi i vettori in un database (es. FAISS)</li>
<li><strong>Ricerca</strong>: quando arriva una domanda, cerchi i chunk più simili nel vector DB</li>
<li><strong>Composizione del prompt</strong>: costruisci il prompt da dare al modello con i risultati più rilevanti</li>
</ol>
<p>FAISS, usato nel corso, è una libreria pensata per eseguire ricerche efficienti di similarità su grandi insiemi di vettori numerici. È veloce e abbastanza facile da usare, anche se richiede attenzione per configurarlo bene in produzione.</p>
<h2 id="in-sintesi-vale-la-pena">In sintesi: vale la pena?</h2>
<p>Il corso è ben fatto, strutturato in modo chiaro e con contenuti aggiornati. Non promette miracoli, ma ti dà una visione realistica di cosa serve per costruire applicazioni AI moderne: modelli, sì, ma anche dati, retrieval, orchestrazione e prompt ben progettati. È utile se:</p>
<ul>
<li>Hai già fatto qualche esperimento con gli LLM e vuoi passare a soluzioni più complete</li>
<li>Ti interessa capire come integrare i modelli con dati aziendali</li>
<li>Vuoi valutare tecnologie come LangChain e capire se fanno al caso tuo</li>
</ul>
<p>In ogni caso, ti lascia qualcosa in mano: idee, strumenti, esempi concreti e una roadmap da seguire per costruire applicazioni AI più solide e mantenibili.</p>
<h2 id="risorse-utili">Risorse utili</h2>
<p>Se vuoi approfondire alcuni degli argomenti trattati nel corso, ecco alcune risorse che ho trovato particolarmente utili durante lo studio:</p>
<ul>
<li><strong>Corso IBM su edX</strong> – <a href="https://learning.edx.org/course/course-v1:IBM+AI0213EN+3T2024/home?ref=andreacasarin.com">Mastering Generative AI Agents with RAG and LangChain</a></li>
<li><strong>LangChain Documentation</strong> – <a href="https://docs.langchain.com/?ref=andreacasarin.com">https://docs.langchain.com/</a></li>
<li><strong>FAISS GitHub</strong> – <a href="https://github.com/facebookresearch/faiss?ref=andreacasarin.com">https://github.com/facebookresearch/faiss</a></li>
<li><strong>OpenAI Cookbook</strong> – <a href="https://github.com/openai/openai-cookbook?ref=andreacasarin.com">https://github.com/openai/openai-cookbook</a></li>
<li><strong>Hugging Face Transformers</strong> – <a href="https://huggingface.co/docs/transformers/index?ref=andreacasarin.com">https://huggingface.co/docs/transformers/index</a></li>
</ul>
<p>Questi link offrono una buona base sia per iniziare che per approfondire a seconda del livello di esperienza.</p>
<p>Alla prossima, e buon lavoro con il codice!</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Autenticazione email: SPF, DKIM e DMARC nella vita reale ]]></title>
        <description><![CDATA[ SPF, DKIM e DMARC sono strumenti validi e ormai indispensabili per proteggere la reputazione email di un dominio. Tuttavia, la loro implementazione richiede un approccio strutturato e multidisciplinare. ]]></description>
        <link>https://www.andreacasarin.com/2025/04/30/autenticazione-email-spf-dkim-e-dmarc-nella-vita-reale.html/</link>
        <guid isPermaLink="false">67eff1a79ce416000144966f</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Wed, 30 Apr 2025 10:30:00 +0200</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2025/04/spf-dkim-dmarc.jpg" medium="image"/>
        <content:encoded><![CDATA[ <h3 id="un-problema-persistente-lautenticazione-email-nel-2025">Un problema persistente: l'autenticazione email nel 2025</h3>
<p>L'email continua a essere uno degli strumenti più usati — e purtroppo più vulnerabili — in ambito business. Nonostante l'emergere di piattaforme moderne che offrono alternative più sicure e tracciabili, l'email rimane centrale nella comunicazione tra aziende. E proprio per questo, anche nel 2025, continua a rappresentare un vettore significativo per attacchi di phishing, spoofing e spam.</p>
<p>Il protocollo SMTP, nato in un contesto molto diverso dall'attuale, non prevede meccanismi robusti per l'autenticazione del mittente. Da qui la necessità di tecnologie come SPF, DKIM e DMARC.</p>
<p>Vediamole da vicino, con lo sguardo tecnico di chi le implementa.</p>
<hr>
<h3 id="spf-una-whitelist-basata-su-ip">SPF: una whitelist basata su IP</h3>
<p>Sender Policy Framework (SPF) permette al dominio mittente di dichiarare esplicitamente quali IP sono autorizzati a spedire email per suo conto. Funziona tramite un record DNS TXT che specifica gli IP (o i domini) autorizzati.</p>
<p><strong>Benefici concreti:</strong> SPF è relativamente semplice da implementare in ambienti controllati. Per esempio, se tutta la posta esce da Google Workspace o da un relay SMTP aziendale noto, SPF può aiutare a bloccare tentativi di spoofing di base.</p>
<p><strong>Le difficoltà reali:</strong></p>
<ul>
<li>SPF verifica l'IP dell'MTA che spedisce la mail, non l'header "From" visibile all'utente. Quindi non previene attacchi di spoofing più sofisticati.</li>
<li>Il limite di 10 lookup DNS può diventare un ostacolo quando si utilizzano molti servizi terzi (CRM, strumenti di marketing, piattaforme di invio notifiche...).</li>
<li>Alcuni mailserver possono gestire in modo non uniforme i risultati SPF softfail.</li>
</ul>
<p><strong>Best practice:</strong></p>
<ul>
<li>Minimizzare le deleghe. Evitare SPF troppo permissivi o con <code>+all</code>.</li>
<li>Monitorare i servizi che inviano per conto del dominio. Se cambiano IP, l’SPF va aggiornato.</li>
<li>Validare la configurazione con strumenti come MXToolbox o Dmarcian.</li>
</ul>
<hr>
<h3 id="dkim-firma-crittografica-per-le-email">DKIM: firma crittografica per le email</h3>
<p>DomainKeys Identified Mail (DKIM) si basa su una firma crittografica del contenuto della mail e di alcuni header. Il dominio pubblica una chiave pubblica nel DNS, che viene usata per verificare la firma inserita nel messaggio.</p>
<p><strong>Benefici concreti:</strong> DKIM aggiunge integrità e autenticazione: se il messaggio è stato alterato in transito o inviato da un servizio non autorizzato, la firma fallisce.</p>
<p><strong>Le difficoltà reali:</strong></p>
<ul>
<li>Non tutti i provider configurano DKIM correttamente di default.</li>
<li>La selezione degli header da firmare può causare fallimenti inaspettati (es. se un mail gateway modifica i campi "Subject" o "From").</li>
<li>La gestione delle chiavi RSA richiede attenzione: lunghezza, rotazione e revoca devono essere parte di un processo strutturato.</li>
</ul>
<p><strong>Best practice:</strong></p>
<ul>
<li>Usare chiavi da almeno 2048 bit.</li>
<li>Firmare almeno i campi From, Subject, Date e i contenuti MIME.</li>
<li>Testare gli invii reali verso provider principali (Gmail, Outlook, Apple Mail) per verificare compatibilità e deliverability.</li>
</ul>
<hr>
<h3 id="dmarc-il-coordinatore-tra-spf-e-dkim">DMARC: il coordinatore tra SPF e DKIM</h3>
<p>Domain-based Message Authentication, Reporting &amp; Conformance (DMARC) coordina SPF e DKIM e introduce una policy su come trattare i messaggi che falliscono i controlli. Inoltre, fornisce report aggregati e forensi.</p>
<p><strong>Benefici concreti:</strong></p>
<ul>
<li>Permette di specificare azioni (none, quarantine, reject) in base alla conformità di SPF/DKIM.</li>
<li>Rende visibile cosa succede realmente grazie ai report aggregate.</li>
</ul>
<p><strong>Le difficoltà reali:</strong></p>
<ul>
<li>I report sono in formato XML e spesso richiedono strumenti terzi per essere analizzati.</li>
<li>Richiede che SPF o DKIM siano <em>aligned</em> con il dominio visibile nel From. Questo è un aspetto spesso trascurato.</li>
<li>Una policy aggressiva impostata troppo presto (es. <code>p=reject</code>) può bloccare email legittime.</li>
</ul>
<p><strong>Best practice:</strong></p>
<ul>
<li>Iniziare con <code>p=none</code> e monitorare per almeno 1-3 mesi.</li>
<li>Analizzare i report con strumenti come Postmark, Dmarcian, o soluzioni open source come OpenDMARC.</li>
<li>Procedere per gradi verso <code>quarantine</code> e solo successivamente verso <code>reject</code>.</li>
</ul>
<hr>
<h3 id="esempio-pratico-configurazioni-dns">Esempio pratico: configurazioni DNS</h3>
<p>Immaginiamo un dominio che utilizza Google Workspace per l’invio della posta e anche una piattaforma di newsletter esterna (es. Mailchimp).</p>
<p><strong>Record SPF:</strong></p>
<pre><code>@ IN TXT "v=spf1 include:_spf.google.com include:servers.mcsv.net -all"
</code></pre>
<p><strong>Record DKIM (Google):</strong></p>
<pre><code>google._domainkey IN TXT "v=DKIM1; k=rsa; p=MIGfMA0G..."
</code></pre>
<p><strong>Record DMARC:</strong></p>
<pre><code>_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@tuodominio.it; adkim=s; aspf=s"
</code></pre>
<p>Questi record sono solo un punto di partenza: ogni servizio esterno ha le sue indicazioni specifiche e, in alcuni casi, può essere necessario configurare chiavi DKIM dedicate o subdomini separati.</p>
<hr>
<h3 id="un-percorso-sostenibile-per-l%E2%80%99adozione">Un percorso sostenibile per l’adozione</h3>
<p>In uno scenario ideale, SPF, DKIM e DMARC sarebbero configurati su ogni dominio. Nella realtà, la loro adozione richiede pianificazione, test approfonditi e monitoraggio costante. L’approccio più efficace è procedere per fasi:</p>
<ol>
<li><strong>SPF first</strong>: è il più semplice da introdurre e spesso già supportato dai provider principali.</li>
<li><strong>DKIM second</strong>: richiede più attenzione ma offre un salto di qualità sulla sicurezza.</li>
<li><strong>DMARC last</strong>: va introdotto con policy leggere e strumenti di osservabilità.</li>
</ol>
<p>Coinvolgere DevOps e SecOps è fondamentale: un record DNS errato può compromettere la deliverability delle email transazionali o addirittura bloccare comunicazioni cruciali con clienti e partner.</p>
<hr>
<h3 id="conclusione-equilibrio-tra-sicurezza-e-affidabilit%C3%A0">Conclusione: equilibrio tra sicurezza e affidabilità</h3>
<p>SPF, DKIM e DMARC sono strumenti validi e ormai indispensabili per proteggere la reputazione email di un dominio. Tuttavia, la loro implementazione richiede un approccio strutturato e multidisciplinare: non bastano configurazioni iniziali corrette, serve anche una manutenzione continua.</p>
<p>Chi desidera mantenere un dominio affidabile e costruire una reputazione solida deve investire in questi standard. Il risultato si traduce in una migliore deliverability, una riduzione delle frodi e una comunicazione aziendale più credibile.</p>
<p>In definitiva, garantire che un’email arrivi a destinazione e sia considerata legittima non è solo una questione tecnica, ma un investimento strategico per la propria organizzazione.</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Modelli Vision in Locale: Applicazioni e Implementazione con LangChain ]]></title>
        <description><![CDATA[ Modelli AI Vision in locale: più efficenza, privacy e velocità! Scopri come integrarli facilmente con LangChain. ]]></description>
        <link>https://www.andreacasarin.com/2025/03/29/modelli-vision-in-locale-applicazioni-e-implementazione-con-langchain.html/</link>
        <guid isPermaLink="false">67e8117a9ce416000144964d</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 29 Mar 2025 16:39:10 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2025/03/modelli-vision-locale-ai.jpg" medium="image"/>
        <content:encoded><![CDATA[ <h2 id="introduzione">Introduzione</h2>
<p>I modelli vision in locale stanno guadagnando popolarità grazie ai loro vantaggi in termini di privacy e controllo sui dati. A differenza delle soluzioni cloud, questi modelli consentono di eseguire elaborazioni direttamente sui dispositivi locali, garantendo tempi di risposta rapidi e una maggiore sicurezza. Questo è particolarmente utile in settori dove i dati sensibili devono rimanere all’interno delle infrastrutture aziendali.</p>
<h2 id="applicazioni-pratiche">Applicazioni Pratiche</h2>
<p>I modelli vision in locale trovano ampio impiego in diversi settori, tra cui:</p>
<ul>
<li><strong>Sorveglianza e Sicurezza</strong>: Riconoscimento facciale o identificazione di oggetti sospetti senza inviare dati a server remoti.</li>
<li><strong>Controllo Qualità Industriale</strong>: Monitoraggio in tempo reale delle linee di produzione per identificare difetti.</li>
<li><strong>Riconoscimento Foto per Ricerca</strong>: Utilizzo di modelli vision per etichettare immagini, organizzarle per contenuto e facilitarne la ricerca all'interno di archivi digitali.</li>
</ul>
<h2 id="implementazione-con-langchain">Implementazione con LangChain</h2>
<p>Di seguito un esempio di utilizzo di LangChain per l'inferenza con un modello di riconoscimento immagini in locale:</p>
<pre><code class="language-python">from langchain import LangChain

llm = OllamaLLM(model="llava")
llm_with_image_context = llm.bind(images=[image_b64])
res = llm_with_image_context.invoke("Describe this image")
</code></pre>
<p>Questo esempio dimostra come utilizzare un modello di visione pre-addestrato con LangChain per il riconoscimento di oggetti. È un punto di partenza semplice e facilmente adattabile a diversi contesti applicativi.</p>
<h2 id="approfondimenti">Approfondimenti</h2>
<p>Ecco alcuni link utili per approfondire l'argomento dei modelli vision in locale e l'uso di LangChain:</p>
<ul>
<li><a href="https://www.langchain.com/?ref=andreacasarin.com">LangChain</a>: Documentazione ufficiale per creare catene e orchestrare modelli.</li>
<li><a href="https://huggingface.co/?ref=andreacasarin.com">Hugging Face</a>: Modelli pre-addestrati per il riconoscimento di oggetti e altre applicazioni di visione.</li>
</ul>
<h2 id="conclusione">Conclusione</h2>
<p>I modelli vision in locale rappresentano una scelta strategica per molte aziende, consentendo di garantire privacy, velocità di esecuzione e controllo dei dati. Con strumenti come LangChain, è possibile implementare soluzioni rapide e sicure per il riconoscimento di oggetti in diversi contesti.</p>
<p>Un aspetto fondamentale dei modelli vision in locale è la loro implementabilità anche con budget modesti. Grazie alla disponibilità di modelli pre-addestrati open source e alla crescente potenza dei dispositivi edge, è possibile realizzare progetti efficienti senza dover investire ingenti somme. Questo approccio consente di migliorare notevolmente l'efficienza di processi aziendali come il controllo qualità, la sorveglianza o la categorizzazione automatica delle immagini, aumentando la produttività e garantendo una gestione ottimale delle risorse.</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Infrastructure as Code: Efficienza, Complessità e Strategia di Adozione ]]></title>
        <description><![CDATA[ Perché Infrastructure as Code?


Negli ultimi anni, il concetto di Infrastructure as Code (IaC) si è imposto come una pratica fondamentale per la gestione scalabile, riproducibile e automatizzata delle infrastrutture IT. Con la crescente adozione di cloud computing e ambienti containerizzati, il provisioning manuale delle risorse non è più sostenibile: ]]></description>
        <link>https://www.andreacasarin.com/2025/02/28/infrastructure-as-code-efficienza-complessita-strategia-adozione.html/</link>
        <guid isPermaLink="false">67c43d969ce416000144963f</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Fri, 28 Feb 2025 12:15:00 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2025/03/infrastructure-as-code-server-view.webp" medium="image"/>
        <content:encoded><![CDATA[ <h2 id="perch%C3%A9-infrastructure-as-code">Perché Infrastructure as Code?</h2>
<p>Negli ultimi anni, il concetto di <em>Infrastructure as Code</em> (IaC) si è imposto come una pratica fondamentale per la gestione scalabile, riproducibile e automatizzata delle infrastrutture IT. Con la crescente adozione di cloud computing e ambienti containerizzati, il provisioning manuale delle risorse non è più sostenibile: troppi errori, processi lenti e scarsa tracciabilità.</p>
<p>L'adozione di IaC consente di trattare le infrastrutture come codice, con file di configurazione versionabili, modulari e testabili. Questo riduce le incoerenze tra ambienti, minimizza gli errori umani e aumenta la velocità di rilascio, abilitando un approccio DevOps più solido. Con il codice al centro della gestione dell'infrastruttura, le aziende possono ottenere maggiore affidabilità e sicurezza, adottando processi che migliorano la ripetibilità delle configurazioni.</p>
<p>L'infrastruttura gestita con codice non solo accelera il time-to-market ma consente anche di adottare strategie di disaster recovery più robuste, eliminando le incongruenze tra ambienti e facilitando il rollback in caso di problemi. Tuttavia, sebbene i benefici siano evidenti, il percorso per adottare IaC senza intoppi presenta ostacoli tecnici e organizzativi che non vanno sottovalutati.</p>
<h2 id="sfide-e-complessit%C3%A0-di-iac">Sfide e Complessità di IaC</h2>
<p>Sebbene i benefici siano evidenti, l'adozione di IaC non è priva di sfide. Il primo ostacolo è culturale: molti team IT sono abituati a gestire l'infrastruttura in modo manuale o semi-automatizzato. Il passaggio a una mentalità "code-driven" richiede un cambio di paradigma e una curva di apprendimento.</p>
<p>A livello tecnico, la gestione della configurazione e del provisioning attraverso codice introduce nuovi livelli di complessità:</p>
<ul>
<li><strong>Gestione dello stato</strong>: strumenti come Terraform mantengono lo stato dell'infrastruttura, ma questo file di stato diventa un punto critico di fallimento. Se non gestito correttamente, potrebbe introdurre problemi di sincronizzazione tra ambienti.</li>
<li><strong>Dipendenze e orchestrazione</strong>: il deployment coordinato di risorse richiede una gestione attenta delle dipendenze. Senza una strategia chiara, si rischia di creare configurazioni difficili da mantenere e aggiornare.</li>
<li><strong>Sicurezza e permessi</strong>: definire infrastrutture via codice introduce rischi di esposizione accidentale di credenziali e configurazioni sensibili. I file di configurazione devono essere protetti da leak accidentali, preferibilmente attraverso strumenti di secret management come HashiCorp Vault o AWS Secrets Manager.</li>
<li><strong>Debugging e rollback</strong>: errori nel codice di IaC possono avere impatti devastanti sugli ambienti di produzione. Avere una strategia di rollback efficace e monitorare le modifiche è essenziale.</li>
<li><strong>Compatibilità multi-cloud</strong>: con molte aziende che adottano strategie multi-cloud, il codice IaC deve essere sufficientemente flessibile da gestire ambienti eterogenei senza eccessive personalizzazioni.</li>
</ul>
<p>Uno studio del 2022 (<a href="https://arxiv.org/abs/2206.10344?ref=andreacasarin.com">[2206.10344] Static Analysis of Infrastructure as Code: a Survey</a>) ha analizzato le tecniche di analisi statica applicate a IaC, evidenziando la necessità di strumenti più avanzati per rilevare e prevenire difetti nei script IaC, al fine di garantire la sicurezza e l’affidabilità delle infrastrutture distribuite.</p>
<p>Tutti questi aspetti fanno emergere una verità scomoda: IaC non semplifica l'infrastruttura di per sé, ma ne cambia la gestione, trasformando i problemi operativi in problemi software. Per questo motivo, IaC deve essere affrontato con la stessa attenzione al design, alla modularità e ai test che si applicano allo sviluppo software tradizionale.</p>
<h2 id="strumenti-principali">Strumenti Principali</h2>
<p>L'ecosistema IaC offre strumenti specializzati per ogni fase della gestione dell'infrastruttura:</p>
<h3 id="terraform"><strong>Terraform</strong></h3>
<p>Terraform, sviluppato da HashiCorp, è uno dei tool più diffusi per la definizione e gestione dell'infrastruttura come codice. Usa il proprio linguaggio dichiarativo (HCL) per descrivere le risorse e gestisce lo stato dell'infrastruttura per garantire idempotenza e riproducibilità. Supporta molteplici provider cloud (AWS, GCP, Azure) e ambienti on-premise.</p>
<p>Uno dei principali vantaggi di Terraform è la sua capacità di orchestrare l'intero ciclo di vita dell'infrastruttura, dall'inizializzazione alla distruzione, con il comando <code>terraform apply</code>. Il suo modello dichiarativo permette di definire lo stato desiderato, lasciando al tool il compito di determinare quali azioni eseguire.</p>
<h3 id="ansible"><strong>Ansible</strong></h3>
<p>Ansible è un tool di automazione agentless, basato su YAML, che permette di configurare sistemi, applicazioni e infrastrutture. A differenza di Terraform, che si concentra sul provisioning, Ansible è ideale per la gestione della configurazione e l'automazione operativa. Può essere utilizzato per gestire il patching, l'installazione di software e il deployment di applicazioni su ambienti server.</p>
<p>Essendo basato su SSH, Ansible è estremamente semplice da integrare, senza la necessità di installare agent sui nodi gestiti. Tuttavia, rispetto a strumenti più strutturati come Terraform, Ansible è meno adatto alla gestione di infrastrutture intere, eccellendo invece nell'automazione della configurazione.</p>
<h3 id="docker-swarm-kubernetes"><strong>Docker Swarm &amp; Kubernetes</strong></h3>
<p>Se IaC si occupa del provisioning dell'infrastruttura, orchestratori come Docker Swarm e Kubernetes gestiscono il deployment e la scalabilità delle applicazioni containerizzate. Kubernetes, in particolare, è diventato lo standard de facto per orchestrare workload distribuiti, offrendo resilienza, scalabilità e automazione avanzata.</p>
<p>L'integrazione tra Terraform e Kubernetes consente di definire sia l'infrastruttura che i cluster containerizzati in modo coerente. Kubernetes utilizza manifest YAML per descrivere lo stato desiderato dei container, un concetto simile a quello di IaC, ma focalizzato sulla gestione delle applicazioni anziché sull'infrastruttura sottostante.</p>
<h2 id="un-approccio-graduale-alliac">Un Approccio Graduale all'IaC</h2>
<p>Molte aziende falliscono nell'adozione di IaC a causa di un approccio troppo aggressivo. Un'implementazione efficace deve essere graduale e mirata:</p>
<ol>
<li><strong>Identificare le aree critiche</strong>: iniziare con ambienti di sviluppo o staging prima di passare alla produzione. Adottare IaC senza una strategia progressiva può generare più problemi di quanti ne risolva.</li>
<li><strong>Modularizzare il codice</strong>: definire componenti riutilizzabili per ridurre la complessità e favorire il riutilizzo tra progetti diversi. L'uso di moduli Terraform o ruoli Ansible aiuta a mantenere il codice pulito e manutenibile.</li>
<li><strong>Versionare e testare</strong>: integrare il codice IaC in pipeline CI/CD con test automatici. Strumenti come <code>terratest</code> o <code>kitchen</code> consentono di validare le configurazioni prima di applicarle su larga scala.</li>
<li><strong>Automatizzare progressivamente</strong>: partire dalla gestione delle VM, poi containerizzazione, infine orchestrazione. L'automazione deve seguire un percorso logico e sostenibile per il team.</li>
<li><strong>Monitorare e migliorare</strong>: l'adozione di IaC non finisce con il deployment iniziale. Il monitoraggio continuo con strumenti come Prometheus e Grafana permette di individuare colli di bottiglia e migliorare le configurazioni.</li>
</ol>
<p>L'IaC non è una soluzione plug-and-play, ma un investimento strategico. Un'adozione intelligente e progressiva permette di massimizzarne i benefici senza introdurre rischi eccessivi. Con un piano ben strutturato, IaC può diventare un pilastro fondamentale per infrastrutture IT moderne, efficienti e scalabili.</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ AI in Locale: Una Soluzione sicura ed economica ]]></title>
        <description><![CDATA[ Il crescente utilizzo di modelli di intelligenza artificiale sta cambiando il modo in cui affrontiamo una vasta gamma di problemi, da quelli legati all&#39;automazione a quelli della personalizzazione dei servizi. Sebbene molte organizzazioni si siano affidate a soluzioni basate su cloud per sfruttare queste tecnologie, c&#39;è ]]></description>
        <link>https://www.andreacasarin.com/2025/01/31/ai-locale-sicura-economica.html/</link>
        <guid isPermaLink="false">679d06566695b60001e38832</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Fri, 31 Jan 2025 19:10:52 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2025/01/DALL-E-2025-01-31-18.27.09---A-futuristic-workstation-setup-featuring-a-powerful-desktop-PC-with-multiple-monitors--one-displaying-AI-code-and-another-showing-a-neural-network-vis.webp" medium="image"/>
        <content:encoded><![CDATA[ <p>Il crescente utilizzo di modelli di intelligenza artificiale sta cambiando il modo in cui affrontiamo una vasta gamma di problemi, da quelli legati all'automazione a quelli della personalizzazione dei servizi. Sebbene molte organizzazioni si siano affidate a soluzioni basate su cloud per sfruttare queste tecnologie, c'è una tendenza crescente verso l'adozione di modelli AI in locale. Questo approccio non solo offre vantaggi in termini di privacy e controllo sui dati, ma può anche ridurre i costi operativi a lungo termine. Tuttavia, come ogni tecnologia emergente, l'adozione di modelli AI in locale porta con sé una serie di sfide pratiche e tecniche che vanno considerate con attenzione.</p><h2 id="i-benefici-realistici-dei-modelli-ai-in-locale">I Benefici Realistici dei Modelli AI in Locale</h2><h3 id="privacy-e-controllo-dei-dati">Privacy e Controllo dei Dati</h3><p>Uno dei principali motivi per cui le aziende e i singoli sviluppatori stanno esplorando soluzioni AI in locale è la possibilità di mantenere il controllo completo sui propri dati. In un'epoca in cui la privacy è diventata una preoccupazione centrale, evitare il caricamento di dati sensibili su server remoti può essere un fattore decisivo. In particolare, con normative come il GDPR in Europa, la possibilità di lavorare con modelli di AI senza trasferire dati personali su piattaforme esterne è un vantaggio enorme. Questo controllo può ridurre il rischio di violazioni della sicurezza e migliorare la trasparenza nelle operazioni aziendali.</p><h3 id="riduzione-dei-costi-cloud">Riduzione dei Costi Cloud</h3><p>Molti modelli AI offrono un’API cloud che consente di eseguire inferenze in remoto. Tuttavia, questi servizi spesso comportano costi ricorrenti che possono crescere rapidamente, soprattutto se il volume delle richieste aumenta. Usare un modello AI in locale, invece, permette di eliminare la necessità di pagare per l'infrastruttura cloud e per le risorse computazionali scalabili, con il vantaggio di avere costi fissi più prevedibili legati all’acquisto e gestione di hardware.</p><h3 id="personalizzazione-e-indipendenza">Personalizzazione e Indipendenza</h3><p>Implementare un modello AI in locale consente anche una maggiore personalizzazione. Puoi scegliere il modello che meglio si adatta ai tuoi bisogni specifici, senza dover subire le limitazioni imposte dai provider di servizi cloud. Inoltre, le soluzioni in locale sono meno soggette a cambiamenti nelle politiche di pricing o nelle funzionalità, che possono influire negativamente su un servizio cloud nel lungo termine.</p><h2 id="le-sfide-dellimplementazione-ai-in-locale">Le Sfide dell'Implementazione AI in Locale</h2><h3 id="potenza-di-calcolo-e-hardware">Potenza di Calcolo e Hardware</h3><p>Il principale ostacolo all'adozione di modelli AI in locale è il requisito di hardware specializzato. A meno che tu non stia lavorando con modelli relativamente leggeri, avrai bisogno di risorse computazionali consistenti. Le GPU NVIDIA, in particolare, sono ampiamente utilizzate per il training e l'inferenza di modelli AI grazie alla loro potenza e supporto per librerie come CUDA. Tuttavia, queste soluzioni possono risultare costose e richiedono una gestione accurata del sistema. Le macchine basate su architettura ARM come quelle con Apple Silicon (M1, M2) sono anche un'opzione interessante, soprattutto per sviluppatori che già utilizzano hardware Mac, ma sono ancora limitate rispetto alle GPU NVIDIA in termini di performance puramente AI-driven.</p><p>Se hai intenzione di utilizzare un modello di grande scala o di lavorare con dataset complessi, non sarà sufficiente un normale laptop. Avrai bisogno di una workstation potente o di un server equipaggiato con GPU appropriate, e anche in questo caso il costo dell'infrastruttura potrebbe essere proibitivo per alcuni.</p><h3 id="gestione-e-installazione-del-software">Gestione e Installazione del Software</h3><p>Anche se i modelli AI sono ormai molto più accessibili, l’installazione e la gestione di questi sistemi in locale possono risultare complicati. Molti sviluppatori, abituati a lavorare con API cloud, potrebbero trovarsi in difficoltà con la configurazione e l'installazione dei modelli. Le dipendenze software, la compatibilità hardware, e le impostazioni specifiche per ogni tipo di modello richiedono attenzione e competenze tecniche.</p><h2 id="conclusioni-un-approccio-realistico-allai-in-locale">Conclusioni: Un Approccio Realistico all'AI in Locale</h2><p>L’adozione di modelli AI in locale offre indubbi vantaggi in termini di privacy, controllo e riduzione dei costi operativi. Tuttavia, non è una soluzione senza sfide. Le risorse hardware necessarie possono essere costose e le difficoltà tecniche nell'installazione e gestione del software non devono essere sottovalutate. Detto ciò, per molti sviluppatori e aziende, i benefici superano di gran lunga gli ostacoli.</p><p>Se sei pronto a fare il salto, soluzioni come Ollama e OpenWebUI, abbinate a hardware adeguato, possono semplificare notevolmente il processo. L'adozione di AI in locale è una mossa pragmatica che risponde a esigenze reali, ma richiede un certo impegno per essere implementata correttamente. Con la giusta preparazione, però, puoi sfruttare appieno il potenziale dei modelli AI, ottenendo il massimo in termini di efficienza, privacy e costi.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Website Refresh for 2025 and Beyond ]]></title>
        <description><![CDATA[ I&#39;m excited to announce the restyling of my personal blog. I&#39;ve worked on making the site more modern and user-friendly, powered by Ghost CMS. This refresh is more than just a new coat of paint - it&#39;s part of a broader effort to better ]]></description>
        <link>https://www.andreacasarin.com/2025/01/02/website-refresh-for-2025-and-beyond.html/</link>
        <guid isPermaLink="false">6761a721ad66200001667d10</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Thu, 02 Jan 2025 11:30:23 +0100</pubDate>
        <media:content url="https://images.unsplash.com/photo-1518773553398-650c184e0bb3?crop&#x3D;entropy&amp;cs&#x3D;tinysrgb&amp;fit&#x3D;max&amp;fm&#x3D;jpg&amp;ixid&#x3D;M3wxMTc3M3wwfDF8c2VhcmNofDJ8fGNvZGV8ZW58MHx8fHwxNzM0NDU0MTQyfDA&amp;ixlib&#x3D;rb-4.0.3&amp;q&#x3D;80&amp;w&#x3D;2000" medium="image"/>
        <content:encoded><![CDATA[ <p>I'm excited to announce the restyling of my personal blog. I've worked on making the site more modern and user-friendly, powered by Ghost CMS. This refresh is more than just a new coat of paint - it's part of a broader effort to better share my journey in software engineering.</p><p>The update includes:</p><ul><li>A <strong>cleaner</strong>, more focused <strong>design</strong> that puts content first</li><li>A new <strong>professional logo</strong> that represents my values as a digital craftsman</li><li>Improved <strong>navigation</strong> to help you find projects and insights</li><li><strong>Ghost CMS</strong> powering the site, bringing modern publishing features like:<ul><li>Better content management</li><li>Native newsletter capabilities</li><li>Improved reading experience</li><li>SEO optimization out of the box</li><li>Member management for future community features</li></ul></li></ul><p>Coming soon:</p><ul><li>A <strong>newsletter</strong> to share regular insights and updates</li><li>More detailed case studies of <strong>real-world</strong> solutions</li></ul><p>My goal remains unchanged: sharing practical insights and measured results from my software engineering journey.</p><p>Take a look around and <strong>let me know what you think!</strong> Your feedback helps me improve and create more valuable content.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Tempo di bilanci e auguri: ci rivediamo nel 2025 con nuovi progetti ]]></title>
        <description><![CDATA[ È arrivato quel momento dell&#39;anno in cui è bello fermarsi un attimo, fare il punto della situazione e guardare con ottimismo al futuro. Vorrei condividere con voi, che seguite il mio lavoro e collaborate con me, i piani per questo periodo di festività.


Pausa festiva e informazioni utili ]]></description>
        <link>https://www.andreacasarin.com/2024/12/17/tempo-di-bilanci-e-auguri-ci-rivediamo-nel-2025-con-nuovi-progetti.html/</link>
        <guid isPermaLink="false">675014b51a43240001cb90e1</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Tue, 17 Dec 2024 18:09:00 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/12/pexels-ionela-mat-268382825-29607858.jpg" medium="image"/>
        <content:encoded><![CDATA[ <p>È arrivato quel momento dell'anno in cui è bello fermarsi un attimo, fare il punto della situazione e guardare con ottimismo al futuro. Vorrei condividere con voi, che seguite il mio lavoro e collaborate con me, i piani per questo periodo di festività.</p><h2 id="pausa-festiva-e-informazioni-utili-%F0%9F%93%85">Pausa festiva e informazioni utili &nbsp;📅</h2><p>Dal <strong>23 dicembre 2024 al 6 gennaio 2025</strong> mi prenderò una pausa per dedicare del tempo alla famiglia e ricaricare le energie. Per chi ha progetti in corso, sono a disposizione fino al 22 dicembre per organizzare al meglio le attività e assicurarci che tutto proceda senza intoppi.</p><h2 id="riflessioni-sul-2024-%E2%9C%A8">Riflessioni sul 2024 ✨</h2><p>Quest'anno è stato ricco di soddisfazioni e crescita professionale. Ho avuto il privilegio di lavorare con clienti che mi hanno dato fiducia e colleghi che hanno arricchito il mio percorso con le loro competenze. Ogni progetto è stato un'opportunità di apprendimento e miglioramento.</p><h2 id="uno-sguardo-al-2025-%F0%9F%9A%80">Uno sguardo al 2025 🚀</h2><p>Il nuovo anno si prospetta entusiasmante, con nuove idee e progetti in cantiere. Tornerò <strong>operativo il 7 gennaio</strong>, pronto a riprendere le attività con rinnovato entusiasmo e nuove prospettive da esplorare insieme.</p><h2 id="auguri-sinceri-%F0%9F%8E%81">Auguri sinceri 🎁</h2><p>A tutti voi <strong>auguro delle festività serene e un 2025 ricco di successi</strong>. Che sia un anno di crescita e nuove opportunità per tutti noi.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Un&#x27;analisi cinica dei costi nascosti del cloud: perché a volte on-prem ha ancora senso ]]></title>
        <description><![CDATA[ Dopo 15 anni passati a migrare workload su cloud per diverse aziende, ho sviluppato una sana dose di scetticismo verso la narrativa dominante del &quot;cloud-first a tutti i costi&quot;. Non fraintendetemi: il cloud rimane una scelta eccellente in molti scenari, ma la realtà che ho toccato con mano ]]></description>
        <link>https://www.andreacasarin.com/2024/11/26/costi-nascosti-cloud-on-prem.html/</link>
        <guid isPermaLink="false">6746158b1a43240001cb90d3</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Tue, 26 Nov 2024 19:39:04 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/57819.jpg" medium="image"/>
        <content:encoded><![CDATA[ <p>Dopo 15 anni passati a migrare workload su cloud per diverse aziende, ho sviluppato una sana dose di scetticismo verso la narrativa dominante del "cloud-first a tutti i costi". Non fraintendetemi: il cloud rimane una scelta eccellente in molti scenari, ma la realtà che ho toccato con mano è più sfumata di quanto i vendor vogliano farci credere.</p>
<h2 id="la-verit%C3%A0-scomoda-sui-costi-cloud">La verità scomoda sui costi cloud</h2>
<p>Nella mia esperienza, quando analizzo i costi cloud di una tipica azienda media, trovo sempre lo stesso pattern: budget superati e sprechi che fino al 30% della spesa totale.</p>
<p>La scomposizione tipica dei costi cloud che vedo più spesso rivela un quadro interessante:</p>
<ul>
<li>Buona parte delle aziende ha grossi problemi nel controllo dei costi e faticano a fare previsioni accurate di spesa</li>
<li>I costi di egress spesso sono la sorpresa più grande, arrivando fino al 20% del totale</li>
<li>Le risorse zombie sono ovunque: VM, storage e servizi dimenticati che continuano a generare costi</li>
</ul>
<h2 id="lelefante-nella-stanza-la-complessit%C3%A0-nascosta">L'elefante nella stanza: la complessità nascosta</h2>
<p>La promessa del cloud è quella di semplificare la gestione dell'infrastruttura. La realtà che vedo ogni giorno è che spesso si sostituisce complessità hardware con complessità software - e quest'ultima può essere molto più insidiosa da gestire.</p>
<p>Ho notato che circa tre quarti delle organizzazioni con cui lavoro riportano la complessità come principale sfida, specialmente quando si parla di sicurezza e governance.</p>
<h2 id="quando-on-prem-ha-ancora-senso-casi-duso-reali">Quando on-prem ha ancora senso: casi d'uso reali</h2>
<p>Nella mia pratica, ho identificato tre scenari dove l'infrastruttura on-premise risulta ancora vantaggiosa:</p>
<ol>
<li>
<p><strong>Workload prevedibili e stabili</strong><br>
Ho visto ripetutamente come le applicazioni con carichi prevedibili possano costare fino al 30% in meno on-premise su un periodo di 3 anni.</p>
</li>
<li>
<p><strong>Dati con alta località</strong><br>
Quando lavoro con applicazioni data-intensive, la gestione locale dei dati spesso riduce drasticamente non solo i costi ma anche la latenza.</p>
</li>
<li>
<p><strong>Requisiti di compliance stringenti</strong><br>
Nel settore finanziario e sanitario, ho visto la gestione della compliance su cloud aumentare i costi operativi anche del 40%.</p>
</li>
</ol>
<h2 id="limportanza-di-unanalisi-pragmatica">L'importanza di un'analisi pragmatica</h2>
<p>Nel mio lavoro quotidiano, utilizzo questo framework decisionale che si è dimostrato efficace:</p>
<ol>
<li>
<p>Calcolo del TCO su 3 anni includendo:</p>
<ul>
<li>Costi hardware/software</li>
<li>Costi operativi (personale, energia, spazio)</li>
<li>Costi di rete</li>
<li>Costi di migrazione e training</li>
</ul>
</li>
<li>
<p>Analisi dei pattern di utilizzo:</p>
<ul>
<li>Variabilità dei carichi</li>
<li>Requisiti di scalabilità</li>
<li>Località dei dati</li>
<li>Vincoli di compliance</li>
</ul>
</li>
<li>
<p>Valutazione delle competenze interne:</p>
<ul>
<li>Expertise esistente</li>
<li>Costi di formazione</li>
<li>Disponibilità sul mercato</li>
</ul>
</li>
</ol>
<h2 id="lezioni-apprese-sul-campo">Lezioni apprese sul campo</h2>
<p>Dopo centinaia di progetti, queste sono le mie principali osservazioni:</p>
<ol>
<li>
<p><strong>Il cloud non è un risparmio automatico</strong><br>
Quasi metà dei progetti che ho seguito hanno riportato costi superiori alle aspettative iniziali.</p>
</li>
<li>
<p><strong>La complessità si sposta, non scompare</strong><br>
La maggior parte degli sviluppatori con cui lavoro considera la complessità del cloud una delle sfide più significative.</p>
</li>
<li>
<p><strong>L'ibrido non è un male</strong><br>
Le implementazioni di maggior successo che ho visto sono quasi sempre ibride, con un mix intelligente di cloud e on-premise.</p>
</li>
</ol>
<h2 id="conclusione-verso-un-approccio-equilibrato">Conclusione: verso un approccio equilibrato</h2>
<p>La realtà che ho toccato con mano è che non esiste una soluzione universale. Il cloud è fantastico per molti scenari, ma non è la risposta a tutto. Il mio consiglio? Partite dai dati, non dal marketing. Analizzate i vostri workload specifici, calcolate i costi reali (non teorici) e prendete decisioni basate sulla vostra realtà, non sui trend del momento.</p>
<p>Nel dubbio, iniziate piccolo e scalate gradualmente. L'approccio incrementale, per quanto meno sexy, vi permetterà di validare assunzioni e costi prima di committare risorse significative.</p>
<p>Il cloud è uno strumento, non un obiettivo. E come tutti gli strumenti, ha il suo posto e le sue limitazioni. La vera abilità sta nel saperlo utilizzare nel modo giusto, al momento giusto, per il workload giusto.</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ DettoFatto ]]></title>
        <description><![CDATA[ Development and system engineering for the property manager&#39;s robotic ally that communicates with residents and suppliers as if it were you, keeping you updated on all activities performed so you never lose control.

 * Website ]]></description>
        <link>https://www.andreacasarin.com/projects/dettofatto/</link>
        <guid isPermaLink="false">6741d59426097f0001d2bd39</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:16:58 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/dettofatto.jpg" medium="image"/>
        <content:encoded><![CDATA[ <p>Development and system engineering for the property manager's robotic ally that communicates with residents and suppliers as if it were you, keeping you updated on all activities performed so you never lose control.</p><ul><li><a href="https://dettofatto.cloud/?ref=andreacasarin.com">Website</a></li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Zonale ]]></title>
        <description><![CDATA[ Startup of a proximity e-commerce platform that allows small retailers to independently create their own online store and sell to local customers. ]]></description>
        <link>https://www.andreacasarin.com/projects/zonale/</link>
        <guid isPermaLink="false">6741d56f26097f0001d2bd2d</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:15:57 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/zonale.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Startup of a proximity e-commerce platform that allows small retailers to independently create their own online store and sell to local customers.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ UPA Formazione ]]></title>
        <description><![CDATA[ Provision of courses funded by UPA Formazione on the use of Docker and Kubernetes in small businesses. ]]></description>
        <link>https://www.andreacasarin.com/projects/upa-formazione/</link>
        <guid isPermaLink="false">6741d55626097f0001d2bd22</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:15:19 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/upa-formazione.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Provision of courses funded by <strong>UPA Formazione</strong> on the use of Docker and Kubernetes in small businesses.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ SeeSaw ]]></title>
        <description><![CDATA[ Collaboration with SeeSaw for the development of Infrastructure As Code (IaC) systems based on Ansible, Terraform, and Kubernetes on Amazon Web Services (AWS) platform. ]]></description>
        <link>https://www.andreacasarin.com/projects/seesaw/</link>
        <guid isPermaLink="false">6741d53226097f0001d2bd17</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:14:45 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/seesaw.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Collaboration with <strong>SeeSaw</strong> for the development of Infrastructure As Code (IaC) systems based on Ansible, Terraform, and Kubernetes on Amazon Web Services (AWS) platform.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Codemotion ]]></title>
        <description><![CDATA[ Definition of a training path for DevOps engineers, assistance in selecting instructors, and creation of the introductory module for Codemotion (in Italian).

 * Codemotion learning ]]></description>
        <link>https://www.andreacasarin.com/projects/codemotion/</link>
        <guid isPermaLink="false">6741d50e26097f0001d2bd0b</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:14:17 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/codemotion.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Definition of a training path for DevOps engineers, assistance in selecting instructors, and creation of the introductory module for <strong>Codemotion</strong> (in Italian).</p><ul><li><a href="https://www.codemotion.com/learning/tp/i-benefici-di-usare-un-modello-di-devops-1409?ref=andreacasarin.com">Codemotion learning</a></li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ DevPresto ]]></title>
        <description><![CDATA[ An online collection of quick tools for developers and system administrators.

 * Website ]]></description>
        <link>https://www.andreacasarin.com/projects/devpresto-2/</link>
        <guid isPermaLink="false">6741d4e426097f0001d2bcfd</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:13:44 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/devpresto.png" medium="image"/>
        <content:encoded><![CDATA[ <p>An online collection of quick tools for developers and system administrators.</p><ul><li><a href="https://devpresto.com/?ref=andreacasarin.com">Website</a></li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ IZSVe ]]></title>
        <description><![CDATA[ Development of collaboration and business administration tools for the Istituto Zooprofilattico Sperimentale delle Venezie via the MePA platform. ]]></description>
        <link>https://www.andreacasarin.com/projects/izsve/</link>
        <guid isPermaLink="false">6741d4c326097f0001d2bcf1</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:13:00 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/izsve-istituto-zooprofilattico-sperimentale-venezie.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of collaboration and business administration tools for the <strong>Istituto Zooprofilattico Sperimentale delle Venezie</strong> via the MePA platform.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Omniaweb ]]></title>
        <description><![CDATA[ Development of a custom Extract/Transform/Load (ETL) service for MakingScience - Omniaweb. ]]></description>
        <link>https://www.andreacasarin.com/projects/omniaweb/</link>
        <guid isPermaLink="false">6741d4a126097f0001d2bce5</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:12:29 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/omniaweb-makingscience.jpg" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of a custom Extract/Transform/Load (ETL) service for <strong>MakingScience - Omniaweb</strong>.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Oblatum ]]></title>
        <description><![CDATA[ Startup of a global asset management tool based on the Ethereum blockchain.

 *  Article
 *  GitHub ]]></description>
        <link>https://www.andreacasarin.com/projects/oblatum/</link>
        <guid isPermaLink="false">6741d45b26097f0001d2bcd6</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:11:50 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/oblatum.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Startup of a global asset management tool based on the Ethereum blockchain.</p><ul><li>&nbsp;<a href="https://www.andreacasarin.com/2018/12/14/oblatum-blockchain-assets-management.html" rel="noreferrer">Article</a></li><li>&nbsp;<a href="https://github.com/andreacasarin/Oblatum?ref=andreacasarin.com" rel="nofollow noopener noreferrer">GitHub</a></li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Generali s.p.a. ]]></title>
        <description><![CDATA[ Development of a Ruby on Rails backoffice platform for the census and monitoring of remote application servers located at client sites. Authorization management through LDAP server. For Generali s.p.a. Commissioned by IKS s.r.l. ]]></description>
        <link>https://www.andreacasarin.com/projects/generali-s-p-a/</link>
        <guid isPermaLink="false">6741d43c26097f0001d2bcca</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:10:45 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/generali.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of a Ruby on Rails backoffice platform for the census and monitoring of remote application servers located at client sites. Authorization management through LDAP server. For <strong>Generali s.p.a.</strong> Commissioned by IKS s.r.l.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Cryptocurrency Change Bot ]]></title>
        <description><![CDATA[ Creation of a Telegram bot, based on serverless architecture, that returns the exchange rate of major virtual currencies.

 *  Article (italian)
 *  Telegram
 *  GitHub ]]></description>
        <link>https://www.andreacasarin.com/projects/cryptocurrency-change-bot/</link>
        <guid isPermaLink="false">6741d41226097f0001d2bcbb</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:10:10 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/cryptocurrencychangebot.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Creation of a Telegram bot, based on serverless architecture, that returns the exchange rate of major virtual currencies.</p><ul><li>&nbsp;<a href="https://www.andreacasarin.com/2017/09/12/serverless-telegram-bot.html">Article</a> (italian)</li><li>&nbsp;<a href="https://t.me/CryptocurrencyChangeBot?ref=andreacasarin.com" rel="nofollow noopener noreferrer">Telegram</a></li><li>&nbsp;<a href="https://github.com/andreacasarin/CryptocurrencyChangeBot?ref=andreacasarin.com" rel="nofollow noopener noreferrer">GitHub</a></li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ FabKey ]]></title>
        <description><![CDATA[ Implementation of the FabKey system based on Arduino and NFC tags during the IoT course at FabLab Padova. The application reads the tag code, sends an authorization request to a remote server, and, if the response is positive, opens the electronic lock of a door.

 *  Article (italian) ]]></description>
        <link>https://www.andreacasarin.com/projects/fabkey/</link>
        <guid isPermaLink="false">6741d3b126097f0001d2bcab</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:09:11 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/fabkey.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Implementation of the <strong>FabKey</strong> system based on Arduino and NFC tags during the IoT course at FabLab Padova. The application reads the tag code, sends an authorization request to a remote server, and, if the response is positive, opens the electronic lock of a door.</p><ul><li>&nbsp;<a href="https://www.andreacasarin.com/2018/02/28/arduino-nfc-iot-fabkey.html">Article</a> (italian)</li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ domain-scan + Secure the News ]]></title>
        <description><![CDATA[ Development of an Ansible deployment for two open-source tools, developed for hack.developers, which can be used to classify a group of websites based on their HTTPS adoption level.

 *  Article (italian)
 *  GitHub ]]></description>
        <link>https://www.andreacasarin.com/projects/domainscan-securethenews/</link>
        <guid isPermaLink="false">6741d36626097f0001d2bc9b</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:07:53 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/securethenews.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of an Ansible deployment for two open-source tools, developed for hack.developers, which can be used to classify a group of websites based on their HTTPS adoption level.</p><ul><li>&nbsp;<a href="https://www.andreacasarin.com/2017/11/03/hackdev17-ansible-docker.html">Article</a> (italian)</li><li>&nbsp;<a href="https://github.com/andreacasarin/security-recipes/tree/master/securethenews?ref=andreacasarin.com" rel="nofollow noopener noreferrer">GitHub</a></li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Dirify ]]></title>
        <description><![CDATA[ A geolocated search engine based on data provided by the Italian OpenData system and updated by qualified users. It is currently implemented for pharmacies and parapharmacies, schools, museums, and healthcare facilities. ]]></description>
        <link>https://www.andreacasarin.com/projects/dirify/</link>
        <guid isPermaLink="false">6741d33b26097f0001d2bc8f</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:06:38 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/dirify.png" medium="image"/>
        <content:encoded><![CDATA[ <p>A geolocated search engine based on data provided by the Italian OpenData system and updated by qualified users. It is currently implemented for pharmacies and parapharmacies, schools, museums, and healthcare facilities.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Miluna ]]></title>
        <description><![CDATA[ Frontend and backend development for an online contest and secure hosting provision for Miluna. Commissioned by Mibu Lab. ]]></description>
        <link>https://www.andreacasarin.com/projects/miluna/</link>
        <guid isPermaLink="false">6741d30f26097f0001d2bc84</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:05:54 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/miluna.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Frontend and backend development for an online contest and secure hosting provision for <strong>Miluna</strong>. Commissioned by Mibu Lab.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ H-Farm ]]></title>
        <description><![CDATA[ Development of high-profile web solutions and IT infrastructures for the deployment and development of software projects for various startups in the H-Farm ecosystem. ]]></description>
        <link>https://www.andreacasarin.com/projects/h-farm/</link>
        <guid isPermaLink="false">6741d2f126097f0001d2bc79</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:05:07 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/hfarm.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of high-profile web solutions and IT infrastructures for the deployment and development of software projects for various startups in the <strong>H-Farm</strong> ecosystem.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Dainese ]]></title>
        <description><![CDATA[ Development of Magento e-commerce platform and Ruby on Rails backend for managing text content of the institutional website for Dainese in partnership with Develon. ]]></description>
        <link>https://www.andreacasarin.com/projects/dainese/</link>
        <guid isPermaLink="false">6741d2af26097f0001d2bc6e</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:04:01 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/dainese.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of Magento e-commerce platform and Ruby on Rails backend for managing text content of the institutional website for <strong>Dainese</strong> in partnership with Develon.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ TCVI ]]></title>
        <description><![CDATA[ Content management platform modifications. For Teatro Comunale di Vicenza in partnership with Develon. ]]></description>
        <link>https://www.andreacasarin.com/projects/tcvi/</link>
        <guid isPermaLink="false">6741d29926097f0001d2bc63</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:03:37 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/tcvi.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Content management platform modifications. For <strong>Teatro Comunale di Vicenza</strong> in partnership with Develon.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Marzotto ]]></title>
        <description><![CDATA[ Development of Magento e-commerce platform for Marzotto. In partnership with Develon. ]]></description>
        <link>https://www.andreacasarin.com/projects/marzotto/</link>
        <guid isPermaLink="false">6741d28426097f0001d2bc58</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:03:13 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/marzotto.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of Magento e-commerce platform for <strong>Marzotto</strong>. In partnership with Develon.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Montura ]]></title>
        <description><![CDATA[ Development of Magento e-commerce platform for Montura. In partnership with Develon. ]]></description>
        <link>https://www.andreacasarin.com/projects/montura/</link>
        <guid isPermaLink="false">6741d21b26097f0001d2bc4b</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:02:54 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/montura.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of Magento e-commerce platform for <strong>Montura</strong>. In partnership with Develon.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Develon ]]></title>
        <description><![CDATA[ Development and customization of e-commerce platforms based on Magento and dynamic websites with WordPress and Ruby on Rails for Develon. ]]></description>
        <link>https://www.andreacasarin.com/projects/develon/</link>
        <guid isPermaLink="false">6741d20226097f0001d2bc40</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:01:06 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/develon.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development and customization of e-commerce platforms based on Magento and dynamic websites with WordPress and Ruby on Rails for <strong>Develon</strong>.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Venitem ]]></title>
        <description><![CDATA[ Research and development of the new web portal for Venitem. Integration with Facebook and Mailchimp for online community management. Setup of hosting platform. ]]></description>
        <link>https://www.andreacasarin.com/projects/venitem/</link>
        <guid isPermaLink="false">6741d1d926097f0001d2bc35</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:00:40 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/venitem.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Research and development of the new web portal for <strong>Venitem</strong>. Integration with Facebook and Mailchimp for online community management. Setup of hosting platform.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Pixelperfect ]]></title>
        <description><![CDATA[ Co-founder of Pixelperfect, a digital agency specialized in innovative web solutions and internet-based products. ]]></description>
        <link>https://www.andreacasarin.com/projects/pixelperfect/</link>
        <guid isPermaLink="false">6741d19726097f0001d2bc2a</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 14:00:00 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/pixelperfect.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Co-founder of <strong>Pixelperfect</strong>, a digital agency specialized in innovative web solutions and internet-based products.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Webster ]]></title>
        <description><![CDATA[ Development of backend and frontend system for managing product showcases (home page, categories, newsletter) for Webster.it and Libreria Universitaria. ]]></description>
        <link>https://www.andreacasarin.com/projects/webster/</link>
        <guid isPermaLink="false">6741d17926097f0001d2bc20</guid>
        <category><![CDATA[ project ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 23 Nov 2024 13:58:55 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/webster.png" medium="image"/>
        <content:encoded><![CDATA[ <p>Development of backend and frontend system for managing product showcases (home page, categories, newsletter) for <strong>Webster.it</strong> and <strong>Libreria Universitaria</strong>.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Reverse engineering an IoT API ]]></title>
        <description><![CDATA[ Reverse engineering IoT device APIs is an enlightening exercise that combines networking knowledge, security understanding, and problem-solving skills. ]]></description>
        <link>https://www.andreacasarin.com/2024/10/26/reverse-engineering-an-iot-api.html/</link>
        <guid isPermaLink="false">671ccc65a7df1000018bec3c</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 26 Oct 2024 13:16:05 +0200</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/iot-reverse-engineering-diagram.svg" medium="image"/>
        <content:encoded><![CDATA[ <p>As our homes become increasingly connected, IoT devices have become an integral part of our daily lives. While these smart devices offer convenience and automation, understanding how they communicate can be both fascinating and educational. Today, I'd like to share my experience diving into the world of IoT device analysis, specifically focusing on reverse engineering an IoT device's API.</p>
<h2 id="why-reverse-engineer-iot-apis">Why Reverse Engineer IoT APIs?</h2>
<p>Before diving into the technical details, you might wonder why someone would want to reverse engineer an IoT device's API. There are several legitimate reasons:</p>
<ul>
<li>Understanding device security and privacy implications</li>
<li>Developing custom integrations with home automation systems</li>
<li>Learning about network protocols and IoT communication patterns</li>
<li>Troubleshooting device issues</li>
<li>Creating documentation for undocumented APIs</li>
</ul>
<h2 id="the-setup">The Setup</h2>
<p>For this exploration, I used a combination of common networking tools and my home network setup, which includes:</p>
<ul>
<li>An OpenWRT router (providing advanced networking capabilities)</li>
<li>A MacBook Pro (as the analysis platform)</li>
<li>The target IoT device</li>
<li>Basic networking tools: tcpdump, Wireshark, and mitmproxy</li>
</ul>
<p>The beauty of this setup is that it's relatively simple and accessible to anyone with basic networking knowledge and a willingness to learn.</p>
<h2 id="network-traffic-analysis-approach">Network Traffic Analysis Approach</h2>
<p>My journey began with passive network analysis. Instead of immediately attempting to intercept traffic, I first observed the device's communication patterns. This non-intrusive approach is crucial for several reasons:</p>
<ol>
<li>It helps understand the device's normal behavior</li>
<li>It reveals the frequency and types of communications</li>
<li>It identifies the endpoints the device communicates with</li>
<li>It provides insights into the protocol patterns used</li>
</ol>
<p>Using OpenWRT's capabilities, I set up a remote packet capture using tcpdump and streamed it directly to Wireshark on my Mac. This elegant solution allowed me to capture and analyze traffic in real-time without storing large capture files on the router:</p>
<pre><code class="language-bash">ssh user@openwrt.local tcpdump -i lan host 192.168.123.123 -U -s0 -w - | sudo /Applications/Wireshark.app/Contents/MacOS/wireshark -k -i -
</code></pre>
<p>This command creates a powerful pipeline where:</p>
<ul>
<li>tcpdump captures packets on the router's LAN interface</li>
<li>The capture is filtered to focus only on our IoT device</li>
<li>The data is streamed directly to Wireshark for real-time analysis</li>
</ul>
<h2 id="man-in-the-middle-analysis">Man-in-the-Middle Analysis</h2>
<p>After understanding the basic communication patterns, I moved to a more active analysis approach using mitmproxy. This powerful tool allows us to intercept and inspect HTTPS traffic, which is increasingly common in IoT devices:</p>
<pre><code class="language-bash">mitmproxy --set tls_version_client_min=SSL3
</code></pre>
<p>The use of mitmproxy with a custom certificate provides several advantages:</p>
<ul>
<li>Ability to inspect encrypted traffic</li>
<li>Possibility to modify requests and responses for testing</li>
<li>Better understanding of the API structure and authentication mechanisms</li>
<li>Real-time interaction with the device's communication</li>
</ul>
<p>Man-in-the-Middle (MITM) analysis is a technique where network traffic is intercepted and analyzed as it passes between two points - in our case, between an IoT device and its server. Think of it as being a "postal inspector" who can open, read, and even modify letters being sent between two parties, all while both parties believe they're communicating directly with each other.</p>
<ol>
<li>
<p><strong>Traffic Interception</strong>:</p>
<ul>
<li>The MITM proxy positions itself between the IoT device and the internet</li>
<li>All traffic is routed through this proxy instead of going directly to its destination</li>
<li>This is typically achieved by configuring network settings or DNS</li>
</ul>
</li>
<li>
<p><strong>SSL/TLS Handling</strong>:</p>
<ul>
<li>For encrypted traffic (HTTPS), the proxy acts as two participants:
<ul>
<li>It presents itself as the server to the IoT device</li>
<li>It presents itself as the device to the server</li>
</ul>
</li>
<li>This allows it to decrypt, inspect, and re-encrypt the traffic</li>
</ul>
</li>
<li>
<p><strong>Traffic Analysis</strong>:</p>
<ul>
<li>Once intercepted, the traffic can be:
<ul>
<li>Viewed in real-time</li>
<li>Logged for later analysis</li>
<li>Modified before being forwarded</li>
<li>Replayed or duplicated for testing</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="best-practices-and-ethical-considerations">Best Practices and Ethical Considerations</h2>
<p>While reverse engineering can be an exciting technical challenge, it's important to approach it responsibly:</p>
<ol>
<li><strong>Always work with devices you own</strong>: Never attempt to reverse engineer devices or networks without explicit permission</li>
<li><strong>Keep security in mind</strong>: Document any vulnerabilities you discover and report them responsibly</li>
<li><strong>Respect privacy</strong>: Be mindful of any personal data you might encounter during analysis</li>
<li><strong>Document everything</strong>: Good documentation helps both your understanding and potential future reference</li>
<li><strong>Stay legal</strong>: Ensure your activities comply with local laws and regulations</li>
</ol>
<h2 id="tools-references">Tools &amp; References</h2>
<p>For those interested in exploring IoT reverse engineering, here are the official resources for the tools used in this article:</p>
<h3 id="core-tools">Core Tools</h3>
<ul>
<li><strong>Wireshark</strong> (<a href="https://wireshark.org/?ref=andreacasarin.com">wireshark.org</a>)
<ul>
<li>The world's foremost network protocol analyzer</li>
<li>Features a rich GUI interface</li>
<li>Supports deep packet inspection and analysis</li>
<li>Available for Windows, macOS, and Linux</li>
</ul>
</li>
<li><strong>tcpdump</strong> (<a href="https://tcpdump.org/?ref=andreacasarin.com">tcpdump.org</a>)
<ul>
<li>Command-line packet analyzer</li>
<li>Standard in most Unix-like operating systems</li>
<li>Perfect for remote capture and analysis</li>
<li>Lightweight and powerful</li>
</ul>
</li>
<li><strong>mitmproxy</strong> (<a href="https://mitmproxy.org/?ref=andreacasarin.com">mitmproxy.org</a>)
<ul>
<li>Free and open source interactive HTTPS proxy</li>
<li>Features both command-line and web interfaces</li>
<li>Perfect for API inspection and modification</li>
<li>Extensive documentation for advanced usage</li>
</ul>
</li>
</ul>
<h3 id="additional-resources">Additional Resources</h3>
<ul>
<li><strong>OpenWRT</strong> (<a href="https://openwrt.org/?ref=andreacasarin.com">openwrt.org</a>)
<ul>
<li>Open-source router firmware</li>
<li>Extensive networking capabilities</li>
<li>Perfect for advanced network analysis</li>
<li>Large community and documentation</li>
</ul>
</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Reverse engineering IoT device APIs is an enlightening exercise that combines networking knowledge, security understanding, and problem-solving skills. While the tools and techniques might seem complex at first, they provide valuable insights into how our connected devices work.</p>
<p>This exploration is just the beginning – there's much more to discover in the world of IoT communication. Whether you're a developer looking to create custom integrations, a security researcher interested in device behavior, or simply a curious technologist, understanding how IoT devices communicate can open up new possibilities for home automation and device integration.</p>
<p>Did you find this IoT reverse engineering journey interesting? This is just one of many technical adventures I share regularly. <strong>Subscribe to my newsletter</strong> to receive:</p>
<ul>
<li>In-depth technical tutorials and walkthroughs</li>
<li>Tips and tricks for network analysis and security</li>
<li>Early access to new articles and exclusive content</li>
<li>Real-world case studies and problem-solving approaches</li>
<li>Code snippets and tool recommendations</li>
</ul>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ GitLab CI Docker Builds into Kubernetes Without Kaniko ]]></title>
        <description><![CDATA[ Introduction


In the fast-paced world of DevOps and cloud-native applications, continuous integration and deployment (CI/CD) pipelines are the backbone of efficient software delivery. GitLab CI, Docker, and Kubernetes have emerged as powerful tools in this ecosystem, each bringing its own strengths to the table. However, combining these technologies to ]]></description>
        <link>https://www.andreacasarin.com/2024/09/14/gitlab-ci-docker-builds-into-kubernetes-without-kaniko.html/</link>
        <guid isPermaLink="false">66e5756630783c00010a91be</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 14 Sep 2024 13:41:31 +0200</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/DALL-E-2024-09-14-13.39.07---A-landscape-infographic-style-image-with-the-following-elements_-Central-focus-is-a-large-container-representing-Docker-in-Docker-blue--with-the-GitLa-1.webp" medium="image"/>
        <content:encoded><![CDATA[ <h2 id="introduction">Introduction</h2>
<p>In the fast-paced world of DevOps and cloud-native applications, continuous integration and deployment (CI/CD) pipelines are the backbone of efficient software delivery. GitLab CI, Docker, and Kubernetes have emerged as powerful tools in this ecosystem, each bringing its own strengths to the table. However, combining these technologies to create a seamless build and deploy pipeline can be challenging, especially when it comes to building Docker images within a Kubernetes environment.</p>
<p>GitLab CI offers robust automation capabilities, Docker provides consistent and portable environments, and Kubernetes excels at orchestrating containerized applications. The challenge lies in bridging these technologies effectively, particularly when building Docker images as part of your CI pipeline running in Kubernetes.</p>
<p>Traditionally, tools like Kaniko have been used to build Docker images without requiring a Docker daemon. While Kaniko is a powerful solution, it's not always the best fit for every scenario. In this article, we'll explore an alternative approach: using Docker-in-Docker (DinD) with GitLab CI's Kubernetes executor to build Docker images directly within your Kubernetes cluster.</p>
<p>This method leverages GitLab Runner's Kubernetes executor and the Docker-in-Docker technique to create a flexible and powerful build environment. By the end of this article, you'll understand how to:</p>
<ol>
<li>Set up GitLab Runner with the Kubernetes executor</li>
<li>Implement Docker builds in your GitLab CI pipeline</li>
<li>Build and push Docker images from within Kubernetes</li>
</ol>
<p>Let's dive in and explore how to harness the power of GitLab CI, Docker, and Kubernetes to create an efficient and scalable build pipeline.</p>
<h2 id="2-understanding-the-docker-in-docker-dind-approach">2. Understanding the Docker-in-Docker (DinD) Approach</h2>
<p>Docker-in-Docker (DinD) is a technique that allows you to run Docker inside a Docker container. This approach is particularly useful in CI/CD environments where you need to build Docker images as part of your pipeline, but you don't have direct access to the host's Docker daemon.</p>
<h3 id="how-docker-in-docker-works">How Docker-in-Docker Works</h3>
<p>In a typical Docker setup, containers interact with the Docker daemon running on the host machine. With DinD, we create a container that has its own Docker daemon. This container can then be used to build, run, and manage other Docker containers independently of the host system.</p>
<p>The process works as follows:</p>
<ol>
<li>A Docker container is started with its own Docker daemon.</li>
<li>This container has the ability to create and manage other Docker containers and images.</li>
<li>Within your CI/CD pipeline, you interact with this containerized Docker daemon to build your application images.</li>
</ol>
<h3 id="advantages-of-docker-in-docker">Advantages of Docker-in-Docker</h3>
<ol>
<li><strong>Isolation</strong>: DinD provides an isolated environment for building and testing Docker images, reducing potential conflicts with other processes on the host system.</li>
<li><strong>Flexibility</strong>: It allows you to use Docker commands in your CI/CD pipeline without needing to modify the host system or rely on shared Docker resources.</li>
<li><strong>Security</strong>: By isolating the Docker build process, you can potentially enhance security by limiting the impact of compromised build scripts.</li>
<li><strong>Consistency</strong>: DinD ensures that your build environment is consistent across different CI/CD runners, as it's contained within a Docker image itself.</li>
</ol>
<h3 id="potential-drawbacks-and-considerations">Potential Drawbacks and Considerations</h3>
<ol>
<li><strong>Performance</strong>: Running Docker inside Docker can have some performance overhead compared to using the host's Docker daemon directly.</li>
<li><strong>Complexity</strong>: DinD adds another layer to your CI/CD setup, which can increase complexity and potential points of failure.</li>
<li><strong>Storage</strong>: Each DinD container has its own storage, which means you may need to manage caching and cleanup more carefully to avoid excessive disk usage.</li>
<li><strong>Security Considerations</strong>: While DinD can enhance security through isolation, it also requires running containers with elevated privileges, which should be carefully managed.</li>
</ol>
<h3 id="dind-in-gitlab-ci-and-kubernetes">DinD in GitLab CI and Kubernetes</h3>
<p>In the context of GitLab CI and Kubernetes, we'll be using DinD to create a Docker build environment within our Kubernetes-based CI runners. This approach allows us to leverage Kubernetes for scaling our CI/CD infrastructure while still maintaining the flexibility to build Docker images as part of our pipeline.</p>
<p>By understanding the DinD approach, we can better appreciate how it enables us to build Docker images within a Kubernetes environment, providing a powerful alternative to tools like Kaniko.</p>
<h2 id="3-setting-up-the-kubernetes-executor">3. Setting Up the Kubernetes Executor</h2>
<p>The Kubernetes executor for GitLab Runner allows you to use Kubernetes to run your CI/CD jobs. This section will guide you through the process of setting up and configuring the Kubernetes executor to support Docker-in-Docker (DinD) builds.</p>
<h3 id="31-overview-of-gitlab-runners-kubernetes-executor">3.1 Overview of GitLab Runner's Kubernetes Executor</h3>
<p>The Kubernetes executor creates a Pod for each GitLab CI job. This Pod contains the following containers:</p>
<ol>
<li>A helper container to handle Git operations</li>
<li>A container for the CI job itself</li>
<li>Additional service containers as needed (in our case, a Docker daemon container)</li>
</ol>
<h3 id="32-prerequisites">3.2 Prerequisites</h3>
<p>Before setting up the Kubernetes executor, ensure you have:</p>
<ul>
<li>A running Kubernetes cluster</li>
<li><code>kubectl</code> installed and configured to access your cluster</li>
<li>Helm installed (optional, but recommended for easier installation)</li>
</ul>
<h3 id="33-installing-gitlab-runner-in-your-kubernetes-cluster">3.3 Installing GitLab Runner in Your Kubernetes Cluster</h3>
<p>You can install GitLab Runner using Helm or by applying Kubernetes manifests directly. Here's how to do it using Helm:</p>
<ol>
<li>
<p>Add the GitLab Helm repository:</p>
<p><code>helm repo add gitlab https://charts.gitlab.io</code></p>
</li>
<li>
<p>Install GitLab Runner:</p>
<p><code>helm install --namespace gitlab gitlab-runner gitlab/gitlab-runner \   --set gitlabUrl=https://gitlab.com/ \  --set runnerRegistrationToken=&lt;your-runner-token&gt;</code></p>
</li>
</ol>
<p>Replace <code>&lt;your-runner-token&gt;</code> with your actual GitLab runner registration token.</p>
<h3 id="34-configuring-the-executor-for-dind">3.4 Configuring the Executor for DinD</h3>
<p>To enable Docker-in-Docker builds, you need to modify the GitLab Runner configuration. Create a <code>values.yaml</code> file with the following content:</p>
<pre><code>gitlabUrl: https://gitlab.com/ 
runnerRegistrationToken: "&lt;your-runner-token&gt;" 
runners:   
	config: |    
	[[runners]]      
	[runners.kubernetes]        
	image = "ubuntu:20.04"        
	privileged = true      
	[[runners.kubernetes.volumes.empty_dir]]        
	name = "docker-certs"        
	mount_path = "/certs/client"        
	medium = "Memory"   
</code></pre>
<p>Apply this configuration:</p>
<p><code>helm upgrade --install --namespace gitlab gitlab-runner gitlab/gitlab-runner -f values.yaml</code></p>
<h3 id="35-explaining-the-configuration">3.5 Explaining the Configuration</h3>
<ul>
<li><code>privileged = true</code>: This allows the runner to use Docker-in-Docker.</li>
<li><code>volumes.empty_dir</code>: This creates a shared volume for Docker certificates.</li>
<li><code>services</code>: This specifies the Docker-in-Docker service container.</li>
<li><code>helpers.image</code>: This sets the GitLab Runner helper image.</li>
</ul>
<h3 id="36-verifying-the-setup">3.6 Verifying the Setup</h3>
<p>To verify that your Kubernetes executor is set up correctly:</p>
<ol>
<li>Go to your GitLab project's CI/CD settings.</li>
<li>Check that the runner is registered and active.</li>
<li>Run a simple pipeline to test the setup.</li>
</ol>
<p>With this configuration, your GitLab Runner in Kubernetes is now ready to handle Docker-in-Docker builds. In the next section, we'll look at how to implement Docker builds in your GitLab CI pipeline using this setup.</p>
<h2 id="4-implementing-docker-builds-in-gitlab-ci">4. Implementing Docker Builds in GitLab CI</h2>
<p>Now that we have our Kubernetes executor set up with Docker-in-Docker capabilities, let's implement Docker builds in our GitLab CI pipeline. This section will guide you through creating a <code>.gitlab-ci.yml</code> file, defining stages and jobs, and configuring the Docker service.</p>
<h3 id="41-creating-a-gitlab-ciyml-file">4.1 Creating a <code>.gitlab-ci.yml</code> File</h3>
<p>In the root of your project, create a file named <code>.gitlab-ci.yml</code>. This file will define your CI/CD pipeline.</p>
<h3 id="42-defining-stages-and-jobs">4.2 Defining Stages and Jobs</h3>
<p>Let's start with a basic structure for our pipeline:</p>
<pre><code>stages:   
	- build  
	- test  
	- deploy 

variables:   
	DOCKER_TLS_CERTDIR: "" 
	
build:   
	stage: build  
	image: docker:20.10.16  
	services:    
		- docker:20.10.16-dind  
	before_script:    
		- docker info  
	script:    
		- docker build -t my-app:$CI_COMMIT_SHA .    
		- docker push my-app:$CI_COMMIT_SHA 

test:   
	stage: test  
	script:    
		- echo "Run your tests here" 

deploy:   
	stage: deploy  
	script:    
		- echo "Deploy to Kubernetes here"
</code></pre>
<h3 id="43-explaining-the-configuration">4.3 Explaining the Configuration</h3>
<p>Let's break down the key components of this configuration:</p>
<ul>
<li><code>stages</code>: Defines the pipeline stages: build, test, and deploy.</li>
<li><code>variables</code>:
<ul>
<li><code>DOCKER_TLS_CERTDIR: ""</code>: This disables TLS for the Docker daemon, which is fine for CI/CD environments but not recommended for production.</li>
</ul>
</li>
<li><code>build</code> job:
<ul>
<li><code>image: docker:20.10.16</code>: Uses the Docker image as the base for this job.</li>
<li><code>services: - docker:20.10.16-dind</code>: Specifies the Docker-in-Docker service.</li>
<li><code>before_script</code>: Runs <code>docker info</code> to verify the Docker setup.</li>
<li><code>script</code>: Contains the Docker build and push commands.</li>
</ul>
</li>
</ul>
<h3 id="44-configuring-the-docker-service">4.4 Configuring the Docker Service</h3>
<p>The <code>services</code> section in the <code>build</code> job is crucial for enabling Docker-in-Docker:</p>
<p><code>services:   - docker:20.10.16-dind</code></p>
<p>This starts a Docker daemon inside the job's container, allowing us to use Docker commands in our script.</p>
<h3 id="45-building-the-docker-image">4.5 Building the Docker Image</h3>
<p>In the <code>script</code> section of the <code>build</code> job, we use standard Docker commands:</p>
<p><code>script:   - docker build -t my-app:$CI_COMMIT_SHA .  - docker push my-app:$CI_COMMIT_SHA</code></p>
<ul>
<li><code>docker build</code>: Builds the image using the Dockerfile in your project root.</li>
<li><code>$CI_COMMIT_SHA</code>: A GitLab CI variable containing the commit SHA, used here as the image tag.</li>
<li><code>docker push</code>: Pushes the built image to a registry (you'll need to configure authentication, which we'll cover in the next section).</li>
</ul>
<h3 id="46-adding-authentication-for-docker-registry">4.6 Adding Authentication for Docker Registry</h3>
<p>To push images, you'll need to authenticate with your Docker registry. Add these lines to your <code>build</code> job:</p>
<p><code>before_script:   - docker info  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin $DOCKER_REGISTRY</code></p>
<p>Make sure to set <code>DOCKER_USERNAME</code>, <code>DOCKER_PASSWORD</code>, and <code>DOCKER_REGISTRY</code> as CI/CD variables in your GitLab project settings.</p>
<p>With this configuration, you now have a mimimal GitLab CI pipeline that can build Docker images using Docker-in-Docker within a Kubernetes environment.</p>
<h2 id="7-conclusion">7. Conclusion</h2>
<p>Throughout this article, we've explored a powerful approach to building Docker images and deploying them to Kubernetes using GitLab CI, all without relying on Kaniko. Let's recap the key points we've covered:</p>
<ol>
<li>We started by understanding the Docker-in-Docker (DinD) approach, which allows us to build Docker images within our CI/CD pipeline running in Kubernetes.</li>
<li>We then set up the Kubernetes executor for GitLab Runner, configuring it to support DinD builds.</li>
<li>We implemented Docker builds in our GitLab CI pipeline, creating a <code>.gitlab-ci.yml</code> file that defines our build, test, and deploy stages.</li>
</ol>
<p>This approach offers several advantages:</p>
<ul>
<li><strong>Flexibility</strong>: By using DinD, we maintain the full capabilities of Docker in our build process, allowing for complex multi-stage builds and custom Docker commands.</li>
<li><strong>Familiarity</strong>: For teams already comfortable with Docker, this method leverages existing knowledge and tools.</li>
<li><strong>Integration</strong>: This setup integrates seamlessly with GitLab CI and Kubernetes, creating a smooth workflow from code commit to deployment.</li>
</ul>
<p>However, it's important to note that this method isn't without its considerations:</p>
<ul>
<li><strong>Resource Usage</strong>: Running Docker inside Docker can be more resource-intensive than alternative methods like Kaniko.</li>
<li><strong>Security</strong>: While we've discussed security best practices, running containers in privileged mode (as required for DinD) needs careful management.</li>
</ul>
<p>As with any CI/CD solution, the key to success is continuous improvement. Regularly review your pipeline, gather feedback from your team, and stay updated with the latest best practices in the rapidly evolving world of DevOps.</p>
<p>Remember, the goal of CI/CD is to enhance your team's ability to deliver value to your users. Whether you choose this DinD approach, Kaniko, or another method, the most important factor is that it meets your team's needs and helps you deliver high-quality software efficiently and reliably.</p>
<p>By mastering these techniques, you're well-equipped to build robust, efficient CI/CD pipelines that can handle complex Docker builds and Kubernetes deployments. As you implement and refine this process, you'll be contributing to a faster, more reliable software delivery lifecycle for your organization.</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Vacanze estive 2024 ]]></title>
        <description><![CDATA[ É arrivato il momento di una pausa!

Sarò in vacanza in due periodi questa estate: dal 15 al 21 luglio e dal 19 al 30 agosto.

Durante queste date non sarò disponibile per nuove richieste o per lavorare su progetti in corso. Vi chiedo gentilmente di considerare queste date per ]]></description>
        <link>https://www.andreacasarin.com/2024/07/01/vacanze-estive-2024.html/</link>
        <guid isPermaLink="false">6682b96a7f948600013b31dd</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Mon, 01 Jul 2024 16:24:29 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.andreacasarin.com/content/images/2024/07/camille-minouflet-d7M5Xramf8g-unsplash.jpg" class="kg-image" alt loading="lazy"><figcaption>Photo by <a href="https://unsplash.com/@caminouflet?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Camille Minouflet</a> on <a href="https://unsplash.com/photos/photo-of-seashore-d7M5Xramf8g?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a></figcaption></figure><p>É arrivato il momento di una pausa! <br><br>Sarò in vacanza in due periodi questa estate: <strong>dal 15 al 21 luglio e dal 19 al 30 agosto</strong>.</p><p>Durante queste date non sarò disponibile per nuove richieste o per lavorare su progetti in corso. Vi chiedo gentilmente di considerare queste date per eventuali scadenze o necessità. Se avete qualcosa di urgente, vi prego di farmelo sapere in anticipo così da poter pianificare al meglio.</p><p>Auguro anche a voi delle <strong>splendide vacanze</strong>, sperando che possiate godervi un po' di relax e divertimento!</p><p>Grazie mille per la vostra comprensione. Ci sentiamo presto!</p><p></p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Docker and docker compose resource management ]]></title>
        <description><![CDATA[ As developers, we&#39;re always striving to create environments that mimic production settings as closely as possible. When deploying with a simple Docker Compose setup, you might be surprised at just how granularly you can manage resources. This is especially true when dealing with issues that only appear under ]]></description>
        <link>https://www.andreacasarin.com/2024/05/25/docker-and-docker-compose-resource-management.html/</link>
        <guid isPermaLink="false">6651b52eab4165000133e7f4</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 25 May 2024 11:55:32 +0200</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2024/11/ian-taylor-jOqJbvo1P9g-unsplash-1.jpg" medium="image"/>
        <content:encoded><![CDATA[ <p>As developers, we're always striving to create environments that mimic production settings as closely as possible. When deploying with a simple Docker Compose setup, you might be surprised at just how granularly you can manage resources. This is especially true when dealing with issues that only appear under heavy loads in production.</p>
<p>I recently encountered such an issue on a project I'd been working on. The problem only showed up in production, and it took me digging into Docker Compose resource limit specifications to find the solution. By tuning Docker resources and limiting them in specific ways, we were able to replicate the bug and finally fix it.</p>
<h2 id="docker-resources-taming-the-beast">Docker Resources: Taming the Beast</h2>
<p>Docker provides runtime options that allow you to fine-tune container running resources. By default, containers have no resource constraints, using as much of a given resource as the host's kernel scheduler allows. However, this can be problematic in production environments where resources are limited.</p>
<p>Fortunately, Docker offers ways to control how much memory or CPU a container can use by setting runtime configuration flags with the&nbsp;<code>docker run</code>&nbsp;command. The official documentation explores when and why you should set such limits, as well as the potential implications of doing so: <a href="https://docs.docker.com/config/containers/resource_constraints/?ref=andreacasarin.com">Runtime options with Memory, CPUs, and GPUs | Docker Docs</a>.</p>
<h2 id="dynamic-resource-management-the-power-of-docker-update">Dynamic Resource Management: The Power of&nbsp;<code>docker update</code></h2>
<p>But what about containers that are already running? Can we still tune their resources? Thankfully, the answer is yes. Docker's&nbsp;<code>update</code>&nbsp;command allows you to dynamically update container configuration and prevent containers from consuming too many resources on your host.</p>
<p>With a single command, you can place limits on a single container or multiple containers at once. Simply provide a space-separated list of container names or IDs.</p>
<p>Find out more here: <a href="https://docs.docker.com/reference/cli/docker/container/update/?ref=andreacasarin.com">docker container update | Docker Docs</a></p>
<h2 id="compose-resources-orchestrating-constraints">Compose Resources: Orchestrating Constraints</h2>
<p>When using Docker Compose as an orchestrator, you can specify resource constraints in the&nbsp;<code>resources</code>&nbsp;section of your Compose file. This allows you to configure physical resource constraints for your containers.</p>
<p>You can specify limits and reservations for resources such as memory, CPUs, and GPUs. These constraints are enforced by the platform, ensuring that containers don't consume more than their allocated share.</p>
<p>For example:</p>
<ul>
<li><code>limits</code>: The platform must prevent the container from allocating more.</li>
<li><code>reservations</code>: The platform must guarantee the container can allocate at least the configured amount.</li>
</ul>
<p>You can read all the details on: <a href="https://docs.docker.com/compose/compose-file/deploy/?ref=andreacasarin.com#resources">Compose Deploy Specification | Docker Docs</a></p>
<h2 id="conclusion-a-cohesive-development-environment">Conclusion: A Cohesive Development Environment</h2>
<p>Docker provides a powerful way to create development environments that closely mirror production settings. By leveraging Docker Compose and its resource management capabilities, you can ensure that your containers run efficiently and effectively.</p>
<p>Make sure to drop your email down here to get new articles as they are published!</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Grafana Agent(s), meets Alloy ]]></title>
        <description><![CDATA[ As an indie software developer, I frequently have to deploy monitoring solutions for software I develop or support. I recently had the pleasure of exploring the evolution of Grafana from a visualization tool to a comprehensive monitoring suite with various modules. In this article, we&#39;ll dive into its ]]></description>
        <link>https://www.andreacasarin.com/2024/05/04/grafana-agent-meets-alloy.html/</link>
        <guid isPermaLink="false">663517d2b6a36900015054b9</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 04 May 2024 11:08:48 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2024/05/grafana-alloy-architecture-diagram-2.png" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><p>As an indie software developer, I frequently have to deploy monitoring solutions for software I develop or support. I recently had the pleasure of exploring the evolution of Grafana from a visualization tool to a comprehensive monitoring suite with various modules. In this article, we'll dive into its collector and explore the journey of migrating to the new Alloy agent.</p>
<h1 id="introducing-alloy-collector">Introducing Alloy Collector</h1>
<p>Alloy is the latest addition to the Grafana ecosystem, offering enhanced performance and scalability for data collection. Unlike its predecessor Flow Agent, Alloy introduces a more efficient and robust data ingestion mechanism. It's an open source distribution of the OpenTelemetry Collector that's 100% OTLP compatible.</p>
<p>Grafana Agent proved to be flexible, performant, and compatible with multiple ecosystems. Then they launched Promtail for Loki logs and the Grafana Agent Operator for Kubernetes-specific cases. It worked but the many options made it harder to determine which agents to use.</p>
<p>Grafana Agent and Grafana Agent Operator are deprecated and will enter into Long-Term Support beginning today (April 9, 2024). This means both projects will no longer receive new feature updates, as all future innovation will be focused on Alloy. Grafana Labs recommends to begin planning a transition towards the new Grafana Alloy collector.</p>
<h1 id="show-me-the-code-deploy-alloy-collector">Show me the code: deploy Alloy Collector</h1>
<p>Using Alloy requires a minimal setup:</p>
<ul>
<li>grab your distribution package or binary</li>
<li>create a service to auto start or use the distribution's provided one</li>
<li>create a configuration file to manage some log/metrics ingestion and forward it to your Grafana instance of choice.</li>
</ul>
<p>Given you installed the, let's say, Debian package you'll go ahead and create a configuration file in <code>/etc/alloy/config.alloy</code>:</p>
<pre><code class="language-yaml">prometheus.exporter.self &quot;integrations_alloy&quot; { }

discovery.relabel &quot;integrations_alloy&quot; {
  targets = prometheus.exporter.self.integrations_alloy.targets

  rule {
    target_label = &quot;instance&quot;
    replacement  = constants.hostname
  }

  rule {
    target_label = &quot;alloy_hostname&quot;
    replacement  = constants.hostname
  }

  rule {
    target_label = &quot;job&quot;
    replacement  = &quot;integrations/alloy-check&quot;
  }
}

prometheus.scrape &quot;integrations_alloy&quot; {
  targets    = discovery.relabel.integrations_alloy.output
  forward_to = [prometheus.relabel.integrations_alloy.receiver]  

  scrape_interval = &quot;60s&quot;
}

prometheus.relabel &quot;integrations_alloy&quot; {
  forward_to = [prometheus.remote_write.metrics_service.receiver]

  rule {
    source_labels = [&quot;__name__&quot;]
    regex         = &quot;(prometheus_target_sync_length_seconds_sum|prometheus_target_scrapes_.*|prometheus_target_interval.*|prometheus_sd_discovered_targets|alloy_build.*|prometheus_remote_write_wal_samples_appended_total|process_start_time_seconds)&quot;
    action        = &quot;keep&quot;
  }
}

prometheus.remote_write &quot;metrics_service&quot; {
  endpoint {
    url = &quot;{{ grafana_metrics_url }}&quot;

    basic_auth {
      username = &quot;{{ grafana_metrics_id }}&quot;
      password = &quot;{{ grafana_cloud_token }}&quot;
    }
  }
}

loki.write &quot;grafana_cloud_loki&quot; {
  endpoint {
    url = &quot;{{ grafana_logs_url }}&quot;

    basic_auth {
      username = &quot;{{ grafana_logs_id }}&quot;
      password = &quot;{{ grafana_cloud_token }}&quot;
    }
  }
}

loki.relabel &quot;journal&quot; {
  forward_to = []

  rule {
    source_labels = [&quot;__journal__systemd_unit&quot;]
    target_label  = &quot;unit&quot;
  }
  rule {
    source_labels = [&quot;__journal__boot_id&quot;]
    target_label  = &quot;boot_id&quot;
  }
  rule {
    source_labels = [&quot;__journal__transport&quot;]
    target_label  = &quot;transport&quot;
  }
  rule {
    source_labels = [&quot;__journal_priority_keyword&quot;]
    target_label  = &quot;level&quot;
  }
  rule {
    source_labels = [&quot;__journal__hostname&quot;]
    target_label  = &quot;instance&quot;
  }
}

loki.source.journal &quot;read&quot; {
  forward_to = [
    loki.write.grafana_cloud_loki.receiver,
  ]
  relabel_rules = loki.relabel.journal.rules
  labels = {
    &quot;job&quot; = &quot;integrations/node_exporter&quot;,
  }
}

</code></pre>
<p>This can be a nice starting point, it will:</p>
<ul>
<li>get metrics from the instance and tag/label them;</li>
<li>grab the journal logs and tag/label them;</li>
<li>push everything to Grafana Cloud (as long as you replace placeholders with real credentials).</li>
</ul>
<h1 id="migrate-to-alloy">Migrate to Alloy</h1>
<p>If you are currently using Grafana tools, such as Grafana Agent or Grafana Agent Operator, Grafana Labs has converters and tools for moving to Grafana Alloy:</p>
<ul>
<li><a href="https://grafana.com/docs/alloy/latest/tasks/migrate/from-operator/?pg=blog&plcmt=body-txt&ref=andreacasarin.com">Migrate from Operator</a></li>
<li><a href="https://grafana.com/docs/alloy/latest/tasks/migrate/from-prometheus/?pg=blog&plcmt=body-txt&ref=andreacasarin.com">Migrate from Prometheus</a></li>
<li><a href="https://grafana.com/docs/alloy/latest/tasks/migrate/from-promtail/?pg=blog&plcmt=body-txt&ref=andreacasarin.com">Migrate from Promtail</a></li>
<li><a href="https://grafana.com/docs/alloy/latest/tasks/migrate/from-static/?pg=blog&plcmt=body-txt&ref=andreacasarin.com">Migrate from Grafana Agent Static</a></li>
<li><a href="https://grafana.com/docs/alloy/latest/tasks/migrate/from-flow/?pg=blog&plcmt=body-txt&ref=andreacasarin.com">Migrate from Grafana Agent Flow</a></li>
</ul>
<p>If you are using vanilla OpenTelemetry Collector:</p>
<ul>
<li><a href="https://grafana.com/docs/alloy/latest/tasks/migrate/from-otelcol/?pg=blog&plcmt=body-txt&ref=andreacasarin.com">Migrate from OpenTelemetry Collector</a></li>
</ul>
<p>In my experience they are not 100% plug-and-play but they will help for sure.</p>
<h1 id="closing-thoughts">Closing Thoughts</h1>
<p>I'm thrilled to have migrated my project to Alloy Collector. Grafana Cloud's free tier offers a great starting point for small-scale deployments, and the option to switch to an on-premise setup provides flexibility. For those still using Flow Agent, it's time to make the jump to Alloy and reap the benefits of improved performance and scalability.</p>
<p>Find more here:</p>
<ul>
<li><a href="https://grafana.com/blog/2024/04/09/grafana-agent-to-grafana-alloy-opentelemetry-collector-faq/?ref=andreacasarin.com">From Agent to Alloy: Why we transitioned to the Alloy collector and why you should, too | Grafana Labs</a></li>
<li><a href="https://grafana.com/blog/2024/04/09/grafana-alloy-opentelemetry-collector-with-prometheus-pipelines/?ref=andreacasarin.com">Introducing an OpenTelemetry Collector distribution with built-in Prometheus pipelines: Grafana Alloy | Grafana Labs</a></li>
<li><a href="https://grafana.com/docs/alloy/latest/?ref=andreacasarin.com">Grafana Alloy | Grafana Alloy documentation</a></li>
</ul>
<p>With many and more features, full open-source development and standard compatibility it will be my monitoring solution of choice for the time being.</p>
<p>Feel free to subscribe down below to stay in touch I'll make sure to report if things will change in that regard.</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Caddy: an Nginx - Traefik - HAProxy alternative ]]></title>
        <description><![CDATA[ Are you tired of adding tools to your Kubernetes clusters? Do you want a more integrated and straightforward approach to ingress control? Look no further than Caddy, an Nginx, Traefik, and HAProxy alternative. In this article, we&#39;ll explore how Caddy could simplify your Kubernetes management tasks while providing ]]></description>
        <link>https://www.andreacasarin.com/2024/03/28/caddy-nginx-traefik-haproxy-kubernetes.html/</link>
        <guid isPermaLink="false">66056564b6a369000150547f</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Thu, 28 Mar 2024 13:45:23 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2024/03/caddy-logo-light.svg" class="kg-image" alt loading="lazy"></figure><p>Are you tired of adding tools to your Kubernetes clusters? Do you want a more integrated and straightforward approach to ingress control? Look no further than Caddy, an Nginx, Traefik, and HAProxy alternative. In this article, we'll explore how Caddy could simplify your Kubernetes management tasks while providing advanced features like caching and automatic HTTPS.</p><p>As someone who is using Nginx as ingress for K8S with cert manager to manage HTTPS, I understand the struggle of managing multiple tools for cluster routing. Following the principle of "https-anywhere," we need an ingress controller that can handle both Kubernetes service access types and automatic HTTPS. I tried Traefik thinking it was the solution, until i discovered it has no cache support on the community version and rolled back to Nginx. Then I stumbled upon Caddy thanks to <a href="https://paulbutler.org/2024/the-haters-guide-to-kubernetes/?ref=andreacasarin.com">Paul Butler – The hater’s guide to Kubernetes</a>. This led me on a journey to discover Caddy, a lightweight and modern ingress controller that offers the features we need without the bloat of other solutions.</p><h2 id="simple-easy-fast-fun">Simple, easy, fast, fun</h2><p>Caddy is incredibly easy to use and set up, thanks to its simple and intuitive configuration file format. You can easily create and manage ingress rules, and Caddy provides a fun and interactive way to monitor your cluster's traffic flow. With Caddy, you don't need extensive knowledge of networking protocols or Kubernetes configurations; it takes only minutes to set up and start enjoying the benefits of this solution.</p><h2 id="full-fledged-cache-acme-client">Full-fledged: cache, Acme client</h2><p>One area where Caddy outshines other ingress controllers is its built-in caching mechanism. This feature allows you to offload some of the traffic load from your Kubernetes services to Caddy's cache, ensuring a smoother and faster experience for your users. Additionally, Caddy integrates with the popular Acme client, enabling automated SSL/TLS certificates management for your services. With these features, you can simplify your cert management tasks and avoid the headaches of dealing with multiple tools for this critical aspect of ingress control.</p><h2 id="modern-and-well-documented">Modern and well-documented</h2><p>Caddy is modern in every sense of the word: its syntax, configuration file format, and overall design are all tailored to provide an enjoyable development experience. The official documentation is also top-notch, featuring a comprehensive guide on how to get started with Caddy as well as detailed descriptions of all available configurations options. By following their guidelines, even less tech-savvy users can set up and manage Caddy efficiently and effectively.</p><h2 id="closingreference">Closing/Reference</h2><p>While I'm not using Caddy yet for my existing projects, I plan to give it a try for new endeavors. By leveraging its simple configuration syntax, built-in caching capabilities, and Acme support, we can significantly simplify our Kubernetes management tasks and enhance user experience. Follow me on Twitter for future updates and feel free to drop your email for any further inquiries!</p><p>Resources:</p><ul><li>Caddy server official documentation - <a href="https://caddyserver.com/docs/?ref=andreacasarin.com">https://caddyserver.com/docs/</a></li><li>Caddy ingress controller for Kubernetes - <a href="https://github.com/caddyserver/ingress?ref=andreacasarin.com">https://github.com/caddyserver/ingress</a></li><li>GitHub repository for Caddy server - <a href="https://github.com/caddyserver/caddy?ref=andreacasarin.com">https://github.com/caddyserver/caddy</a></li><li>Caddy getting started documentation - <a href="https://caddyserver.com/docs/getting-started?ref=andreacasarin.com">https://caddyserver.com/docs/getting-started</a></li></ul> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Understanding Kubernetes Service Access Types ]]></title>
        <description><![CDATA[ Understanding Kubernetes service access types has been tough for me. It felt confusing and overwhelming at times. So, I decided to write this article to help others who might feel the same way. My goal is to break down these concepts into simpler terms. I hope to make it easier ]]></description>
        <link>https://www.andreacasarin.com/2024/02/28/understanding-kubernetes-service-access-types.html/</link>
        <guid isPermaLink="false">65df539c487d5f00017300a9</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Wed, 28 Feb 2024 16:41:16 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2024/02/service-access-types-1.webp" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><p>Understanding Kubernetes service access types has been tough for me. It felt confusing and overwhelming at times. So, I decided to write this article to help others who might feel the same way. My goal is to break down these concepts into simpler terms. I hope to make it easier for you to get a handle on how to use these services in your own projects. Let's dive into the three main types of Kubernetes services: ClusterIP, NodePort, and LoadBalancer, providing insights into their use cases, advantages, and limitations.</p>
<h2 id="clusterip-internal-service-access">ClusterIP: Internal Service Access</h2>
<h3 id="overview">Overview</h3>
<p>ClusterIP is the default Kubernetes service type, making it a fundamental concept for new Kubernetes users to grasp. It assigns a unique IP address to the service within the cluster, enabling pod-to-pod communication. This IP address is reachable only from within the cluster, making ClusterIP services an excellent choice for internal communication between different services in your application.</p>
<h3 id="use-cases">Use Cases</h3>
<p>ClusterIP services are ideal for scenarios where you do not need external traffic to reach your application components. Examples include backend services like databases or internal APIs that should only be accessible to other components within the same Kubernetes cluster.</p>
<h3 id="advantages">Advantages</h3>
<ul>
<li><strong>Isolation and Security</strong>: Since ClusterIP services are only accessible within the cluster, they offer an additional layer of security by isolating internal network traffic from external access.</li>
<li><strong>Simplicity</strong>: Being the default service type, ClusterIP services are straightforward to set up, requiring minimal configuration.</li>
</ul>
<h3 id="limitations">Limitations</h3>
<ul>
<li><strong>Internal Access Only</strong>: The major limitation of ClusterIP is that it cannot be accessed from outside the Kubernetes cluster, making it unsuitable for services that need to be exposed to the internet or external networks.</li>
</ul>
<h2 id="nodeport-external-access-via-nodes">NodePort: External Access via Nodes</h2>
<h3 id="overview">Overview</h3>
<p>NodePort is a type of Kubernetes service that makes your service accessible from outside the Kubernetes cluster by opening a specific port on all nodes (VMs or physical servers) of the cluster. Traffic that is sent to this port is forwarded to the service. The NodePort service type extends the functionality of ClusterIP by adding a layer that allows external access.</p>
<h3 id="use-cases">Use Cases</h3>
<p>NodePort services are useful when you need external access to your application but do not have a LoadBalancer available or for testing purposes. They are also helpful in environments where direct access to each node is possible.</p>
<h3 id="advantages">Advantages</h3>
<ul>
<li><strong>External Access</strong>: NodePort services allow external clients to access services running inside the Kubernetes cluster, offering a straightforward method to expose your application to the outside world.</li>
<li><strong>Flexibility</strong>: They provide a simple way to access services from outside the Kubernetes cluster, especially in environments where a LoadBalancer might not be available or necessary.</li>
</ul>
<h3 id="limitations">Limitations</h3>
<ul>
<li><strong>Port Management</strong>: Since NodePort services require opening a specific port across all nodes, managing these ports and avoiding conflicts can become challenging as the number of services grows.</li>
<li><strong>Scalability</strong>: Directly exposing services through NodePort can lead to scalability issues, as it bypasses the more sophisticated load balancing capabilities of a LoadBalancer service.</li>
</ul>
<h2 id="loadbalancer-cloud-provider-integration-for-scalability">LoadBalancer: Cloud-Provider Integration for Scalability</h2>
<h3 id="overview">Overview</h3>
<p>The LoadBalancer service type integrates Kubernetes with the cloud provider's load balancer, allowing for automatic creation and management of an external load balancer. This load balancer distributes external traffic to the Kubernetes services, offering a seamless way to expose services to the internet.</p>
<h3 id="use-cases">Use Cases</h3>
<p>LoadBalancer services are ideal for production environments where you need to expose your application to the internet reliably and scalably. They are commonly used for front-end web applications, APIs, or any service that requires robust, scalable external access.</p>
<h3 id="advantages">Advantages</h3>
<ul>
<li><strong>Scalability and Reliability</strong>: LoadBalancer services leverage the scalability and reliability of cloud provider platforms, providing a high level of availability for your applications.</li>
<li><strong>Simplicity</strong>: The process of exposing a service to the external internet is simplified, as the cloud provider automatically handles the creation and configuration of the load balancer.</li>
</ul>
<h3 id="limitations">Limitations</h3>
<ul>
<li><strong>Cost</strong>: Utilizing LoadBalancer services can incur additional costs, as cloud providers charge for the load balancing resources that are provisioned. Usually to avoid greater costs you will create a LoadBalancer service for the ingress only, then the ingress (like Traefik or Nginx) provides cluster smart routing.</li>
<li><strong>Cloud-Dependent</strong>: This service type is dependent on the cloud provider's infrastructure, making it less suitable for on-premises or bare-metal environments.</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Understanding the differences between ClusterIP, NodePort, and LoadBalancer services in Kubernetes is crucial for architects and developers looking to efficiently design and deploy applications. Each service type offers unique advantages and is suited to different use cases, from internal cluster communication to exposing applications to the external world. By leveraging these services intelligently, you can ensure that your applications are scalable, secure, and accessible according to your needs.</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ OpenAI launches the GPT Store ]]></title>
        <description><![CDATA[ Introduction to the GPT Store


The GPT Store marks a revolutionary step in the AI world, introducing a unique platform where innovative GPTs crafted by community developers come to life. This initiative by OpenAI transforms how we access and leverage Generative Pre-trained Transformers (GPTs), making cutting-edge AI technology more accessible. ]]></description>
        <link>https://www.andreacasarin.com/2024/01/23/openai-gpt-store-launch.html/</link>
        <guid isPermaLink="false">65aefe700ee856000160c142</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Tue, 23 Jan 2024 01:00:36 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2024/01/gpt-store.jpg" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><h2 id="introduction-to-the-gpt-store">Introduction to the GPT Store</h2>
<p>The GPT Store marks a revolutionary step in the AI world, introducing a unique platform where innovative GPTs crafted by community developers come to life. This initiative by OpenAI transforms how we access and leverage Generative Pre-trained Transformers (GPTs), making cutting-edge AI technology more accessible. The store serves as a digital marketplace, showcasing a diverse range of GPT applications, from enhancing productivity to revolutionizing education and lifestyle sectors. It's not just a store; it's a gateway to the future of AI, where tech enthusiasts can explore the possibilities of GPTs.</p>
<h2 id="the-vision-and-impact-of-the-gpt-store">The Vision and Impact of the GPT Store</h2>
<p>The GPT Store embodies OpenAI's vision of AI technology accessible. It's designed to be a breeding ground for innovation and creativity in AI. By making GPTs more accessible, the store is set to significantly impact various industries, from small businesses leveraging AI for growth to educators integrating advanced technology into learning. It's a shift towards more inclusive and widespread use of AI. The GPT Store is changing how we use AI.</p>
<h2 id="features-and-offerings-of-the-gpt-store">Features and Offerings of the GPT Store</h2>
<p>The GPT Store stands out for its diverse range of offerings, catering to various needs and industries. Key features include:</p>
<ul>
<li><strong>Variety of Applications</strong>: From chatbots to content creation tools, the store houses GPTs designed for multiple purposes.</li>
<li><strong>User-Friendly Interface</strong>: It offers an intuitive platform, making it easy for beginners to explore and use GPTs.</li>
<li><strong>Community-Centric Approach</strong>: The store encourages submissions from developers, creating a vibrant community of AI enthusiasts and innovators.</li>
</ul>
<p>This diversity not only showcases the versatility of GPTs but also opens up endless possibilities for users to integrate AI into their projects and workflows.</p>
<h2 id="community-and-developer-engagement">Community and Developer Engagement</h2>
<p>A cornerstone of the GPT Store is its commitment to fostering a robust community. It's a place where developers, from seasoned AI experts to beginners, can contribute their GPT creations, share insights, and learn from each other. This engagement:</p>
<ul>
<li><strong>Encourages Innovation</strong>: By pooling diverse ideas, the store accelerates innovation in AI applications.</li>
<li><strong>Supports Learning and Development</strong>: New developers find a supportive environment for honing their skills.</li>
<li><strong>Facilitates Collaboration</strong>: The platform enables collaborations, leading to more refined and effective GPT solutions.</li>
</ul>
<p>This, hopefully, vibrant ecosystem not only enriches the store's offerings but also propels the AI field forward by harnessing collective creativity and knowledge.</p>
<h2 id="looking-ahead-the-future-of-ai-with-the-gpt-store">Looking Ahead: The Future of AI with the GPT Store</h2>
<p>As we look to the future, the GPT Store is poised to play a pivotal role in shaping AI's trajectory. Its potential to democratize AI development suggests a future where AI integration becomes standard across various sectors, fostering innovation and efficiency. I can foresee:</p>
<ul>
<li><strong>Wider Adoption in Everyday Solutions</strong>: GPTs will likely become integral in daily tech solutions, enhancing user experiences.</li>
<li><strong>Advancement in AI Research and Development</strong>: The store could become a hub for groundbreaking AI research.</li>
<li><strong>Community-Driven AI Evolution</strong>: The collective contributions will continuously refine and advance GPT applications.</li>
</ul>
<p>Find out more here: <a href="https://openai.com/blog/introducing-the-gpt-store?ref=andreacasarin.com">Introducing the GPT Store</a>.</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Auguri! ]]></title>
        <description><![CDATA[ Un caloroso augurio di buone feste!

Vi ringrazio per il sostegno nell&#39;ultimo anno. Approfittiamo della stagione festiva per rilassarci e accogliere il nuovo anno con entusiasmo.


Buone feste e felice Anno Nuovo!

Estendo a voi i miei auguri per un periodo di festività sereno e un nuovo anno ]]></description>
        <link>https://www.andreacasarin.com/2023/12/18/auguri-2023-2024.html/</link>
        <guid isPermaLink="false">65808665123a850001e1fb45</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Mon, 18 Dec 2023 18:56:59 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.andreacasarin.com/content/images/2023/12/anita-austvika-wa_WELhBHqs-unsplash.jpg" class="kg-image" alt loading="lazy"><figcaption>Foto di <a href="https://unsplash.com/it/@anitaaustvika?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Anita Austvika</a> su <a href="https://unsplash.com/it/foto/un-salotto-addobbato-per-natale-con-ghirlande-appese-al-muro-wa_WELhBHqs?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a></figcaption></figure><h1 id="un-caloroso-augurio-di-buone-feste">Un caloroso augurio di buone feste!</h1><p>Vi ringrazio per il sostegno nell'ultimo anno. Approfittiamo della stagione festiva per rilassarci e accogliere il nuovo anno con entusiasmo. </p><h2 id="buone-feste-e-felice-anno-nuovo">Buone feste e felice Anno Nuovo!</h2><p>Estendo a voi i miei auguri per un periodo di festività sereno e un nuovo anno di gioia e successo. Ricordate di celebrare la bellezza della vita!</p><h2 id="vacanze">Vacanze</h2><p>Sarò in <strong>vacanza dal 22 dicembre al 7 gennaio</strong> con accesso limitato alle e-mail. Ritornerò riposato e pronto per assistervi il 7 gennaio.</p><h1 id="a-warm-holiday-wish">A warm holiday wish!</h1><p>Thank you for your support over the past year. Let's use the holiday season to relax and welcome the new year with enthusiasm.</p><h2 id="happy-holidays-and-a-joyful-new-year">Happy Holidays and a Joyful New Year!</h2><p>I extend to you my wishes for a peaceful holiday season and a new year of joy and success. Remember to celebrate the beauty of life!</p><h2 id="holidays">Holidays</h2><p>I will be on <strong>holiday from December 22nd to January 7th</strong> with limited access to emails. I will return rested and ready to assist you on January 7th.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Kubernetes, my DevOps Stack ]]></title>
        <description><![CDATA[ Introduction to Kubernetes


Kubernetes, often abbreviated as K8s, is an open-source container orchestration platform that automates the deployment, scaling, and management of applications. As a pivotal aspect of DevOps, it allows expansive control over containerized applications and services. Kubernetes&#39; proliferating popularity is indicative of its robust framework and broad ]]></description>
        <link>https://www.andreacasarin.com/2023/12/09/kubernetes-my-devops-stack.html/</link>
        <guid isPermaLink="false">65747b59d0d2220001812974</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 09 Dec 2023 15:40:16 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.andreacasarin.com/content/images/2023/12/growtika-ZfVyuV8l7WU-unsplash.jpg" class="kg-image" alt loading="lazy"><figcaption>Foto di <a href="https://unsplash.com/it/@growtika?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Growtika</a> su <a href="https://unsplash.com/it/foto/un-gruppo-di-scatole-blu-ZfVyuV8l7WU?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a></figcaption></figure><!--kg-card-begin: markdown--><h1 id="introduction-to-kubernetes">Introduction to Kubernetes</h1>
<p>Kubernetes, often abbreviated as K8s, is an open-source container orchestration platform that automates the deployment, scaling, and management of applications. As a pivotal aspect of DevOps, it allows expansive control over containerized applications and services. Kubernetes' proliferating popularity is indicative of its robust framework and broad ecosystem. However, Kubernetes is a double-edged sword—its sheer complexity can be overwhelming.</p>
<p>This complexity can, nevertheless, be tamed with the right tools. These are the tools, from command-line interfaces to visualizers, I use to simplify the interaction with Kubernetes.</p>
<p>These utilities make Kubernetes more approachable without undermining its powerful functionalities.</p>
<h1 id="mastering-kubernetes-with-kubectl">Mastering Kubernetes With 'kubectl'</h1>
<p><code>kubectl</code> is your gateway to interacting with Kubernetes. This command-line tool communicates with Kubernetes clusters (groupings of nodes), executing commands through the Kubernetes API. You can use <code>kubectl</code> to deploy applications, inspect resources, and manage your cluster.</p>
<p>For instance, with a single <code>kubectl apply</code> command, you can deploy an application onto your Kubernetes cluster. Moreover, <code>kubectl</code> also helps with debugging and updating applications in real time, making it indispensable in the DevOps stack.</p>
<p>However, remember, <code>kubectl</code> is a very sharp tool: use <code>kubectl config use-context</code> to make sure you're running commands on the right cluster!</p>
<h1 id="simplifying-kubernetes-configuration-with-kustomize">Simplifying Kubernetes Configuration With 'kustomize'</h1>
<p>kustomize is a standalone tool used for customizing Kubernetes configurations. It manipulates the configuration directly, side-stepping templating and maintaining the original YAML structure. This results in cleaner, more maintainable configurations.</p>
<p>Let's say you want to alter the number of replicas of an object across different environments (dev, staging, and prod). Instead of having separate YAML files for each environment, 'kustomize' allows you to apply changes directly, maintaining a single source of truth.</p>
<p>Despite the emergence of helm, kustomize still holds its ground due to its simplicity, underline 'Kubernetes native' philosophy, and seamless integration with <code>kubectl</code>.</p>
<h1 id="enhancing-kubernetes-development-workflow-with-skaffold-and-kompose">Enhancing Kubernetes Development Workflow With 'skaffold' and 'kompose'</h1>
<p><code>skaffold</code> and <code>kompose</code> are tools that supercharge the Kubernetes development workflow.</p>
<p><code>skaffold</code> automates the process of building, pushing, and deploying applications to a Kubernetes environment. It handles the workflow, allowing you to focus on writing and maintaining applications.</p>
<p><code>kompose</code>, on the other hand, is a conversion tool. With a simple <code>kompose convert</code> command, you can transform Docker Compose files into Kubernetes resources. This allows developers already versed in Docker to make a smooth transition to Kubernetes.</p>
<h1 id="visualizing-kubernetes-with-k9s">Visualizing Kubernetes With 'k9s'</h1>
<p><code>k9s</code> provides a terminal-based UI to interact with your Kubernetes cluster. It helps you to visualize and manage your applications in real time. With the capability of viewing logs, events, and pods on the fly, <code>k9s</code> serves as an invaluable tool for tracking and monitoring your Kubernetes.</p>
<h1 id="conclusion">Conclusion</h1>
<p>Kubernetes is a powerhouse, but its complexity can be intimidating. These tools—<code>kubectl</code>, <code>kustomize</code>, <code>skaffold</code>, <code>kompose</code>, and <code>k9s</code>—make Kubernetes a lot more approachable.</p>
<p>When used in harmony, they can propel your DevOps to new heights, encapsulating the essence of what Kubernetes was intended - automating, simplifying, and iterating. At the end of the day, continuous learning and utilisation of such tools can help to unravel the true potential of Kubernetes.</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Getting started with Python and Pandas ]]></title>
        <description><![CDATA[ Python has established itself as as a reputable language in the realms of scripting and programming. Of all the sectors, data science stands out as one where Python has shown great promise, mainly attributable to its library Pandas. Arguably, one of the most utilized Python libraries for data manipulation, Pandas ]]></description>
        <link>https://www.andreacasarin.com/2023/11/11/getting-started-with-python-and-pandas.html/</link>
        <guid isPermaLink="false">654f6c5edc07b00001e3a136</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 11 Nov 2023 13:01:18 +0100</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2023/11/mika-baumeister-Wpnoqo2plFA-unsplash-1.jpg" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: markdown--><p>Python has established itself as as a reputable language in the realms of scripting and programming. Of all the sectors, data science stands out as one where Python has shown great promise, mainly attributable to its library Pandas. Arguably, one of the most utilized Python libraries for data manipulation, Pandas have grown in popularity, given its powerful features and direct compatibility with Excel for Python coding. This has enabled it to reach a wide audience, making data science fascinating and simpler.</p>
<h1 id="setting-up-python">Setting up Python</h1>
<p>The journey to harnessing the power of Pandas starts with setting up Python and importing the library. Once this is done, users can embark on the journey to explore and manipulate data efficiently.</p>
<h2 id="leveraging-ide">Leveraging IDE</h2>
<p>For Python programming, one can use Jupyter Lab, a powerful Integrated Development Environment (IDE). You can delve into this more comprehensively on <a href="https://jupyter.org/?ref=andreacasarin.com">Project Jupyter | Home</a>.</p>
<h2 id="colaboratory-%E2%80%93-a-gem-from-google">Colaboratory – A Gem from Google</h2>
<p>If you wish to avoid setting up an environment, Google has made it easier with Colaboratory. You can explore more about it here: <a href="https://colab.research.google.com/?ref=andreacasarin.com">Welcome to Colaboratory - Colaboratory</a>.</p>
<h1 id="power-of-pandas">Power of Pandas</h1>
<p>Pandas is an open-source, Python library providing high-performance, easy-to-use data structures and data tools. While it resembles a spreadsheet allowing users to manipulate and analyze structured data, understanding every aspect of Pandas can feel like learning a new language. Let's shed some light into some of its core features.</p>
<h2 id="working-with-the-pandas-dataframe">Working with the Pandas DataFrame</h2>
<p>One of the first steps is understanding the pandas DataFrame. This two-dimensional labeled data structure has columns that potentially hold different types of data. It’s a lot like a database or a spreadsheet and versatile enough to accommodate various data formats.</p>
<h2 id="reading-and-writing-functions">Reading and Writing Functions</h2>
<p>Pandas simplifies the process of reading in various file types and writing your DataFrame to files or databases. It’s a hassle-free way to manage data processing, allowing you to focus more on data analysis.</p>
<h2 id="exploring-your-data">Exploring Your Data</h2>
<p>Understanding your data is vital - a task made easy by built-in functions such as 'head', 'tail', and 'sample'. These functions allow you to quickly explore your data set, seeing both the big picture and the crucial details.</p>
<h2 id="boolean-expressions-and-loc-method">Boolean Expressions and .loc Method</h2>
<p>Another important concept is understanding how to filter data using Boolean expressions with the .loc method. This method provides a way to select data based on specific conditions.</p>
<h2 id="querying-data">Querying Data</h2>
<p>The '.query' function takes data filtering further. This method allows you to filter data based on complex logic statements and conditions. It's a more dynamic way to retrieve data.</p>
<h2 id="summarizing-data">Summarizing Data</h2>
<p>To draw conclusions from your data, employing several summarization methods may quickly analyze your data. This allows us to perform aggregate functions such as mean, sum, and count with ease.</p>
<h2 id="grouping-data">Grouping Data</h2>
<p>Pandas' 'groupby' method is particularly useful when working with categorical types. This allows specific column groupings, providing a structured and organized way of viewing data.</p>
<h2 id="creating-new-columns">Creating New Columns</h2>
<p>Creating new columns based on operations on existing columns is another key part of data wrangling. With this, we can generate new fields from our data that provide additional insights.</p>
<h2 id="sorting-data">Sorting Data</h2>
<p>You can sort your data through specific column types using the 'sort_values' method. This provides a streamlined way of organizing your data for easier analysis.</p>
<h2 id="handling-missing-data">Handling Missing Data</h2>
<p>Working with real data means dealing with missing values. On such occasions, methods like 'dropna' and 'fillna' come in handy, allowing you to handle missing values in an effective way.</p>
<h2 id="combining-data">Combining Data</h2>
<p>Lastly, the option to stack together or merge data frames using methods such as 'concat' and 'merge' helps in creating a comprehensive dataset.</p>
<p>In conclusion, mastering pandas involves understanding these essentials but also requires continuous practice. For a better understanding, this <a href="https://www.youtube.com/watch?v=DkjCaAMBGWM&ref=andreacasarin.com">Learning Pandas? Start Here - YouTube tutorial</a> delivers an excellent starting point for your journey into mastering Pandas. It covers all these concepts and more, demonstrating how they come together for data manipulation and analysis.</p>
<h1 id="pandasai-%E2%80%93-simplifying-data-science">PandasAI – Simplifying Data Science</h1>
<p>The data science field is constantly evolving, and for those fans of Pandas, exciting news awaits: PandasAI. This new Python library for data science integrates AI into data analysis, making it conversational and even more interactive.</p>
<p>After setting up an OpenAI API key and installing necessary libraries such as Pandas, PandasAI, and OpenAI, you're set to explore the immense power of PandasAI.  Like all things, PandasAI has its weaknesses, struggling with complex queries. Despite its limitations, it's noteworthy that this tool provides a robust framework for interacting with data frames in a conversational manner.</p>
<h1 id="so-what">So what?</h1>
<p>In conclusion, Python and Pandas provide a great avenue for harnessing the power of data in a simpler yet powerful way. Combining this with innovations such as PandasAI unlocks the future of data science, one filled with promises of more efficient and reliable data analysis.</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ The one trick to fix Ansible errors output ]]></title>
        <description><![CDATA[ As long as everything is all right


My job involves a lot of things, but managing infrastructure as code using Ansible holds a special spot in my heart. Each day is driven by the thrill of seeing ansible&#39;s efficiency and how easily it simplifies tasks over the traditional ]]></description>
        <link>https://www.andreacasarin.com/2023/10/15/ansible-fix-errors-output.html/</link>
        <guid isPermaLink="false">652c089a4fd5d700010f992a</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sun, 15 Oct 2023 17:52:36 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: markdown--><h1 id="as-long-as-everything-is-all-right">As long as everything is all right</h1>
<p>My job involves a lot of things, but managing infrastructure as code using Ansible holds a special spot in my heart. Each day is driven by the thrill of seeing ansible's efficiency and how easily it simplifies tasks over the traditional scripts.</p>
<p>Not limited to just managing infrastructure, Ansible has proven invaluable for an assorted variety of tasks. From configuration management, application deployment, to orchestrating complex IT tasks. It plays a crucial role in interconnecting my systems.</p>
<p>A key integration that has caught my attention is its ability to <a href="https://docs.ansible.com/ansible/latest/collections/community/general/terraform_module.html?ref=andreacasarin.com">invoke Terraform</a>. Yes, that's right! Using Ansible, you can automate your Terraform procedures, making it an even more powerful tool in your IT toolbox.</p>
<h1 id="when-you-encounter-a-problem">When you encounter a problem</h1>
<p>Using Ansible is not all smooth sailing though. When confronted with errors, the Ansible command output can quickly turn into a jigsaw puzzle. The output is often cluttered and almost unreadable. Navigation through the maze of code to correct the issue becomes a significant challenge.</p>
<p>I used to refrain from directly tackling this problem, opting for the lengthy process of copy-pasting the command output into an editor to simplify it and make the errors easier to spot. Every time I did this, I wished for a better solution.</p>
<h1 id="discovering-ansible-stdout-callback-plugins">Discovering Ansible stdout callback plugins</h1>
<p>My prayers for a more readable output were answered when I stumbled upon Ansible <a href="https://docs.ansible.com/ansible/latest/collections/callback_index_stdout.html?ref=andreacasarin.com">stdout callback plugins</a>. These plugins handle Ansible's output in various ways to meet your needs.</p>
<p>Okay, it's not really a trick, but it looks like one. A quick change to my <code>ansible.cfg</code> file by adding <code>stdout_callback = yaml</code> drastically impacted the readability of the command output. It brought life to the previously chaotic mess. The output display, transformed through YAML, was crisp, clean, and straightforward to comprehend.</p>
<h1 id="trying-out-stdoutcallback-plugins">Trying out stdout_callback plugins</h1>
<p>If you too are intrigued and want to explore stdout callback plugins for yourself, here are the steps to do it:</p>
<ol>
<li>Go to your Ansible Configuration file <code>ansible.cfg</code></li>
<li>Under the <code>defaults</code> section, add <code>stdout_callback = yaml</code>.</li>
</ol>
<p>This simple addition will transform your Ansible output, making it much more readable and easy to manage.</p>
<p>Harness the power of Ansible stdout callback plugins. They not only make your results more readable, but they also save you the hassle of having to manually format your output, making your work with Ansible more intuitive and error-free!</p>
<h1 id="onward-with-ansible">Onward with Ansible</h1>
<p>Incorporate the efficiency of Ansible in your daily tasks and experience its potential beyond just managing infrastructure. Don’t forget to try invoking Terraform with Ansible and employing stdout callback plugins for a smooth workflow experience. It has greatly improved my job as a devops, and I am confident it will do the same for you.</p>
<p>Happy ansible-ing!</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Autonomous AI Agents in minutes ]]></title>
        <description><![CDATA[ Introduction to Autonomous AI Agents


Artificial Intelligence (AI) continues to revolutionize the technology landscape, with one of the most promising advancements being Autonomous AI Agents. Autonomous AI agents are systems powered by AI that can make decisions on their own and take actions to achieve specific goals, without any human ]]></description>
        <link>https://www.andreacasarin.com/2023/09/08/autonomous-ai-agents-in-minutes.html/</link>
        <guid isPermaLink="false">64fb3e56cab97d0001f1fa94</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Fri, 08 Sep 2023 18:15:00 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.andreacasarin.com/content/images/2023/09/erhan-astam-yLcK3Itx6ok-unsplash.jpg" class="kg-image" alt loading="lazy"><figcaption>Foto di <a href="https://unsplash.com/it/@vaultzero?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Erhan Astam</a> su <a href="https://unsplash.com/it/foto/yLcK3Itx6ok?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></figcaption></figure><!--kg-card-begin: markdown--><h2 id="introduction-to-autonomous-ai-agents">Introduction to Autonomous AI Agents</h2>
<p>Artificial Intelligence (AI) continues to revolutionize the technology landscape, with one of the most promising advancements being Autonomous AI Agents. Autonomous AI agents are systems powered by AI that can make decisions on their own and take actions to achieve specific goals, without any human intervention. Given their ability to self-direct, they are at the cutting edge of AI development. This article will delve deeper into the concept of autonomous AI agents, their connections with other AI technologies, the challenges they face, and their future implications.</p>
<h2 id="understanding-the-concept-autonomous-ai-agents">Understanding the Concept: Autonomous AI Agents</h2>
<p>An autonomous AI agent performs actions and makes decisions independently, based on its perception of the environment or the state of affairs. Autonomy and 'agenthood' are vital elements for these systems. In simple terms, autonomy gives them the freedom to decide, while 'agenthood' implies the agent's capacity to act, consequently affecting its environment.</p>
<p>An autonomous AI agent consists of three major components. Firstly, it perceives the environment, gathering information through sensors or other data input methods. Secondly, it takes autonomous decisions based on the perceived information, typically using AI algorithms. Lastly, it performs actions to meet its objectives, affecting its surroundings in the process, via tools.</p>
<h2 id="related-concepts-technologies">Related Concepts &amp; Technologies</h2>
<p>The concept of Autonomous AI Agents isn't isolated. It's closely tied with other AI technologies from Neural Networks to Machine, Deep and Reinforcement Learning. These technologies provide the underpinning for the functioning of an autonomous AI agent.</p>
<p>Machine Learning helps systems learn from data, Deep Learning facilitates processing of complex data, and Reinforcement Learning enables the agent to learn from its actions and their results, improving over time.</p>
<h2 id="autonomous-ai-agents-challenges-and-limitations">Autonomous AI Agents: Challenges and Limitations</h2>
<p>Contrasting with Autonomous AI agents are Non-autonomous AI agents. These rely heavily on constant human input to make decisions and perform actions. While autonomous AI agents have the advantage of decision-making freedom and efficiency, they're also more complex and pose ethical issues.</p>
<p>Developing and implementing autonomous AI systems isn’t without challenges. They present technical challenges like the need for high computational power and dealing with vast and dynamic data sets. Ethical challenges arise from the system's ability to make decisions that might affect human life and well-being. Similarly, they also pose regulatory challenges, as laws need to evolve to encompass these sophisticated AI systems.</p>
<h2 id="the-future-of-autonomous-ai-agents">The Future of Autonomous AI Agents</h2>
<p>The future of autonomous AI agents looks promising, however a focus on AI Transparency and Explainability, Ethics, Regulation is necessary. With rapid advancements, the need for AI systems to be transparent and explainable is crucial. Alongside, ethical and regulatory considerations need to keep pace with technology.</p>
<p>In conclusion, Autonomous AI Agents hold immense potential to disrupt numerous sectors and transform how we interact with technology. Understanding, nurturing, and regulating these agents responsibly will be pivotal in shaping a future where humans and AI collaborate effectively.</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Ruby on Rails and JS, an hard relationship ]]></title>
        <description><![CDATA[ Since RoR 4, the management of JavaScript in Ruby on Rails has undergone several evolutions over the years. Initially, the Rails asset pipeline, powered by Sprockets, handled JavaScript files along with other static assets. Then came the Webpacker gem in Rails 5.1, offering a more modern approach to handling ]]></description>
        <link>https://www.andreacasarin.com/2023/08/12/ruby-on-rails-and-js-hard-relationship.html/</link>
        <guid isPermaLink="false">64d79cc5e5792b00016908e1</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 12 Aug 2023 17:00:18 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2023/08/rails_and_javascript.jpg" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><p>Since RoR 4, the management of JavaScript in Ruby on Rails has undergone several evolutions over the years. Initially, the Rails asset pipeline, powered by Sprockets, handled JavaScript files along with other static assets. Then came the Webpacker gem in Rails 5.1, offering a more modern approach to handling JavaScript, leaning into the JavaScript ecosystem with npm and Webpack. Most recently, Rails 7 introduced a new method with Importmap, which simplifies JavaScript management by allowing direct browser imports without a package bundler.</p>
<h1 id="sprockets">Sprockets</h1>
<p>Initially, Rails used a system called Sprockets to handle both JavaScript and CSS assets. This system allowed the easy management of dependencies between various files and their minification for production.</p>
<p>Sprockets is a component in Rails that manages your JavaScript, CSS, and image assets. It compiles and serves these assets, facilitating their easy management. Sprockets allows the organization of assets in a way that maintains dependencies between various files and also minifies them for production, thereby enhancing performance by reducing file size.</p>
<h1 id="webpacker">Webpacker</h1>
<p>With the introduction of Rails 6, a new option was introduced: Webpacker. This choice was dictated by the popularity of Webpack in the JavaScript world, which offers greater flexibility and better integration with the modern JavaScript ecosystem.</p>
<p>Webpacker is a wrapper for Webpack, a popular JavaScript module bundler. It's used in Rails to manage JavaScript, allowing for the integration of modern JavaScript features and libraries into a Rails application. With Webpacker, you can write your JavaScript in a modular way and bundle it for efficient delivery to the client.</p>
<h1 id="importmap">Importmap</h1>
<p>With Rails 7, the Rails team introduced another option: importmap. This is a more modern method for handling JavaScript, which avoids the need for transpiling or bundling. Importmap leverages standard JavaScript modules (ESM), making the use of modern JavaScript packages simpler.</p>
<p>While it appears quite straightforward, it intentionally lacks many features supported by the previous asset pipeline implementation. That's why I personally favor a more JavaScript-centric approach on the frontend side.</p>
<h1 id="jsbuildercssbuilder-and-propshaft">JsBuilder/CssBuilder and Propshaft</h1>
<p>Choosing JSBuilder/CSSBuilder and Propshaft over Importmap may be beneficial for complex applications with many dependencies. These tools provide robust asset management, offering features like code minification and optimization (like treeshacking).</p>
<p>JSBuilder and CSSBuilder are tools used in Ruby on Rails for managing JavaScript and CSS assets. They allow efficient organization and optimization of code. Propshaft, introduced in Rails 7, is an asset pipeline responsible for handling static assets. It simplifies tasks such as asset compression, fingerprinting for cache busting, and serving assets in both development and production environments.</p>
<p>Together, JSBuilder/CSSBuilder and Propshaft provide a comprehensive solution for managing all types of assets within a Rails application. This combination allows for streamlined and efficient asset management.</p>
<h1 id="bibliography">Bibliography</h1>
<ul>
<li><a href="https://github.com/rails/sprockets?ref=andreacasarin.com">GitHub - rails/sprockets: Rack-based asset packaging system</a></li>
<li><a href="https://github.com/rails/importmap-rails?ref=andreacasarin.com">GitHub - rails/importmap-rails: Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling.</a></li>
<li><a href="https://github.com/rails/propshaft?ref=andreacasarin.com">GitHub - rails/propshaft: Deliver assets for Rails</a></li>
</ul>
<h1 id="how-to-and-guides">How to and guides</h1>
<ul>
<li><a href="https://github.com/rails/importmap-rails?ref=andreacasarin.com">GitHub - rails/importmap-rails: Use ESM with importmap to manage modern JavaScript in Rails without transpiling or bundling.</a></li>
<li><a href="https://eagerworks.com/blog/import-maps-in-rails-7?ref=andreacasarin.com">How to use Import Maps in Rails 7 (with examples)</a></li>
<li><a href="https://medium.com/@henrikbjorn/til-using-activeadmin-with-importmap-rails-289cde6f76b8?ref=andreacasarin.com">TIL: Using ActiveAdmin with importmap-rails | by Henrik Hauge Bjørnskov | Medium</a></li>
</ul>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ VIM for fun and profit ]]></title>
        <description><![CDATA[ Coming from Visual Studio Code


For Visual Studio Code (VS Code) users who are seeking to expand their coding capabilities, exploring Vim can be a transformative experience. Vim, a powerful and highly customizable text editor, offers a unique approach to code editing that focuses on efficiency, speed, and minimalism. While ]]></description>
        <link>https://www.andreacasarin.com/2023/07/09/vim-for-fun-profit.html/</link>
        <guid isPermaLink="false">64aaaf6b3883e00001f61ce6</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sun, 09 Jul 2023 15:13:22 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2023/07/vim-logo.jpg" class="kg-image" alt loading="lazy"></figure><!--kg-card-begin: markdown--><h1 id="coming-from-visual-studio-code">Coming from Visual Studio Code</h1>
<p>For Visual Studio Code (VS Code) users who are seeking to expand their coding capabilities, exploring Vim can be a transformative experience. Vim, a powerful and highly customizable text editor, offers a unique approach to code editing that focuses on efficiency, speed, and minimalism. While VS Code provides a rich and user-friendly integrated development environment (IDE), Vim takes a different approach by providing a lightweight and keyboard-centric editing experience. By delving into Vim, VS Code users can unlock a new level of productivity, fine-grained control over their editing workflow, and a wealth of plugins and configurations that can be tailored to their specific needs. Embracing Vim within the VS Code ecosystem can prove to be a rewarding journey, empowering developers to refine their coding skills and streamline their workflows.</p>
<h1 id="trying-out-vim-the-easy-way">Trying out Vim, the easy way</h1>
<p>For Visual Studio Code (VS Code) users who are interested in exploring Vim but prefer to stay within the familiar confines of their IDE, the Vim plugin for VS Code offers a seamless transition into the world of Vim. With the Vim plugin, developers can enjoy the benefits of Vim's powerful editing features and productivity enhancements directly within their VS Code environment. The plugin provides a Vim emulation layer, allowing users to leverage Vim's renowned modal editing, efficient navigation, and advanced text manipulation commands—all without having to leave the comfort of their beloved VS Code. This integration provides an excellent opportunity for VS Code users to dip their toes into the Vim ecosystem, gradually adopting Vim's principles and gradually discovering the immense productivity gains it offers. Whether you're a seasoned Vim user or a curious newcomer, the Vim plugin for VS Code provides a convenient bridge that allows you to harness the power of Vim without sacrificing the familiarity and convenience of your preferred IDE.</p>
<h1 id="using-vim-the-full-dive">Using Vim, the full dive</h1>
<p>When you feel ready to fully embrace the Vim philosophy and make a complete switch, it is worth considering Neovim as your editor of choice. Neovim is a modern fork of Vim that offers improved performance, enhanced extensibility, and a more active development community. To jumpstart your Neovim journey, utilizing a configuration starter like LazyVim or Kickstart.nvim can prove immensely helpful. These starter configurations provide a solid foundation, offering pre-configured settings, keybindings, and plugins that align with best practices and optimize your workflow. By leveraging these configuration starters, you can quickly customize Neovim to suit your needs, saving time and effort in setting up your editor from scratch. With Neovim and the guidance of these configuration starters, you can embark on a seamless transition into the world of Vim, unleashing your productivity and embracing the full potential of this legendary text editor.</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Testing Rails Applications Frontend Using Capybara and Selenium on Docker ]]></title>
        <description><![CDATA[ Modern web applications rely on dynamic content, interactive features, and responsive designs to provide a seamless user experience. Ensuring that these applications perform optimally requires extensive testing of both the frontend and backend components. For Rails applications, Capybara and Selenium WebDriver are commonly used tools for testing frontend functionality, while ]]></description>
        <link>https://www.andreacasarin.com/2023/06/10/capybara-testing-on-docker.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1e2</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 10 Jun 2023 13:30:22 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>Modern web applications rely on dynamic content, interactive features, and responsive designs to provide a seamless user experience. Ensuring that these applications perform optimally requires extensive testing of both the frontend and backend components. For Rails applications, Capybara and Selenium WebDriver are commonly used tools for testing frontend functionality, while Docker provides a lightweight containerization platform for easy deployment and scaling of your application.</p><figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2023/06/capybara-on-docker.jpg" class="kg-image" alt="" loading="lazy" width="1023" height="735" srcset="https://www.andreacasarin.com/content/images/size/w600/2023/06/capybara-on-docker.jpg 600w, https://www.andreacasarin.com/content/images/size/w1000/2023/06/capybara-on-docker.jpg 1000w, https://www.andreacasarin.com/content/images/2023/06/capybara-on-docker.jpg 1023w" sizes="(min-width: 720px) 720px"></figure><p>This guide will examine how to set up a testing environment for your Rails application frontend using Capybara and Selenium WebDriver within a Docker container. We will also discuss important considerations when choosing the appropriate configuration for your tests.</p><h2 id="introduction-to-capybara-and-selenium-webdriver">Introduction to Capybara and Selenium WebDriver</h2><p>Capybara is a popular acceptance test framework for Ruby web applications that simulates user interactions with your application in a browser. It provides a high-level API that allows you to interact with your application's UI elements, navigate between pages, fill forms, click buttons, and perform other actions as if you were an actual user.</p><p>Selenium WebDriver is an open-source browser automation framework widely used for automating web browsers through programs and performing browser automation. It supports various programming languages like Java, C#, Python among others. When combined with Capybara, it enables developers to run tests across different browsers (Chrome, Firefox) without changing the test code.</p><h2 id="setting-up-your-testing-environment">Setting Up Your Testing Environment</h2><p>To set up your Rails application frontend testing environment using Capybara and Selenium on Docker:</p><p>Install Docker: If you don't already have Docker installed on your system, follow the <a href="https://docs.docker.com/engine/install/?ref=andreacasarin.com">official installation guide</a>.</p><p>Configure Capybara: In your Rails project's <code>test</code> directory (or <code>spec</code> if you're using RSpec), create or update the <code>test_helper.rb</code> (or <code>spec_helper.rb</code>) file with the following Capybara configuration:</p><pre><code class="language-ruby">require 'capybara/rails'
require 'capybara/minitest'

Capybara.register_driver :chrome_headless do |app|
  Capybara::Selenium::Driver.new(
    app,
    browser: :remote,
    url: 'http://chrome_selenium:4444/wd/hub',
    desired_capabilities: Selenium::WebDriver::Remote::Capabilities.chrome('goog:ChromeOptions': { 'args': %w[ignore-certificate-errors no-sandbox headless disable-gpu] })
  )
end

Capybara.default_driver = :chrome_headless
Capybara.javascript_driver = :chrome_headless
</code></pre><p>This configuration sets up a new Capybara driver called <code>chrome_headless</code> that uses the Selenium WebDriver to connect to a remote Chrome browser running in headless mode.</p><p>Create a <code>Dockerfile</code> for your Rails application, if you haven't already. The Dockerfile should include instructions to install your application's dependencies and set up the runtime environment.</p><p>Create a <code>docker-compose.yml</code> file in your Rails project's root directory with the following contents:</p><pre><code class="language-yaml">version: '3'

services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - chrome_selenium

  chrome_selenium:
    image: seleniarm/standalone-chromium:4.1.2-20220227
    logging:
      driver: json-file
    networks:
      - network
    volumes:
      - /dev/shm:/dev/shm

networks:
  network:

</code></pre><p>This configuration sets up two services, <code>web</code> and <code>chrome_selenium</code>, which are your Rails application and the Selenium WebDriver running in a headless Chrome browser, respectively. The <code>web</code> service depends on the <code>chrome_selenium</code> service.</p><ol><li>Start your Docker containers using the command <code>docker-compose up</code>.</li></ol><p>With this setup, you can now create and run frontend tests for your Rails application using Capybara and Selenium WebDriver within Docker containers.</p><h2 id="https-testing-considerations">HTTPS Testing Considerations</h2><p>When testing HTTPS-enabled applications with Capybara and Selenium, it's crucial to be aware of HSTS (HTTP Strict Transport Security) preload lists that may enforce HTTPS connections. If your application's domain is included in an HSTS preload list, any HTTP connection attempts will automatically be redirected to HTTPS by modern web browsers.</p><p>To avoid complications during testing, ensure that you're using a domain that's not included in an HSTS preload list. Chrome and Firefox use the same preload list, which can be found in the <a href="https://github.com/chromium/chromium/blob/master/net/http/transport_security_state_static.json?ref=andreacasarin.com">Chromium source code</a>.</p><p>Additionally, avoid using generic or widely-used TLDs (Top-Level-Domains) which may be on the browsers HSTS preload list (<a href="https://wiki.mozilla.org/SecurityEngineering/HTTP_Strict_Transport_Security_(HSTS)_Preload_List?ref=andreacasarin.com">SecurityEngineering/HTTP Strict Transport Security (HSTS) Preload List - MozillaWiki</a>), the most common is <code>.dev</code> (which is now owned by Google - <a href="https://chromium-review.googlesource.com/c/chromium/src/+/669923/2/net/http/transport_security_state_static.json?ref=andreacasarin.com">…/transport_security_state_static.json · Gerrit Code Review</a>) but you can check the whole list in Chrome source code (Firefox uses the same): <a href="https://github.com/chromium/chromium/blob/master/net/http/transport_security_state_static.json?ref=andreacasarin.com">chromium/transport_security_state_static.json at master · chromium/chromium · GitHub</a>.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Ruby on Rails cache poisoning ]]></title>
        <description><![CDATA[ The cache poisoning attack is a sophisticated method used by hackers to manipulate data in a server&#39;s cache. This article discusses one of the most common cache poisoning attacks that exploit the HTTP X-Forwarded-Host header. This type of attack is particularly insidious because it can result in the ]]></description>
        <link>https://www.andreacasarin.com/2023/05/13/ruby-on-rails-and-cache-poisoning.html/</link>
        <guid isPermaLink="false">645f8f4b3bfa9e00014f04cd</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 13 May 2023 15:32:22 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>The cache poisoning attack is a sophisticated method used by hackers to manipulate data in a server's cache. This article discusses one of the most common cache poisoning attacks that exploit the HTTP X-Forwarded-Host header. This type of attack is particularly insidious because it can result in the display of harmful content to users, data manipulation, or theft of sensitive information.</p><figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2023/05/photo-1551269901-5c5e14c25df7.webp" class="kg-image" alt loading="lazy"></figure><p>The HTTP X-Forwarded-Host header is commonly used in network environments where a proxy server or load balancer is present. This header indicates the original host requested by the client. However, if an attacker manages to manipulate the X-Forwarded-Host header, they can direct the client's requests to a harmful host. This can lead to a series of security problems, such as the disclosure of confidential information and data manipulation.</p><p>A cache poisoning attack via the setting of X-Forwarded-Host occurs when an attacker sends an HTTP request with a manipulated X-Forwarded-Host header. If the server accepts this request and stores it in its cache, all subsequent requests for that resource will be directed to the harmful host specified in the X-Forwarded-Host header. This can lead to a wide range of attacks, including identity theft, data manipulation, and the spread of malware.</p><p>Turns out Ruby on Rails until version 6 is indeed vulnerable to those kind of attacks: <a href="https://github.com/rails/rails/issues/29893?ref=andreacasarin.com">The X-Forwarded-Host HTTP header is always trusted and is used in url_for · Issue #29893 · rails/rails (github.com)</a></p><p>So beware and always filter the hosts you going to receive via X-Forwarded-Host, if those are even needed. Otherwise do yourself a favour and delete the header before addressing each request.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Docker for Mac 98% faster with VirtIOfs ]]></title>
        <description><![CDATA[ If you are a developer who uses Docker Desktop on your Mac, you might have noticed that it can be quite slow when it comes to file sharing between the host and the guest operating systems. This can affect the performance and responsiveness of your applications, especially if they rely ]]></description>
        <link>https://www.andreacasarin.com/2023/04/08/docker-for-mac-virtio-performances.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1e5</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 08 Apr 2023 12:12:46 +0200</pubDate>
        <media:content url="https://www.andreacasarin.com/content/images/2023/04/docker.jpeg" medium="image"/>
        <content:encoded><![CDATA[ <p>If you are a developer who uses Docker Desktop on your Mac, you might have noticed that it can be quite slow when it comes to file sharing between the host and the guest operating systems. This can affect the performance and responsiveness of your applications, especially if they rely on a lot of disk IO operations. Fortunately, there is a new feature that can significantly improve the file sharing speed and make your development experience much smoother: VirtIOfs.</p><p>VirtIOfs is a virtualization technology that allows faster and more efficient file sharing between the host and the guest operating systems. It uses a shared memory region to transfer data between the two systems, instead of copying files back and forth. This reduces the CPU usage and memory consumption, as well as the latency and overhead of file sharing. According to a recent benchmark by Docker, VirtIOfs can make Docker Desktop on MacOS up to 98% faster than without VirtIOfs.</p><p>Some of the benefits of using VirtIOfs for file sharing are:</p><ul><li>Reduced CPU usage and memory consumption: VirtIOfs eliminates the need for copying files between the host and the guest operating systems, which saves CPU cycles and memory space. This can also free up resources for other tasks and improve the overall performance of your system.</li><li>Improved performance and responsiveness of applications: VirtIOfs enables faster file access and modification, which can improve the speed and responsiveness of your applications. For example, if you are using a web framework that reloads your code on every change, you will notice a much shorter feedback loop with VirtIOfs enabled.</li><li>Enhanced compatibility and security: VirtIOfs supports all file system features that are supported by MacOS, such as extended attributes, hard links, symlinks, etc. This means that you don't have to worry about any compatibility issues or data loss when using VirtIOfs. Moreover, VirtIOfs uses a secure communication channel between the host and the guest operating systems, which prevents any unauthorized access or tampering with your files.</li></ul><p>To enable VirtIOfs on Docker Desktop, you need to follow these simple steps:</p><ul><li>Update to the latest version of Docker Desktop and MacOS: You need to have Docker Desktop version 4.6.0 or higher and MacOS version 12.0 or higher to use VirtIOfs. You can check your current versions by going to About Docker Desktop and About This Mac in your menu bar.</li><li>Go to Preferences &gt; Experimental Features and check the box for Use virtiofs for file sharing: This will enable VirtIOfs as the default file sharing mechanism for Docker Desktop on MacOS. You can also toggle this option on or off for individual containers by using the --mount flag with the type=virtiofs option.</li><li>Restart Docker Desktop and enjoy the speed boost: After enabling VirtIOfs, you need to restart Docker Desktop for the changes to take effect. You should notice a significant improvement in the file sharing speed and performance of your applications.</li></ul><p>Here are the official release announcement: <a href="https://www.docker.com/blog/speed-boost-achievement-unlocked-on-docker-desktop-4-6-for-mac/?ref=andreacasarin.com">Speed boost achievement unlocked on Docker Desktop 4.6 for Mac | Docker</a></p><p>VirtIOfs is a game-changer for developers who use Docker Desktop on their Macs. It can make your development experience faster, smoother, and more enjoyable. If you haven't tried it yet, I highly recommend you to give it a shot and see for yourself how much difference it can make.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ ChatGPT &quot;kinda&quot; integrates itself with Alfred App on MacOS ]]></title>
        <description><![CDATA[ Alfred is a popular productivity app for macOS that allows you to launch apps, search for files, and automate tasks using custom workflows. If you would like to integrate OpenAI&#39;s GPT-3 based ChatGPT with Alfred, you can do so by building a custom workflow in Alfred.


Here&#39; ]]></description>
        <link>https://www.andreacasarin.com/2023/03/11/chatgpt-integrates-its-self-with-alfred-app-on-macos.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1e8</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 11 Mar 2023 12:32:20 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>Alfred is a popular productivity app for macOS that allows you to launch apps, search for files, and automate tasks using custom workflows. If you would like to integrate OpenAI's GPT-3 based ChatGPT with Alfred, you can do so by building a custom workflow in Alfred.</p>
<p>Here's a step-by-step guide on how to integrate ChatGPT with Alfred, written by ChatGPT itself:</p>
<hr>
<ol>
<li>Install the Alfred app on your Mac if you haven't already.</li>
<li>Create a new workflow in Alfred by clicking on the "Workflows" tab in the Alfred preferences and then clicking the "+" button in the bottom left corner.</li>
<li>Add a "Script Filter" object to the workflow by double-clicking on it in the left panel and dragging it to the right panel.</li>
<li>In the "Script Filter" object, paste the following Python code, which uses the OpenAI API to send a request to the ChatGPT model and returns the response as a list of Alfred results:</li>
</ol>
<pre><code>import os
import requests

query = "{query}"

def send_query_to_openai(prompt):
    response = requests.post("https://api.openai.com/v1/engines/davinci/jobs",
        headers={
            "Content-Type": "application/json",
            "Authorization": "Bearer "+ os.environ["OPENAI_API_KEY"]
        },
        json={
            "prompt": prompt,
            "max_tokens": 1024,
            "temperature": 0.5,
        },
    )
    if response.status_code != 200:
        raise ValueError("Failed to send query to OpenAI")
    response_json = response.json()
    return response_json['choices'][0]['text'].strip()

def main():
    response = send_query_to_openai(query)
    print(response)

main()
</code></pre>
<ol start="5">
<li>In the "Script Filter" object, set the "Keyword" to "chatgpt" and the "Argument Placeholder" to "{query}".</li>
<li>Add an "Environment Variable" object to the workflow by double-clicking on it in the left panel and dragging it to the right panel.</li>
<li>In the "Environment Variable" object, set the "Name" to "OPENAI_API_KEY" and the "Value" to your OpenAI API key.</li>
<li>Save the workflow and give it a name, such as "ChatGPT".</li>
</ol>
<p>Now, you can activate the ChatGPT workflow by typing "chatgpt" followed by your query in the Alfred search bar. The response from the ChatGPT model will be displayed in the Alfred results.</p>
<p>Note: This is just a basic example of how to integrate ChatGPT with Alfred, and you can customize the workflow further to better suit your needs.</p>
<hr>
<p>In my specific case that wasn't working, but it's still a cool experiment. YMMV.</p>
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Docker build caching in GitLab ]]></title>
        <description><![CDATA[ As a software developer, you’re probably familiar with the time it takes to build a Docker image, especially if your application is complex and requires many dependencies. But did you know that you can speed up your builds by using caching strategies?


In this article, we’ll explore the ]]></description>
        <link>https://www.andreacasarin.com/2023/02/11/docker-build-caching-in-gitlab.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1e1</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 11 Feb 2023 13:37:40 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: markdown--><p>As a software developer, you’re probably familiar with the time it takes to build a Docker image, especially if your application is complex and requires many dependencies. But did you know that you can speed up your builds by using caching strategies?</p>
<p>In this article, we’ll explore the different ways to optimize your Docker builds in GitLab, by using the BUILDKIT_INLINE_CACHE, tagging with both latest and sha_commit, and using the docker-compose cache from option.</p>
<h2 id="buildkitinlinecache">BUILDKIT_INLINE_CACHE</h2>
<p>The BUILDKIT_INLINE_CACHE environment variable can be used to enable build caching in GitLab CI/CD pipelines. When set to 1, it allows GitLab to cache the intermediate build layers, which can significantly speed up subsequent builds. To enable this feature, simply add the following line to your .gitlab-ci.yml file:</p>
<pre><code>variables:   DOCKER_BUILDKIT: 1
</code></pre>
<h2 id="tagging-with-both-latest-and-shacommit">Tagging with both latest and sha_commit</h2>
<p>Tagging your Docker images with both the latest and the sha_commit (the unique identifier for each commit) can also improve your build times. By tagging with the latest tag, you can ensure that your latest build is always accessible, and by tagging with the sha_commit, you can guarantee that you can access specific builds at any time.</p>
<pre><code>image: docker:stable  
stages:   
    - build  
build:   
    stage: build   
    script:     
        - docker build -t myimage:latest .     
        - docker build -t myimage:$CI_COMMIT_SHA .
</code></pre>
<h2 id="using-docker-compose-cache-from">Using docker-compose cache from</h2>
<p>The docker-compose cache from option allows you to cache intermediate build layers when using docker-compose. This can be particularly useful when building multi-container applications, as it allows you to cache the dependencies and intermediate layers for each container. To use this feature, simply add the following line to your docker-compose.yml file:</p>
<pre><code>version: '3.7' 
services:   
    web:     
        build: .     
        cache_from:       
            - web:latest
</code></pre>
<h2 id="what-to-expect">What to expect</h2>
<p>One of the benefits of combining these caching strategies is that you can leverage the cache without prior pulling of all the last images' layers. This means that you don't need to wait for the entire image to be pulled from the repository to start the build process. Instead, GitLab can use the cached layers from previous builds to start the build process, reducing the time it takes to complete the build.</p>
<p>By using the BUILDKIT_INLINE_CACHE environment variable, GitLab can cache the intermediate build layers, which can be used in subsequent builds. This means that if you make changes to your code, docker will only have to build the layers that have changed, instead of starting from scratch. This can significantly speed up your builds and reduce the time it takes to complete a build.</p>
<p>The docker-compose cache from option also works in a similar way, allowing you to cache the dependencies and intermediate layers for each container in your multi-container application. This means that if you make changes to one container, you don't need to rebuild all the other containers from scratch, as the cached layers can be used.</p>
<p>In summary, by leveraging these caching strategies, you can significantly speed up your Docker builds in GitLab, without having to wait for the entire image to be pulled from the repository. This can save you time, reduce the number of build failures, and improve the overall performance of your CI/CD pipelines.</p>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Databases on NFS shares ]]></title>
        <description><![CDATA[ Last week I was trying to deploy a MariaDB container to my home lab which has to use TrueNAS share as persistent storage. I&#39;m currenly using NFS storage for my homelab docker cluster. I wasn&#39;t working right, due to some Lock errors.

So I found out ]]></description>
        <link>https://www.andreacasarin.com/2023/01/14/database-on-nfs-shares.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1e6</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 14 Jan 2023 14:14:04 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>Last week I was trying to deploy a MariaDB container to my home lab which has to use TrueNAS share as persistent storage. I'm currenly using NFS storage for my homelab docker cluster. I wasn't working right, due to some Lock errors.</p><p>So I found out that running a Sqlite db or really anything which requires files lock over NFS keep is really buggy when managed remotely via <code>rpc.statd</code> and <code>rpc.lockd</code>.</p><p>You can however opt for local locks, if the share is mount only by one user/server.</p><p>To enable local locks in TrueNAS, set a sysctl tunable in System-&gt;Tunables of <code>vfs.nfsd.enable_locallocks=1</code>. Then add <code>local_lock=all</code> to your NFS mount options.</p><p>That leads to an NFS share that can only be mounted by a single client safely, however that's usually the case with a database share.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Buone feste 🎄 ]]></title>
        <description><![CDATA[ Un augurio di serene feste e felice nuovo anno. Colgo l’occasione per segnalarvi che sarò in ferie dal 24/12 all’8/1.

A presto,

Andrea Casarin
andreacasarin.com
Facebook | Twitter | Linkedin ]]></description>
        <link>https://www.andreacasarin.com/2022/12/23/buone-feste-2022-2023.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1e7</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Fri, 23 Dec 2022 18:00:00 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.andreacasarin.com/content/images/2022/12/clint-patterson-1-wBnPhsmJY-unsplash.jpg" class="kg-image" alt loading="lazy"><figcaption>Foto di <a href="https://unsplash.com/ja/@cbpsc1?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Clint Patterson</a> su <a href="https://unsplash.com/it/foto/1-wBnPhsmJY?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>.</figcaption></figure><p>Un augurio di serene feste e felice nuovo anno. Colgo l’occasione per segnalarvi che sarò in ferie dal 24/12 all’8/1.</p><p>A presto,</p><p>Andrea Casarin<br><a href="https://www.andreacasarin.com/">andreacasarin.com</a><br><a href="https://www.facebook.com/andreacasarinofficial/">Facebook</a> | <a href="https://twitter.com/a_casarin?ref=andreacasarin.com">Twitter</a> | <a href="https://www.linkedin.com/in/andreacasarinofficial/?ref=andreacasarin.com">Linkedin</a></p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Kubernetes state and metrics monitoring ]]></title>
        <description><![CDATA[ When moving your workload from some VMs to a Kubernetes cluster you may find yourself losing grasp on what&#39;s happening, it happens to all of us.

However K8S has some great ways to make sure you are on top of your cluster status, you just have to make ]]></description>
        <link>https://www.andreacasarin.com/2022/12/10/kubernetes-state-and-metrics-monitoring.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1de</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 10 Dec 2022 11:22:38 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>When moving your workload from some VMs to a Kubernetes cluster you may find yourself losing grasp on what's happening, it happens to all of us.</p><p>However K8S has some great ways to make sure you are on top of your cluster status, you just have to make sure you setup them right.</p><p><strong>metrics-server</strong></p><p>Gets resource metrics from Kubelets and exposes them through the Kubernetes Api Server via Metrics API, think at them as:</p><ul><li>CPU</li><li>memory</li><li>network usage</li></ul><p>Used primarly for horizontal and vertical autoscaling, accessed via console with <code>kubectl top</code>.</p><p><strong>kube-state-metrics</strong></p><p>Gets metrics from Kubernetes Api Server end generates metrics about in cluster objects, think at them as:</p><ul><li>Resource requests and limits</li><li>Number of objects–nodes, pods, namespaces, services, deployments</li><li>Number of pods in a running/terminated/failed state</li></ul><p>Used primarly as a data source for monitoring.</p><p><strong>So what?</strong></p><p>You may want to use both to gain observability over the cluster using some sort of service to aggregate and store those metrics then visualize in a user friendly way. </p><p>My current preferred way is via Prometheus + Grafana, or NewRelic to combine even more data (eg. logs).</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Postgres, where and null ]]></title>
        <description><![CDATA[ Some days ago I was working on a project which uses Postgres as DBMS. Postgres is great, but it has some significant differences if you are used to MySql. I learned one of them the hard way.

While doing a simple select query I was looking for tuples which were ]]></description>
        <link>https://www.andreacasarin.com/2022/11/13/postgres-select-and-null-values.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1e3</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sun, 13 Nov 2022 14:51:38 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>Some days ago I was working on a project which uses Postgres as DBMS. Postgres is great, but it has some significant differences if you are used to MySql. I learned one of them the hard way.</p><p>While doing a simple <code>select</code> query I was looking for tuples which were <code>where x != 42</code> trying to extract all of them regardless of <code>x</code> being some number or null.</p><p>That didn't work as I expected. In Postgres if you select something via <code>where x != 42</code> it will not extract tuples <code>where x is null</code>. </p><p>So, if you are doing something like I did make sure to explicitly include <code>null</code> as a <code>where</code> condition, for example <code>where x != 42 or x is null</code>.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ OpenSSH ssh-dsa and ssh-rsa ]]></title>
        <description><![CDATA[ OpenSSH 8.8 is deprecating ssh-rsa and ssh-dss as key types.

In the SSH protocol, the &quot;ssh-rsa&quot; signature scheme uses the SHA-1 hash algorithm in conjunction with the RSA public key algorithm. It is now possible to perform chosen-prefix attacks against the SHA-1 algorithm for less than USD$ ]]></description>
        <link>https://www.andreacasarin.com/2022/10/08/ssh-deprecating-ssh-dsa-and-ssh-rsa.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1da</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 08 Oct 2022 10:05:00 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>OpenSSH 8.8 is deprecating ssh-rsa and ssh-dss as key types.</p><p>In the SSH protocol, the "ssh-rsa" signature scheme uses the SHA-1 hash algorithm in conjunction with the RSA public key algorithm. It is now possible to perform chosen-prefix attacks against the SHA-1 algorithm for less than USD$50K. [<a href="https://www.openssh.com/txt/release-8.7?ref=andreacasarin.com">https://www.openssh.com/txt/release-8.7</a>]</p><p>So you will get this error:</p><!--kg-card-begin: html--><pre class="language-clike">
<code class="language-clike">no matching host key type found. Their offer: ssh-rsa,ssh-dss</code>
</pre><!--kg-card-end: html--><p>You can add those algorithms back, with:</p><!--kg-card-begin: html--><pre class="language-clike">
<code class="language-clike">HostKeyAlgorithms +ssh-rsa,ssh-dss</code>
</pre><!--kg-card-end: html--><p>in /etc/ssh_config.</p><p>Of course this is a workaround, please update your keys.</p><p>I would go with <a href="https://en.wikipedia.org/wiki/Twisted_Edwards_curve?ref=andreacasarin.com">https://en.wikipedia.org/wiki/Twisted_Edwards_curve</a>, to generate such key you issue a simple command:</p><!--kg-card-begin: html--><pre class="language-clike">
<code class="language-clike">ssh-keygen -t ed25519</code>
</pre><!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Nginx caching on Kubernetes ]]></title>
        <description><![CDATA[ Nginx ingress is one of the best ingress you can use on your K8S cluster, by default it comes with a lot of features but caching is not enabled. Let&#39;s see how to set up a simple static cache for our websites.

On cluster ingress (this is managed ]]></description>
        <link>https://www.andreacasarin.com/2022/09/11/nginx-caching-on-kubernetes.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1e4</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sun, 11 Sep 2022 10:43:00 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>Nginx ingress is one of the best ingress you can use on your K8S cluster, by default it comes with a lot of features but caching is not enabled. Let's see how to set up a simple static cache for our websites.</p><p>On cluster ingress (this is managed by an Nginx config map):</p><pre><code>proxy_cache_path /tmp/nginx-cache levels=1:2 keys_zone=static-cache:32m max_size=5g inactive=7d use_temp_path=off;
proxy_cache_valid any 5m;
proxy_cache_valid 200 30m;</code></pre><p>On application ingress (managed via deploy):</p><pre><code>proxy_ignore_headers Set-Cookie;
proxy_cache static-cache;
</code></pre><p>Watch out for proxy_ignore_headers, these could cache cookies and/or break sessions. You could use something like:</p><pre><code>  if ($uri ~ "/admin/") {
    set $app_nocache 1;
  }
  if ($http_cookie ~* "logged_in") {
    set $arg_nocache 1;
  }
  proxy_no_cache $cookie_nocache $arg_nocache $app_nocache;
</code></pre><p>To avoid caching dynamic pages/admin areas.</p><p>And to add a nice touch:</p><pre><code>add_header X-Cache-Status $upstream_cache_status;
</code></pre><p>So that you can watch your response headers to check the cache status for that particular request.</p><p>Enjoy!</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Static assets optimization for websites ]]></title>
        <description><![CDATA[ I recently restyled my website (this one!) switching from Wordpress to GhostCMS and SvelteKit (which are great,but that&#39;s a story for another day). In the process I wanted to reach some good speed to please both the users and Google.

One of the mayor aspect of this ]]></description>
        <link>https://www.andreacasarin.com/2022/07/09/static-assets-optimization-for-websites.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1db</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 09 Jul 2022 11:17:11 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>I recently restyled my website (<a href="https://andreacasarin.com/?ref=andreacasarin.com">this one!</a>) switching from Wordpress to GhostCMS and SvelteKit (which are great,but that's a story for another day). In the process I wanted to reach some good speed to please both the users and <a href="https://developers.google.com/speed/pagespeed/insights/?ref=andreacasarin.com">Google</a>.</p><p>One of the mayor aspect of this is static assets optimization, here are a few tips I found out in my journey.</p><h3 id="images">Images</h3><p>PJPEG: jpeg images are loaded from top to bottom, progressive jpeg from back to front. So they will load the whole sized image and then refine it from a resolution standpoint. Thats great for browsers and users alike.</p><p>WEBP: thats a new format from Google with better compression then PNG, alpha channel and slightly better then JPG. Unfortunately it's still not widely supported.</p><p>AVIF: new better format and an open one, quite well supported but still niche. This has potential to become the new way to go.</p><p>I decided to optimize my images with GIMP by setting the smallest possibile size and removing all the extra data attached (exif, resolution, ecc). I tend to go PJPEG 90% quality when possibile, then PNG compression 9.</p><p>You can try <a href="https://squoosh.app/?ref=andreacasarin.com">https://squoosh.app/</a> to test the results for different formats.</p><p>Make then sure you set width and height to an absolute number (no 'px') to define the base size and aspect ratio, then set the responsive size via css.</p><h3 id="javascript-and-stylesheet">Javascript and stylesheet</h3><p>For JS always defer (load asynchronously execute at the end), if not possible use async (load asincrously execute as soon as loaded).</p><p>For stylesheets there is no simple way to load asynchronously, however you can trick the browser via:</p><pre><code class="language-xml">&lt;link href="style.css" rel="preload" as="style" onload="this.rel='stylesheet'"&gt;
&lt;noscript&gt;&lt;link rel="stylesheet" href="style.css"&gt;&lt;/noscript&gt;
</code></pre><p>To please Google page speed algorithm it looks like the minimum caching time is 1 year, so make sure to add a Cache-Control header to cache your static content for 1+ year (for 1 year use max-age: 31536000).</p><p>And, of course, minimize and gzip.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Ansible forks/serial on a task level ]]></title>
        <description><![CDATA[ If your inventory contains the same host multiple times (think dynamic inventories or something defined via Terraform) and then you run a playbook against that (eg. target: all) you&#39;ll end up trying to run the same tasks simultaneously on the same host.

That&#39;s not usually an ]]></description>
        <link>https://www.andreacasarin.com/2022/06/11/ansible-forks-on-a-task-level.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d8</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 11 Jun 2022 12:17:19 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>If your inventory contains the same host multiple times (think dynamic inventories or something defined via Terraform) and then you run a playbook against that (eg. target: all) you'll end up trying to run the same tasks simultaneously on the same host. </p><p>That's not usually an issue, however some tasks require a lock (eg. apt install pkg) thus breaking for errors or timeouts.</p><p>Ansible has some attributes to manage this situations, like:</p><ul><li><a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_strategies.html?ref=andreacasarin.com#id2">forks</a> at a configuration level</li><li><a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_strategies.html?ref=andreacasarin.com#setting-the-batch-size-with-serial">serial</a> at a playbook level</li></ul><p>What if you can define it on a task level? That would be great since you could then only limit tasks which actually require locks instead of slowing down everything. </p><p>Looks like it has been asked before: <a href="https://github.com/ansible/ansible/issues/12170?ref=andreacasarin.com">https://github.com/ansible/ansible/issues/12170</a> and, although not documented yet it's been implemented:</p><ul><li><a href="https://github.com/ansible/ansible/pull/42528?ref=andreacasarin.com">https://github.com/ansible/ansible/pull/42528</a></li><li><a href="https://github.com/ansible/ansible/pull/60702?ref=andreacasarin.com">https://github.com/ansible/ansible/pull/60702</a></li></ul><p>So here we go:</p><!--kg-card-begin: markdown--><pre><code>- name: Testcommand: 
  echo 'test'
  throttle: 1
</code></pre>
<!--kg-card-end: markdown--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ eBPF application monitoring on Kubernetes ]]></title>
        <description><![CDATA[ Just a quick one, since I recently found out about Pixie which is a super interesting opensource project recently bought by NewRelic.

It&#39;s an agent which you can install on your k8s cluster (or on your standard VM). It uses eBPF to collect deep data from Linux Kernel, ]]></description>
        <link>https://www.andreacasarin.com/2022/05/03/pixie-opensource-monitoring.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d9</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Tue, 03 May 2022 18:23:00 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>Just a quick one, since I recently found out about Pixie which is a super interesting opensource project recently bought by NewRelic.</p><p>It's an agent which you can install on your k8s cluster (or on your standard VM). It uses <a href="https://ebpf.io/?ref=andreacasarin.com">eBPF</a> to collect deep data from Linux Kernel, granting the ability to monitor an application without the need of an APM (Application Performance Management). It promises a maximum 5% overhead.</p><p>The frontend uses PxL Script (which is similar to python + panda) to fetch data from backend, which is queried directly.</p><p>You can use it <a href="https://px.dev/?ref=andreacasarin.com">standalone</a>, on <a href="https://github.com/pixie-io/pixie?ref=andreacasarin.com">premise</a>, or for example with <a href="https://www.youtube.com/watch?v=MaEgVRyFE-A&ref=andreacasarin.com">NewRelic</a> (since the data stays on your host there is no cost for data ingestion).</p><p>That's a great video from Pixie explaining the technology in details: <a href="https://www.youtube.com/watch?v=shJ45UJvFR4&ref=andreacasarin.com">https://www.youtube.com/watch?v=shJ45UJvFR4</a>.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Backup Kubernetes volumes in AWS ]]></title>
        <description><![CDATA[ When using Kops on AWS to deploy your Kubernetes cluster you&#39;ll find yourself with multiple elastic block storage volumes which are the PersistentVolumeClaim implementation on AWS. Snapshots are then a great way to provide backups, and especially so if coupled with lifecycle manager which can define your backup ]]></description>
        <link>https://www.andreacasarin.com/2022/04/09/backup-kubernetes-volumes-in-aws.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d7</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Sat, 09 Apr 2022 12:04:17 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>When using <a href="https://kops.sigs.k8s.io/?ref=andreacasarin.com">Kops</a> on AWS to deploy your Kubernetes cluster you'll find yourself with multiple elastic block storage volumes which are the PersistentVolumeClaim implementation on AWS. Snapshots are then a great way to provide backups, and especially so if coupled with <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/snapshot-lifecycle.html?ref=andreacasarin.com">lifecycle manager</a> which can define your backup schedule and retention.</p><p>Usually when defining a life-cycle policy you create a tag filter to select specifics volumes and then a schedule to snapshot them and how many you want to keep.</p><p>So it would be great to add tags to volumes provisioned by Kubernetes that way you could create a life cycle policy to backup them automatically when marked with a specific tag. </p><p>Unfortunately that's currently not possible on the standard provisioner:</p><ul><li><a href="https://github.com/kubernetes/kubernetes/pull/49390?ref=andreacasarin.com">https://github.com/kubernetes/kubernetes/pull/49390</a></li><li><a href="https://github.com/kubernetes/kubernetes/issues/50898?ref=andreacasarin.com">https://github.com/kubernetes/kubernetes/issues/50898</a></li></ul><p>But you can use the AWS EBS CSI driver instead of the k8s in-tree one (which looks like will be deprecated one day), then you can add tags this way:</p><ul><li><a href="https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/e175fe64989019e2d8f77f5a5399bad1dfd64e6b/charts/aws-ebs-csi-driver/values.yaml?ref=andreacasarin.com">https://github.com/kubernetes-sigs/aws-ebs-csi-driver/blob/e175fe64989019e2d8f77f5a5399bad1dfd64e6b/charts/aws-ebs-csi-driver/values.yaml</a></li></ul><p>In fact the AWS EBS CSI provisioner ability to add extra tags got merged to master branch sometime in 2019 (<a href="https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/333?ref=andreacasarin.com">https://github.com/kubernetes-sigs/aws-ebs-csi-driver/issues/333</a>).</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ DevPresto resources for developers ]]></title>
        <description><![CDATA[ DevPresto is a fast online resource collection for developers.

It features some tools (like markup formatting, sql formatting, md5 calculation) and will host a series of hand-picked guides and tutorials.

It aims to be a useful website for everyday development or system administration.

Most of our favorite instruments live in ]]></description>
        <link>https://www.andreacasarin.com/2022/02/07/devpresto.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1dc</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Mon, 07 Feb 2022 09:33:45 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p><a href="https://www.devpresto.com/?ref=andreacasarin.com">DevPresto</a> is a fast online resource collection for developers.</p><p>It features some tools (like <a href="https://www.devpresto.com/formatters/xml?ref=andreacasarin.com">markup formatting</a>, <a href="https://www.devpresto.com/formatters/sql?ref=andreacasarin.com">sql formatting</a>, <a href="https://www.devpresto.com/calculators/md5?ref=andreacasarin.com">md5 calculation</a>) and will host a series of hand-picked guides and tutorials.</p><figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2021/10/devpresto.png" class="kg-image" alt loading="lazy"></figure><p>It aims to be a useful website for everyday development or system administration.</p><p>Most of our favorite instruments live in our editor/terminal of choice, but sometimes you just need a quick tool to be able to share or check something on the go. I've been there a few times.</p><p>I used to search Google for a json formatter or an md5 calculator from my phone, just to find out that most of those results were not usable on mobile, or slow, or both.</p><p>So I decided to assemble my own online toolset in my spare time, and that's how DevPresto began to take shape. In that regard I'd like to thanks the whole open-source community which helped me a lot.</p><p>It's a microservice based application, the backend is written in JS on NodeJS with Express, the frontend is Vue based with Nuxt.js.</p><p>It's currently running on a Kubernetes cluster deployed via Kops on AWS, it makes use of Skaffold to manage it's deployment via Gitlab CI.</p><p>Since I's a side-project I can't assure timely responses but feel free to report any bug or submit a request by email to: info <em>at</em> devpresto <em>dot</em> com, I might make it open source if it gains some traction.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Switching from Minitest to RSpec ]]></title>
        <description><![CDATA[ Minitest is great and it now the standard tool to test a Ruby on Rails application, I have been using it for a long time and it works great. However while working on a client&#39;s project I found that RSpec tests are easier to read and its ecosystem ]]></description>
        <link>https://www.andreacasarin.com/2021/12/23/switching-from-minitest-to-rspec.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d6</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Thu, 23 Dec 2021 08:00:00 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p><a href="https://guides.rubyonrails.org/testing.html?ref=andreacasarin.com">Minitest</a> is great and it now the standard tool to test a Ruby on Rails application, I have been using it for a long time and it works great. However while working on a client's project I found that <a href="https://rspec.info/?ref=andreacasarin.com">RSpec</a> tests are easier to read and its ecosystem provides a faster and cleaner way to write tests.</p><figure class="kg-card kg-image-card"><img src="https://www.andreacasarin.com/content/images/2021/12/rspec.jpg" class="kg-image" alt loading="lazy"></figure><p>Said that I decided to switch the test suite for an application I was working on to RSpec, to try and learn this different tool. I also opted in for <a href="https://matchers.shoulda.io/?ref=andreacasarin.com">shoulda_matchers</a> and <a href="https://github.com/thoughtbot/factory_bot?ref=andreacasarin.com">factory_bot</a> which seems to be the de-facto standard.</p><p>Here are a few hints if you want to follow the same path.</p><h2 id="one-assertion-per-test">One assertion per test.</h2><p>That's it, write multiple tests with one assertion each, seems unpractical at firsts but it really helps in the long run.</p><h2 id="prefer-isexpectedexpects-over-should">Prefer is_expected/expects over should.</h2><p>Pretty straightforward, as per <a href="https://relishapp.com/rspec/rspec-core/docs/subject/one-liner-syntax?ref=andreacasarin.com">documentation</a> now is_expected is the preferred syntax.</p><h2 id="use-subject-for-main-testing-object">Use subject for main testing object.</h2><p>You are supposed to define a subject which serve as main test object, then expect something from it.</p><h2 id="use-let-for-other-objects">Use let for other objects.</h2><p>With let you can define other objects which will be edge loaded for each test as they are used. If you need that object before explicitly calling it you can use let! instead.</p><h2 id="when-using-callbacks-aftersave-remember-to-save">When using callbacks after(:save) remember to save.</h2><p>This one is for factory_bot actually: you'll find yourself using callbacks to define associated object in a one-to-many or many-to-many relationship. I these cases make sure to save the object in the callback too.</p><h2 id="use-allowvalue-to-test-custom-validations">Use allow_value() to test custom validations.</h2><p>Now on with shoulda_matchers, which has a lot of cool ways to test model validations, however if you want to test some custom ones you can simply use allow_value and test for true or false.</p><h2 id="remember-eq-tests-equality-be-tests-identity">Remember eq() tests equality, be() tests identity.</h2><p>That's easy, but often overlooked, make sure you are testing for the right thing.</p><h2 id="backtrace-to-get-context">Backtrace to get context.</h2><p>You can add `--backtrace` to your tests to have some clue on why they are failing.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ VirtualBox 6.1.28 and Minikube issues ]]></title>
        <description><![CDATA[ So VirtualBox 6.1.28 has been released and with it the support for Linux 5.14 and, of course, a lot of other interesting features.

I just discovered one the hard way, while upgrading my Arch machine.

I&#39;m using minikube for local Kubernetes development, minikube itself it& ]]></description>
        <link>https://www.andreacasarin.com/2021/10/27/virtualbox-6-1-28-and-minikube-issues.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1df</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Wed, 27 Oct 2021 17:29:25 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <p>So VirtualBox 6.1.28 has been released and with it the support for Linux 5.14 and, of course, a lot of other interesting features.</p><p>I just discovered one the hard way, while upgrading my Arch machine. </p><p>I'm using minikube for local Kubernetes development, minikube itself it's a VM which by default runs on VirtualBox (and a bunch of other platforms). It creates a host-only network plus a nat network to make the magic possibile.</p><p>The default host-only network CIDR is 192.168.99.1/24, and here comes the problem: turns out that the latest VirtualBox version has some security limitations for host only network ranges: <a href="https://www.virtualbox.org/manual/ch06.html?ref=andreacasarin.com#network_hostonly">https://www.virtualbox.org/manual/ch06.html#network_hostonly</a> (In my case the reported error was: <code>VBoxManage: error: Code E_ACCESSDENIED (0x80070005) - Access denied (extended info not available)</code>).</p><p>You can either add the minikube default to the allowed ranges or change the default itself to be in the VirtualBox range. </p><p>I did the latter with a simple: <code>minikube config set host-only-cidr "192.168.56.1/24"</code>.</p> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ PSD2 dal punto di vista di uno sviluppatore ]]></title>
        <description><![CDATA[ Cos’é la PSD2




La direttiva dell’UE 2015/2366 (Payment Service Directive 2 – PSD2) è una nuova legge Europea che ha come oggetto il mercato dei pagamenti nell’Unione. È un’evoluzione della direttiva 2007/64/CE (Payment Service Directive – PSD).



Photo by Web Hosting on Unsplash




FinTech e ]]></description>
        <link>https://www.andreacasarin.com/2019/10/29/psd2-punto-di-vista-sviluppatore.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d5</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Tue, 29 Oct 2019 10:00:58 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><h2>Cos’é la PSD2<b><br />
</b></h2>
<p>La direttiva dell&#8217;UE 2015/2366 (Payment Service Directive 2 &#8211; PSD2) è una nuova legge Europea che ha come oggetto il mercato dei pagamenti nell’Unione. È un’evoluzione della direttiva 2007/64/CE (Payment Service Directive &#8211; PSD).</p>
<div>
<div ><img src="https://www.andreacasarin.com/content/images/2019/10/psd2.jpg" alt="PSD2 photo wallet" /><p>Photo by Web Hosting on Unsplash</p></div>
</div>
<h2>FinTech e Europa</h2>
<p>Il settore FinTech non ha avuto fin&#8217;ora molto successo in Europa a differenza del mercato Americano. Molti strumenti non avevano la possibilità di funzionare qui a causa della mancanza di API per la connessione agli istituti bancari.</p>
<p>Attori come Intuit, con <a href="https://www.mint.com/?ref=andreacasarin.com" target="_blank" rel="nofollow noopener">Mint</a> sono presenti da tempo in America e permettono l’aggregazione dei dati economici presenti su diversi account per avere una visione d’insieme e per l’automazione di alcuni scenari.</p>
<p>In Italia (ed in Europa), purtroppo, questo é stato impossibile fino ad ora per la mancanza di interfacce macchina di comunicazione con la banca. Alcuni soggetti, come <a href="https://www.yolt.com/?ref=andreacasarin.com" target="_blank" rel="nofollow noopener">Yolt</a> hanno aggirato il problema utilizzando l’accesso utente e “visualizzando” i dati presenti nella pagina, ma il risultato é spesso instabile e lento.</p>
<p>Tutto questo sarà un ricordo, con l’adeguamento delle banche alla nuova direttiva sarà possibile accedere ai dati bancari tramite interfacce dedicate.</p>
<h2>I cambiamenti</h2>
<p><a href="https://www2.deloitte.com/content/dam/Deloitte/it/Documents/technology/B_Payment%20Service%20Directive-new.pdf?ref=andreacasarin.com" target="_blank" rel="nofollow noopener">Deloitte</a> delinea chiaramente il perimetro della normativa nel suo ottimo documento di approccio al nuovo sistema.</p>
<p>Essa consiste in 6 cambiamenti fondamentali:</p>
<ol>
<li>La PSD 2 include nello scope le cosiddette «one leg out» transactions in tutte le divise. Per la precedente PSD I il perimetro era limitato alle transazioni in Euro.</li>
<li>Invece di effettuare i pagamenti direttamente dalla propria banca, PSD 2 consente a player terzi di effettuare un pagamento attraverso un Payments Initiation Service Provider (PISP), che trasmette le istruzioni alla banca detentrice del conto del payer.</li>
<li>PSD 2 definisce un nuovo set di regole per aprire l’accesso a terze parti alle informazioni relative ai conti necessarie per effettuare un pagamento, favorendo il ruolo degli account aggregators (AISP).</li>
<li>PSD 2 introduce nuovi requisiti di sicurezza riguardanti l’accesso ai conti, i pagamenti elettronici e che impongono severe linee guida per l’implementazione da parte degli AISP e dei PISP.</li>
<li>Viene posto un cap alle interchange fees pari allo 0.2% e 0.3% del valore della transazione rispettivamente per le carte di debito e per le carte di credito.</li>
<li>Ulteriori trasposizioni della SEPA in legge: in PSD 2 la regolamentazione riguardante il diritto di refund per gli SDD è armonizzata con le direttiva SEPA.</li>
</ol>
<p>I punti 2 e 3 sono senz’altro i più interessanti dal punto di vista dell’innovazione. Essi delineano una certa apertura alle nuove tecnologie da parte degli strumenti bancari che avverrà su due fronti:</p>
<ul>
<li>la lettura dei dati finanziari da parte di soggetti terzi;</li>
<li>la possibilità da parte di soggetti terzi di agire come “intermediari” per i pagamenti digitali.</li>
</ul>
<h2>I nuovi attori</h2>
<p>PSD2 delinea quindi la presenza di due nuovi attori, Third Party Players (TPP), nel mercato finanziario.</p>
<p>I TPP sono suddivisi in:</p>
<ul>
<li>Account Information Services Providers (AISP);</li>
<li>Payment Initiation Service Providers (PISP).</li>
</ul>
<p>Un soggetto AISP autorizzato può chiedere il permesso all’utente di connettersi al conto corrente bancario e utilizzarne le informazioni per fornire un servizio.</p>
<p>Le attività registrate come AISP sono autorizzate alla sola lettura delle informazioni bancarie. Possono perciò solo recuperare le informazioni ma non spostare denaro per conto del cliente.</p>
<p>Servizi e strumenti che generalmente possono essere offerti da un AISP sono:</p>
<ul>
<li>confronto di costi, gestione statistica di entrate e uscite;</li>
<li>velocizzazione dell’accesso a prodotti finanziari come prestiti, mutui o investimenti.</li>
</ul>
<p>Un soggetto PISP può chiedere il permesso all’utente per connettersi al conto corrente bancario ed effettuare pagamenti al suo posto.</p>
<p>Ci sono diversi motivi per i quali questo può essere utile, come:</p>
<ul>
<li>applicazioni che gestiscono automaticamente spese ricorrenti e risparmi;</li>
<li>applicazioni che garantiscono al cliente di non superare un budget per, ad esempio, evitare gli interessi sullo scoperto.</li>
</ul>
<h2>La sicurezza prima di tutto</h2>
<p>I TPP, dovranno seguire le stesse regole dei fornitori di servizi di pagamento tradizionali per poter operare. Si dovrà pertanto procedere con la registrazione e l’autorizzazione da parte delle autorità competenti, che vigileranno sui nuovi soggetti.</p>
<p>L’authority bancaria Europea (European Banking Authority &#8211; EBA), ha sviluppato un archivio elettronico in cui verranno registrate tutte le informazioni riguardanti i pagamenti e, nello specifico, sui PISP e gli AISP che avranno l&#8217;autorizzazione ad operare in UE nell&#8217;ambito della direttiva PSD2. In questo modo sarà il cliente potrà verificare se l’attività a cui sta affidando i sui dati è effettivamente autorizzata ad offrire il servizio.</p>
<p>La direttiva PSD2 é stata poi integrata con il regolamento delegato UE/2018/389 contenente le norme tecniche per l&#8217;autenticazione forte del cliente (Strong Customer Authentication &#8211; SCA) e gli standard aperti di comunicazione comuni e sicuri (Common and Secure Communication &#8211; CSC).</p>
<p>I requisiti di Strong Customer Authentication, ai quali le banche si stanno già adeguando, prevedono la combinazione di almeno due fattori di autenticazione tra i seguenti tre:</p>
<ul>
<li>&#8220;Knowledge factors&#8221; (conoscenza), qualcosa che solo l&#8217;utente conosce, ad esempio la password o il PIN;</li>
</ul>
<ul>
<li>&#8220;Possession factors&#8221; (possesso), qualcosa che solo l&#8217;utente possiede, ad esempio uno smartphone o una chiavetta/token;</li>
</ul>
<ul>
<li>&#8220;Inherent factors&#8221; (inerenza), qualcosa che é l’utente, generalmente i dati biometrici.</li>
</ul>
<p>I requisiti di Common and Secure Communication sono invece più generici e volti ad assicurare la compatibilità tra i vari istituti e la sicurezza della trasmissione. In particolare ci si riferisce alla normativa <a href="https://en.wikipedia.org/wiki/ISO_20022?ref=andreacasarin.com" target="_blank" rel="noopener">ISO 20022</a> e ci si assicura che ciascuna banca provveda a pubblicare la documentazione per un canale di comunicazione standard e sicuro.</p>
<h2>Le opportunità</h2>
<p>PSD2 finalmente introduce alcune innovazioni nel comparto finanziario Europeo che permetteranno lo sviluppo del settore FinTech anche da questa parte dell’oceano. Le banche che attualmente non concedono l’accesso alle informazioni memorizzate nei conti dei loro clienti, con la PSD2 dovranno permettere l’accesso ai terzi che dispongono di una licenza e che sono stati autorizzati dal cliente in modo esplicito.</p>
<p>Le possibilità sono molte, alcune in ordine sparso:</p>
<ul>
<li>aggregazione di dati a scopo statistico per la finanza personale;</li>
<li>riconciliazione automatica da parte di gestionali aziendali;</li>
<li>intermediazione dei pagamenti a scopo di risparmi o gestione del budget.</li>
</ul>
<p>Per chi volesse approfondire la tematica é disponibile la direttiva completa all&#8217;indirizzo: <a href="https://eur-lex.europa.eu/legal-content/IT/TXT/?uri=CELEX%3A32015L2366&ref=andreacasarin.com" target="_blank" rel="noopener">https://eur-lex.europa.eu/legal-content/IT/TXT/?uri=CELEX:32015L2366</a> e le linee guida dell’autorità bancaria Europea all’indirizzo: <a href="https://eba.europa.eu/regulation-and-policy/payment-services-and-electronic-money?ref=andreacasarin.com" target="_blank" rel="noopener">https://eba.europa.eu/regulation-and-policy/payment-services-and-electronic-money</a>.</p>
<p>Purtroppo, la normativa per diventare AISP o PISP è molto stringente, ben venga se serve a garantire la sicurezza dei clienti, d’altro canto limita molto le possibilità di innovare da parte delle imprese meno strutturate.</p>
<p>Fortunatamente stanno nascendo piattaforme come <a href="https://www.openwrks.com/?ref=andreacasarin.com" target="_blank" rel="nofollow noopener">OpenWRKS</a> che si ripropongono di agire come intermediari per lo sviluppo di soluzioni come quelle elencate sopra da parte di piccoli soggetti.</p>
<p>Credo questa sia una delle evoluzioni piú importanti del settore, almeno fino a quando le <a href="https://www.andreacasarin.com/2017/09/26/serverless-telegram-bot.html">criptovalute</a> non troveranno il loro spazio e la <a href="https://www.andreacasarin.com/2018/12/14/oblatum-blockchain-assets-management.html">blockchain non sarà utilizzata più estensivamente</a>.</p>
<div></div>
<div></div>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Page Speed: S3 recursive image optimization ]]></title>
        <description><![CDATA[ I have been recently involved in a website optimization project for SEO purposes. One of its major steps was the (lossless) image optimization to improve performances and, of course, to make sure to be Google Page Speed friendly.



Google Page Speed Insights


PageSpeed Insights is a tool from Google which ]]></description>
        <link>https://www.andreacasarin.com/2019/04/30/page-speed-s3-recursive-image-optimization.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d4</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Tue, 30 Apr 2019 18:14:10 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><p>I have been recently involved in a website optimization project for SEO purposes. One of its major steps was the (lossless) image optimization to improve performances and, of course, to make sure to be Google Page Speed friendly.</p>
<h2>Google Page Speed Insights</h2>
<p>PageSpeed Insights is a tool from Google which &#8220;analyzes the content of a web page, then generates suggestions to make that page faster&#8221;.</p>
<div ><img src="https://www.andreacasarin.com/content/images/2019/04/page-speed-1.jpg" alt="Page Speed S3 recursive image optimization" /><p>Photo by Jannik Selz on Unsplash</p></div>
<p>It&#8217;s the base index for every website performace optimization and might as well be the index that Google uses in its search engine to adjust a website position to reflect its performaces (<a href="https://developers.google.com/speed/?ref=andreacasarin.com">https://developers.google.com/speed/</a>).</p>
<p>Let&#8217;s see how much we can improve.</p>
<h2>Our own case</h2>
<p>The website is a simple WordPress customization backed by AWS S3 for assets storage.</p>
<p>AWS S3 has no computational power but transfers between S3 and EC2 are very cheap (<a href="https://aws.amazon.com/s3/pricing/?ref=andreacasarin.com">https://aws.amazon.com/s3/pricing/</a>) so I decided to leverage an AWS EC2 spot instance to download each image, run the optimization and upload it back to the storage.</p>
<p>The process is pretty straightforward, but still a bit annoying to be done manually.</p>
<h2>The automation</h2>
<p>I created a simple bash script to automate the whole operation. I think may be useful for someone else out there, so here it is:</p>
<p><script src="https://gist.github.com/andreacasarin/893f854f517e50592a9cf26e4413e0fb.js"></script></p>
<p>To use the script just download the Gist &#8211; make a backup -, make it executable &#8211; make a backup -, customize &#8220;credentials&#8221; and &#8220;configuration&#8221; sections &#8211; make a backup &#8211; and run it with:</p>
<p><code>./s3_recursive_image_optimization.sh</code></p>
<p>In case I forgot to mention: make sure to have a backup in case anything goes wrong.</p>
<h2>Results</h2>
<p>We are pretty happy with what we got, a straight &#8220;A&#8221;.</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/04/page-speed-s3-recursive-image-optimization-2.png" alt="" /></p>
<p>Also, since we automated to whole process, in case some images will not be optimized before being uploaded in the future we can still run the script again for the new ones.</p>
<p>If you&#8217;re wondering how your website is doing with Page Speed and other performance metrics, you can check it for free on GtMetrix: <a href="https://gtmetrix.com/?ref=andreacasarin.com">https://gtmetrix.com/</a>.</p>

<p>Update: Janis from Experte wrote me an email to let me know about their pagespeed tool. It's great. It let's you test the entire website with a single click. Go check it out at <a href="https://www.experte.com/pagespeed?ref=andreacasarin.com">https://www.experte.com/pagespeed</a>.</p>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Trello + Zapier + Google Sheets &#x3D; Time Tracking ]]></title>
        <description><![CDATA[ Trello, un tool di organizzazione con più di 10 milioni di utenti, è diventato uno strumento essenziale per la gestione dei miei progetti. Lo trovo un software fantastico, è molto flessibile e può essere adattato a molteplici esigenze. Inoltre è estremamente semplice da usare, tanto che spesso condivido le bacheche ]]></description>
        <link>https://www.andreacasarin.com/2019/03/28/trello-zapier-google-sheets-time-tracking.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d3</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Thu, 28 Mar 2019 19:23:05 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><p><a href="https://trello.com/andreacasarin/recommend?ref=andreacasarin.com">Trello</a>, un tool di organizzazione con più di 10 milioni di utenti, è diventato uno strumento essenziale per la gestione dei miei progetti. Lo trovo un software fantastico, è molto flessibile e può essere adattato a molteplici esigenze. Inoltre è estremamente semplice da usare, tanto che spesso condivido le <a href="https://www.andreacasarin.com/2017/05/04/e-tu-di-cosa-ti-occupi.html">bacheche di progetto con il cliente</a> che può così restare aggiornato sugli sviluppi e inserire nuovi task.</p>
<p>La scelta di essere minimalista ha portato il team di Trello a dei compromessi e, anche se molti sono superabili tramite &#8220;Power-Up&#8221;, senz’altro non è un tool adatto a tutti. Uno dei principali limiti è la gestione del tempo, in particolare non è possibile registrare il tempo impiegato per ciascun task.</p>
<h2>Automazioni con Zapier</h2>
<p>Molti <a href="https://help.trello.com/article/941-time-tracking?ref=andreacasarin.com">software di terze</a> parti si ripropongono di risolvere questo problema: alcuni nativamente, altri attraverso software di integrazione come Zapier.</p>
<p>Per chi non lo conoscesse, Zapier, come IFTTT, è un software online che permette di far comunicare diverse applicazioni allo scopo di automatizzare alcune attività; con la differenza, rispetto IFTTT, di poter creare workflow articolati con più passaggi.</p>
<p>Purtroppo nessuno strumento permette, attualmente, di avere un riassunto delle ore spese in un compito direttamente su Trello: è possibile avviare timer dal task ma poi è necessario consultare l&#8217;applicazione collegata per avere un resoconto.</p>
<h2>Collegamento di Trello con Zapier</h2>
<p>Le applicazioni integrabili con Zapier sono più di 1000 e tra queste figurano sia Trello che Google Sheets, quindi è possibile creare dei “trigger” basati su azioni eseguite dalla prima per eseguire delle operazioni sulla seconda.</p>
<p>L&#8217;obiettivo è che, aggiungendo un commento ad una scheda con la parola chiave: &#8220;Time: &#8221; seguita da un tempo in minuti in una nuova riga, venga creata una nuova linea nel nostro foglio di calcolo indicante chi ha commentato, cos&#8217;ha commentato, in che scheda e il tempo indicato. Vediamo dapprima il trigger e le operazioni di estrazione dei dati.</p>
<p>Accediamo quindi a Zapier, clicchiamo &#8220;Make a Zap!&#8221; per iniziare e aggiungiamo la prima applicazione o &#8220;trigger&#8221;, cioè Trello:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-1.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<p>Configuriamola per essere eseguita quando c&#8217;è un nuovo commento in una scheda, quindi procediamo con le opzioni di default avendo cura di scegliere la bacheca e l&#8217;utente per i quali eseguire l&#8217;automazione, se necessario. Aggiungiamo poi un filtro di tipo &#8220;Only continue if&#8230;&#8221; per filtrare solo i commenti che contengono un&#8217;indicazione riguardo il tempo, in questo modo:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-2.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<p>quindi, sempre nel medesimo filtro:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-3.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<p>aggiungiamo poi un&#8217;azione di tipo &#8220;Formatter by Zapier&#8221;, testuale:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-4.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<p>che configuriamo come di seguito per estrarre la stringa numerica dopo la nostra parola chiave:</p>
<h2><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-5.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></h2>
<p>aggiungiamo un&#8217;ulteriore azione di tipo &#8220;Formatter by Zapier&#8221;, sempre testuale:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-6.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<p>che configuriamo in questo modo per estrarre la stringa di testo che motiva il tempo speso:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-7.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<p>a questo punto:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-8.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<h2>Collegamento di Google Sheets con Zapier</h2>
<p>Abbiamo collegato Trello con Zapier ed estratto le informazioni di cui abbiamo bisogno, ora possiamo procedere con l&#8217;inserimento di questi dati nel nostro foglio di calcolo.</p>
<p>Creiamo un nuovo foglio di calcolo su Google Sheets, nell&#8217;esempio il foglio si chiama &#8220;Time Tracking&#8221; e le colonne sono, nell&#8217;ordine: &#8220;Who&#8221;, &#8220;Where&#8221;, &#8220;What&#8221;, &#8220;How much&#8221;; è possibile cambiare formato e nome del foglio, ma in tal caso deve essere adattata anche la configurazione di Zapier.</p>
<p>Procediamo quindi su Zapier creando una nuova azione di tipo Google Sheets:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-8.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<p>selezionato &#8220;Create a Spreadsheet Row&#8221; procediamo configurandola in questo modo per selezionare il documento e foglio corretti e quindi valorizzare le colonne:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-10.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<h2>Proviamo l&#8217;integrazione</h2>
<p>L&#8217;automazione è completa, procediamo quindi con un test.</p>
<p>Commentando una scheda su Trello (di una bacheca/utente abilitati) con un testo ed una riga vuota contenente la parola chiave più un valore numerico, l&#8217;automazione creerà una riga nel foglio di calcolo indicante i dati rilevanti. O almeno l&#8217;idea è questa.</p>
<p>Aggiungiamo un commento ad una scheda, rispettando il formato:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-11-1.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<p>e, in massimo 5 minuti dovremmo vedere il risultato in Google Sheets:</p>
<p><img src="https://www.andreacasarin.com/content/images/2019/03/trello-zapier-google_sheets-time_tracking-12.png" alt="Trello + Zapier + Google Sheets = Time Tracking - Step" /></p>
<h2>Approfondimenti</h2>
<p>Questo è solo un’esempio di ciò che è possibile creare con <a href="https://trello.com/andreacasarin/recommend?ref=andreacasarin.com">Trello</a>, le possibilità sono pressochè infinite: puoi approfondire l’argomento sul sito di <a href="https://zapier.com/app/home?ref=andreacasarin.com">Zapier</a> o, se ti serve un’integrazione più semplice, <a href="http://ifttt.com/?ref=andreacasarin.com">IFTTT</a>.</p>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Blockchain backed assets management: Oblatum. ]]></title>
        <description><![CDATA[ Dealing with assets property certificates is, most of the times, cumbersome.
In Italy when you buy a car you have to pay at least € 235 in property transfer. When you buy a house it starts from around € 5000. Even if you buy something not legally regulated but valuable (in terms ]]></description>
        <link>https://www.andreacasarin.com/2018/12/14/oblatum-blockchain-assets-management.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d2</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Fri, 14 Dec 2018 16:50:06 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><div>Dealing with assets property certificates is, most of the times, cumbersome.</div>
<div>In Italy when you buy a car you have to pay at least € 235 in property transfer. When you buy a house it starts from around € 5000. Even if you buy something not legally regulated but valuable (in terms of money) you need to keep your receipt and register your purchase for warranty purposes on a proprietary software given by the manufacturer. Then if you sell it, or more so if you are <span >the one who buys </span> second-hand, it’s hard, when possible, to get warranty transferred to the new owner. Been there, done that.</div>
<div>I think that’s not the way it has to be and with blockchain we can fix it.</div>
<h2>Asset management</h2>
<div>It is pretty easy to deal with assets management as there aren’t some many things you can do with those. Let&#8217;s take a bicycle, what comes to mind are four major operations:</div>
<ul>
<li>
<div>create an asset (you just bought it),</div>
</li>
<li>
<div>transfer an assets (you sold it to someone else),</div>
</li>
<li>
<div>delete an assets (it’s gone),</div>
</li>
<li>
<div>report as stolen or lost or broken for warranty purposes.</div>
</li>
</ul>
<div ><img src="https://www.andreacasarin.com/content/images/2018/11/oblatum-3.jpg" alt="Asset management on blockchain" /><p>Photo by Héctor Martínez.</p></div>
<div>Problem is with assets you have to get things right, and that’s why the most valuable of them are legally regulated. You should really avoid having someone go to some office and reclaim another one house as it was his own, right? Same should be for bikes. So those few actions need to be stored in a really secure manner.</div>
<div>Thing is, with blockchain, you can do that at a fraction of the cost we are currently paying, in a more organized, secure, paper-less way.</div>
<h2>Blockchain</h2>
<div>Blockchain is the technology that enables cryptocurrencies to work.</div>
<div></div>
<div>
<div ><img src="https://www.andreacasarin.com/content/images/2018/11/blockchain_ethereum_bitcoin.jpg" alt="Bitcoin, Ethereum: coins based on blockchain." /><p>Photo by Thought Catalog.</p></div>
</div>
<div></div>
<div>When you buy, let’s say, some Bitcoins or Ethereum you are actually making a transaction, as it would be for real money, of a fungible item which is the coin itself. What blockchain is really good at is keeping a history of those transactions.</div>
<div>The point is that, sure, you can use blockchain technology for coins, and that’s pretty interesting but you can use it for a bunch of other things too.</div>
<div>With blockchain we can make sure we have an immutable database that stores assets ownership, but you have to develop some kind of contract, let’s call it a “certificate&#8221; which identifies a single asset.</div>
<div>That’s because the difference between these and coins is that assets are non-fungible, meaning that my bicycle is not just “a bicycle” and it’s different from your one.</div>
<h2>Oblatum platform</h2>
<div>That’s the why and the how we built Oblatum.</div>
<div></div>
<div><img src="https://www.andreacasarin.com/content/images/2018/11/oblatum-2.png" alt="Oblatum, blockchain based assets management." /></div>
<div></div>
<div>Oblatum mission is to organize the world’s asset in a transparent and secure way that enables people prosperity and promote financial inclusion.</div>
<div>We have chosen to start from tracing bicycle. We leverage the Ethereum blockchain to create a digital certificate associated with the bicycle which enhances transparency and prevents the reselling of stolen bicycles.</div>
<div>Our solution can be easily applied to different assets and can be complemented with many different services attached to any registered asset. By relaying on the Ethereum blockchain we contribute to the Ethereum community, one of the most active community in the crypto-world, and we benefit from the open innovation.</div>
<h2>Try our demo</h2>
<div>We are going to release a demo of Oblatum today! Register to <a href="http://www.oblatum.io/?ref=andreacasarin.com">www.oblatum.io</a> to try a new way to manage your assets.</div>
<div>Feel free to open issues, for errors or problems you may find, on GitHub: <a href="https://github.com/andreacasarin/oblatum?ref=andreacasarin.com">https://github.com/andreacasarin/oblatum</a>. It&#8217;s open-source!</div>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Applicazioni web a pagina singola, un manifesto ]]></title>
        <description><![CDATA[ Le applicazioni web a pagina singola (SPA o interfacce web a pagina singola SPI) sono ormai diventate una realtà e hanno superato, grazie agli avanzamenti delle tecnologie web, quasi tutte le problematiche iniziali. Tuttavia non sono ancora così diffuse, soprattutto da questa parte dell’oceano. Ho avuto il piacere di ]]></description>
        <link>https://www.andreacasarin.com/2018/10/02/applicazioni-web-pagina-singola-manifesto.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d1</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Tue, 02 Oct 2018 20:15:04 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ 
<!--kg-card-begin: html-->
<p><em>Le applicazioni web a pagina singola (SPA o interfacce web a pagina singola SPI) sono ormai diventate una realtà e hanno superato, grazie agli avanzamenti delle tecnologie web, quasi tutte le problematiche iniziali. Tuttavia non sono ancora così diffuse, soprattutto da questa parte dell’oceano. Ho avuto il piacere di leggere un “vecchio” manifesto che rappresenta il movimento agli albori delle SPI e ho pensato di riproporlo, tradotto in italiano. Eccolo.</em></p>
<div ><img src="https://www.andreacasarin.com/content/images/2018/10/applicazioni-web-a-pagina-singola-0.png" alt="Manifesto applicazioni web a pagina singola" /><p>Photo by Danika Perkinson.</p></div>
<h2>Manifesto dell&#8217;interfaccia a pagina singola</h2>
<h3>Origini della tecnologia web</h3>
<p>Quando <a href="https://it.wikipedia.org/wiki/Tim_Berners-Lee?ref=andreacasarin.com">Tim Berners Lee</a> ha inventato il web, stava cercando un sistema per pubblicare documenti scientifici accessibili da remoto, attraenti dal punto di vista estetico, semplici da codificare e di facile utilizzo anche per un non tecnico.</p>
<p>In un documento scientifico, le citazioni esterne verso altri documenti sono indispensabili in modo che il lettore, se lo desidera, possa approfondire maggiormente il tema in questione.</p>
<p>Per queste ragioni il World Wide Web è stato concepito come un sistema basato su una pagina (documento) con collegamenti ipertestuali.</p>
<p>Inizialmente il web era un mondo fatto di pagine statiche e link, ma presto la generazione di pagine dinamiche e in generale l’uso del web a servizio di applicazioni web-based ha notevolmente complicato le cose.</p>
<h3>L’arrivo delle applicazioni web</h3>
<p>Per tanti anni sono stati messi in campo molti sforzi per adattare il paradigma web di pagine e link al campo dello sviluppo di applicazioni. In un’applicazione web infatti la visione di Berners circa documenti statici e link non esiste.</p>
<p>Sono stati fatti diversi tentativi di approccio legato allo sviluppo di applicazioni:</p>
<ul>
<li><strong>Modello 1</strong>: traduzione diretta dei modelli originali di pagine e link, dove le pagine sono generate dinamicamente;</li>
<li><strong>Modello 2 o MVC</strong>: qui i link non puntano direttamente a una pagina già decisa a priori, ma un controller decide quale sarà la pagina successiva in base alle operazioni eseguite nella fase di transizione di pagina;</li>
<li><strong>Modello MVC basato sui componenti (Modello 3?)</strong>: sofisticata versione del Modello 2 che simula come funziona un’applicazione desktop. Si basa su componenti ed eventi: qualsiasi azione dell’utente implica la completa ricostruzione e il ricaricamento della pagina, andando a modificare parzialmente alcune parti a seconda dell’azione eseguita. La pagina e la pagina di transizione sono gestite da componenti che cambiano in base all’evento, simulando il funzionamento dei componenti della programmazione GUI desktop.</li>
</ul>
<p>In periodi più recenti è stata introdotta la tecnica AJAX, che con l’aiuto del JavaScript consente parziali cambiamenti nelle pagine sino a ottenere nuovi dati dal server senza necessità di ricaricamento. Nonostante la tecnica di parziale cambio pagina sia di molto antecedente all’introduzione dell’XMLHttpRequest (base della programmazione AJAX) in Internet Explorer, questa è stata la sua spinta verso il successo.</p>
<p>Adesso milioni di siti web e di web application usano AJAX per fornire una migliore esperienza all’utente grazie a un’interfaccia più responsive che permette di evitare parzialmente il fastidioso ricaricamento delle pagine.</p>
<p>Nonostante l’uso massiccio di AJAX, ci sentiamo di affermare che il web segue un modello di sviluppo che potremmo chiamare “Modello 2 (MVC) arricchito con AJAX”. Quando si usa AJAX, parlare di “Modello 3” non ha così senso perché AJAX riduce di molto il bisogno della gestione di pagine basata sui componenti (non necessariamente presenti nel Modello 2), e per questo possiamo classificare l’attuale stato dell’arte dello sviluppo web come Modello 3,5. In questo modello la navigazione della pagina è parzialmente evitata nel caso di transizioni di minor stato eseguite da AJAX e JavaScript.</p>
<h2>Quali sono gli svantaggi della navigazione e dello sviluppo basati su pagine?</h2>
<p>Ogni sviluppatore web conosce le problematiche relative alla navigazione di pagine nelle applicazioni web. Oltre alla perdita di larghezza di banda e il tempo per il processo di ricostruzione di intere pagine, ulteriori difficoltà sono date da cache indesiderate, pulsanti di indietro/avanti, moduli disincronizzati a causa della funzione “auto-riempimento” di alcuni browser, e via dicendo. Non è così raro vedere applicazioni web che nascondono i menù e i bottoni del browser o usano frame o iframe (è il caso delle banche) per evitare criticità legate ai bottoni indietro/avanti.</p>
<p>Lo sviluppo basato su pagine web impone uno stile di programmazione strano, ripetitivo (con molte inclusioni) e inefficiente (sia per la larghezza di banda che per la potenza di calcolo), che non si verifica nello sviluppo desktop.</p>
<h2>Cosa impedisce l’uso intensivo di AJAX?</h2>
<p>Nel settore dello sviluppo web siamo abituati a distinguere due tipi di soluzioni: applicazioni web e siti web.</p>
<p>Nel primo caso l’applicazione AJAX è sempre più usata poiché non condivide alcuni requisiti imposti per i siti web. Nei siti web infatti l’uso intensivo di AJAX comporta dei problemi.</p>
<p>In siti web pubblici gli utenti sono abituati al concetto di pagina, e legati alla pagina ci sono una serie di requisiti e servizi che si trovano in ogni sito web, come:</p>
<ul>
<li>Bookmarking: ogni pagina web ha URL differenti, e queste URL possono essere salvate come segnalibro. Poiché AJAX può cambiare parzialmente la pagina l’URL è la stessa, e l’utente non può salvare come segnalibro una vista concreta della pagina stessa;</li>
<li>Search Engine Optimization (SEO): ogni sito web aspira a essere perfettamente indicizzato dai motori di ricerca come Google. I crawlers di oggi vedono il web come web 1.0 e ciò significa che il codice JavaScript è totalmente ignorato. Quindi qualsiasi modifica parziale eseguita tramite AJAX caricata dal server non viene eseguita e non viene indicizzata dai crawler;</li>
<li>Servizi basati sulle visualizzazioni di pagina: in servizi pubblicitari come Google Adsense e nelle visualizzazioni di pagina monitorate con Google Analytics, il numero di pagine caricate è estremamente importante. Ogni cambiamento anche parziale fatto con AJAX non viene contato come nuova visita;</li>
<li>Finestre pop-up.</li>
</ul>
<p>A causa di questi requisiti, l’uso massivo di AJAX non è consigliato nei siti web.</p>
<p>A ogni modo la differenza tra “sito web” e “applicazione web” sta diventando sempre più piccola perché ormai quasi ogni sito web è una sorta di web application&#8230;</p>
<h2>Dovremmo rinunciare all’uso intensivo delle applicazioni AJAX?</h2>
<p><strong>No.</strong></p>
<p>Ci sono soluzioni tecniche per ognuno dei requisiti elencati sopra.</p>
<h2>È possibile lo sviluppo di siti web a pagina singola (SPI)?</h2>
<p><strong>Sì!</strong></p>
<p>È il momento giusto per iniziare la transizione: ne guadagneranno sia gli sviluppatori che gli utenti. Abbiamo la tecnologia e i moderni browser sono sufficientemente qualificati per permetterci di ottenere questo obiettivo.</p>
<p>Per avere successo in questo “nuovo” metodo di sviluppo web dobbiamo soddisfare tutti i precedenti requisiti di ogni sito web.</p>
<h2>Arrivederci pagine, benvenuti stati</h2>
<p>In un’applicazione web senza JavaScript la sequenza di stato equivale alle pagine, e in un’applicazione SPI anche il più piccolo cambiamento implica un nuovo “stato” della pagina. Possiamo distinguere due categorie di stati:</p>
<ul>
<li>Stati fondamentali</li>
<li>Stati secondari</li>
</ul>
<p>La differenza tra uno stato e l’altro è molto importante, poiché gli stati fondamentali diventeranno pagine in caso di bisogno. La differenziazione tra fondamentale e secondario dipende dal sito web.</p>
<p>Per meglio capire i due stati possiamo analizzare un caso vero: la convalida di login.</p>
<p>In un’applicazione basata sul concetto classico di pagina, tipicamente il login è costruito usando due pagine, una per lo username e la password e l’altra che mostra le opzioni utente quando la convalida è corretta. La pagina di login verrà ricaricata mostrando alcuni messaggi di errore accanto al modulo di accesso quando l’utente compila il form con i dati sbagliati.</p>
<p>In un sito web a pagina singola, il login iniziale e la pagina di opzioni utente possono essere considerati gli stati fondamentali, e i messaggi di errore accanto al login gli stati secondari.</p>
<p>Facciamo un altro esempio, quello di un sito web basato su pagine da convertire in SPI. In questo caso gli stati fondamentali saranno le pagine e gli stati secondari quelle pagine con modifiche minori, non abbastanza importanti per il bookmarking o per essere analizzate dai crawler.</p>
<h2>Interfaccia di pagina singola e bookmarking</h2>
<p>Pagine differenti hanno URL differenti. Seguendo la direzione delle SPI come possiamo cambiare uno stato e allo stesso tempo l’URL senza ricaricare per far sì che gli utenti possano salvare il nuovo stato nei preferiti del browser?</p>
<p>C’è un trucchetto che si avvale della parte “àncora” dell’URL (“frammento hash”, “shebang” o “hashbang”). Si tratta dell’ultima parte che, se presente, segue il carattere #. L’àncora, anche conosciuta come collegamento interno alla pagina, è usata per scrollare la pagina in un esatto punto specifico con il contrassegno &lt;a name=&#8221;ref&#8221;&gt;&lt;/a&gt;. L’àncora, se modificata, non ricarica la pagina, quindi se il riferimento URL viene cambiato utilizzando il windows.location accanto allo stato della pagina (in questo caso il nuovo stato è “fondamentale”) con JavaScript e AJAX, non viene eseguito alcun ricaricamento. Poiché la URL e lo stato fondamentale sono stati modificati, l’utente può salvare come segnalibro la URL, che contiene le nuove informazioni di stato.</p>
<p>Quando l’utente vuole tornare indietro alla pagina salvata nei preferiti, lo stato di destinazione viene specificato nella parte “àncora” della URL e il server verrà sottoposto a richiesta. Purtroppo la parte di riferimento non viene inviata al server perché essa non ha nulla a che vedere con la posizione remota in HTTP, quindi avremo bisogno di un processo di post-caricamento.</p>
<p>Il server restituirà una pagina iniziale in cui lo stato di destinazione non è specificato, a ogni modo l’oggetto window.location contiene la URL originale inclusa l’àncora. Quando carichiamo la pagina di destinazione possiamo rilevare con JavaScript se windows.location contiene un’àncora e se questa àncora ha le informazioni richieste sullo stato di destinazione. Se è vero possiamo riscrivere la URL aggiungendo alcuni parametri normali per specificare lo stato di destinazione da caricare. Siccome la URL è effettivamente cambiata, viene eseguita una nuova richiesta al server; questa volta lo stato da caricare si trova in un parametro e il server restituisce una nuova pagina con lo stato richiesto.</p>
<p>Un’altra opzione, migliore delle àncore, arriverà con l’avvento dell’HTML5, l’HTML5 History API.</p>
<h2>Interfaccia di pagina singola e Search Engine Optimization (SEO)</h2>
<p>Il modo più semplice per far sì che il nostro sito web sia processato dai motori di ricerca è quello di offrire due differenti modi di navigazione: SPI per gli utenti e pagine per i web crawlers.</p>
<p>Il prossimo esempio mostra un link con questa idea:</p>
<p>&lt;a href=&#8221;URL page&#8221; onclick=&#8221;return false&#8221;&gt;…&lt;/a&gt;</p>
<p>Questo link non genererà alcuna azione in un browser con JavaScript abilitato perché la navigazione è disabilitata dal “return false” sull’attributo “onclick”, ma quando un bot indicizza questo link ignora l’attributo perché il codice JavaScript non viene eseguito ed elaborerà la specifica URL come pagina successiva da processare.</p>
<p>Nel campo delle applicazioni SPI, le URL usate per la navigazione di pagina/stato devono contenere uno stato di destinazione, lo stesso tipo di URL usato nel bookmarking SPI che utilizza le àncore per indicare lo stato di destinazione, oppure il target viene scritto direttamente come un normale parametro, quest’ultima opzione è preferibile poiché evita una richiesta al server, ovviamente è possibile utilizzare anche URL “parlanti”.</p>
<p>Attualmente Google esegue già la scansione delle URL AJAX, ovvero delle URL che contengono lo stato di destinazione nella parte di riferimento che segue il carattere #! come specificato in <a href="https://developers.google.com/search/docs/ajax-crawling/docs/getting-started?csw=1&ref=andreacasarin.com">Making AJAX Applications Crawlable</a>, in questo caso il sito web/l’applicazione web deve restituire la pagina prevista richiesta con il parametro _escaped_fragment_.</p>
<p>Allo stesso tempo il framework web SPI può aggiungere un codice specifico al gestore di onclick prima di restituire “false” o può associare un processo in ascolto al link utilizzato per la navigazione della pagina/stato, registrato con addEventListener o attachEvent a seconda del browser. Questo processo eseguirà alcune azioni per comandare il server, solitamente usando AJAX, per cambiare lo stato della pagina. Quando il link viene cliccato, questa modifica di stato non è una nuova pagina perché l’attributo onclick=&#8221;&#8230; return false&#8221; evita il comportamento predefinito.</p>
<p>La tecnica descritta è la più semplice e immediata se si utilizzano link visibili compatibili con i bot e con SPI. Puoi sempre separare entrambe le funzioni, per esempio usando link nascosti per gli utenti ma non per i bot insieme ad altri elementi cliccabili per modificare gli stati SPI, servendoti di JavaScript invisibile per i robot.</p>
<p>La caratteristica più importante di un framework con funzionalità SPI è la generazione di pagine come HTML con lo stato richiesto sul tempo di caricamento e allo stesso tempo la modifica di stato deve essere eseguita con JavaScript e l’aggiornamento parziale della pagina. Questi requisiti sono fondamentali per fornire SPI e simulazione di pagina.</p>
<h2>SPI e i bottoni indietro/avanti</h2>
<p>I bottoni indietro/avanti rappresentano una fonte di problemi per i tradizionali siti web basati sulle pagine e dovrebbero essere proibiti il prima possibile. Nonostante gli utenti siano abituati a evitare i bottoni Indietro e Avanti quando compilano e inviano un form con i propri dati (perché questo comporta il rischio di comprare due volte lo stesso biglietto aereo o il medesimo libro), l’uso dei pulsanti Indietro/Avanti è molto diffuso.</p>
<p>Apparentemente il paradigma SPI rompe il tradizionale modo di navigare un sito web, perché in teoria i bottoni Indietro/Avanti non hanno senso in SPI (non vi sono pagine) e i browser non forniscono un buon controllo di questi comandi.</p>
<p>Non è però del tutto vero. Il comportamento Indietro/Avanti può essere simulato al posto della navigazione di pagina (e della cronologia in generale) Indietro/Avanti e può essere usato per cambiare lo stato corrente al precedente/futuro stato. In questo caso un codice JavaScript può individuare quando la parte “àncora” di una URL cambia e richiede all’applicazione di cambiare lo stato. Poiché il browser non cambia la pagina, la tua applicazione è pienamente responsabile del comportamento Indietro/Avanti, evitando i tipici problemi di inaspettato utilizzo di Indietro/Avanti quando l’utente invia un modulo. Ora in SPI non esiste tale modulo e non c’è navigazione di pagine fuori controllo dell’applicazione/sito web.</p>
<h2>SPI e servizi basati sulle visualizzazioni di pagina</h2>
<p>Servizi pubblicitari e contatori di pagine viste si basano sul numero di pagine caricate. In entrambi i casi puoi usare elementi iframe nascosti che contengono una pagina web vuota con gli scripts richiesti per eseguire questi servizi.</p>
<p>Nel caso di servizi pubblicitari come Google Adsense, l’inserimento dinamico di iframe implica il caricamento di nuovi annunci, per questo motivo ogni cambiamento di stato può comportare un nuovo caricamento dell’iframe con l’annuncio. Google Adsense sembra essere in grado di rilevare quando lo script è eseguito dentro un iframe a tiene conto del contenuto della pagina contenitrice. Potrebbe essere una buona scelta inserire un parametro che identifichi lo stato fondamentale che sta caricando l’iframe.</p>
<p>Nel caso del contatore di visite, possiamo usarle per monitorare le visite utente agli stati fondamentali del nostro sito web SPI. In questo caso aggiungiamo un iframe nascosto contenente una pagina web vuota con lo script di monitoraggio. Con un semplice parametro possiamo indicare quale stato fondamentale è stato visitato. Il nostro iframe dovrebbe essere globale (sempre lo stesso nella pagina). Quando la pagina viene caricata per la prima volta, lo stato fondamentale che viene caricato (specificato nella URL) dovrebbe essere indicato all’iframe con un parametro. Dopo il caricamento della pagina, ogni cambiamento di stato fondamentale dovrebbe essere notificato all’iframe modificando la URL via JavaScript secondo il nuovo stato fondamentale: questa URL comporterà un nuovo caricamento dell’iframe (che indicherà una nuova visita).</p>
<h2>SPI e finestre pop-up</h2>
<p>Quando viene creata una nuova finestra, il modello SPI viene compromesso. Il fondamentalismo non va bene, non ci sono problemi se lo stato di questa nuova finestra non ha niente a che vedere con lo stato della finestra genitore, in questo caso le finestre pop-up vanno bene.</p>
<p>Il problema si presenta quando qualsiasi azione messa in pratica sulla finestra pop-up (modale o non modale) ha una qualsiasi influenza sulla finestra genitore, e allora la coordinazione tra le pagine diventa complicata. Per esempio non c’è alcuno standard web per creare finestre modali perché il concetto di pagina è per tradizione sempre stato un elemento indipendente e perciò il suo ciclo di vita diventa difficile da coordinare da un’altra pagina.</p>
<p>Fortunatamente il problema può essere risolto da qualche tempo in SPI: puoi simulare finestre modali o non modali dentro la stessa pagina web, senza che alcuna finestra reale venga creata. Nel caso di finestre non modali, ogni elemento HTML con posizione assoluta può essere una “finestra non modale” e puoi creare finestre modali usando posizioni assolute, controllando lo z-index e l’opacità di elementi “sovrapposti” della pagina (“livelli modali”). Queste soluzioni sono valide in un contesto SPI.</p>
<p>Con un piccolo sforzo, anche lo stato che mostra una finestra modale può essere uno stato fondamentale e perciò navigabile dai bots dei motori di ricerca.</p>
<h2>Un cambiamento culturale per gli sviluppatori web</h2>
<p>Molti web developers (e web frameworks) pensano al web come basato sulle pagine. La riduzione a una singola pagina implica un cambiamento di mentalità davvero importante su come noi creiamo siti web e applicazioni web. Tuttavia questo cambiamento non è poi così radicale grazie ad AJAX che oggi è molto usato e ha ridotto il numero di pagine tipico dei siti web. In sostanza ci ha portati vicino al “nuovo” modello di sviluppo SPI.</p>
<p>Nel nuovo web SPI il tag &lt;form&gt; scompare e in generale scompare il bisogno di sessione utilizzata come gestore di dati che seguono sequenze di pagine. Ora la protagonista è la pagina lato client, con alcune simmetrie nel server (la pagina nel server). Infatti, poiché ci liberiamo dalla coordinazione di pagine con le sessioni, evitiamo una serie di problemi come la cattiva pratica di alcuni utenti che aprono diverse finestre con la stessa pagina. Questa pratica solitamente compromette la sessione e l’applicazione in generale.</p>
<p>La programmazione SPI è basata su eventi allo stesso modo del desktop, perché nel desktop molte delle applicazioni vengono eseguite nella stessa finestra e quando esistono finestre “figlio” queste sono completamente gestite dalla finestra principale e realmente modali.</p>
<p>Seguendo il paradigma evolutivo dello sviluppo web, questo “nuovo” approccio potrebbe essere chiamato Model 4.</p>
<h2>Un cambiamento culturale per gli utenti?</h2>
<p>Non molto. Con i segnalibri e la simulazione Indietro/Avanti gli utenti finali non differenziano tra un sito web SPI e lo stesso sito a pagine. Inoltre il sito SPI sarà più responsivo e verrà rimosso il tipico lampeggio e lo scorrimento della pagina di navigazione.</p>
<h2>Fattibilità tecnica oggi</h2>
<p>Questo manifesto non è una dichiarazione di intenti, ma l’espressione del desiderio di promuovere un “nuovo” modo di costruire siti web già reali. Lo studio tecnico di cui sopra ha sempre avuto il web framework Java ItsNat come la tecnologia base dello sviluppo di siti web SPI. Nonostante ItsNat sia stato concepito sin dal primo giorno per questo tipo di applicazioni/siti, le tecniche precedenti possono essere applicate ad altri framework web, o questi framework possono evolversi per fornire servizi per siti web SPI con requisiti di simulazione di pagina.</p>
<p>Alcuni requisiti di questi siti web SPI per poter sostituire i tradizionali siti web a pagine, come la simulazione di pagina di stati fondamentali sul tempo di caricamento, sono possibili esclusivamente con framework web centrici perché il rendering HTML deve avvenire sul server in fase di caricamento. L’HTML renderizzato in fase di caricamento e lo stesso inserito dinamicamente con JavaScript sono le chiavi caratteristiche di un web framework pronto a costruire siti web SPI. I framework client centrici potrebbero avere un maggior ruolo per la realizzazione dei cosiddetti stati secondari.</p>
<h2>Il manifesto in lingua originale</h2>
<p>Note: questa traduzione potrebbe non essere aggiornata poiché questo manifesto è “vivo”.</p>
<p><a href="http://itsnat.sourceforge.net/php/spim/spi_manifesto_en.php?ref=andreacasarin.com">http://itsnat.sourceforge.net/php/spim/spi_manifesto_en.php</a></p>

<!--kg-card-end: html-->
 ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Unit testing, per un WordPress più sicuro e performante ]]></title>
        <description><![CDATA[ Con oltre il 30% delle preferenze, WordPress è una delle piattaforme più usate al mondo per la realizzazione di siti web. In questo articolo vediamo come sfruttare le potenzialità dello unit testing in WordPress per rendere il tuo sito molto più sicuro e performante.



WordPress, perché piace così tanto


Innanzitutto ]]></description>
        <link>https://www.andreacasarin.com/2018/07/09/unit-testing-wordpress.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1d0</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Mon, 09 Jul 2018 17:49:45 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><p>Con oltre il <b>30% delle preferenze</b>, WordPress è una delle <b>piattaforme più usate al mondo</b> per la <b>realizzazione di siti web</b>. In questo articolo vediamo come <b>sfruttare le potenzialità dello unit testing in WordPress</b> per rendere il tuo <b>sito</b> molto più <b>sicuro</b> e <b>performante</b>.</p>
<h2>WordPress, perché piace così tanto</h2>
<p>Innanzitutto cerchiamo di capire <b>come mai WordPress piace così tanto</b> e cosa gli ha consentito di imporsi nel mercato dei CMS per lo sviluppo dei siti internet. Ecco alcuni punti di forza:</p>
<ul>
<li><b>Bassi costi</b>: con poche decine di euro l’anno acquisti dominio + hosting e sei già pronto per l’installazione. Aggiungendo una piccola somma hai un template personalizzabile;</li>
<li><b>Flessibilità</b>: sebbene WordPress sia nato come piattaforma di blogging è evoluto in uno strumento flessibile che si presta alla realizzazione di siti con funzionalità molto diverse grazie agli innumerevoli plugin;</li>
<li><b>Semplicità di utilizzo</b>: WordPress è molto semplice da usare. In tantissimi lo scelgono per la sua rinomata facilità nell’aggiornamento dei contenuti, dal catalogo prodotti dell’e-commerce agli articoli per il blog;</li>
<li><b>Posizionamento SEO</b>: WordPress ha tutto ciò che serve per ragionare in ottica di posizionamento SEO già di base, inoltre alcuni plugin estendono questa possibilità fino a renderla eccellente (vedasi il famosissimo Yoast SEO);</li>
<li><b>Community di supporto</b>: in quanto software open source, WordPress ha un’attivissima community composta da sviluppatori e appassionati sempre pronti a dare supporto. Plugin, temi, aggiornamenti, quesiti tecnici: nei forum trovi risposta a ogni tua domanda.</li>
</ul>
<p><img src="https://www.andreacasarin.com/content/images/2018/07/wordpress-unit-testing-0.png" alt="Logo WordPress Unit Testing" /></p>
<p>Proprio la popolarità di WordPress è <b>croce e delizia per noi sviluppatori</b>. Perché se da un lato i clienti sono consapevoli della forza di questo strumento, dall’altro non tutti i developer lavorano con accuratezza e anzi, spesso tralasciano step importanti consegnando un prodotto che in quanto a sicurezza e performance lascia a desiderare. Per questo voglio evidenziare l’<b>importanza dello unit testing, anche in WordPress</b>.</p>
<h2>Unit testing: cos’è</h2>
<p>Lo <b>unit testing</b> è un’attività di test che prevede la verifica della correttezza delle singole unità di codice ed è un ottimo metodo per <b>testare il corretto funzionamento di un sito in WordPress</b>. L’idea di fondo è quella di creare un set di test in grado di capire se il codice, dati determinati input, risponda nel modo giusto. Per fare questo si utilizza un tool, <a href="https://phpunit.de/?ref=andreacasarin.com" rel="nofollow">PHPUnit</a>, che consente al developer di verificare che lato codice il comportamento sia corretto.</p>
<p>Come si evince da queste breve descrizione, sottoporre WordPress a unit testing è estremamente <strong>più affidabile e approfondito</strong><strong> dei normali test manuali </strong>che vengono di solito effettuati. Questi nella maggior parte dei casi consistono in un’analisi limitata dell’implementazione del frontend del sito, senza però andare a indagare oltre. Inoltre, non essendo automatizzati, sono soggetti ad errori umani e difficilmente ripetibili.</p>
<h2>Unit testing in WordPress: un breve tutorial</h2>
<p>Vediamo ora passaggio per passaggio <b>come installare e usare PHPUnit Testing in WordPress</b>.</p>
<h3>Installare PHPUnit Testing</h3>
<p>La prima cosa da fare è <a href="https://phpunit.de/manual/6.5/en/installation.html?ref=andreacasarin.com" rel="nofollow"><b>installare PHPUnit Testing</b></a>, con il seguente comando:</p>
<pre><code>composer global require phpunit/phpunit</code></pre>
<h3>Installare WP-CLI</h3>
<p>WP-CLI è l’insieme degli eseguibili da linea di comando per integrare e gestire le installazioni WordPress. Questo sistema fornisce un’interfaccia di linea di comando per azioni che di solito si effettuano sia dentro che fuori l’area amministrativa. Per saperne di più visita la <a href="https://wp-cli.org/it/?ref=andreacasarin.com" rel="nofollow">pagina ufficiale di WP-CLI</a>.</p>
<p>Quello che a noi interessa è che <b>WP-CLI ha semplificato di molto l’installazione di PHPUnit</b>: per alcune operazioni è infatti molto più <b>comodo e veloce</b> usare linee di comando piuttosto che agire via browser. Esiste una <a href="https://make.wordpress.org/cli/handbook/plugin-unit-tests/?ref=andreacasarin.com" rel="nofollow">guida molto dettagliata</a> (in lingua inglese) che spiega come far girare unit tests; di seguito riassumo in italiano i principali step.</p>
<p>Per <b>installare WP-CLI</b>, scrivere il seguente comando:</p>
<pre><code class="language-clike">curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar 
chmod +x wp-cli.phar 
sudo mv wp-cli.phar /usr/local/bin/wp</code></pre>
<p>Ora che hai installato PHPUnit e WP-CLI, useremo quest’ultimo per impostare lo unit test per il plugin.</p>
<h3>Set up dello unit test per plugin</h3>
<p>Accedi alla root della tua installazione di WordPress e scrivi questo comando per generare i file di test del plugin:</p>
<pre><code>wp scaffold plugin-tests wp-my-test</code></pre>
<p>Dopo aver generato i file di test, ecco ora la schermata con la struttura del plugin:</p>
<pre><code>|-bin/
 |----install-wp-tests.sh
 |-tests/
 |----bootstrap.php
 |----test-sample.php
 |-.travis.yml
 |-phpcs.xml.dist
 |-phpunit.xml.dist
 |-wp-my-test.php</code></pre>
<p>Scegli la directory del plugin e lancia l’installazione con questo script, sostituendo &#8220;username&#8221;, &#8220;password&#8221; e &#8220;host&#8221; con i dati relativi alla tua installazione:</p>
<pre><code>bin/install-wp-tests.sh wordpress_test username 'password' host latest</code></pre>
<p>Un consiglio: per fare queste operazioni usa un <b>database di test</b>.</p>
<h3>Esegui gli unit test e verifica il risultato</h3>
<p>Adesso puoi eseguire PHPUnit per lanciare il test di esempio e verificare il risultato:</p>
<pre><code>phpunit</code></pre>
<p>Se è tutto corretto dovresti ottenere:</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/07/wordpress-unit-testing-1.png" alt="Wordpress Unit Testing Sample" /></p>
<p>Puoi quindi procedere con la scrittura dei tuoi test, prendi spunto da &#8220;test-sample.php&#8221; è il file che contiene il test di esempio appena eseguito.</p>
<h2>I benefici dello unit testing in WordPress</h2>
<p>Molti sviluppatori non usano testare in questo modo i loro progetti semplicemente perché non sanno come fare, o peggio ancora perché considerano la fase di test una perdita di tempo. Senz&#8217;altro lo <b>unit testing in WordPress </b>comporta un investimento di tempo, ma porta con se <b>notevoli vantaggi</b>:</p>
<ul>
<li>Hai la sicurezza che pochi o addirittura nessun bug colpiranno il tuo software;</li>
<li>Risparmi tempo e denaro nelle fasi più delicate, ovvero supporto e aggiornamento;</li>
<li>Eviti problemi con i clienti ed eventuali rivalse sul tuo operato.</li>
</ul>
<p>Ecco un breve video riassunto di questo articolo (in inglese):</p>
<p><iframe src="https://www.youtube-nocookie.com/embed/noKQqDsqvOg?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p>Per maggiori informazioni vedi il <a href="https://make.wordpress.org/core/handbook/testing/automated-testing/writing-phpunit-tests/?ref=andreacasarin.com#advanced-topics" rel="nofollow">manuale di WordPress</a> e la <a href="https://phpunit.de/manual/6.5/en/fixtures.html?ref=andreacasarin.com" rel="nofollow">documentazione per PHPUnit</a>.</p>
<p>Se ti serve supporto tecnico per scrivere codice e test <a href="https://www.andreacasarin.com/contacts">contattami</a>!</p>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ IoT con Arduino: una serratura a tag NFC ]]></title>
        <description><![CDATA[ Internet of Things, o brevemente IoT, è un concetto molto utilizzato recentemente, ma il suo significato letterale è piuttosto ampio: si tratta di collegare oggetti, generalmente di uso comune, ad Internet per ampliarne lo spettro di utilizzo. Ma… in pratica?


Ho avuto occasione di partecipare ad un interessante corso pratico, ]]></description>
        <link>https://www.andreacasarin.com/2018/02/28/arduino-nfc-iot-fabkey.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1ca</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Wed, 28 Feb 2018 18:29:03 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><p>Internet of Things, o brevemente <strong>IoT</strong>, è un concetto molto utilizzato recentemente, ma il suo significato letterale è piuttosto ampio: si tratta di collegare oggetti, generalmente di uso comune, ad Internet per ampliarne lo spettro di utilizzo. <strong>Ma… in pratica?</strong></p>
<p>Ho avuto occasione di partecipare ad un interessante corso pratico, organizzato da <a href="https://www.labnetwork.it/?ref=andreacasarin.com" target="blank" rel="nofollow">Lab Network</a>, riguardo Arduino e IoT che mi ha permesso di provare con mano queste tecnologie applicandole ad una problematica comune, ovvero il <strong>controllo degli accessi</strong>.</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/arduino-nfc-iot-fabkey-00.jpg" alt="IoT con Arduino " /></p>
<p>Immaginiamo di dover garantire l’accesso ad una particolare area, stanza, sala per un tempo limitato ad un gruppo di persone: suona familiare? Bene.</p>
<p>Con questa tecnologia possiamo fornire un badge agli utilizzatori e controllare da un semplice pannello del browser se e quando ciascuno di essi può entrare. Il sistema, collegandosi ad Internet, verifica se il proprietario è autorizzato e, solo in caso positivo, invia il comando di apertura alla serratura.</p>
<p>Il sistema è composto da due elementi fondamentali: il dispositivo “IoT” (Arduino + Ethernet, lettore NFC e elettro-serratura) e il servizio remoto per la gestione degli accessi (API).</p>
<h2>API gestione accessi</h2>
<p>Per prima cosa predisponiamo il sistema di gestione degli accessi.</p>
<p>Non scendiamo nel dettaglio del software per il controllo degli accessi in quanto fuori dallo scopo primario di questo articolo; basti pensare che può essere sostanzialmente qualsiasi sistema, esistente o da creato ex-novo, che sia in grado di comunicare tramite Internet.</p>
<p>Ai fini del prototipo possiamo simulare questo comportamento con poche righe di codice che, leggendo un parametro GET della richiesta, lo confrontano con un codice definito come valido. Se i due codici corrisponodono la richiesta sarà approvata, in caso contrario, respinta.</p>
<p>Non ci resta che caricare il servizio su un server raggiungibile tramite Internet e siamo pronti a procedere.</p>
<h2>Dispositivo IoT</h2>
<p>Possiamo quindi passare alla creazione del nostro dispositivo, per farlo abbiamo bisogno di alcuni componenti:</p>
<ul>
<li>Arduino UNO + shield Ethernet;</li>
<li>Adafruit PN532 NFC/RFID reader;</li>
<li>Relè SRD-05VDC-SL-C;</li>
<li>Tag NFC;</li>
<li>Cavi, resistenze e led.</li>
</ul>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/arduino-nfc-iot-fabkey-01.jpg" alt="IoT con Arduino Materiale" /></p>
<p>Effettuiamo il cablaggio semplicemente rispettando i datasheet; perchè il codice proposto funzioni dobbiamo però stare ad alcune scelte riguardo i pin di output di Arduino:</p>
<pre><code>pin A1 =&gt; relé
pin A2 =&gt; led rosso
pin A3 =&gt; led verde
pin A4 =&gt; led giallo
</code></pre>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/arduino-nfc-iot-fabkey-02.jpg" alt="IoT con Arduino Progetto Completo" /></p>
<p>A questo punto possiamo scrivere il programma di gestione del dispositivo, per farlo utilizziamo l’IDE proposto da Arduino stessa, scriviamo il codice e connettiamo il dispositivo tramite USB per caricarlo dopo averlo compilato.</p>
<p>Per evitare di dilungarci vi invito a scaricare il codice completo dal <a href="https://www.labnetwork.it/fabkey-la-serratura-online?ref=andreacasarin.com" rel="nofollow">sito web del corso</a>, riporterò qui solo i passaggi logici più importanti.</p>
<p>In una prima fase dobbiamo:</p>
<ul>
<li>importare le librerie,</li>
<li>configurare lo shield ethernet,</li>
<li>configurare lo shield nfc.</li>
</ul>
<p>Quindi avviamo il setup e inizializziamo tutti i servizi.</p>
<p>A questo punto possiamo iniziare il ciclo vero e proprio, che sarà composto da tre sezioni fondamentali:</p>
<ul>
<li>lettura dei dati dallo shield ethernet,</li>
<li>controllo del valore di risposta ed eventuale apertura della serratura,</li>
<li>invio del codice NFC qualora ve ne fosse uno.</li>
</ul>
<h2>Conclusioni</h2>
<p>La semplice soluzione proposta dal corso è un’ottima base per permettere di capire come le tecnologie IoT possano avere un’applicazione pratica e funzionale anche se, chiaramente, non è sufficiente per una situazione reale (presenta diverse problematiche di sicurezza in primo luogo).</p>
<p>Ritengo il progetto interessante per chi vuole fondere le competenze a livello software con l’elettronica e realizzare un prodotto reale. Inoltre, dopo i dovuti miglioramenti a livello software, sarebbe facile spaziare dalla gestione di una serratura ad altri campi come, ad esempio, l’agricoltura (illuminazione, irrigazione), l’intrattenimento (musica, video), o la domotica.</p>
<p>Qui un breve video del prototipo funzionante:</p>
<p><iframe src="https://www.youtube.com/embed/_8NrWG8XblE?rel=0" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>Se ti serve consulenza per il tuo progetto IoT <a href="https://www.andreacasarin.com/contacts">contattami.</a></p>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ La mia avventura per hack.developers ]]></title>
        <description><![CDATA[ Poco più di un mese fa venni a sapere che il Team per la Trasformazione Digitale avrebbe promosso il più grande hackathon mai realizzato in Italia.


In sostanza un code sprint suddiviso in due differenti tempistiche:


 * 2 giorni di sviluppo in una delle 26 sedi (in altrettante città italiane) predisposte; ]]></description>
        <link>https://www.andreacasarin.com/2017/11/03/hackdev17-ansible-docker.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1c9</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Fri, 03 Nov 2017 18:27:24 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><p>Poco più di un mese fa venni a sapere che il Team per la Trasformazione Digitale avrebbe promosso il più grande hackathon mai realizzato in Italia.</p>
<p>In sostanza un <a href="https://hack.developers.italia.it/?ref=andreacasarin.com">code sprint</a> suddiviso in due differenti tempistiche:</p>
<ul>
<li>2 giorni di sviluppo in una delle 26 sedi (in altrettante città italiane) predisposte;</li>
<li>1 mese opzionale per completare i progetti più complessi.</li>
</ul>
<p>La partecipazione per i soli 2 giorni iniziali prevede la partecipazione alla premiazione della “fast rabbit”, decidendo di procedere anche per il mese successivo invece si accede alla cosiddetta “wise turtle”; l’obiettivo è comune: lo sviluppo di codice open source per i progetti centrali per la PA.</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/hackdev17-ansible-docker-00.jpg" alt="" /></p>
<p>Non avendo mai partecipato ad un evento di questo tipo, tanto meno per un progetto così ambizioso, fui molto incuriosito. Quindi decisi di iscrivermi, almeno per i due giorni di sviluppo in sede.</p>
<h2>Facciamo un passo indietro</h2>
<p>Un <a href="https://it.wikipedia.org/wiki/Hackathon?ref=andreacasarin.com">hackathon</a> è un evento al quale partecipano varie figure del campo informatico. Spesso lo scopo è di completare una o più sfide in un tempo limite prestabilito per concorrere alla vittoria di un premio finale.</p>
<p>Il promotore, <a href="https://teamdigitale.governo.it/?ref=andreacasarin.com">Team per la Trasformazione Digitale</a>, è tecnicamente una struttura commissariale istituita dal governo per avviare la costruzione del cosiddetto “Sistema operativo del Paese”. Il team è composto da diverse figure tecniche di altissimo livello ed esperienza internazionale.</p>
<p>Il focus di questo evento era il contributo alla risoluzione di problematiche legate ai principali progetti del Team, ovvero: Carta d’Identità Elettronica, La fattura elettronica, Anagrafe Nazionale della Popolazione Residente, Il Design System della Pubblica Amministrazione Italiana, I dati aperti della pubblica amministrazione, Data &amp; Analytics Framework, Nodo di pagamento verso la Pubblica Amministrazione, Sistema Pubblico di Identità Digitale.</p>
<h2>La challenge</h2>
<p>La prima mattina, dopo una breve presentazione del progetto e degli sponsor, viene allestito un workspace Slack condiviso e inizia la descrizione delle challenge proposte.</p>
<p>Sin da subito è chiara la loro complessità, la maggior parte di esse richiedono potenzialmente un team di 3-5 persone per una tempistica vicina al mese. Non ho la possibilità di partecipare ad una sfida così lunga e non ho velleità di concorrere per il premio finale, decido quindi di selezionare una piccola challenge che posso potenzialmente completare, da solo, nell’arco di due giorni.</p>
<p>Da ciò che si evince in loco e sulla chat condivisa, la maggior parte dei partecipanti sono sviluppatori; al contrario sembra che i sistemisti o, per meglio dire, i DevOps, non siano così numerosi: sicuramente posso essere più utile in questo frangente.</p>
<p>Dopo aver spulciato il <a href="https://github.com/italia?ref=andreacasarin.com">GitHub dedicato</a> individuo una issue interessante: la creazione di un sistema di deploy in Ansible per un sistema basato su Docker che pubblica un’integrazione tra <a href="https://github.com/freedomofpress/securethenews?ref=andreacasarin.com">Secure the News</a> e <a href="https://github.com/18F/domain-scan?ref=andreacasarin.com">domain-scan</a>.</p>
<p>L’obiettivo è quello di pubblicare una dashboard che visualizza la diffusione delle pratiche di sicurezza nei portali dello Stato:</p>
<ul>
<li>domain-scan è un sistema che unisce diversi strumenti di scansione per il web; utilizzandolo si ottiene, per ciascun dominio, la configurazione HTTPS oltre che altri dati opzionali;</li>
<li>Secure the News e il sistema open-source utilizzato per il portale <a href="https://securethe.news/?ref=andreacasarin.com">https://securethe.news</a>, si tratta di un applicativo web scritto in Python su Django per la visualizzazione grafica dello stato di sicurezza (inteso come implementazione di HTTPS) di un insieme di domini.</li>
</ul>
<h2>Le difficoltà</h2>
<p>Inizialmente la sfida mi era sembrata piuttosto semplice o quanto meno sufficientemente veloce per le mie tempistiche; dopo aver approfondito la questione leggendo il codice dei due tool noto però che il problema è di una complessità decisamente superiore.</p>
<p>I tool sono open-source: il primo, domain-scan, è relativamente semplice e generico; il secondo, Secure the News è stato rilasciato in seguito ad una implementazione specifica, perciò con un’astrazione limitata e relativamente poca documentazione (a meno che non si conosca Django e la mia esperienza con questo framework è pressoché nulla).</p>
<p>Entrambi gli applicativi offrono un esempio di deploy basato su Docker all’interno del repository, purtroppo però sono pensati solo per un ambiente di sviluppo, perciò piuttosto limitati. Decido comunque di utilizzarli come base per velocizzare i tempi e completare la sfida entro i due giorni prestabiliti.</p>
<p>Entro la sera del sabato domain-scan è operativo, quantomeno in locale; decido di chiudere e di dedicare la domenica a Secure the News. Il giorno successivo procedo in questo senso e per ora di pranzo ho un sistema funzionante, ma ci sono un paio di problemi:</p>
<ul>
<li>In primis gli ovvi problemi di prestazioni e sicurezza dell’utilizzo di un sistema pensato per lo sviluppo direttamente in produzione;</li>
<li>In secondo luogo il formato di output di domain-scan non è direttamente compatibile con Secure the News.</li>
</ul>
<p>Sono consapevole del primo punto, ma il secondo mi preoccupa: è necessario scrivere un parser per convertire l’output in un formato compatibile.</p>
<p>Mangio qualcosa e mi attivo subito: l’idea è di creare uno script in Python che si occupa di avviare domain-scan, convertire i risultati e importarli in Secure the News. Riesco a ad arrivare ad una bozza per le 16, ora di scadenza, ma nulla che possa neanche lontanamente andare in produzione.</p>
<p>La sfida però mi ha appassionato, decido quindi di ritagliarmi qualche giorno prima della fine del mese opzionale per rivedere il sistema e completarlo in ottica di una pubblicazione effettiva.</p>
<h2>La consegna</h2>
<p>Qualche giorno fa ho finalmente avuto un po’ di tempo da dedicarci: ho deciso di prendere come base quanto scritto in precedenza e di ridefinire il tutto in ottica di produzione, oltre, chiaramente, a completare lo script di importazione. Ecco il risultato finale.</p>
<p>Ho sviluppato 2 ruoli Ansible il più possibile generici per il deploy su Docker di: domain-scan e Secure the News; ho quindi creato un ulteriore ruolo che si occupasse di gestire l’integrazione dei due eseguendo (direttamente o tramite cron) lo script di import.</p>
<p>Quindi ho unito il tutto con un playbook con default sensibili e funzionali ad un deploy in locale, ma facilmente configurabile per un deploy remoto impostando le variabili nel playbook base e gli host nel file relativo. Ulteriori variabili opzionali sono presenti come default dei vari ruoli.</p>
<p>L’architettura creata da Ansibile, è così composta:</p>
<ul>
<li>un’istanza Docker, per domain-scan, avviata all’occorrenza;</li>
<li>un cluster per Secure the News composto da multipli container Docker:
<ul>
<li>postgres,</li>
<li>node+python,</li>
<li>gunicorn,</li>
<li>nginx;</li>
</ul>
</li>
<li>uno script in python, eseguito tramite cron, che avvia il container domain-scan, converte e importa i dati in Secure the News.</li>
</ul>
<p>Il risultato mi soddisfa: Ansible orchestra i container Docker che ora prevede, oltre all’istanza di domain-scan, anche tutti i container separati per lo stack richiesto da Secure the News. Il sistema di importazione è funzionante e testato per il test usato da Secure the News (phtts).</p>
<p>Consegno quindi il progetto tramite <a href="https://github.com/italia/security-recipes/pull/3?ref=andreacasarin.com">pull request</a>, come richiesto.</p>
<h2>Conclusioni</h2>
<p>Questa esperienza mi ha piacevolmente sorpreso: a partire dalle due giornate in sede, in cui ho avuto l’occasione di conoscere persone appassionate e disponibili, fino alla conclusione di questi giorni, in cui ho avuto modo di apprezzare come il Team per la Trasformazione Digitale stia portando una ventata di nuovo in un frangente in cui l’Italia ha sempre peccato.</p>
<p>Chiaramente un evento come questo non può bastare a rivoluzionare (tecnologicamente) un paese, ma ha senz’altro dato una spinta ulteriore al progetto. Credo siamo nella direzione corretta: finalmente si vedono utilizzati software open-source su scala, metodologie competitive e strumenti moderni anche da parte di un organo statale.</p>
<p><a href="https://github.com/italia?ref=andreacasarin.com">All’indirizzo GitHub del progetto</a> puoi scoprire le altre problematiche aperte e, se ti va, aiutare a risolverle.</p>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Bot Telegram per criptovalute con architettura Serverless ]]></title>
        <description><![CDATA[ Recentemente mi sono trovato a discutere di criptovalute con un caro amico, in particolare argomentavamo sul nostro gruppo Telegram di quanto il loro valore fosse fluttuante. In questo gruppo ci sono diversi amici comuni, più alcuni bot Telegram.


Allora mi sono chiesto: perché non realizzare un bot che fornisce il ]]></description>
        <link>https://www.andreacasarin.com/2017/09/26/serverless-telegram-bot.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1c8</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Tue, 26 Sep 2017 19:25:43 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><p>Recentemente mi sono trovato a discutere di criptovalute con un caro amico, in particolare argomentavamo sul nostro gruppo Telegram di quanto il loro valore fosse fluttuante. In questo gruppo ci sono diversi amici comuni, più alcuni bot Telegram.</p>
<p>Allora mi sono chiesto: <strong>perché non realizzare un bot che fornisce il valore delle valute virtuali? Detto fatto e, per rendere il tutto più interessante, useremo un’architettura serverless.</strong></p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-00.png" alt="Bot Telegram per Criptovalute" /></p>
<p>L’idea di base è semplice: alla ricezione di un messaggio predefinito il bot recupererà il valore della valuta, quindi risponderà all’utente o al gruppo tramite Telegram.</p>
<p>Il tutto potrà essere eventualmente espandibile in futuro ad altre app di messaggistica o ad altre funzionalità: un’idea interessante sarebbe la possibilità di fare trading direttamente dalla chat… ma questa è un’altra storia.</p>
<p>Siamo pronti a cominciare, useremo Python come linguaggio di programmazione per il nostro bot e Amazon Web Services per l’architettura serverless.</p>
<h2>Recupero valore criptovaluta</h2>
<p>Innanzi tutto dobbiamo scrivere il codice che si occuperà di recuperare il valore di una criptovaluta, idealmente tramite API REST.</p>
<p>Con una veloce ricerca recuperiamo delle API pubbliche adatte a questo compito, abbiamo due alternative:</p>
<ul>
<li><a href="https://coinmarketcap.com/api/?ref=andreacasarin.com" target="blank" rel="nofollow">https://coinmarketcap.com/api/</a></li>
<li><a href="https://min-api.cryptocompare.com/?ref=andreacasarin.com" target="blank" rel="nofollow">https://min-api.cryptocompare.com</a></li>
</ul>
<p>La prima è interrogabile in questo modo:</p>
<pre><code>https://api.coinmarketcap.com/v1/ticker/bitcoin/
</code></pre>
<p>e restituisce:</p>
<pre><code>[
    {
        "id": "bitcoin",
        "name": "Bitcoin",
        "symbol": "BTC",
        "rank": "1",
        "price_usd": "4145.22",
        "price_btc": "1.0",
        "24h_volume_usd": "2584150000.0",
        "market_cap_usd": "68467684788.0",
        "available_supply": "16517262.0",
        "total_supply": "16517262.0",
        "percent_change_1h": "-0.19",
        "percent_change_24h": "2.23",
        "percent_change_7d": "2.22",
        "last_updated": "1503224367"
    }
]
</code></pre>
<p>La seconda invece:</p>
<pre><code>https://min-api.cryptocompare.com/data/price?fsym=BTC&amp;tsyms=USD,EUR
</code></pre>
<p>e restituisce:</p>
<pre><code>{"USD":4136.85,"EUR":3542.48}
</code></pre>
<p>La seconda è più comoda per il nostro scopo, con il plus di avere il valore sia in Dollari che in Euro… perfetta.</p>
<p>A questo punto non ci resta che scrivere il codice che, fornita la valuta di partenza e quella di destinazione, ci fornisce il valore di cambio. In Python possiamo scrivere una classe di questo tipo:</p>
<pre><code>import urllib
import json

class Change:
    """Change.class."""

    PRICE_API = "https://min-api.cryptocompare.com/data/price"

    f = 'BTC'
    t = 'USD'

    def __init__(self, f='', t=''):
        """Change.__init__."""
        if(f != ''):
            self.f = f.upper()
        if(t != ''):
            self.t = t.upper()

    def get_value(self):
        """Change.get_value."""
        query = "?fsym={}&amp;tsyms={}".format(self.f, self.t)
        value = json.loads(get_url(self.PRICE_API + query))
        try:
            return "1 {} is worth {} {}".format(self.f, value[self.t], self.t)
        except KeyError:
            return value['Message']
</code></pre>
<p>Il costrutture si occupa di inizializzare le variabili d’istanza con degli eventuali default per valuta di partenza e valuta di destinazione (rispettivamente BTC e EUR).</p>
<p>Il metodo “get_value” invia una richiesta all’api descritta sopra e ritorna una breve stringa che indica il cambio (se l’api ritorna il valore correttamente).</p>
<h2>Interazione con Telegram</h2>
<p>Il secondo passaggio è l’interazione con Telegram. A questo scopo sono disponibili diverse librerie, probabilmente la più famosa per Python è: <a href="https://github.com/python-telegram-bot/python-telegram-bot?ref=andreacasarin.com" target="blank" rel="nofollow">https://github.com/python-telegram-bot/python-telegram-bot</a>.</p>
<p>Vista la semplicità del nostro progetto e visto lo scopo prettamente didattico ci conviene però sviluppare il tutto da zero: saranno solo poche linee di codice.</p>
<p>Innanzi tutto dobbiamo ricevere i messaggi da Telegram per poterli processare e quindi rispondere, ci sono essenzialmente due strade:</p>
<ul>
<li>ascoltare gli aggiornamenti pubblicati da Telegram (es. https://api.telegram.org/botTOKEN/getUpdates);</li>
<li>sfruttare la possibilità di creare un Webhook che verrà invocato da Telegram ad ogni aggiornamento (<a href="https://core.telegram.org/bots/webhooks?ref=andreacasarin.com" target="blank" rel="nofollow">https://core.telegram.org/bots/webhooks</a>).</li>
</ul>
<p>Volendo creare un bot Telegram serverless utilizziamo il secondo metodo, in caso contrario dovremmo invocare il bot manualmente; per ora però non creiamo il Webhook, ci basta sapere il formato in cui riceveremo l’aggiornamento.</p>
<p>La notifica di un nuovo evento arriverà in JSON via POST, il formato è questo: <a href="https://core.telegram.org/bots/api?ref=andreacasarin.com#update" target="blank" rel="nofollow">https://core.telegram.org/bots/api#update</a>. L’oggetto “Message” è a sua volta così strutturato: <a href="https://core.telegram.org/bots/api?ref=andreacasarin.com#message" target="blank" rel="nofollow">https://core.telegram.org/bots/api#message</a>.</p>
<p>Ma c’è di più, nella pagina di documentazione dei Webhook, Telegram ci offre anche un insieme di esempi (già predisposti per cUrl, per altro) pronti per testare il nostro bot.</p>
<p>Per rispondere ad un messaggio ricevuto ci è sufficiente utilizzare l’apposito comando dell’API: <a href="https://core.telegram.org/bots/api?ref=andreacasarin.com#sendmessage" target="blank" rel="nofollow">https://core.telegram.org/bots/api#sendmessage</a>. I due dati richiesti sono “chat_id” che identifica appunto la chat a cui rispondere e “text” che è la nostra risposta.</p>
<p>A partire da questi dati siamo in grado di scrivere il codice per gestire la richiesta e la risposta:</p>
<pre><code>import urllib
import json
import os
class Telegram:
    """Telegram.class."""
    TELEGRAM_TOKEN = os.environ['TELEGRAM_TOKEN']
    TELEGRAM_API = "https://api.telegram.org/bot{}".format(TELEGRAM_TOKEN)
    TELEGRAM_REPLY = TELEGRAM_API + '/sendMessage'
    update = {}
    def __init__(self, update):
        """Telegram.__init__."""
        self.update = update
    def parse(self):
        """Telegram.parse."""
        response = ''
        if 'message' in self.update and 'text' in self.update['message']:
            words = self.update['message']['text'].split(' ')
            mode = words.pop(0)
            if mode.lower() == 'value':
                text = Change(*words).get_value()
                response = self.__reply(text)
        return response
    def __reply(self, text):
        """Telegram.reply."""
        chat = self.update['message']['chat']['id']
        return get_url(self.TELEGRAM_REPLY+"?text={}&amp;chat_id={}".format(text, chat))
</code></pre>
<p>Il costrutture in questo caso popola semplicemente la variabile d’istanza con i dati ricevuti da Telegram.</p>
<p>Il metodo “parse” verifica se il messaggio corrisponde ad un comando del bot e in caso positivo:</p>
<ul>
<li>estrae le variabili e ottiene il valore richesto tramite la classe precedentemente descritta;</li>
<li>risponde al richiedente tramite il metodo “reply”.</li>
</ul>
<p>Al momento non abbiamo ancora generato un token per identificarci con Telegram, prevediamo perciò di leggerlo come variabile d’ambiente (in pieno stile “Twelve-factor App”).</p>
<h2>Definizione bot Telegram</h2>
<p>E’ giunto il momento di informare Telegram della nostra intenzione di creare un nuovo bot.</p>
<p>La creazione e configurazione (privacy, nome, immagine, ecc.) dei bot in Telegram è gestita da… un bot chiamato BotFather, per cominciare iniziamo quindi una chat con lo stesso (<a href="https://t.me/BotFather?ref=andreacasarin.com" target="blank" rel="nofollow">https://t.me/BotFather</a>) e per creare un nuovo bot lanciamo il comando:</p>
<pre><code>/newbot
</code></pre>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-16.png" alt="Bot Telegram per BotFather" /></p>
<p>Dopo aver inserito nome e nome-utente del bot (che deve terminare in “bot”), BotFather ci informa che la creazione è andata a buon fine comunicandoci inoltre il token per le richieste tramite API http:</p>
<pre><code>Done! Congratulations on your new bot. You will find it at
t.me/CryptocurrencyChangeBot. You can now add a description, about section and
profile picture for your bot, see /help for a list of commands. By the way,
when you've finished creating your cool bot, ping our Bot Support if you
want a better username for it. Just make sure the bot is fully operational
before you do this.

Use this token to access the HTTP API:
382957193:AAGMyGuQFOQ0vBoNWOQTWd3GLAPwg9le6VU
</code></pre>
<p>D’ora in poi (fintanto che non lo cancelleremo) possiamo eseguire comandi per il nostro bot con questa sintassi (sostituendo a “TOKEN” il codice che ci è stato fornito da BotFather):</p>
<pre><code>https://api.telegram.org/botTOKEN/COMMAND
</code></pre>
<p>Alcuni comandi sono “informativi”, ad esempio, per ottenere le informazioni di base, usiamo:</p>
<pre><code>https://api.telegram.org/botTOKEN/getMe
</code></pre>
<p>Altri sono “dispositivi”, in seguito vedremo, ad esempio, come impostare il nostro webhook con questo comando:</p>
<pre><code>https://api.telegram.org/botTOKEN/setWebhook?url=WEBHOOK_URL
</code></pre>
<p>Infine dobbiamo notare che di default i bot ricevono:</p>
<ul>
<li>messaggi diretti;</li>
<li>risposte al bot stesso;</li>
<li>comandi diretti.</li>
</ul>
<p>Se volessimo ricevere anche tutti i messaggi dai gruppi dovremmo disabilitare la privacy mode, sempre tramite “BotFather”.</p>
<p>La documentazione completa delle API http per i bot Telegram è disponibile all’indirizzo: <a href="https://core.telegram.org/bots/api?ref=andreacasarin.com" target="blank" rel="nofollow">https://core.telegram.org/bots/api</a>.</p>
<h2>Deploy su AWS serverless</h2>
<p>L’architettura serverless è estremamente vantaggiosa per microservizi con carico estremamente variabile (esattamente come il nostro bot). Il concetto è ben dettagliato da Amazon su: <a href="https://aws.amazon.com/it/serverless/?ref=andreacasarin.com" target="blank" rel="nofollow">https://aws.amazon.com/it/serverless/</a>.</p>
<p>La creazione di una semplice piattaforma serverless senza storage di dati su AWS prevede due passaggi: il primo è la creazione e configurazione di AWS Lambda per il calcolo, il secondo è la configurazione di Amazon API Gateway che richiami la nostra funzione quando invocato.</p>
<h3>AWS Lambda</h3>
<p>Qui è dove il nostro codice verrà eseguito, un servizio in AWS Lambda è detto funzione; per crearne una accediamo ad AWS (<a href="http://aws.amazon.com/?ref=andreacasarin.com" target="blank" rel="nofollow">http://aws.amazon.com</a>) e quindi al pannello Lambda.</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-14.png" alt="Bot Telegram Lambda" /></p>
<p>Clicchiamo “Create a function”, quindi “Author from scratch” e “Next” per saltare, per ora, la creazione di un trigger; inseriamo quindi alcune informazioni di base.</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-07.png" alt="Bot Telegram Lambda 2" /></p>
<p>Carichiamo quindi il nostro codice, definiamo i ruoli per i permessi e le variabili d’ambiente inserendo il token fornito da Telegram come “TELEGRAM_TOKEN”.</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-08.png" alt="Bot Telegram Lambda 3" /></p>
<p>Scegliamo poi l’“Handler”, questa è la singola funzione che viene eseguita alla chiamata del servizio, deve occuparsi di:</p>
<ul>
<li>gestire i parametri;</li>
<li>eseguire il codice necessario;</li>
<li>rispondere in maniera appropriata ad AWS.</li>
</ul>
<p>Abbiamo già visto in dettaglio il formato della chiamata che riceveremo da Telegram, Amazon API Gateway la incapsulerà nei dati della richiesta (“event”) e la inoltrerà alla nostra funzione insieme ad altri dati relativi all’ambiente (“context”), maggiori dettagli qui: <a href="http://docs.aws.amazon.com/lambda/latest/dg/python-programming-model-handler-types.html?ref=andreacasarin.com" target="blank" rel="nofollow">http://docs.aws.amazon.com/lambda/latest/dg/python-programming-model-handler-types.html</a> (per Python).</p>
<p>Per ora concentriamoci solo su “event”, il formato è questo (la richiesta Telegram è incapsulata in event[‘body’]): <a href="http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html?ref=andreacasarin.com#api-gateway-simple-proxy-for-lambda-input-format" target="blank" rel="nofollow">http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-simple-proxy-for-lambda-input-format</a>.</p>
<p>La nostra funzione Lambda dovrà inoltre a sua volta rispondere correttamente ad Amazon API Gateway per evitare che le chiamate vengano interpretate come errore, il formato corretto è questo: <a href="http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html?ref=andreacasarin.com#api-gateway-simple-proxy-for-lambda-output-format" target="blank" rel="nofollow">http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-simple-proxy-for-lambda-output-format</a>.</p>
<p>A questo punto abbiamo tutti gli elementi per comporre una semplice funzione handler che si occupi di estrarre i dati di cui abbiamo bisogno e di rispondere a dovere alla richiesta. Eccola:</p>
<pre><code class="language-clike">def lambda_handler(event='', context=''):
    """handler."""
    response = Telegram(json.loads(event['body'])).parse()
    return {"statusCode": '200', "body": response}
</code></pre>
<p>La documentazione completa di AWS Lambda è disponibile qui: <a href="http://docs.aws.amazon.com/lambda/latest/dg/welcome.html?ref=andreacasarin.com" target="blank" rel="nofollow">http://docs.aws.amazon.com/lambda/latest/dg/welcome.html</a>.</p>
<h3>Amazon API gateway</h3>
<p>Una volta perfezionata la funzione Lambda è necessario definire l’endpoint che ad una determinata richiesta richiami la funzione stessa, questa è la funzione di Amazon API gateway.</p>
<p>Accediamo quindi al servizio e creiamo una nuova API definendo alcune impostazioni di base.</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-09.png" alt="Bot Telegram Api Gateway" /></p>
<p>Dopo averla creata dobbiamo definire la risorsa da pubblicare. Clicchiamo su “Actions” quindi “Create Method”. Il webhook del bot Telegram, come da documentazione, invia una chiamata POST, andiamo perciò a definire una nuova risorsa di questo tipo che imposteremo per richiamare la nostra funzione Lambda:</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-11.png" alt="Bot Telegram Api Gateway 2" /></p>
<p>A questo punto non ci resta altro che rendere disponibile il tutto: clicchiamo quindi nuovamente “Actions” quindi “Deploy API”, definiamo per finire il nome dell’ambiente:</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-13.png" alt="Bot Telegram Api Gateway 3" /></p>
<p>Ora abbiamo a disposizione l’indirizzo che useremo come webhook su Telegram per richiamare il nostro servizio:</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-15.png" alt="Bot Telegram Api Gateway 3" /></p>
<p>La documentazione qui: <a href="https://aws.amazon.com/it/api-gateway/?ref=andreacasarin.com" target="blank" rel="nofollow">https://aws.amazon.com/it/api-gateway/</a>.</p>
<h3>Webhook Bot Telegram</h3>
<p>E’ tutto pronto! A questo punto non ci resta che dire a Telegram a quale indirizzo riferirsi per interrogare il nostro bot: ovvero definire il “webhook”.</p>
<p>Per impostarlo procediamo tramite API con il comando visto sopra e, di default, Telegram notificherà tutti gli eventi della chat; se vogliamo evitare di caricare inutilmente il servizio ci conviene limitare le chiamate ai soli aggiornamenti pertinenti, è possibile farlo dettagliando il tipo di richieste durante l’impostazione:</p>
<pre><code>https://api.telegram.org/botTOKEN/setWebhook?url=WEBHOOK_URL&amp;allowed_updates=["message","channel_post"]
</code></pre>
<p>Possiamo poi richiedere informazioni riguardo il Webhook tramite:</p>
<pre><code>https://api.telegram.org/botTOKEN/getWebhookInfo
</code></pre>
<h2>Conclusioni</h2>
<p>Abbiamo raggiunto il nostro obiettivo, il bot è pronto per ricevere domande e rispondere a tono.</p>
<p><img src="https://www.andreacasarin.com/content/images/2018/03/serverless-telegram-bot-01.png" alt="Bot Telegram Finito" /></p>
<p>E’ sicuramente migliorabile in diversi aspetti, il primo probabilmente è la gestione degli errori &#8211; praticamente assente &#8211; oltre che la sintassi molto basilare.</p>
<p>Come esperimento è comunque sufficiente per capire meglio come funzionano i bot, strumenti in rapida diffusione molto comodi per scopi informativi e ludici e recentemente in sperimentazione anche per scopi commerciali e promozionali da parte di diverse realtà.</p>
<p>Inoltre è stato un buon pretesto per provare la creazione di un servizio serverless: senz’altro una tecnologia molto interessante in quanto permette di creare applicazioni senza costi fissi e perfettamente scalabili, l’ideale per la sperimentazione di nuove idee.</p>
<p>Tutto il codice visto sopra è liberamente disponibile su GitHub all’indirizzo <a href="https://github.com/andreacasarin/CryptocurrencyChangeBot?ref=andreacasarin.com" target="blank" rel="nofollow">https://github.com/andreacasarin/CryptocurrencyChangeBot</a>, il bot Telegram, inoltre, è attivo, per utilizzarlo è sufficiente aggiungerlo tramite questo link: <a href="https://t.me/CryptocurrencyChangeBot?ref=andreacasarin.com" target="blank" rel="nofollow">https://t.me/CryptocurrencyChangeBot</a>.</p>
<p>Non ha comandi diretti ma reagisce a particolari messaggi inviati, ovvero:</p>
<pre><code>Value
</code></pre>
<p>è la forma più semplice e restituisce il valore dei Bitcoin in Dollari americani,</p>
<pre><code>Value eth
</code></pre>
<p>restituisce il valore di Ethereum (ad esempio) in Dollari americani,</p>
<pre><code>Value eth eur
</code></pre>
<p>infine restituisce il valore della valuta richiesta in Euro.</p>
<p>Se ti serve supporto per realizzare il tuo bot Telegram <a href="https://www.andreacasarin.com/contacts">ingaggiami</a>!</p>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ E tu di cosa ti occupi? ]]></title>
        <description><![CDATA[ Spesso mi viene chiesto di cosa mi occupo esattamente e devo dire che molte volte ho anche avuto difficoltà a dare una risposta chiara. Così ho pensato di scrivere un articolo a riguardo, sperando che possa aiutarmi a mettere nero su bianco una presentazione semplice e precisa della mia occupazione. ]]></description>
        <link>https://www.andreacasarin.com/2017/05/04/e-tu-di-cosa-ti-occupi.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1c7</guid>
        <category><![CDATA[ italiano ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Thu, 04 May 2017 19:21:27 +0200</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><p>Spesso mi viene chiesto di cosa mi occupo esattamente e devo dire che molte volte ho anche avuto difficoltà a dare una risposta chiara. Così ho pensato di scrivere un articolo a riguardo, sperando che possa aiutarmi a mettere nero su bianco una presentazione semplice e precisa della mia occupazione.</p>
<p><strong>Per la maggior parte del mio tempo mi occupo di digitale in azienda, aiuto gli imprenditori a snellire il loro lavoro tramite soluzioni informatiche.</strong></p>
<p>Seguo aziende, nuove o affermate, che hanno problemi nella gestione delle informazioni. Analizzo la situazione attuale e progetto una situazione ideale definendo passaggi necessari per raggiungerla. Quindi intervengo per raggiungere gli obiettivi.</p>
<p>In passato si era limitati alle soluzioni locali e i prodotti più avanzati erano baluardo delle grosse aziende, ora, fortunatamente, non è più così. Agendo in modo indipendente non vincolo i miei clienti e non ho vincoli dai miei fornitori, così posso ridurre i costi fissi e proporre sempre una soluzione ad-hoc.</p>
<p>Per finire, vi lascio un consiglio, sperando che possa aiutarvi a scegliere, anche autonomamente, il meglio per la vostra attività.</p>
<p>Ormai il mercato, ed in special modo quello informatico, non ha più confini territoriali. Nella scelta di una soluzione confrontate anche i servizi offerti da grosse aziende internazionali (penso, ad esempio, a G Suite per le email aziendali, AWS per il cloud computing o Atlassian per il project management) alle proposte del vostro fornitore locale, spesso possono essere estremamente competitive per costi e prestazioni.</p>
<p>Se non hai già una persona di riferimento per il digitale in azienda <a href="https://www.andreacasarin.com/#contacts">offrimi un caffè</a>, potremo parlare di come l’informatica può migliorare il tuo business.</p>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>
    <item>
        <title><![CDATA[ Ecco andreacasarin.com ]]></title>
        <description><![CDATA[ Benvenuto su andreacasarin.com, questo è il mio primo post e voglio cogliere l’occasione per descrivermi e descrivere lo scopo di questo progetto.


Nel mio percorso professionale ho avuto esperienze diverse, a partire dal lavoro dipendente per piccole e grandi realtà, fino co-fondare una digital agency, Pixelperfect, nel 2011. ]]></description>
        <link>https://www.andreacasarin.com/2017/01/23/benvenuto-andreacasarin-com.html/</link>
        <guid isPermaLink="false">6413659f27504f000136e1c6</guid>
        <category><![CDATA[  ]]></category>
        <dc:creator><![CDATA[ Andrea Casarin ]]></dc:creator>
        <pubDate>Mon, 23 Jan 2017 09:37:50 +0100</pubDate>
        <media:content url="" medium="image"/>
        <content:encoded><![CDATA[ <!--kg-card-begin: html--><p>Benvenuto su andreacasarin.com, questo è il mio primo post e voglio cogliere l’occasione per descrivermi e descrivere lo scopo di questo progetto.</p>
<p>Nel mio percorso professionale ho avuto esperienze diverse, a partire dal lavoro dipendente per piccole e grandi realtà, fino co-fondare una digital agency, <a href="http://www.pixelperfect.it/?ref=andreacasarin.com">Pixelperfect</a>, nel 2011. Nel 2017 ho deciso di proseguire in una direzione diversa, votata alla massima dinamicità, e sono diventato ufficialmente un <a href="https://www.andreacasarin.com/">freelance</a>.</p>
<p>L’informatica ed in particolare il mondo del web è una mia passione, oltre che il mio lavoro: entrambe le facce di questa medaglia mi portano ad aggiornarmi continuamente e sperimentare nuove tecnologie. Tramite andreacasarin.com sito voglio condividere proprio questo.</p>
<p>Pubblicherò, senza una cadenza precisa, <a href="https://www.andreacasarin.com/#posts">articoli</a> tecnici riguardo i miei progetti o opinioni riguardo le tecnologie che sto utilizzando, cercando confronti costruttivi con altri appassionati e professionisti.</p>
<p>Userò inoltre questa vetrina sul web per creare un piccolo <a href="https://www.andreacasarin.com/#skills">curriculum</a> e mostrare i miei progetti più interessanti per permettere a chi vuole realizzare progetti correlati di conoscere le mie referenze ed eventualmente di chiedermi supporto.</p>
<p>Sentiti perciò libero di <a href="https://www.andreacasarin.com/#contacts">contattarmi</a> per salutarmi, esprimermi la tua opinione o propormi un progetto, faccio il possibile per rispondere a ciascun contatto che ricevo.</p>
<!--kg-card-end: html--> ]]></content:encoded>
    </item>

</channel>
</rss>
