UbuntuNginxCloudflare TunnelSystemdGitBashFail2ban

Self-Hosted Infrastructure

Ubuntu home server running multiple production websites via Cloudflare Tunnel, nginx, and systemd. Zero public ports, full control.

Cooper Howling
Status: active

Overview

Rather than relying on cloud hosting providers, we run our production websites on a home server. This gives us full control over the stack, eliminates recurring hosting costs, and serves as a hands-on learning environment for infrastructure management.

Architecture

The server runs Ubuntu and hosts multiple independent websites, each isolated in its own directory with its own systemd service and nginx server block.

Traffic Flow

Internet → Cloudflare (DNS + SSL + WAF)
         → Cloudflare Tunnel (outbound-only)
         → nginx (localhost:80)
         → Node.js / Python backends (localhost:3001, 8000, etc.)

Key Components

  • Cloudflare Tunnel (cloudflared) — establishes an outbound-only connection to Cloudflare’s edge. The server has zero public ports, making it invisible to port scanners.
  • Nginx — reverse proxy with separate server blocks per domain. Handles static asset caching, rate limiting, security headers, and upstream proxying.
  • Systemd — each application runs as a managed service with automatic restart, logging, and resource limits.
  • Git-based deployment — push code from development machine, SSH into server, pull, build, restart service.

Security

  • No public ports (SSH is tunneled or local-only)
  • Fail2ban for SSH brute-force protection
  • Cloudflare WAF and Bot Fight Mode
  • Per-site CSP headers and rate limiting
  • Environment variables for all secrets
  • Unprivileged service users

Sites Hosted

  • howlingglobal.com — Astro SSR (Node.js)
  • calgaryhomeestimate.com — FastAPI + React (Python/Node.js)