Infrastructure Architecture
Comprehensive CI/CD infrastructure specification for Hetzner Cloud VPS deployment
RippleCore Infrastructure Architecture
Comprehensive CI/CD infrastructure specification for Hetzner Cloud VPS deployment
Target Scale: Medium (3-10 apps, 1K-50K users) Pattern: Service-Oriented Architecture with shared services Expertise Level: Intermediate (Docker/Git proficiency) Management Philosophy: Balanced control with managed tooling
Table of Contents
- Architecture Overview
- Server Infrastructure
- Network Architecture
- Technology Stack
- Deployment Environments
- Scaling Strategy
- Cost Analysis
Architecture Overview
High-Level Architecture Diagram
┌─────────────────────────────────────────────────────────────────┐
│ INTERNET (Users) │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ DNS + Cloudflare (Optional) │
│ app.domain.com → 88.99.xxx.xxx (Production App Server) │
│ api.domain.com → 88.99.xxx.xxx (Production App Server) │
│ www.domain.com → 88.99.xxx.xxx (Production App Server) │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ PRODUCTION APP SERVER (CPX32) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Traefik Reverse Proxy (SSL Termination) │ │
│ │ - Let's Encrypt SSL certificates │ │
│ │ - Auto-renewal every 90 days │ │
│ │ - HTTP → HTTPS redirect │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Main App │ │ API Server │ │ Marketing │ │
│ │ (Next.js) │ │ (Next.js) │ │ Web │ │
│ │ Port: 3000 │ │ Port: 3002 │ │ Port: 3001 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ↓ ↓ │
└─────────────────────────────────────────────────────────────────┘
↓
Private Network (10.0.0.0/16)
↓
┌─────────────────────────────────────────────────────────────────┐
│ PRODUCTION DB SERVER (CPX22) │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ PostgreSQL 18 │ │ Redis 7 │ │
│ │ Port: 5432 │ │ Port: 6379 │ │
│ │ - Multi-tenant data │ │ - Session store │ │
│ │ - Drizzle ORM │ │ - Cache layer │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Automated Backups (Daily 3 AM) │ │
│ │ → Hetzner Object Storage (S3-compatible) │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ CI/CD SERVER (CPX11) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Dokploy │ │
│ │ - Git-based deployments │ │
│ │ - Environment management │ │
│ │ - Zero-downtime deployments │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Docker Build Cache │ │
│ │ GitHub Container Registry Mirror │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ STAGING SERVER (CPX22) │
│ - All services on single server (apps + DB + Redis) │
│ - Production-like configuration for QA testing │
│ - PR preview environments (ephemeral) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ GITHUB ACTIONS (CI) │
│ - Lint & Type Check (Biome) │
│ - Run Tests (Vitest) │
│ - Build Docker Images │
│ - Security Scan (Trivy) │
│ - Push to GitHub Container Registry │
└─────────────────────────────────────────────────────────────────┘Server Infrastructure
Production Environment
App Server (CPX32 - 4 vCPU, 8GB RAM, 80GB NVMe SSD)
Monthly Cost: €11.99 Location: Falkenstein, Germany (eu-central)
Hosted Services:
- Main Application (Next.js 16 + React 19) - Port 3000
- API Server (Next.js API routes) - Port 3002
- Marketing Website (Next.js) - Port 3001
- Traefik Reverse Proxy - Ports 80/443
- Netdata (monitoring agent) - Port 19999
Resource Allocation:
Main App:
cpu_limit: 1.5 vCPU
memory_limit: 3GB
API Server:
cpu_limit: 1.5 vCPU
memory_limit: 2GB
Marketing Web:
cpu_limit: 0.5 vCPU
memory_limit: 1GB
Traefik:
cpu_limit: 0.3 vCPU
memory_limit: 512MB
System Reserve:
cpu: 0.2 vCPU
memory: 1.5GBJustification:
- CPX32 provides headroom for traffic spikes (2-3x baseline)
- NVMe SSD ensures fast Docker image loading
- 8GB RAM supports 3 apps + reverse proxy comfortably
Database Server (CPX22 - 3 vCPU, 4GB RAM, 80GB NVMe SSD)
Monthly Cost: €8.49 Location: Falkenstein, Germany (same datacenter as app server)
Hosted Services:
- PostgreSQL 18 (Docker container) - Port 5432
- Redis 7 (Docker container) - Port 6379
- Backup Cron Jobs (daily 3 AM backups)
- Netdata (monitoring agent) - Port 19999
Resource Allocation:
PostgreSQL:
cpu_limit: 2 vCPU
memory_limit: 2.5GB
shared_buffers: 512MB
effective_cache_size: 1.5GB
Redis:
cpu_limit: 0.5 vCPU
memory_limit: 1GB
maxmemory: 768MB
maxmemory_policy: allkeys-lru
System Reserve:
cpu: 0.5 vCPU
memory: 512MBStorage Strategy:
- Database Data: 40GB allocated (current: ~5GB, 3-year growth)
- Redis Data: 5GB allocated (RDB snapshots + AOF)
- Backup Staging: 10GB (compressed dumps before S3 upload)
- System/Logs: 25GB
Justification:
- Dedicated server prevents resource contention
- Isolated failures (app crash ≠ DB crash)
- Independent scaling path (add read replicas)
- Better security (private network only)
CI/CD Server (CPX11 - 2 vCPU, 2GB RAM, 40GB SSD)
Monthly Cost: €4.15 Location: Falkenstein, Germany
Hosted Services:
- Dokploy - Port 3000 (web UI)
- Docker Engine - For container orchestration
- Traefik (bundled with Dokploy) - Ports 80/443
- Netdata - Port 19999
Responsibilities:
- Git webhook receiver (GitHub → Dokploy)
- Docker image builder (optional, can use GitHub Actions)
- Deployment orchestrator
- Environment variable management
- SSL certificate management
Justification:
- CPX11 sufficient for Dokploy management interface
- Actual builds happen in GitHub Actions (no compute needed)
- Can be upgraded to CPX21 if local builds needed
Staging Server (CPX22 - 3 vCPU, 4GB RAM, 80GB SSD)
Monthly Cost: €8.49 Location: Falkenstein, Germany
Hosted Services:
- All production apps (combined on single server)
- PostgreSQL 18 (staging database)
- Redis 7 (staging cache)
- PR preview environments (ephemeral Docker containers)
Purpose:
- Production-like environment for QA testing
- Integration testing before production deployment
- Preview deployments for pull requests
- Customer demo environment
Justification:
- Single server acceptable (not critical workload)
- Cost-effective for non-production use
- Can be resized if preview environments grow
Object Storage (Backups)
Hetzner Object Storage (S3-compatible)
Current Usage: 10GB (database backups)
Monthly Cost: €0.25 (€0.005/GB/month)
Backup Structure:
s3://ripplecore-backups/
├── postgres/
│ ├── daily/ (7-day retention)
│ ├── weekly/ (4-week retention)
│ └── monthly/ (12-month retention)
└── redis/
└── snapshots/ (7-day retention)Additional Infrastructure
Floating IPs (2x)
- Production App Server: 1 floating IP (€1.17/mo)
- Staging Server: 1 floating IP (€1.17/mo) Total: €2.34/month
Benefits:
- Instant failover (reassign IP to new server)
- No DNS propagation delay during DR
- Persistent IP even if server replaced
Cloud Firewall (Free)
- Ingress rules (allow 80, 443, 22 from specific IPs)
- Egress rules (allow all for package updates)
- Applied to all 4 servers
Network Architecture
Security Groups & Firewall Rules
App Server (Production + Staging):
Ingress:
- Port 80 (HTTP): 0.0.0.0/0 (public)
- Port 443 (HTTPS): 0.0.0.0/0 (public)
- Port 22 (SSH): <YOUR_OFFICE_IP>/32 (restricted)
- Port 19999 (Netdata): <YOUR_OFFICE_IP>/32 (restricted)
Egress:
- All ports: 0.0.0.0/0 (required for package updates, webhooks)Database Server:
Ingress:
- Port 5432 (PostgreSQL): 10.0.0.0/16 (private network only)
- Port 6379 (Redis): 10.0.0.0/16 (private network only)
- Port 22 (SSH): <YOUR_OFFICE_IP>/32 (restricted)
- Port 19999 (Netdata): <YOUR_OFFICE_IP>/32 (restricted)
Egress:
- All ports: 0.0.0.0/0 (required for backups to S3)CI/CD Server:
Ingress:
- Port 80 (HTTP): 0.0.0.0/0 (redirect to HTTPS)
- Port 443 (HTTPS): 0.0.0.0/0 (Dokploy UI + webhooks)
- Port 22 (SSH): <YOUR_OFFICE_IP>/32 (restricted)
Egress:
- All ports: 0.0.0.0/0 (GitHub webhooks, Docker Hub)Private Networking
Hetzner Cloud Private Network:
- CIDR:
10.0.0.0/16 - Subnet:
10.0.1.0/24(production) - Subnet:
10.0.2.0/24(staging)
Server Assignments:
Production:
app_server: 10.0.1.2
db_server: 10.0.1.3
Staging:
staging_server: 10.0.2.2
CI/CD:
cicd_server: 10.0.1.4Benefits:
- Database access only via private network (no public exposure)
- Low-latency communication between app and DB (<1ms)
- Free data transfer within private network
Technology Stack
Infrastructure Layer
| Component | Technology | Version | Purpose |
|---|---|---|---|
| Cloud Provider | Hetzner Cloud | - | VPS hosting, object storage |
| OS | Ubuntu | 24.04 LTS | Server operating system |
| Container Runtime | Docker | 27.x | Application containerization |
| Reverse Proxy | Traefik | 3.x | Load balancing, SSL termination |
| Deployment Platform | Dokploy | Latest | Git-based deployment automation |
| Container Registry | GitHub Container Registry | - | Docker image storage |
Application Layer
| Component | Technology | Version | Purpose |
|---|---|---|---|
| Framework | Next.js | 16.x | React framework (apps + API) |
| Database | PostgreSQL | 18 | Relational data storage |
| Cache | Redis | 7.x | Session store + application cache |
| ORM | Drizzle | Latest | Type-safe database queries |
| Auth | better-auth | Latest | Authentication & sessions |
CI/CD Layer
| Component | Technology | Version | Purpose |
|---|---|---|---|
| CI Platform | GitHub Actions | - | Automated testing & building |
| CD Platform | Dokploy | Latest | Deployment orchestration |
| Security Scanning | Trivy | Latest | Container vulnerability scanning |
| Artifact Storage | GitHub Container Registry | - | Docker image hosting |
Monitoring Layer
| Component | Technology | Version | Purpose |
|---|---|---|---|
| Infrastructure Monitoring | Netdata | Latest | CPU, RAM, disk, network metrics |
| Uptime Monitoring | UptimeRobot | - | Health check monitoring |
| Error Tracking | Sentry | Latest | Application error tracking |
| Log Management | Docker Logs | - | Container log aggregation |
Deployment Environments
Environment Matrix
| Environment | Branch | Server | Domain | Purpose | Auto-Deploy |
|---|---|---|---|---|---|
| Development | develop | Local | localhost:3000 | Feature development | No |
| Preview/PR | feature/* | Staging | pr-123.staging.domain.com | PR review | Yes |
| Staging | staging | Staging | staging.domain.com | QA testing | Yes |
| Production | main | Production | app.domain.com | Live users | Yes (with approval) |
Environment Configuration Strategy
Shared Configuration (all environments):
- Same codebase (Git monorepo)
- Same Docker images (tagged by environment)
- Same infrastructure-as-code (different variables)
Environment-Specific Variables:
# Development (.env.local)
DATABASE_URL=postgresql://ripplecore:dev@localhost:5432/ripplecore
REDIS_URL=redis://:dev@localhost:6379
BETTER_AUTH_URL=http://localhost:3000
# Staging (Dokploy env vars)
DATABASE_URL=postgresql://ripplecore:staging@10.0.2.2:5432/ripplecore_staging
REDIS_URL=redis://:staging@10.0.2.2:6379
BETTER_AUTH_URL=https://staging.your-domain.com
# Production (Dokploy env vars - encrypted)
DATABASE_URL=postgresql://ripplecore:<secret>@10.0.1.3:5432/ripplecore_prod
REDIS_URL=redis://:<secret>@10.0.1.3:6379
BETTER_AUTH_URL=https://app.your-domain.comScaling Strategy
Vertical Scaling (Current Phase)
When to Upgrade Servers:
| Server | Current | Upgrade Trigger | Next Size | New Cost |
|---|---|---|---|---|
| App Server | CPX32 (4 vCPU, 8GB) | CPU >70% sustained | CPX42 (8 vCPU, 16GB) | €26.99/mo (+€15) |
| DB Server | CPX22 (3 vCPU, 4GB) | RAM >80% sustained | CPX32 (4 vCPU, 8GB) | €11.99/mo (+€3.50) |
| CI/CD | CPX11 (2 vCPU, 2GB) | Build timeouts | CPX21 (3 vCPU, 4GB) | €6.35/mo (+€2.20) |
Vertical Scaling Limits:
- Hetzner Cloud max: CCX63 (48 vCPU, 192GB RAM) - €334.99/mo
- Practical limit for single app server: CPX52 (16 vCPU, 32GB) - €61.99/mo
Horizontal Scaling (Future Phase)
Trigger Conditions (when vertical scaling insufficient):
- Traffic: >50K concurrent users
- Apps: >10 applications deployed
- Geographic: Multi-region required
- Availability: 99.9%+ SLA needed
Horizontal Scaling Architecture:
┌─────────────────────────────────────────────────────────────┐
│ Hetzner Cloud Load Balancer (€5.83/mo) │
│ - Distributes traffic across app servers │
│ - Health checks with automatic failover │
│ - SSL termination (Let's Encrypt) │
└─────────────────────────────────────────────────────────────┘
↓
┌────────────────┴────────────────┐
↓ ↓
┌─────────────────┐ ┌─────────────────┐
│ App Server 1 │ │ App Server 2 │
│ CPX32 (8GB) │ │ CPX32 (8GB) │
│ - Main App │ │ - Main App │
│ - API Server │ │ - API Server │
│ - Marketing │ │ - Marketing │
└─────────────────┘ └─────────────────┘
↓ ↓
└────────────────┬────────────────┘
↓
┌─────────────────────┐
│ Database Server │
│ CPX32 (8GB) │
│ + Read Replicas │
└─────────────────────┘Additional Costs at Horizontal Scale:
- Load Balancer: €5.83/mo
- 2nd App Server: €11.99/mo
- DB Read Replica: €8.49/mo (CPX22)
- Total Add: €26.31/mo (€62/mo total infrastructure)
Database Scaling Path
Phase 1: Single PostgreSQL instance (current) Phase 2: Primary + Read Replica Phase 3: Primary + Multiple Read Replicas Phase 4: Managed PostgreSQL (e.g., Neon, Supabase, AWS RDS)
Read Replica Setup (when needed):
Primary (CPX32 - 8GB):
- All writes (INSERT, UPDATE, DELETE)
- Critical reads (transactions, admin)
Read Replica 1 (CPX22 - 4GB):
- Reporting queries
- Analytics dashboards
- Non-critical reads
Application Logic:
- Write operations → Primary
- Read operations → Read Replica (with fallback to Primary)
- Connection pooling via PgBouncerCost Analysis
Monthly Infrastructure Costs (Current Architecture)
| Component | Specification | Monthly Cost | Annual Cost |
|---|---|---|---|
| Production App Server | CPX32 (4 vCPU, 8GB RAM) | €11.99 | €143.88 |
| Production DB Server | CPX22 (3 vCPU, 4GB RAM) | €8.49 | €101.88 |
| CI/CD Server | CPX11 (2 vCPU, 2GB RAM) | €4.15 | €49.80 |
| Staging Server | CPX22 (3 vCPU, 4GB RAM) | €8.49 | €101.88 |
| Object Storage | ~50GB (backups) | €0.25 | €3.00 |
| Floating IPs | 2x static IPs | €2.34 | €28.08 |
| Cloud Firewall | Free | €0.00 | €0.00 |
| Subtotal | €35.71 | €428.52 |
External Service Costs (Optional)
External Service Costs:
- UptimeRobot: Free tier - €0.00/month, €0.00/year (50 monitors, 5-minute checks)
- Netdata Cloud: Free tier - €0.00/month, €0.00/year (Team dashboards, less than 5 nodes)
- Sentry: Free tier - €0.00/month, €0.00/year (10K events/month, or €26/month paid) | GitHub Actions | Free | €0.00 | €0.00 | 2,000 min/mo (public repos) | | Subtotal | | €0.00 | €0.00 |
Total Monthly Cost: €35.71 (~$39 USD)
Cost Comparison (Equivalent AWS Infrastructure)
AWS Equivalent (us-east-1 region):
- 2x t3.medium (2 vCPU, 4GB) - $60/mo
- 2x t3.large (2 vCPU, 8GB) - $120/mo
- RDS PostgreSQL db.t3.medium - $65/mo
- ElastiCache Redis cache.t3.micro - $15/mo
- S3 Storage 50GB - $1.15/mo
- ALB Load Balancer - $16.20/mo
- Total: ~$277/mo (~8x more expensive)
Hetzner Advantage: 87% cost savings vs. AWS for equivalent resources
Cost Projections (3-Year Growth)
Year 1 (Current - 5K users):
- Infrastructure: €35.71/mo
- Estimated traffic: 100K requests/day
Year 2 (Growth - 20K users):
- Upgrade App Server: CPX42 (€26.99/mo, +€15)
- Add Load Balancer: €5.83/mo
- Estimated total: €57/mo (+60%)
Year 3 (Scale - 50K users):
- 2x App Servers: CPX42 (€53.98/mo)
- Upgrade DB: CPX32 (€11.99/mo)
- Add Read Replica: CPX22 (€8.49/mo)
- Load Balancer: €5.83/mo
- Estimated total: €86/mo (+141% from Year 1)
Still 70% cheaper than AWS at Year 3 scale
Implementation Resources
Related Documentation
- CI/CD Pipeline: See
CI_CD_PIPELINE.mdfor GitHub Actions + Dokploy setup - Monitoring: See
MONITORING.mdfor Netdata + UptimeRobot configuration - Backup & DR: See
BACKUP_RECOVERY.mdfor backup automation and disaster recovery - Deployment Checklist: See
DEPLOYMENT_CHECKLIST.mdfor pre-launch verification
Quick Start Commands
# Provision servers via Hetzner Cloud Console or CLI
hcloud server create --name ripplecore-app-prod --type cpx32 --image ubuntu-24.04 --location fsn1
hcloud server create --name ripplecore-db-prod --type cpx22 --image ubuntu-24.04 --location fsn1
# Install Dokploy (on CI/CD server)
curl -sSL https://dokploy.com/install.sh | sh
# Setup monitoring (on each server)
bash <(curl -Ss https://my-netdata.io/kickstart.sh)Support & Community
- Hetzner Support: https://console.hetzner.cloud (ticket system)
- Dokploy Discord: https://discord.gg/2tBnJ3jDJc
- RippleCore Team: [Your internal Slack/Discord channel]
Document Version: 1.0 Last Updated: 2025-01-23 Author: Infrastructure Team Review Cycle: Quarterly (or after major architecture changes)