Indice dei contenuti dell'articolo:
Siamo entusiasti di annunciare vernice.js, ovvero l’integrazione Open Source sotto licenza AGPL, del supporto per Varnish nel CMS Ghost, che consente il purge selettivo della cache Varnish quando viene pubblicato un nuovo post o modificato uno esistente. Questo miglioramento assicura che i contenuti serviti agli utenti siano sempre aggiornati e riflettano le ultime modifiche in tempo reale. Per rendere possibile questa integrazione, abbiamo sviluppato in MANAGED SERVER SRL, un middleware chiamato Vernice.js, un middleware lato server scritto in Javascript per nodejs, progettato per interfacciarsi con Varnish Cache tramite i webhook del CMS Ghost. Questo middleware ascolta gli eventi di modifica dei contenuti in Ghost e invia richieste di purge a Varnish, garantendo che la cache sia sempre aggiornata.
Questa integrazione è particolarmente utile poiché Ghost non offre nativamente il supporto per una Full Page Cache lato server. Varnish, con l’aiuto di Vernice.js, può quindi essere di grande aiuto per blog ad alto traffico, sia per supportare picchi di traffico che per ridurre i tempi di risposta come il TTFB (Time To First Byte).
Varnish Cache è un acceleratore HTTP progettato per siti web dinamici con contenuti pesanti. Funziona come un reverse proxy che memorizza nella cache le risposte del server web, migliorando le performance e riducendo il carico sul server. Grazie a Vernice.js, possiamo sfruttare appieno le capacità di Varnish per offrire contenuti sempre freschi e veloci.
Vernice.js garantisce che ogni volta che un contenuto viene modificato o pubblicato in Ghost, la cache di Varnish viene aggiornata immediatamente, mantenendo i contenuti serviti sempre freschi. L’uso di Varnish riduce il carico sul server backend e migliora i tempi di risposta (TTFB), un vantaggio cruciale per blog ad alto traffico. Questa configurazione aiuta a gestire picchi di traffico senza compromettere le performance del sito, rendendo il sito più affidabile e veloce.
Implementando Vernice.js, possiamo sfruttare appieno la potenza di Varnish per migliorare le performance e l’affidabilità del nostro sito Ghost. Questo garantisce un’esperienza utente ottimale anche durante i periodi di traffico intenso, mantenendo i contenuti sempre aggiornati e riducendo significativamente i tempi di risposta.
A differenza di altre soluzioni trovate online sul Web e sui vari repository di GitHub, che tendono a pulire l’intera Cache quando viene aggiornato un post o pubblicato un nuovo post, il nostro middleware vernice.js è particolarmente scrupoloso nell’effettuare un purge granulare e selettivo dei soli contenuti aggiornati. Se ad esempio avessimo un Blog Ghost popolato da 100 mila post, ed aggiornassimo un post modificando il suo contenuto, vernice.js si occuperà di fare il purge della home page e della URL del post aggiornato, lasciando in cache tutti gli altri post.
Ciò permette di ottenere un elevatissima HIT RATIO rendendo la cache particolarmente funzionante con tutti i vantaggi conseguenti.
Cos’è Varnish?
Varnish è un acceleratore HTTP progettato per siti web dinamici. Funziona come un reverse proxy che memorizza nella cache le risposte del server web per migliorare le performance e ridurre il carico sul server. Questo significa che, una volta che una pagina web è stata richiesta e memorizzata nella cache di Varnish, ulteriori richieste per quella stessa pagina vengono servite direttamente dalla cache, senza dover passare per il server backend. Questo non solo accelera la consegna dei contenuti agli utenti, ma riduce anche notevolmente il carico sul server, permettendo di gestire un numero molto maggiore di richieste simultanee.
Varnish è particolarmente efficace per migliorare la velocità di risposta dei siti web e gestire elevati volumi di traffico. È in grado di gestire migliaia di richieste al secondo, rendendolo ideale per siti web che ricevono grandi quantità di traffico. Inoltre, Varnish offre una serie di funzionalità avanzate come la configurazione di regole di caching personalizzate, supporto per il load balancing e l’abilitazione di tecniche di accelerazione HTTP avanzate come Edge Side Includes (ESI). Grazie a queste caratteristiche, Varnish non solo migliora le prestazioni, ma anche la scalabilità e l’affidabilità dei siti web, rendendolo uno strumento essenziale per siti dinamici e ad alto traffico.
Se volete approfondire Varnish Cache abbiamo scritto un’esauriente guida a questo indirizzo Comprendere la logica di Varnish Cache
Come funziona Vernice.js ?
Vernice.js è stato concepito come un middleware scritto in Node.js che si frappone tra Ghost e Varnish. Funziona in modo indipendente da entrambi i sistemi, ricevendo le chiamate webhook da Ghost, elaborando i dati ricevuti e interfacciandosi con Varnish per eseguire il purge selettivo della cache.
Quando Ghost invia una chiamata webhook in seguito alla pubblicazione, aggiornamento o eliminazione di un contenuto, Vernice.js riceve questa richiesta. I webhook di Ghost includono un payload JSON contenente dettagli rilevanti, come l’URL del contenuto modificato. Vernice.js estrae le URL coinvolte nel processo di purging, inclusi l’URL specifico del contenuto e la home page del sito.
Il middleware analizza il payload JSON del webhook per ottenere urlObject.pathname
e urlObject.host
. Queste informazioni sono essenziali perché Varnish non può elaborare direttamente un payload JSON. Vernice.js utilizza queste informazioni per formattare adeguatamente le richieste di purge che verranno inviate a Varnish.
Il processo funziona come segue: una volta estratti i dettagli necessari, Vernice.js invia una richiesta HTTP di tipo PURGE
a Varnish per il percorso specificato e per la home page. Questo permette a Varnish di invalidare selettivamente la cache solo per le URL interessate, garantendo che gli utenti ricevano sempre i contenuti più aggiornati. Sebbene il comando inviato sia di tipo PURGE
, Varnish può essere configurato per tradurre questo comando in un BAN
, che è un metodo efficace per la pulizia selettiva della cache.
Un aspetto importante da considerare è che, sebbene teoricamente si potrebbe collegare direttamente i webhook di Ghost a Varnish, in pratica ciò non è fattibile. Questo perché Varnish non può interpretare e gestire un payload JSON inviato dai webhook di Ghost. Vernice.js risolve questo problema agendo come intermediario che traduce le informazioni del webhook in un formato comprensibile per Varnish.
Cos’è una Custom Integration in Ghost?
Le Custom Integrations in Ghost permettono di collegare Ghost con applicazioni e strumenti esterni tramite webhooks, estendendo notevolmente le capacità del CMS. Le Custom Integrations sono configurazioni personalizzabili che consentono a Ghost di interagire con servizi esterni in modo automatico e reattivo.
I webhooks sono chiamate HTTP che Ghost invia a un URL specificato quando si verificano determinati eventi, come la pubblicazione, l’aggiornamento o la cancellazione di un post, la creazione di una pagina, o l’aggiunta di un tag. Quando uno di questi eventi si verifica, Ghost invia una richiesta HTTP POST al webhook configurato, includendo nel payload della richiesta i dettagli dell’evento.
Queste integrazioni consentono agli sviluppatori di estendere le funzionalità di Ghost e automatizzare diversi processi. Ad esempio, è possibile configurare un webhook per inviare notifiche a un servizio di chat come Slack ogni volta che viene pubblicato un nuovo post, aggiornare automaticamente una sitemap, o come nel nostro caso, purgare la cache di Varnish per garantire che i contenuti più recenti siano serviti agli utenti.
Le Custom Integrations offrono un alto grado di flessibilità, permettendo di collegare Ghost a praticamente qualsiasi servizio che supporti l’API webhook. Questo significa che puoi creare flussi di lavoro personalizzati e automatizzati che rispondono in tempo reale agli eventi che si verificano nel tuo sito Ghost. Queste integrazioni sono configurabili direttamente dall’interfaccia di amministrazione di Ghost, rendendo semplice l’aggiunta di nuovi webhooks e la gestione di quelli esistenti.
Grazie alle Custom Integrations, è possibile migliorare l’efficienza operativa e fornire funzionalità avanzate senza dover modificare direttamente il codice sorgente di Ghost. Questo approccio modulare e scalabile rende Ghost una piattaforma estremamente versatile e potente per la gestione dei contenuti.
Configurazione di Ghost per Utilizzare gli Hook tramite Web API
Per integrare correttamente Ghost con il middleware VERNICE.JS e consentire il purge selettivo della cache di Varnish, è necessario configurare Ghost affinché utilizzi gli Hook tramite Web API. Di seguito sono riportati i passaggi dettagliati per eseguire questa configurazione a partire dall’immagine fornita.
Accedi al pannello di amministrazione di Ghost e vai su Settings (Impostazioni), quindi seleziona Advanced (Avanzato). Nella sezione Integrations (Integrazioni), seleziona la scheda Custom (Personalizzato) e clicca su Add custom integration (Aggiungi integrazione personalizzata).
Una volta selezionata l’opzione per aggiungere un’integrazione personalizzata, compila i dettagli richiesti per creare una nuova integrazione. Dovrai inserire un nome per l’integrazione, ad esempio “Varnish Purge”, e una breve descrizione, come “Purge Varnish at content modification”. Dopo aver salvato l’integrazione, appariranno le opzioni per configurare i webhooks.
Nella schermata dell’integrazione Varnish Purge, clicca su Add webhook (Aggiungi webhook) e compila i dettagli del webhook. Seleziona l’evento che deve attivare il webhook, ad esempio “Post Published” o “Post Updated”, e inserisci il target URL del server dove è in esecuzione il middleware VERNICE.JS. Ad esempio, se il middleware è in esecuzione sulla stessa macchina di Ghost e sulla porta 3000, l’URL potrebbe essere http://127.0.0.1:3000/webhook
.
Ripeti il processo per aggiungere altri webhooks che coprano tutti gli eventi di interesse, come la pubblicazione, l’aggiornamento e la cancellazione di post, pagine o altri contenuti.
Esempio di Configurazione del Webhook
Di seguito un esempio di come dovrebbe apparire la configurazione di un webhook per l’aggiornamento (update) di un post:
Verifica della Configurazione
Assicurati che Ghost stia inviando correttamente i webhook quando vengono effettuate modifiche ai contenuti. Puoi verificarlo controllando i log del middleware vernice.js. Dovresti vedere i messaggi di log che indicano la ricezione di richieste di purge per i percorsi specifici.
Codice Middleware VERNICE.JS
Il middleware deve essere in esecuzione su un server Node.js, pronto a ricevere e processare i webhook. Ecco un riepilogo del codice per VERNICE.JS:
/** * * * (`-. ('-. _ .-') .-') _ ('-. * _(OO )_ _( OO) ( \( -O ) ( OO ) ) _( OO) * ,--(_/ ,. \(,------. ,------. ,--./ ,--,' ,-.-') .-----. (,------. * \ \ /(__/ | .---' | /`. ' | \ | |\ | |OO) ' .--./ | .---' * \ \ / / | | | / | | | \| | ) | | \ | |('-. | | * \ ' /, (| '--. | |_.' | | . |/ | |(_/ /_) |OO ) (| '--. * \ /__) | .--' | . '.' | |\ | ,| |_.' || |`-'| | .--' * \ / | `---. | |\ \ | | \ | (_| | (_' '--'\ | `---. * `-' `------' `--' '--' `--' `--' `--' `-----' `------' * * * * VERNICE.JS a Ghost <=> Varnish Middleware Selective Cache Purger and Daemon Cleaner. * * Copyright (c) 2024 - Managed Server S.r.l. - Licensed under AGPL 3.0 https://www.gnu.org/licenses/agpl-3.0.en.html * * * Description: * This Node.js middleware is designed to bridge the Ghost CMS with a selective Varnish Purging system. * It listens for webhooks from Ghost related to content changes (like posts, pages, tags) and triggers * selective cache purging in Varnish. This ensures that the content served to users is always fresh and up-to-date. * * Requirement: * Node.js and express, axios, url, body-parser. Varnish Cache 3.0 or Higher. A Linux OS support systemd. * * Usage: * Run this script in a Node.js environment. Configure Ghost to send webhooks to this middleware. * The middleware will process these webhooks and send requests to the Varnish server to purge the cache as needed. * * Note: * Ensure that webhooks in Ghost and Varnish cache purging rules are correctly set up for this middleware to function properly. * */ const express = require('express'); const axios = require('axios'); const { URL } = require('url'); const bodyParser = require('body-parser'); const app = express(); const port = 3000; console.log('\x1b[32m%s\x1b[0m', " \n" + " (`-. ('-. _ .-') .-') _ ('-. \n" + " _(OO )_ _( OO) ( \\( -O ) ( OO ) ) _( OO) \n" + " ,--(_/ ,. \\(,------. ,------. ,--./ ,--,' ,-.-') .-----. (,------. \n" + " \\ \\ /(__/ | .---' | /`. ' | \\ | |\\ | |OO) ' .--./ | .---' \n" + " \\ \\ / / | | | / | | | \\| | ) | | \\ | |('-. | | \n" + " \\ ' /, (| '--. | |_.' | | . |/ | |(_/ /_) |OO ) (| '--. \n" + " \\ /__) | .--' | . '.' | |\\ | ,| |_.' || |`-'| | .--' \n" + " \\ / | `---. | |\\ \\ | | \\ | (_| | (_' '--'\\ | `---. \n" + " `-' `------' `--' '--' `--' `--' `--' `-----' `------' \n" + "\n"+ " VERNICE.JS a Ghost <=> Varnish Middleware Selective Cache Purger and Daemon Cleaner. \n"+ "\n" + " Copyright (c) 2024 - Managed Server S.r.l. - Licensed under AGPL 3.0 \n" + "\n" ); app.use(bodyParser.json({ limit: '64mb' })); app.post('/webhook', async (req, res) => { if (req.body.post && req.body.post.current && req.body.post.current.url) { const fullUrl = req.body.post.current.url; const urlObject = new URL(fullUrl); const postPath = urlObject.pathname; const host = urlObject.host; console.log(`Richiesta di PURGE per il percorso: ${postPath} e host: ${host}`); try { // Effettua una richiesta PURGE per la home page axios.request({ method: 'PURGE', url: 'http://127.0.0.1:80/', headers: { 'Host': host } }).catch(error => { console.error('Errore durante la chiamata di PURGE per la home page', error); }); // Effettua una richiesta PURGE per l'URL specifico axios.request({ method: 'PURGE', url: `http://127.0.0.1:80${postPath}`, headers: { 'Host': host } }).catch(error => { console.error('Errore durante la chiamata di PURGE per l\'URL specifico', error); }); res.status(200).send('Richieste di PURGE inviate'); } catch (error) { console.error('Errore generico nel blocco try', error); res.status(500).send('Errore durante l\'invio delle richieste di PURGE'); } } else { console.log('Payload del webhook non valido o mancante di informazioni cruciali'); res.status(400).send('Richiesta webhook non valida'); } }); app.listen(port, () => { console.log(`Server VERNICE.JS in ascolto sulla porta ${port}`); });
Seguendo questi passaggi, sarai in grado di configurare Ghost per inviare webhook al middleware vernice.js assicurando così che ogni modifica ai contenuti si rifletta immediatamente nella cache di Varnish, migliorando le prestazioni e l’esperienza utente del tuo sito.
Mantenere attivo il servizio tramite una Unit Systemd.
Per assicurarsi che il middleware Vernice.js rimanga attivo e si avvii automaticamente al riavvio del sistema, è necessario configurare una unità systemd. Questo è fondamentale per garantire che il servizio sia sempre disponibile per gestire i webhooks inviati da Ghost. A tal fine, creeremo un file di configurazione in /lib/systemd/system/vernice.service
che conterrà il seguente codice:
[Unit] Description=Vernice.js systemd service for vernice.js Node Varnish Cache Purger After=network.target [Service] Type=simple WorkingDirectory=/root User=root ExecStart=/usr/bin/node /root/vernice.js Restart=always [Install] WantedBy=multi-user.target
Ricordati di adattare i path in base alla posizione del file vernice.js, nella Unit Systemd sopra si da per scontato che stia girando nella directory /root con i privilegi root.
La sezione [Unit] definisce le informazioni basilari e le dipendenze del servizio. Il parametro Description
fornisce una breve descrizione del servizio. Il parametro After=network.target
indica che il servizio deve essere avviato solo dopo che il target di rete (network.target
) è stato raggiunto, assicurando che le risorse di rete necessarie siano disponibili.
La sezione [Service] definisce come deve essere eseguito il servizio. Il parametro Type=simple
specifica che il servizio è semplice e avviato direttamente dal comando indicato in ExecStart
. Il parametro WorkingDirectory=/root
imposta la directory di lavoro del servizio su /root
. Il parametro User=root
specifica che il servizio deve essere eseguito con l’utente root. Il parametro ExecStart=/usr/bin/node /root/vernice.js
indica il comando per avviare il middleware Vernice.js; in questo caso, viene utilizzato Node.js per eseguire lo script vernice.js
situato nella directory /root
. Il parametro Restart=always
configura il servizio per riavviarsi automaticamente se dovesse terminare in modo inaspettato, garantendo così una maggiore affidabilità.
La sezione [Install] definisce come e quando il servizio deve essere avviato. Il parametro WantedBy=multi-user.target
specifica che il servizio deve essere avviato come parte del target multi-user
, che è uno dei livelli di esecuzione standard di systemd e include la modalità multi-utente senza interfaccia grafica.
Dopo aver creato il file di configurazione, è necessario attivare e avviare il servizio con i seguenti comandi:
sudo systemctl daemon-reload sudo systemctl enable vernice.service sudo systemctl start vernice.service
Questi comandi ricaricheranno la configurazione dei servizi di systemd, abiliteranno il servizio per l’avvio automatico al boot e avvieranno immediatamente il servizio Vernice.js. Con questa configurazione, Vernice.js sarà sempre attivo e pronto a gestire i webhooks di Ghost per il purge selettivo della cache di Varnish.
Configurazione di Varnish per Ghost
A livello di configurazione Varnish, per politica aziendale non ci addentriamo nella configurazione della configurazione e del relativo VCL, adottandone una versione specifica e personalizzata estesa con Inline C, tuttavia la configurazione può essere applicata semplicemente accertandosi che il blocco recv di Varnish possa essere in grado di gestire correttamente il comando PURGE effettuando il BAN selettivo della URL.
Seguentemente possiamo vedere un breve snippet della configurazione in cui c’è il controllo dell’IP richiedente (che deve corrispondere o all’IP della macchina o all’IP localhost) che successivamente procedere al BAN della URL che viene passata dal middleware vernice.js.
if (req.http.x-forwarded-for) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } if (req.request == "PURGE") { if ((req.http.X-Forwarded-For == "91.107.202.139, 127.0.0.1") || (req.http.X-Forwarded-For == "127.0.0.1")) { ban("req.url ~ ^" + req.url + "$ && req.http.host == " + req.http.host); } else { error 405 "Not allowed."; } }
Qualora abbiate la necessità di installare e configurare Varnish potremmo fornire consulenza commerciale in merito ed eventualmente estendere anche le funzionalità.
Potrete trovare eventuali upgrade, fork, e correzioni al repository GitHub ufficiale all’indirizzo https://github.com/MarcoMarcoaldi/Vernice.js