Come ho realizzato un sito a costo zero con Hugo e DigitalOcean
Premessa
Di recente ho deciso di effettuare un cambio abbastanza radicale nella mia vita professionale. Da Settembre 2023 infatti ho deciso di intraprendere la libera professione dopo più di 10 anni passati come dipendente di aziende (la maggior parte dei quali come CTO e Tech Lead), anche se molto variegate. Sono infatti stato sia in startups che in corporates multinazionali. Ora sono giunto alla decisione di diventare un Fractional CTO (se volete sapere di cosa mi occupo potete dare uno sguardo qui ) ed una delle prime cose che ho affrontato è stata quella di incrementare la mia presenza online. Quindi ho fatto un po’ di lifting al mio linkedin, al mio CV ed ho anche deciso di creare un sito web personale con cui promuovere la mia nuova attività. Ed eccoci quindi a questo post che descrive come ho realizzato il mio sito utilizzando HUGO e Digital Ocean senza spendere un soldo (o quasi).
Cosa ho usato
Lo scopo che mi sono prefissato quando ho deciso di creare il mio sito web personale è stato quello di poterlo realizzare e mantenere online spendendo il meno possibile in termini economici investendo quindi tutto sulle mie capacità tecniche. Questo è risultato nella scelta di tecnologie che sono open source e completamente gratuite ma che richiedono un po’ di capacità tecniche per implementarle.
Hugo
Dopo un po’ di scouting di varie opzioni ho deciso di usare Hugo come framework per la realizzazione del mio sito web.
Hugo, come scritto nel suo sito web:
E’ uno dei generatori di siti web statici open-source più popolari. Con la sua formidabile velocità e flessibilità, Hugo rende la costruzione di siti web di nuovo divertente.
In questo pay-off c’è tutto quello che serve sapere sul perché ho scelto Hugo come framework:
- E’ un generatore di siti web statici
- E’ open-source ed ha una folta community di sostenitori e creatori di contenuti (come il tema che ho usato)
- E’ estremamente veloce, flessibile e customizabile
- Guilty pleasure personale (ma non troppo): è realizzato in golang
- E’ gratis
Il fatto che Hugo generi siti web statici è un vantaggio non indifferente perché generalmente l’hosting per questo tipo di siti web è decisamente poco oneroso o addirittura del tutto gratuito come in questo caso.
DigitalOcean
DigitalOcean è un cloud provider abbastanza amato dai builders e/o makers (come il sottoscritto) per la sua semplicità di gestione delle risorse, delle tipologie di servizi cloud che mette a disposizione dei prezzi estremamente concorrenziali sul mercato dell’hosting cloud (puoi avere una VM minima ma ad un prezzo di $4/mese).
Quello che ho deciso di usare è un servizio chiamato App Platform che ti permette di pubblicare del codice o artefatti direttamente sul cloud senza doverti preoccupare della infrastruttura sottostante; è quello che in gergo di chiama Platform-as-a-Service (PaaS). Questo servizio permette di pubblicare siti web statici (quindi di solo HTML/CSS/JavaScript) in modo completamente gratuito.
Canva
Canva è un tool online, credo ben noto a tutti, per il design e la progettazione grafica che mi ha permesso con poco sforzo di generare tutte le grafiche necessarie al mio sito web. Ovviamente ha il piano gratuito con features più che sufficienti a generare le grafiche di cui ho avuto bisogno: un banner/background ed un logo.
GitHub e Git
GitHub è una famosa piattaforma di sviluppo collaborativo basata su Git, che è un sistema di controllo delle versioni distribuito. Il tutto è necessario per tenere traccia degli aggiornamenti che si fanno al sito web e per la pubblicazione automatica di questi su Digital Ocean tramite la sua integrazione nativa.
Cosa ho fatto
La prima cosa che ho fatto ovviamente è stata quella di rendermi operativo con Hugo.
Installare Hugo
L’installazione di Hugo sulla propria macchina di sviluppo locale può essere fatta in diversi modi. Avendo un Mac io l’ho installato usando homebrew
$ brew install hugo
ma qui si possono trovare tutti i metodi di installazione. Una volta installato mi sono assicurato che tutto funzionasse con il comando
$ hugo version
Scelta del tema
Dato che il mio scopo era quello di realizzare il sito, almeno per questa prima versione, nella maniera più semplice ed economica possibile, ho deciso di cercare un tema che mi piacesse tra tutti quelli messi a disposizione della community (qui c’è la lista di tutti i temi ). Dopo qualche ricerca ho deciso di utilizzare il tema Toha; semplice e con tutte le funzionalità per lo sviluppo di un sito web personale, compreso di blog.
P.S: in pieno spirito open source ho anche contribuito con una piccola pull request su github per sistemare alcune cose, qui potete vedere il mio contributo.
Inizializzazione del sito con Hugo
Ora che ho tutti i prerequisiti posso inizializzare il progetto. Per farlo ho usato la CLI fornita da hugo per generare un nuvo sito web:
$ hugo new site example-personal-site
$ cd example-personal-site
una volta generato il sito, ho inizializzato il tema scelto. Per farlo ho dovuto decidere dove avere il repository del mio sito web. Io ho scelto GitHub perchè ha una integrazione nativa in DigitalOcean che consente la pubblicazione automatica delle modifiche che fate al sito.
Avendo chiamato il progetto example-personal-site
, ho inzializzato i moduli hugo con
$ git init
$ hugo mod init github.com/kyserbyte/example-personal-site
Una volta fatto, la struttura delle cartelle che ho ottenuto è la seguente
.
├── archetypes
│ └── default.md
├── assets
├── content
├── data
├── go.mod
├── hugo.toml
├── i18n
├── layouts
├── static
└── themes
Questa è la struttura base dei siti web realizzati con Hugo.
Ho poi configurato il tema scelto modificando il file hugo.toml
, che si presenta così
baseURL = 'https://example-personal-site.org/'
languageCode = 'en-us'
title = 'My New Hugo Site'
[module]
[[module.imports]]
path = "github.com/hugo-toha/toha/v4"
#(... omissis)
Ora è possibile installare il tema
$ hugo mod tidy
$ hugo mod npm pack
$ npm install
Ed ecco che finalmente sono pronto a vedere se tutto funziona a dovere.
$ hugo server -D
questo comando avvia un server locale con il sito all’indirizzo http://localhost:1313. Un salto sul browser et voilà, il sito è online (in locale ovviamente). Ho provato poi a fare una build pubblicabile con
$ hugo
questo comando genera una nuova cartella chiamata public
in cui c’è l’intero sito web statico e pronto per essere pubblicato.
A questo punto ho personalizzato il sito web ed il tema per inserire i contenuti e le grafiche così come li ho pensati e realizzati. Il dettaglio di questo lavoro esula dallo scopo di questo post, ma ne potete vedere il risultato qui.
Messa online del sito
Una volta raggiunto il risultato di personalizzazione che volevo ottenere, sono passato alla messa online effettiva del sito web.
Come primo passo quindi ho acquistato il dominio scelto; questa è l’unica spesa che ho sostenuto. Poi mi sono aperto un account su Digital Ocean. Una volta registrato ho creato un project e dopo aver completato la creazione ho creato una nuova risorsa di tipo App. Nella pagina di creazione della App, ho abilitato l’integrazione di DigitalOcean con GitHub, garantendo l’accesso al repository dove è presente la codebase Hugo per il sito web.
Fatto questo ho selezionato la repo, spuntata la casella di autodeply e fatto next
.
Digital Ocean qui fa una sua analisi della codebase per cercare di individuare quale tipo di App si sta cercando di deployare. Purtroppo, essendoci i file di moduli di golang (il linguaggio in cui è scritto Hugo), Digital Ocean non è in grado di identificare autonomamente che si tratta di un sito Hugo e quindi di uno static web site. Per fargli digerire la cosa, nella schermata di configurazione del servizio che mi si è aperta ho cliccato su edit
della app
edit
su Resource Type e qui ho scelto Static Site
.
Salvato tutto mi sono assicurato cliccando su Edit Plan
che mi avesse settato sul piano Basic e gratuito (Digital Ocean ne mette a disposizione massimo 3 per account).
Sulle Environment Variables non ho settato nulla e sono andato avanti; su Info mi sono assicurato che fosse selezionato il progetto giusto. Ne ho fatto la review, mi sono assicurato che tutto fosse come mi aspettassi ed ho creato la risorsa.
Containerizzazione per la build
Nonostante abbia indicato che si tratta di uno Static Site, Digital Ocean ancora tenta di fare una build di un progetto golang e per questo il primo tentativo di deployment fallisce miseramente. Dopo vari tentativi e facendo un po’ di ricerca online scopro che è possibile far fare una build a Digital Ocean tramite docker e Dockerfile. Bene, allora tento questa strada. Ho creato una nuova directory nel repository col nome .do
. Dentro questa cartella ho creato un file Dockerfile
con questo contenuto, molto semplice
FROM ghcr.io/peaceiris/hugo:latest-full
WORKDIR /app
COPY . /app
RUN npm install
RUN hugo -d public
Questo file è necessario per darlo in pasto a Digital Ocean per farglielo eseguire ed estrarre quello che viene buildato da Hugo nella cartella public.
Ottenuto il modo di fare la build del sito Hugo tramite docker, ho dovuto instruire Digital Ocean su come usare questi files. Per fare questo ho dovuto recuperare il file di App Spec che Digital Ocean usa per configurare l’intera app, compreso il deployment.
Nei settings dell’applicazione c’è una voce specifica che si chiama App Spec, facendo edit si ottiene l’attuale configurazione.
Ne ho copiato il contenuto e l’ho incollato nel file app.yaml
dentro la cartella .do
. Per far funzionare le cose è stato necessario cambiare la sezione relativa agli static sites, ottenendo il seguente contenuto
alerts:
- rule: DEPLOYMENT_FAILED
- rule: DOMAIN_FAILED
features:
- buildpack-stack=ubuntu-22
ingress:
rules:
- component:
name: example-personal-site
match:
path:
prefix: /
name: example-personal-site
region: fra
static_sites:
- dockerfile_path: .do/Dockerfile
github:
branch: main
deploy_on_push: true
repo: Kyserbyte/example-personal-site
name: example-personal-site
source_dir: /
output_dir: /app/public
in sostanza cambiando la configurazione da go a docker.
Push delle modifiche su GitHub e upload del nuovo file su Digital Ocean, sempre tramite i settings dell’app, nella stessa sezione da dove ho preso la config c’è la possibilità di fare upload del file.
Il push verso GitHub fa automaticamente partire il deployment su Digital Ocean, grazie all’integrazione fatta prima. Qualche attimo di attesa et voilà, il mio sito è online raggiungibile tramite un indirizzo specifico che mi ha sseganto Digital Ocean.
Configurazione DNS
Ultimo passaggio effettuato è stato quello di associare l’indirizzo IP pubblico che mi hasseganto Digital Ocean con il nome di dominio che ho acquistato. Ho inserito un record di tipo A che associa il domain all’IP.
Conclusioni
Questo è quello che ho fatto per mettere online il mio sito web personale. Se volete adottare lo stesso approccio dovete ovviamente customizzare tutto a vostro piacimento, dalla scelta del tema, ai vari nomi (chiaramente non chiamerete il progetto ed il sito example-personal-site) ma la procedura rimane la stessa. Godetevi il vostro sito web personale gratuito (o quasi) , io lo sto facendo 😁