Dietro le quinte

Cosa succede da git push
alla produzione.

Questo sito non è una vetrina statica: è costruito come una piattaforma reale, con CI/CD, quality gate, osservabilità e AI integrata. Ho scomposto tutto fase per fase — non per riempire, ma per mostrare cosa controllo davvero prima di considerare una release pronta.

Lo dico subito: è volutamente over-engineered

Per un portfolio personale questa architettura è esagerata, e va benissimo così. Volevo una piattaforma vera, production-ready — il portfolio è la dimostrazione pratica di come costruisco i prodotti dei clienti.

Pipeline CI/CD

Il flusso, fase per fase

01

Push su GitHub → trigger Actions

Un push su branch main avvia automaticamente la GitHub Action del repository coinvolto (frontend o backend). Nessun deploy fatto a mano: da qui in poi il processo è deterministico e tracciato.

GitHubbranch: mainwebhook trigger
02

Runner self-hosted sulla VPS

Il job viene preso in carico da un runner self-hosted installato direttamente sul server di produzione. Nessun costo di minuti CI, nessun trasferimento di rete tra runner e server: tutto gira già dove deve girare.

GitHub Actionsself-hosted runnerVPS
03

SonarQube analysis (solo backend)

Prima di toccare qualsiasi file sul server, il workflow backend esegue mvn clean package sonar:sonar: analisi statica del codice Java per code smell, vulnerabilità e duplicazioni. Il quality gate è configurato come asincrono — il risultato è tracciato ma non blocca il deploy.

SonarQubemvn sonar:sonarquality gate asyncsolo backend
04

rsync del sorgente sulla VPS

Il codice sorgente del repository viene copiato nella cartella di destinazione sul server via rsync, escludendo .git. Non vengono trasferiti artefatti compilati: la compilazione avviene dopo, dentro Docker.

rsync--exclude=.git/home/ubuntu/portfolio/
05

docker compose build

Docker ricostruisce l'immagine dal Dockerfile locale presente nella cartella copiata. È qui che avviene la compilazione vera: il Dockerfile del frontend esegue ng build e copia il dist in Nginx; quello del backend esegue mvn package e incapsula il JAR. Le immagini finali non contengono sorgenti né tool di build.

docker compose build--no-cacheDockerfile localemulti-stage
06

docker compose up -d

Compose riavvia solo il container aggiornato (portfolio_frontend o portfolio_backend) senza toccare il resto della stack. Il vecchio container viene sostituito con quello nuovo appena l'immagine è pronta.

docker compose up -dsolo il container aggiornato
07

Nginx reverse proxy

Nginx è sempre in esecuzione e continua a rispondere durante il deploy. Gestisce TLS, header di sicurezza e routing: serve i file statici del frontend direttamente, passa le chiamate /api/* al container Spring Boot.

NginxTLS / HTTPSheader securityrouting /api/*
08

Osservabilità: Loki + Grafana

Loki raccoglie i log da tutti i container Docker e da Nginx. Grafana li espone con dashboard real-time. Se qualcosa si rompe, lo scopro io prima degli utenti.

LokiGrafanaDocker logsNginx logs
Architettura

Come sono collegati i pezzi

Due flussi principali: le richieste HTTP e il ciclo RAG per il chatbot AI.

Flusso HTTP
Browserclient
Nginxproxy + TLS + routing
AngularSPA Angular
Spring Boot 4REST API
PostgreSQLdati + vettori
Flusso RAG & AI
Chatbotdomanda utente
Spring AIRAG pipeline
pgvectorsimilarity search
OpenAIembeddings + chat
Osservabilità
Dockercontainer logs
Nginxaccess + error logs
Lokilog aggregation
Grafanadashboard + alert
In pratica

Un deploy, in poche righe

L'intero rilascio sta in un file YAML. Leggibile, versionato, ripetibile: un push fa tutto il resto.

# deploy-backend.yml
runs-on: self-hosted
steps:
  - ./mvnw clean package sonar:sonar # quality gate asincrono
  - rm -rf /home/ubuntu/portfolio/backend/*
  - rsync -av --exclude='.git' ./ /home/ubuntu/portfolio/backend/
  - docker compose build --no-cache portfolio_backend
  - docker compose up -d portfolio_backend

# deploy-portfolio-frontend.yml
runs-on: self-hosted
steps:
  - rm -rf /home/ubuntu/portfolio/frontend/*
  - rsync -av --exclude='.git' ./ /home/ubuntu/portfolio/frontend/
  - docker compose build --no-cache portfolio_frontend
  - docker compose up -d portfolio_frontend

Ti serve qualcuno che pensi anche al «dopo il deploy»?

Architettura, sicurezza, delivery e osservabilità non sono un extra: sono il lavoro vero. Parliamone.