Skip to content

dmitriimaksimovdevelop/startup-infra

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hetzner Kubernetes Infrastructure

Production-ready Kubernetes cluster on Hetzner Cloud, fully managed with Terraform. Designed for small startups and indie projects that need a cost-effective, secure, and automated infrastructure.

What You Get

A single terraform apply provisions:

  • Talos Linux cluster (immutable, minimal, no SSH) on Hetzner Cloud
  • Cilium CNI with eBPF (replaces kube-proxy), Hubble observability
  • Traefik ingress controller with Gateway API support
  • cert-manager with Let's Encrypt for automatic TLS
  • Hetzner CCM + CSI for cloud load balancers and persistent volumes
  • VictoriaMetrics + Grafana for metrics monitoring
  • Loki + Promtail for centralized log aggregation
  • GitHub Actions Runner Controller (ARC) for in-cluster CI/CD runners
  • Hetzner DNS management for your domain
  • Werf-based application deployment pipeline

Architecture

                    Internet
                       |
              [ Hetzner LB (Traefik) ]
                       |
        +--------------+--------------+
        |              |              |
   [ cp-1 ]      [ cp-2 ]      [ cp-3 ]      (Talos Linux, control plane)
        |              |              |
        +----- Private Network -------+
                       |
              [ Hetzner LB (K8s API) ]
                       |
                  You / CI/CD

Estimated Monthly Cost (Hetzner)

Resource Type ~Cost/mo
3x Control Plane cx33 ~34.47 EUR
1x API Load Balancer lb11 ~5.39 EUR
1x Traefik Load Balancer lb11 ~5.39 EUR
Object Storage (state + logs) S3 ~1-3 EUR
Total ~46-48 EUR

Workers are optional. By default, workloads run on control plane nodes.

Prerequisites

Quick Start

1. Prepare Hetzner Cloud

See docs/HETZNER_SETUP.md for detailed instructions:

  • Create an API token
  • Create an S3 bucket for Terraform state
  • Upload a Talos Linux snapshot

2. Configure Variables

cd terraform

# Copy and edit the example files
cp terraform.tfvars.example terraform.tfvars
cp backend.tfvars.example backend.tfvars

# Edit terraform.tfvars with your values
# Edit backend.tfvars with your S3 credentials
# Edit backend.tf to set your bucket name

3. Deploy

# Initialize Terraform (downloads providers, connects to backend)
terraform init

# Review the execution plan
terraform plan

# Apply (~10 minutes for initial deployment)
terraform apply

4. Access Your Cluster

# Save kubeconfig
terraform output -raw kubeconfig > ../kubeconfig
export KUBECONFIG=../kubeconfig

# Verify
kubectl get nodes
kubectl get pods -A

See docs/BOOTSTRAP.md for the full step-by-step guide.

Project Structure

.
├── terraform/                  # Infrastructure as Code
│   ├── variables.tf            # All input variables
│   ├── versions.tf             # Provider versions and configuration
│   ├── backend.tf              # S3 remote state configuration
│   ├── network.tf              # Hetzner private network
│   ├── firewall.tf             # Firewall rules
│   ├── load_balancer.tf        # K8s API load balancer
│   ├── servers.tf              # Hetzner servers (control plane + workers)
│   ├── talos.tf                # Talos machine configs, bootstrap, kubeconfig
│   ├── talos_patches.tf        # Talos machine config patches
│   ├── cilium.tf               # Cilium CNI (inline manifest for Talos)
│   ├── hcloud_ccm.tf           # Hetzner Cloud Controller Manager
│   ├── csr_approver.tf         # Kubelet CSR auto-approver
│   ├── gateway_api.tf          # Gateway API CRDs + kubeconfig
│   ├── traefik.tf              # Traefik ingress controller
│   ├── cert_manager.tf         # cert-manager, ClusterIssuer, Gateway, Certificate
│   ├── dns.tf                  # Hetzner DNS zone and records
│   ├── monitoring.tf           # VictoriaMetrics, Grafana, Loki, Promtail, CSI
│   ├── arc.tf                  # GitHub Actions Runner Controller
│   ├── outputs.tf              # Terraform outputs
│   ├── locals.tf               # Local computed values
│   ├── terraform.tfvars.example
│   ├── backend.tfvars.example
│   └── charts/                 # Local Helm charts
│       └── hcloud-secret/      # Hetzner Cloud token secret
├── charts/                     # Shared Helm library charts
│   └── app-template/           # Reusable Deployment+Service+Secret templates
├── apps/                       # Application deployments (Werf + Helm)
│   └── myapp/                  # Example app (Nginx static site)
│       ├── Dockerfile
│       ├── werf.yaml
│       └── .helm/              # Helm chart (uses app-template)
├── .github/workflows/          # CI/CD pipeline examples
│   ├── infra.yaml.example      # Terraform plan/apply workflow
│   └── deploy.yaml.example     # Werf deploy workflow
├── docs/                       # Documentation
│   ├── HETZNER_SETUP.md        # Hetzner Cloud preparation guide
│   ├── BOOTSTRAP.md            # Step-by-step bootstrap guide
│   └── APPLICATIONS.md         # Werf deployment & app-template reference
├── Makefile                    # Convenience commands
├── SECURITY.md                 # Security policy and considerations
└── LICENSE                     # Apache 2.0

Deploying Applications

Applications are built and deployed with Werf -- a CLI tool that handles Docker build, push to GHCR, and Helm deploy in one step. Each app lives in apps/<name>/ with a Dockerfile and Helm chart.

The included myapp is a minimal example: an Nginx container serving a static HTML page. It demonstrates the full pattern:

apps/myapp/
├── Dockerfile          # Build instructions (nginx + index.html)
├── werf.yaml           # Tells Werf which Dockerfile to build
├── index.html          # Your application code
└── .helm/
    ├── Chart.yaml      # Depends on shared app-template library chart
    ├── templates/
    │   └── app.yaml    # {{ include "app-template.all" . }}
    └── values.yaml     # Replicas, ports, resources, env, secrets

The shared charts/app-template/ library chart generates Deployment + Service + Secret from values.yaml -- no boilerplate YAML needed.

# Create a new app from the example
make new-app NAME=my-service

# Edit apps/my-service/Dockerfile and .helm/values.yaml
# Push to main branch -- the deploy workflow handles the rest

See docs/APPLICATIONS.md for the full guide: values reference, advanced examples, local development with Werf, and CI/CD setup.

Customization

Adding Workers

# In terraform.tfvars
worker_count      = 2
worker_server_type = "cx33"

Changing Server Types

See Hetzner server types for available options:

  • cx22 -- 2 vCPU, 4 GB RAM (~4.49 EUR/mo)
  • cx33 -- 3 vCPU, 8 GB RAM (~11.49 EUR/mo)
  • cx43 -- 4 vCPU, 16 GB RAM (~18.49 EUR/mo)

Disabling Components

Components are modular Terraform files. To disable a component, remove or rename the file:

# Disable ARC (GitHub Actions runners)
mv terraform/arc.tf terraform/arc.tf.disabled

# Disable monitoring stack
mv terraform/monitoring.tf terraform/monitoring.tf.disabled

Destroying the Cluster

cd terraform
terraform destroy

Warning: This will permanently delete ALL cluster resources including volumes and data.

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Open a pull request

License

This project is licensed under the Apache License 2.0 -- see the LICENSE file for details.

About

Production-ready Kubernetes on Hetzner Cloud with Talos Linux, Cilium, Traefik, cert-manager, VictoriaMetrics, Loki, and GitHub Actions runners. Designed for startups.

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors