Skip to content
Portfolio

Hetzner VPS & Docker Foundation

To ensure reliable performance and complete control over the environment, the foundation of this project is built on a Hetzner Virtual Private Server (VPS). To maintain a reproducible and isolated environment, all services are containerized using Docker and managed via Docker Compose.

  • Provider: Hetzner Cloud
  • OS: Ubuntu 24.04 LTS
  • Location: Nuremberg

Before deploying any containers, the host machine requires basic security hardening to prevent unauthorized access.

To secure remote access, password authentication is completely disabled in favor of cryptographic keys.

Furthermore, the server does not accept SSH connections from the public IP. Administrative access is strictly routed through the private Tailscale overlay network (100.x.x.x), rendering the server completely invisible to automated bot scanners.

Terminal window
# Connecting via the secure ZTNA tunnel
ssh root@100.x.x.x
apt update && apt upgrade -y

The official Docker engine is installed to manage the application lifecycle.

Terminal window
docker --version
docker compose version

The infrastructure is managed using modular, decoupled docker-compose.yml files for each service. To ensure maximum isolation while allowing traffic routing, containers that need to communicate with the Nginx Proxy Manager are connected via an external Docker network named proxy-network. Instead of running heavy Node.js servers, the built static files for the Astro portfolio and Starlight documentation are served using ultra-fast, lightweight Alpine Nginx containers.

# Snippet: Static Site Containers
services:
# Astro portfolio
web-portfolio:
image: nginx:alpine
container_name: astro-site
restart: unless-stopped
networks:
- proxy-network
volumes:
# Serves the actual static build via read-only mounts
- ./public_html:/usr/share/nginx/html:ro
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
# Starlight docs
web-docs:
image: nginx:alpine
container_name: starlight-docs
restart: unless-stopped
networks:
- proxy-network
volumes:
- ./docs:/usr/share/nginx/html:ro
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro

To verify the foundation is solid, running docker info should return the active server parameters without permission errors.

Proceed to Cloudflare DNS & Edge Routing to see how public traffic is directed to this server.