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 app settings in Digital Ocean
e poi edit su Resource Type e qui ho scelto Static Site.
Edit app settings in Digital Ocean

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.

Edit app settings in Digital Ocean

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 😁