diff --git a/infra/haproxy/README.md b/infra/haproxy/README.md new file mode 100644 index 0000000..e922d30 --- /dev/null +++ b/infra/haproxy/README.md @@ -0,0 +1,93 @@ +# HAProxy Configuration + +## Rationale + +This HAProxy instance serves as the primary entry point for the +homeserver infrastructure. It acts as a unified reverse proxy that +allows services from both Docker and Kubernetes environments to be +exposed behind a single, cohesive frontend. By using HAProxy with +SNI-based routing, the following can be achieved: + +- **Centralize SSL/TLS termination** across multiple backend + environments +- **Route traffic dynamically** based on the requested domain to either + Docker or Kubernetes services +- **Maintain a single point of entry** for external clients while + distributing load across heterogeneous backends +- **Simplify certificate management** by terminating SSL at one + location +- **Note**: TLS termination and certificate management are not handled in this + setup; SSL/TLS traffic is passed through to backend services + +## Overview + +HAProxy is used as a reverse proxy and load balancer to route incoming +HTTPS traffic to the appropriate backend services in the homeserver +setup. + +This HAProxy configuration implements SNI (Server Name Indication) +based routing to direct traffic to either the Kubernetes cluster or +Docker backend based on the requested domain. + +## Global Settings + +- **Logging**: Logs are written to syslog at `/dev/log` (local0) and + localhost (local2) +- **Admin Socket**: Accessible at `/run/haproxy/admin.sock` for + statistics and administration +- **Max Connections**: 10,000 concurrent connections +- **User/Group**: Runs as `haproxy` user and group + +## Default Timeout Settings + +- **Connect Timeout**: 5 seconds +- **Client Timeout**: 3600 seconds (1 hour) +- **Server Timeout**: 3600 seconds (1 hour) + +## Frontend Configuration + +The HAProxy frontend listens on port 443 (HTTPS) and TCP mode is used +for SSL/TLS traffic. + +### SNI-Based Routing + +Traffic is routed based on the SSL SNI (Server Name Indication) +hostname: + +**Kubernetes Backend** (`k8s_backend`): + +- Domains ending with `.mydomain.com` + +**Docker Backend** (`docker_backend`): + +- Domains ending with `.docker.mydomain.com` + +## Backend Configuration + +### Kubernetes Backend + +- **Server**: `k8s-ingress` at `192.168.1.141:443` +- **Mode**: TCP +- **Health Checks**: Enabled (10s interval, 3 failures to mark + down, 2 successes to mark up) + +### Docker Backend + +- **Server**: `docker-proxy` at `192.168.1.135:443` +- **Mode**: TCP +- **Health Checks**: Enabled (10s interval, 3 failures to mark + down, 2 successes to mark up) + +## Usage + +The SSL hello packet is automatically inspected to determine the SNI +hostname, and the connection is routed to the appropriate backend +service. + +## Notes + +- TCP mode is used to preserve SSL/TLS encryption end-to-end +- Domain patterns marked with `# example` are placeholders and should + be customized for the setup +- The TCP routing logs can be monitored via journald for debugging and + verification purposes. `journalctl -u haproxy -f` diff --git a/infra/haproxy/haproxy.cfg b/infra/haproxy/haproxy.cfg new file mode 100644 index 0000000..f7ad199 --- /dev/null +++ b/infra/haproxy/haproxy.cfg @@ -0,0 +1,42 @@ +global + log /dev/log local0 + log 127.0.0.1 local2 + stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners + stats timeout 30s + user haproxy + group haproxy + daemon + maxconn 10000 + +defaults + log global + mode tcp + option dontlognull + timeout connect 5s + timeout client 3600s + timeout server 3600s + +frontend https-in + bind *:443 + mode tcp + option tcplog + + tcp-request inspect-delay 5s + tcp-request content accept if { req_ssl_hello_type 1 } + + acl is_docker req_ssl_sni -i -m end .docker.mydomain.com + acl is_k8s req_ssl_sni -i -m end .mydomain.com + + # More specific wins → put docker rule first + use_backend docker_backend if is_docker + use_backend k8s_backend if is_k8s + + default_backend k8s_backend + +backend k8s_backend + mode tcp + server k8s-ingress 192.168.1.141:443 check inter 10s fall 3 rise 2 + +backend docker_backend + mode tcp + server docker-proxy 192.168.1.135:443 check inter 10s fall 3 rise 2 \ No newline at end of file diff --git a/infra/terraform/proxmox/terraform.tfvars b/infra/terraform/proxmox/terraform.tfvars index e0e6542..c50da55 100644 --- a/infra/terraform/proxmox/terraform.tfvars +++ b/infra/terraform/proxmox/terraform.tfvars @@ -3,28 +3,28 @@ pm_ssh_public_key_path = "/home/taqi/.ssh/homeserver.pub" pm_ssh_private_key_path = "/home/taqi/.ssh/homeserver" vms = [ - { - name = "vm6" - node_name = "homeserver1" - vm_id = 105 - ip_address = "192.168.1.151/24" - gateway = "192.168.1.1" - dns_servers = ["1.1.1.1"] - cores = 2 - memory = 4096 - disk_size = 20 - }, - { - name = "vm7" - node_name = "homeserver2" - vm_id = 205 - ip_address = "192.168.1.161/24" - gateway = "192.168.1.1" - dns_servers = ["1.1.1.1"] - cores = 2 - memory = 4096 - disk_size = 20 - }, + # { + # name = "vm6" + # node_name = "homeserver1" + # vm_id = 105 + # ip_address = "192.168.1.151/24" + # gateway = "192.168.1.1" + # dns_servers = ["1.1.1.1"] + # cores = 2 + # memory = 4096 + # disk_size = 20 + # }, + # { + # name = "vm7" + # node_name = "homeserver2" + # vm_id = 205 + # ip_address = "192.168.1.161/24" + # gateway = "192.168.1.1" + # dns_servers = ["1.1.1.1"] + # cores = 2 + # memory = 4096 + # disk_size = 20 + # }, { name = "vm8" node_name = "homeserver3" @@ -57,6 +57,17 @@ vms = [ cores = 2 memory = 2048 disk_size = 20 + }, + { + name = "vm11" + node_name = "homeserver3" + vm_id = 304 + ip_address = "192.168.1.175/24" + gateway = "192.168.1.1" + dns_servers = ["1.1.1.1"] + cores = 2 + memory = 2048 + disk_size = 20 } ]