Il metallo (virtuale)
Spero non vi siate accorti di niente, e questo sarebbe un grande risultato. Da qualche giorno ho infatti fatto quello che pensavo di fare da un po’: prendermi un serverino tutto mio [1] e migrarci dentro i miei vari siti. Ci sono svariati ottimi motivi, tra cui il fatto che il mio vecchio hosting provider forniva una versione disperatamente antica di PHP [2] e mi dicono che le versioni nuove siano sufficientemente meglio in termini di prestazioni, API, e senso in generale, quindi volevo provare. Inoltre è un po’ che volevo usare cose che non sono in PHP, tipo roba in Ruby e via così. Quindi, complice il fatto che sto cominciando a gestire server di un certo livello per lavoro, ho fatto il grande balzo, ho scelto un provider affidabile e sufficientemente amico del portafogli, e ho cominciato al mia nuova avventura in Serverland.
Sicurezza: ridurre la superficie di attacco
Fino a poco tempo fa avrei scelto una distribuzione di Linux adeguata, avrei installato e configurato tutti i vari servizi al suo interno, e avrei passato notti insonni a chiedermi se avevo fatto tutto il necessario per mettere la macchina (virtuale) in sicurezza. Questo approccio ha una falla fondamentale: tutti i servizi pascolano felici nella macchina alla pari, vengono eseguiti con più o meno privilegi, e ciò significa che qualsiasi falla in qualsiasi dei servizi permetta ad un attaccante di scalare i privilegi fino a diventare root, porterebbe l’attaccante ad essere root nella macchina, con tutte le conseguenze del caso. Per fortuna, persone molto più intelligenti di me hanno già pensato ad una soluzione.
I container sono un meccanismo a livello kernel che permette di eseguire un qualsiasi processo in modo controllato ed isolato dal sistema operativo, così che solo lo stretto indispensabile gli sia accessibile [3]. In questo modo, un attaccante che riuscisse a bucare il servizio avrebbe accesso solo al piccolo mondo a disposizione di quel servizio, e se riuscisse a scalare i privilegi e diventare root, non sarebbe root nella macchina ma solo nel container, senza molte speranze di uscirne. Il problema è che configurare container è piuttosto complicato e macchinoso, ogni servizio o applicazione richiede configurazioni particolari e non sempre immediate. Sarebbe molto bello se esistesse un metodo per standardizzare il modo in cui il SO vede, tratta, e parla con questi container.
Docker è uno di questi metodi: adottando piuttosto letteralmente il concetto di container – quelli che si usano per trasportare merci, per intenderci – Docker fornisce un modo per creare, configurare, ed eseguire applicazioni in container offrendo al SO un’interfaccia uniforme e prevedibile, e all’applicazione che vive nel container tutto quello che le serve per fare il suo lavoro. In questo modo non ci si deve più preoccupare di come configurare container e SO perché si parlino senza rogne, ma ci basta descrivere di cosa il container ha bisogno – porte, file system, rete… – e Docker si farà carico di configurare tutto come si deve. Ulteriore vantaggio: possiamo avere lo stesso servizio – diciamo Apache – configurato in modi selvaggiamente diversi – diciamo con diverse versioni di PHP, a loro volta con diversi moduli caricati – per diverse applicazioni senza doverci preoccupare di eventuali conflitti ed effetti collaterali. Non ridete perché è proprio quello che mi è toccato fare.
Servizi
La prima necessità è stata di trasportare i miei vari siti nel modo più indolore possibile. In più, ho pensato che sarebbe stato carino replicare più fedelmente possibile una configurazione tipo shared hosting [4] in modo che se qualcuno di voi volesse dividere i costi del server si troverebbe un ambiente familiare (wink wink, nudge nudge). Quindi l’idea era preparare, per ogni dominio, un container HTTPD con vari Virtual Host e con supporto a PHP, un container *SQL con gli appositi utenti e database al bisogno, e un container SFTP generale con utenti nelle cui home vengono rese disponibili le varie directory htdocs
dei rispettivi container HTTPD. Le scelte sono ricadute su
- Apache HTTPD 2.4 con PHP 7
- MariaDB 10.1
- ProFTPD 1.3.5
che mi sono sembrate scelte sensate. A ProFTPD ci sono arrivato dopo un lungo, doloroso percorso in cui ho cercato inutilmente di piegare OpenSSH al mio volere. Ha vinto OpenSSH. In ogni caso sono contentissimo di ProFTPD.
Tanti piccoli container
Il sito più facile da trasportare è stato andreafranceschini.org, anche perché non abbisogna di database. Questo sito, tuttavia, ha una particolarità: ce l’ho sotto controllo di versione con git, e lo aggiornavo automaticamente usando git-ftp. Ora che ho un server tutto mio vorrei poter evitare tali abomini e fare il deployment interamente con git, ma per questo mi serve un container per git che ancora non ho.
Poi è venuta la volta di sbonk.it, che è stato relativamente facile da trasportare. Il sito gira su WordPress, e quindi l’immagine [5] basata su Apache e PHP 7 ha funzionato bene.
Quello che mi ha fatto penare è stato morpheu5.net. O meglio, Drupal 6 che tiene su il www. Tutti gli altri sottodomini, servizi, e altre cose hanno funzionato a meraviglia al primo tentativo – incluso il MorphLog, che gira su WordPress – ma Drupal 6 non supporta PHP oltre la versione 5. Ufficialmente non supporta niente oltre la 5.2, e considerando che la più recente versione della serie 5 è la 5.6, questo poteva essere una noia. Per fortuna PHP 5.6 non ha portato troppi stravolgimenti rispetto alla 5.2, quindi presto fatta un’immagine con Apache e PHP 5.6, et voilà – www è servito.
Non mi dilungherò sulle questioni di rete, ma sappiate che Docker crea una rete virtuale in modo che i container possano comunicare tra loro, e l’host (la macchina che ospita i container) con i container stessi. Il risultato è che ciascuno di quei container che ho descritto sopra ha un suo indirizzo IP, proprio come se fosse una vera macchina virtuale, e l’applicazione all’interno può mettersi in ascolto su tutte le porte che vuole. Fino a qui, però, i container non hanno alcun modo di entrare in contatto col mondo fuori dall’host [6]. Un’opzione è “pubblicare” le porte dei container attraverso le porte sull’host. Purtroppo, per come funzionano le cose, questo significherebbe che, una volta che uno dei container, per esempio uno degli HTTPD, si è impossessato di una porta sull’host, per esempio la 80, che è quella tipicamente usata per HTTPD, nessun altro container può mettersi in ascolto sulla stessa porta dell’host. Bisognerebbe quindi pubblicare un secondo container HTTPD sulla porta, diciamo, 81, ma a quel punto buona fortuna a spiegare ai visitatori che l’URL è http://www.morpheu5.net:81/ – perché 81 non è standard, e quindi i browser non la assumono implicitamente se manca. Un’altra soluzione è usare un reverse proxy, che è un modo carino per dire un servizio che si incarica di intercettare tutte le connessioni su una certa porta dell’host e re-indirizzarle al container appropriato. La mia scelta è ricaduta su NGINX, che è estremamente leggero, rapido, e indicato per fare il proxy. In questo modo, NGINX intercetta le connessioni sui tre domini e le gira ai tre container HTTPD appropriati, che si smazzano i sottodomini internamente via Virtual Host. Un ulteriore vantaggio di ciò è che i container HTTPD non hanno alcun canale diretto con il mondo esterno, ma tutte le comunicazioni passano esclusivamente attraverso NGINX, aggiungendo quindi un ulteriore strato di protezione, dato che NGINX gira a sua volta in un microscopico container dedicato al solo scopo di fare da reverse proxy.
Guardando oltre
Ci sono svariate cose che vorrei sperimentare, ora che ho un sistema flessibile per le mani. La prima cosa, come ho detto più su, è mettere in piedi un piccolo repository git privato perché quello attuale basato su Dropbox comincia a starmi stretto, e di pagare github non mi va. Sì, anche io a volte scrivo software non open source, e un po’ me ne vergogno, ma alla fine della giornata bisogna pure pagare le bollette.
Poi vorrei sperimentare un sistema per condividere preset per Circular Bells – no, non ci sono ancora nella versione pubblicata – e le risorse che avevo col vecchio hosting provider erano un po’ limitate.
Se poi qualcuno volesse – seriamente – contribuire un po’ ai costi, sarei ben felice di tenergli su uno o più siti – sempre che non abbiate richieste di uptime del 99.99999%, che di questi tempi se riesco ad arrivare a 99% è già oro che cola. Ah, e non ho al momento in programma di fornire e-mail. Se vi va, possiamo parlarne – le cifre sono modiche e l’offerta non è necessariamente limitata al classico sito in shared hosting.
Insomma, per il momento è tutto molto bello. Devo mettermi di buona lena e implementare una politica di backup sensata, perché al momento sto facendo a mano, e ciò non è bello. Per tutto il resto, parliamone.
- Un VPS, che qua non siamo mica a crescere i soldi sugli alberi.[↑]
- Non che io sia un grande fan di PHP, ma WordPress, Drupal, e svariate altre cose lo usano.[↑]
- La questione è un po’ più complessa di così, lo so, e so anche che i container non sono un’invenzione di Linux.[↑]
- HTTPD, PHP, *SQL, (S)FTP, per intenderci…[↑]
- Non vi ho spiegato cos’è un’immagine: diciamo, semplificando, che un’immagine è l’idea platonica di cui i relativi container sono istanze nel mondo reale. In pratica, un’immagine è un prefabbricato – le pareti del container – a cui vanno aggiunti arredamento e decorazioni – i dati della specifica copia dell’applicazione che vogliamo mettere in un particolare container.[↑]
- L’host è la macchina che ospita i vari container, in questo caso è la macchina virtuale che ho acquistato.[↑]
Giocattoli nuovi, di nuovo – MorphLog dice:
[…] quando tempo fa mi ero comprato un serverino virtuale con cui giocare? Ci ho giocato per un anno, ci ho tenuto su […]