Skip to content

Repository files navigation

Portfolio & Technical Blog

Personal portfolio built with Astro, TypeScript and Docker, deployed to a self-hosted Linux VPS through a GitHub Actions CI/CD pipeline.

The project focuses on containerization, reverse proxying, automated deployments, networking and production infrastructure.

🌐 caixeta.dev


Architecture

Project Infrastructure

The application runs on a self-hosted Linux VPS behind Cloudflare, with Traefik handling reverse proxying and TLS, and Nginx serving the generated Astro application.

Network Flow

Internet
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Cloudflare  β”‚
β”‚              β”‚
β”‚ DNS / Proxy  β”‚
β”‚ Bot Defense  β”‚
β”‚ DDoS         β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β”‚ HTTPS
       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ VPS ────────────────────┐
β”‚                                             β”‚
β”‚                 Traefik                     β”‚
β”‚          Reverse Proxy / TLS                β”‚
β”‚                     β”‚                       β”‚
β”‚                     β–Ό                       β”‚
β”‚                  Nginx                      β”‚
β”‚                     β”‚                       β”‚
β”‚                     β–Ό                       β”‚
β”‚              Astro Static Site              β”‚
β”‚                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Cloudflare is used as the public edge layer, keeping the VPS origin IP hidden from normal visitors and providing an additional security layer in front of the infrastructure.

Traffic is routed through Cloudflare before reaching Traefik on the VPS.

This provides:

  • Origin IP protection through Cloudflare's proxy
  • DDoS protection
  • Bot protection and filtering
  • DNS management
  • HTTPS/TLS at the edge
  • Reverse proxying through Traefik
  • A separation between the public edge and the application infrastructure

Production Infrastructure

The production environment is composed of:

  • Cloudflare β€” DNS, proxy, edge security and bot protection
  • Linux VPS β€” self-hosted production environment
  • Docker & Docker Compose β€” application packaging and orchestration
  • Traefik β€” reverse proxy, routing and TLS
  • Nginx β€” static file serving, compression and caching
  • Let's Encrypt β€” TLS certificates
  • GitHub Container Registry β€” Docker image registry

The application uses a multi-stage Docker build:

Node.js
   β”‚
   β”œβ”€β”€ Install dependencies
   └── Build Astro application
            β”‚
            β–Ό
         /dist
            β”‚
            β–Ό
      Nginx Alpine
            β”‚
            β–Ό
      Production Container

Node.js and the build tooling are not included in the final runtime image.


CI/CD

The deployment pipeline is fully automated with GitHub Actions.

Pull Requests

Pull Request
     β”‚
     β”œβ”€β”€ Prettier check
     └── Astro production build

Production Deployment

Push to main
     β”‚
     β–Ό
GitHub Actions
     β”‚
     β”œβ”€β”€ Run CI checks
     β”œβ”€β”€ Build Docker image
     β”œβ”€β”€ Push image to GHCR
     └── Trigger authenticated webhook
                    β”‚
                    β–Ό
                   VPS
                    β”‚
             Docker Compose
                    β”‚
                    β–Ό
             New application

Images are tagged with the Git commit SHA, allowing each production deployment to reference an immutable version.

The deployment webhook is protected with HMAC-SHA256 authentication, so only authorized requests can trigger a deployment.


Blog & Content

The portfolio also includes a technical blog built with MDX and Astro Content Collections.

Posts are version-controlled alongside the application:

src/posts/
β”œβ”€β”€ lsof-command-tutorial.mdx
β”œβ”€β”€ how-inode-works.mdx
β”œβ”€β”€ ssh-config.mdx
└── ...

Content is statically generated during the Astro build, so the production environment does not require a database or application server.

This gives the blog a simple Git-based publishing workflow:

MDX β†’ Git β†’ CI β†’ Build β†’ Docker β†’ Production

Tech Stack

Area Technologies
Application Astro, TypeScript, React, MDX, Tailwind CSS
Edge / Security Cloudflare, DNS Proxy, DDoS & Bot Protection
Infrastructure Linux, VPS, Docker, Docker Compose
Networking Traefik, Nginx, HTTPS, Let's Encrypt
CI/CD GitHub Actions, GHCR, Docker Buildx
Security HMAC-SHA256 deployment authentication
Content Astro Content Collections, MDX

Key Engineering Practices

  • Self-hosted production environment running on a Linux VPS
  • Cloudflare as the public edge layer, hiding the origin IP and filtering malicious/bot traffic
  • Multi-stage Docker builds with a minimal runtime image
  • Automated CI/CD with GitHub Actions
  • Immutable deployments using Git commit SHA image tags
  • Authenticated deployment webhook protected with HMAC-SHA256
  • Reverse proxy and TLS with Traefik
  • Static content delivery through Nginx
  • Git-based content management for the technical blog

Local Development

corepack enable
pnpm install
pnpm dev

Build for production:

pnpm build

About

🌱 my personal website built with astro, where i showcase my projects and write about what I’m learning.

Topics

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages