~/xavifortes

The site is the portfolio.

This website doesn't just talk about DevSecOps — it runs on a stack that demonstrates it. Every component is provisioned with IaC, every deployment is GitOps-driven, every secret is encrypted at rest. Here's the full breakdown.

OpenTofuTerragruntk3s v1.33.5ArgoCDGitHub ActionsCloudflare WAFTraefikcert-managerTrivyCheckovSOPS + Ageghcr.io
User
──HTTPS──▶
Cloudflare WAF
──proxy──▶
GRA8 HAProxy
──:443──▶
MAD1 Traefik
──route──▶
xavifortes-web pod
1

Push / PR

Developer pushes code to GitHub

──▶
2

Lint + Scan

ESLint, Prettier, Trivy, Checkov

──▶
3

Build Image

Multi-stage Docker build

──▶
4

Push to ghcr.io

Tagged :sha-<SHA> + :latest

──▶
5

Bump SHA

CI commits new tag to deployment.yaml

──▶
6

ArgoCD Sync

Cluster self-heals within ~3min

──▶
7

Live

xavifortes.com serves new build

Cloudflare WAF

IaC — Terraform

DDoS protection, bot management, custom WAF rules, rate limiting. SSL/TLS Full Strict mode. Acts as the global entry point for all traffic to xavifortes.com.

Cloudflare DNS

IaC — Terraform

DNS records managed 100% in Terraform via the cloudflare/cloudflare provider. No manual clicks in the dashboard. A record targets GRA8 HAProxy.

OVH GRA8 — HAProxy

OVH GRA8 · 2vCPU / 2GB

OVH VPS in Gravelines (GRA8). HAProxy routes :80/:443 to MAD1 Traefik, :6443 to kubeadm API server, :25565 to Minecraft. Provisioned with OpenTofu.

k3s HA — OVH MAD1 (3 nodes)

k3s v1.33.5 · OVH MAD1

3-node etcd k3s cluster on OVH Madrid LocalZone. Each node is 4vCPU/8GB. OpenTofu provisions the VPS instances; Ansible bootstraps k3s. Kubeconfig fetched via SOPS-encrypted vars.

Traefik Ingress

Helm · ArgoCD-managed

Handles TLS termination inside the cluster. Receives traffic from GRA8 HAProxy and routes to the correct Kubernetes service. IngressRoute CRDs used for routing.

cert-manager

Helm · ArgoCD-managed

Automatic TLS certificate provisioning from Let's Encrypt via ACME HTTP-01. Certificate resources live in the k8s manifests in this repo.

Longhorn

Helm · ArgoCD-managed

Distributed block storage across the 3 MAD1 nodes. Used for any stateful workloads. Portfolio site is stateless — Longhorn used by Matrix, Grafana, InfluxDB, etc.

ArgoCD

App-of-Apps pattern

Installed in the MAD1 cluster. Watches this repository's kubernetes/apps/ directory. Any merged change to the image tag or manifests is automatically applied to the cluster within ~3 minutes.

Image Tag Auto-Update

GitHub Actions → git commit

The CI pipeline commits the new ghcr.io image SHA back to deployment.yaml on every merge to main. ArgoCD detects the drift and self-heals. No manual kubectl apply, ever.

Lint & Format

Pull Request gate

ESLint + Prettier on Astro/TypeScript. tofu fmt + tofu validate on the Cloudflare Terraform. Runs on every PR.

Security Scans

Trivy · Checkov

Trivy scans the built Docker image for CVEs (CRITICAL/HIGH = fail). Checkov scans all Terraform configs for misconfigurations. Both must pass before merge.

Docker Build & Push

ghcr.io · multi-stage

Multi-stage Dockerfile: node:20-alpine builds Astro, nginx:alpine serves the static dist/. Image pushed to ghcr.io/xavifortes/web with both :sha-<SHA> and :latest tags.

Tag Bump Commit

GitOps trigger

After a successful push, the workflow updates kubernetes/apps/xavifortes-web/deployment.yaml with the new image SHA and commits it back to main, triggering ArgoCD.

GitHub Container Registry (ghcr.io)

ghcr.io/xavifortes/web

Private registry. Images tagged by git SHA for full traceability. ArgoCD pulls from ghcr.io using a k8s imagePullSecret. No self-hosted registry ops overhead.

almond — Ryzen 7 5800X / 64GB

Proxmox 8.4

Primary Proxmox node. Hosts kubeadm k8s cluster (3 VMs), k3s-ha node (1 VM), and LXCs: cloudflared, WireGuard, PostgreSQL, Minecraft, coder-server.

peanut — Ryzen 5 3600 / 32GB

Proxmox 8.4

Secondary Proxmox node. Hosts: TrueNAS SCALE (ZFS NAS), Home Assistant OS, nginx proxy manager, AdGuard, Homarr, PostgreSQL replica.

Self-Hosted GitHub Runners

ARC 0.9.3

ARC (Actions Runner Controller) on the MAD1 k3s cluster provides ephemeral self-hosted runners for the shellnet-infrastructure repo CI. Terraform plans run inside the cluster with LAN access.

Both repositories are public. Read the code, not just the claims.