Aggiornare Writefreely, visualizzare le immagini: self hosting, docker compose e volumi

Nello scrivere il post sull'inflazione mi sono accorto che una cosa semplice e scontata come pubblicare un'immagine sul proprio blog poteva essere meno scontata se il blog in questione lo gestite voi dall'inizio alla fine.

Quello che segue è un racconto su: – come aggiornare la versione del proprio software (se quest'onere è in carico a voi) – come rendere caricare un'immagine dal proprio pc al proprio sito se non c'è un comodo modo per fare l'upload – come fare in modo che chi si connette a vostrosito/static/immagine_caricata_a_fatica non si becchi un 404.

A livello di strumenti, ci sarà da parlare di: – VPS: la vostra casa online, il vostro server. La macchina a cui vi connettete per tenere su il tutto. – Docker/container: la baracca si regge su Docker. Quello che vi serve – blog, database, qualsiasi cosa – sta dentro vari contenitori. Docker si occupa di creare tutte le scatole, metterci dentro quello che volete e di far parlare le cose tra di loro. Ad esempio: la scatola 1 è un blog, la scatola due un e-commerce. Entrambe hanno bisogno di sapere che esiste una scatola 7 con il database. – ngix: per gestire le immagini (questo non me lo aspettavo).

Il tutto per arrivare a poter vedere questa immagine immagine sull'inflazione di qualche post fa

Writefreely e l'aggiornamento

Writefreely ultimamente ha avuto qualche problemino, almeno da quanto ho letto relativamente a Noblogo, il servizio di blog powered by writefreely gestito da Devol. Mi pare che sia qualcosa legato alla creazione di blog spam in un contesto multi utente. Qualcosa potete leggerlo qui.

Il problema era sulla versione v0.17.0. Questo blog gira puoi lui con writefreely. Ho sudato freddo. Questo mi ha fatto pensare: da quando ho tirato su tutta mia baracca con writefreely a che versione sono? Che è successo? Sto spammando blog di neonazi e non me ne sono accorto?

Tocca quindi imparare un nuovo pezzo del self-hosting. Tocca a te aggiornare il software. Visto che avevo in sospeso un problemino con le immagini, mi ci sono messo.

Come aggiornare le versioni delle cose selfhostate

Come dice Boskov, “aggiornamento si fa cliccando su aggiorna”. Che nel mondo dei terminali vuol dire “fai un sudo qualcosa update da qualche parte”.

Ad esempio, sulla vostra VPS ogni tot tocca fare un aggiornamento dei pacchetti. O magari il vostro orchestratore di container ha una nuova versione e dalla UI di Coolify o Portainer c'è un pulsante per fare l'update.

Solo che non è così semplice. Perché il blog viene tirato su dentro la sua scatola (container) seguendo una ricetta (immagine). Il quadro è simile a questo.

La baracca, che alcuni chiamano indiecloud, si regge su più servizi che stanno dentro le loro belle scatoline (container). A volte qualcosa può andare storto. Una scatola casca e si rompe, qualcuno la calpesta, o altro. Il container va giù. Tocca quindi sostituire la scatola con una dove avete ricostruito per bene la app del vostro castello come si deve. Quindi ritirate su il container e lo fate ripartire. Basta un click (o un comando). Fichissimo.

Questo però ha un problema con questa prima idea di aggiornamento. La scatola contiene il vostro drago rosso. La nuova versione di writefreely è un drago blu. Fate update del rosso a blu. Bello. Però funziona fino a quando per disgrazia non va giù tutto e voi sostituite la scatola. Nelle vostre istruzioni, la ricetta dice che il drago è rosso. Non è la soluzione giusta.

A noi interessa cambiare le istruzioni e metterci dentro il drago blu. Così a ogni riavvio prendiamo l'elemento giusto.

Quindi non bisogna entrare nel container e fare l'aggiornamento ma bisogna riscrivere le regole. In tecnichese tocca aggiornare il docker compose, in pratica il grande omino che sa dove stanno i pezzi dei lego, conosce tutte le ricette e dice come comporre i lego nelle varie scatole.

In pratica è bastato cambiare una sola riga:

image: ghcr.io/writefreely/writefreely:v0.17.1

(per decoro non vi dico a che versione ero prima).

Tutto finito? Purtroppo no. La nuova versione ha dentro dei cambi allo schema del database – in pratica: a come vengono organizzate e salvate le cose. Ci sono nuove feature e il fix del bug nella nuova versione – alcune feature includono interazioni col fediverso. Per realizzare queste cose nuove tocca modificare lo schema del database... e ha senso: se da doomani volete tenere conto non solo dei libri che leggete ma di quante volte vi alzate col piede sinistro, vi tocca iniziare una nuova fila di X...

Per rendere questi cambiamenti attuali bisogno dire al nostro drago blu “aggiorna il tuo schema del database”. C'è anche un rituale magico per fare il cambio: writefreely db migrate.

Questo comando possiamo lanciarlo da dentro il nostro container in cui gira l'applicazione di writefreely. Quindi usando il dockerese una cosa del genere:

docker exec containerid /go/cmd/writefreely/writefreely db migrate.

Quindi entro sulla VPS e ci metto un sudo davanti per eseguire il comando con i giusti poteri. Funzionerà?

Ovviamente non può essere tutto così facile.

Loading config.ini configuration...

ERROR: app.go:150: Unable to load configuration: open config.ini: no such file or directory`

La configurazione era nel posto sbagliato. Riproviamo dicendo al comando dove sta la configurazione

docker exec containerid /go/cmd/writefreely/writefreely -c /data/config.ini db migrate
Loading /data/config.ini configuration...
Connecting to sqlite3 database...
Migrating to V17: fix post signature character set
Closing database connection...

(Tra le nuove feature, c'è monetizzazione e link automatico col fediverso https://webmonetization.org/#start . Ho aggiornato per scoprire cose nuove.)

Ma... perché funziona?

Avevamo detto che non basta fare le modifiche nel container perché al primo riavvio vanno perse. Perché per la migrazione del database dovrebbe essere diverso?

Qui ci sono due risposte possibili: 1. il database di riferimento è esterno (sta in un container tutto suo – e vediamo quanti voti prende) 2. usiamo un qualche trucco per persistere i dati tra un riavvio e l'altro.

Writefreely vuole essere autarchico e tutto in un punto. Quindi nella sua ricetta usa già SQLite come database. Se volete costruire una casa dove scrivere con Writefreely dovete solo prendere un container e installare lì dentro Writefreely, senza mal di testa per far parlare il vostro blog con un database, senza dover negoziare la struttura di come salviamo i post, etc. Senza troppe seccature extra oltre a quelle di “installiamo Writefreely da qualche parte, poi facciamo in modo che io possa scriverci e le persone leggermi”. Dobbiamo quindi usare il trucco per persistere i dati.

Ci sta infatti che, in un mondo di scatoloni e sostituzioni, servano dei riferimenti a cose che restano stabili. Questi wanderwall in docker li han chiamati volumi. In pratica prendiamo una cartella della macchina in cui inizieremo a far comparire e sparire i diversi container e diciamo che, container per container, certi dati devono persistere e vanno salvati o letti da una cartella specifica.

Nel grande magazzino in cui abbiamo messo gli scatoloni col lego colorato stiamo dicendo ad alcuni scatoloni di leggere o salvare su una mensola condivisa. Ad esempio potremmo toccare il cibo per il drago.

In questo modo possiamo salvarci il nuovo schema del database, senza ripartire da zero tutte le volte.

Immagini

Per le immagini, questa cosa dei volumi ci torna utile. Come faccio a mostrare la mia immagine dell'inflazione? Devo mettere su un volume le immagini da mostrare come file statici. In questo modo riuscirò a mostrarle.

In pratica l'idea è questa: 1. dal nostro pc mandiamo l'immagine sulla nostra VPS 2. la VPS la mette a disposizione di writefreely 3. e noi possiamo linkarla scrivendo il post. Come quando usiamo un po' di markdown per scrivere una nota in obsidian.

Quindi, copiamo le cose con scp. Apriamo un terminale e:

scp /path/to/your/graph.png user@domain:/home/.../writefreely/static/graph.png

Qui stiamo buttando su l'immagine nella cartella static di writefreely, che possiamo leggere per mettere immagini quando scriviamo i post. I ... indicano dove abbiamo messo il container di writefreely.

Questo funziona perché, nel docker compose, abbiamo un volume per writefreely definito così

volumes:
- /home/.../writefreely:/data

(Da capo: i ... completano il percorso su dove abbiamo messo il container di writefreely.)

Basta? No

A questo punto l'immagine è sulla VPS pronta per essere linkata. Aggiorno il post, linko l'immagine tutto felice e... 404. L'immagine non si vede. Anche se è *tutto giustoé. Che è successo? Che da fuori, cioè per l'internet, l'immagine non è visibile. Non è che chiunque bussi alla porta del nostro server deve trovare risposta e vedere l'immagine. Arriva nginx: tra i suoi compiti c'è quello di essere un server che mette a disposizione i file statici. Tipo le nostre immagini.

Per prima cosa tocca aggiungere una scatola e metterci dentro nginx. Ci penserà lui a servire le immagini a chi le vuole.

Aggiungiamo una ricetta al docker compose

# STATIC FILES (Nginx)

static-files:
image: nginx:alpine
restart: always
volumes:
- /home/.../writefreely/static:/usr/share/nginx/html:ro

networks:
- quello del vostro orchestratore

labels:
- a seconda di cosa usate potrebbero esser configurate.

In pratica la riga che ci serve è quella dei volumi. Stiamo collegando una cartella del container di writefreely – static – a una cartella del container di nginx /usr/share/nginx/html. Writefreely gestisce in quella cartella i file statici – è dove abbiamo caricato l'immagine! – mentre, lato nginx, è da dove vengono serviti i file. Ecco fatto.

La parte sul network riguarda come l'orchestratore fa parlare tra di loro le applicazioni presenti al suo interno. Sono dei canali di comunicazione tra le parti. Ad esempio: potrebbe esserci il network per tutte le applicazioni che hanno bisogno di parlare con la scatola del database (non è il caso di Writefreely che, come abbiamo visto, gestisce la cosa in proprio).

Le labels sono invece dati extra che possiamo attaccare ai container. Possiamo usarle in modo che altri servizi che gestiscono più container possano capire cosa fare con quel container in base a quello che ci abbiamo scritto. Sono dei post-it. E sono sufficientemente potenti: un'etichetta con scritto sì/no e prima il nome di un servizio può dire al servizio se “fare cose o meno” al nostro scatolone di Writefreely. Ad esempio "traefik.enable=true".

Nel mio caso c'era da mettere d'accordo anche Traefik nella gestione rotte e nel servire le immagini. In pratica tocca dire a Traefik che, se qualcuno cerca di accedere a un file statico (static, dove spesso e volentieri mettiamo le immagini), allora il traffico va inoltrato al container di nginx che si prenderà in cura di mostra l'immagine.

Recap: volevamo solo delle immagini, adesso abbiamo volumi ed nginx

In pratica funziona così. Writefreely fa di tutto per essere efficiente e non avere fronzoli. Lo abbiamo già visto con la storia del database. L'assenza di fronzoli include i non avere un box per fare l'upload dei file. L'idea è che usi i link con immagini hostate su altri siti. Se però fai una chart tua e non la metti da altre parti – perché mettere in piedi un archivio con AWS ed S3 è seccante o altri motivi – allora tocca gestire il tutto in autonomia. Ecco che arriva Nginx a fare da server per i file statici. Se i file sono in una certa cartella (quella del volume con static di mezzo), sono accessibili all'esterno.

Poi, in tutto questo, c'è traefix a dirigere il traffico: se qualcuno vuole vedere il blog, traefik manda la richesta a writefreely. Quando però writefreely vuole accedere all'immagine allora si pesca in casa propria.

E poi?

Già che c'ero, ho scoperto che qualcosa aveva distrutto il mio scatolone chitarristico. Quindi ho dovuto prendere e trovare qualcosa per essere avvisato se qualcosa va giù. Però questa sarà un'altra storia...

#indiecloud #docker #selfhosting #writefreely

Ci si vede nel Fediverso?

In attesa di capire come funzionano i commenti in Writefreely, e se val la pena aggiungerli, mi trovate qui nel fediverso.