docs: rewrite README with structured overview and quick start guide
Replaces the minimal project description with a comprehensive README including a component overview table, quick start instructions, common Ansible operations, and links to detailed documentation. Aligns with Red Panda Approval™ standards.
This commit is contained in:
117
ansible/haproxy/deploy.yml
Normal file
117
ansible/haproxy/deploy.yml
Normal file
@@ -0,0 +1,117 @@
|
||||
---
|
||||
- name: Deploy HAProxy
|
||||
hosts: ubuntu
|
||||
tasks:
|
||||
- name: Check if host has haproxy service
|
||||
set_fact:
|
||||
has_haproxy_service: "{{'haproxy' in services}}"
|
||||
|
||||
- name: Skip hosts without haproxy service
|
||||
meta: end_host
|
||||
when: not has_haproxy_service
|
||||
|
||||
- name: Create haproxy group
|
||||
become: true
|
||||
ansible.builtin.group:
|
||||
name: "{{haproxy_group}}"
|
||||
gid: "{{haproxy_gid}}"
|
||||
system: true
|
||||
|
||||
- name: Create haproxy user
|
||||
become: true
|
||||
ansible.builtin.user:
|
||||
name: "{{haproxy_user}}"
|
||||
comment: "{{haproxy_user}}"
|
||||
group: "{{haproxy_group}}"
|
||||
uid: "{{haproxy_uid}}"
|
||||
system: true
|
||||
|
||||
- name: Add group haproxy to ansible_user
|
||||
become: true
|
||||
ansible.builtin.user:
|
||||
name: "{{ansible_user}}"
|
||||
groups: "{{haproxy_group}}"
|
||||
append: true
|
||||
|
||||
- name: Create required directories
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
path: "{{haproxy_directory}}"
|
||||
owner: "{{haproxy_user}}"
|
||||
group: "{{haproxy_group}}"
|
||||
state: directory
|
||||
mode: '750'
|
||||
|
||||
- name: Create /etc/haproxy directory
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
path: /etc/haproxy
|
||||
owner: root
|
||||
group: root
|
||||
state: directory
|
||||
mode: '755'
|
||||
|
||||
- name: Create certs directory
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
path: /etc/haproxy/certs
|
||||
owner: "{{haproxy_user}}"
|
||||
group: "{{haproxy_group}}"
|
||||
state: directory
|
||||
mode: '750'
|
||||
|
||||
- name: Check if certificate already exists
|
||||
become: true
|
||||
stat:
|
||||
path: "{{ haproxy_cert_path }}"
|
||||
register: cert_file
|
||||
|
||||
- name: Generate self-signed wildcard certificate
|
||||
become: true
|
||||
command: >
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048
|
||||
-keyout {{ haproxy_cert_path }}
|
||||
-out {{ haproxy_cert_path }}
|
||||
-subj "/C=US/ST=State/L=City/O=Agathos/CN=*.{{ haproxy_domain }}"
|
||||
-addext "subjectAltName=DNS:*.{{ haproxy_domain }},DNS:{{ haproxy_domain }}"
|
||||
when: not cert_file.stat.exists and 'certbot' not in services
|
||||
|
||||
- name: Set certificate permissions
|
||||
become: true
|
||||
ansible.builtin.file:
|
||||
path: "{{ haproxy_cert_path }}"
|
||||
owner: "{{haproxy_user}}"
|
||||
group: "{{haproxy_group}}"
|
||||
mode: '640'
|
||||
|
||||
- name: Install HAProxy
|
||||
become: true
|
||||
ansible.builtin.apt:
|
||||
name: haproxy
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Template HAProxy configuration
|
||||
become: true
|
||||
ansible.builtin.template:
|
||||
src: "haproxy.cfg.j2"
|
||||
dest: /etc/haproxy/haproxy.cfg
|
||||
owner: "{{haproxy_user}}"
|
||||
group: "{{haproxy_group}}"
|
||||
mode: "640"
|
||||
validate: haproxy -c -f %s
|
||||
register: haproxy_config
|
||||
|
||||
- name: Enable and start HAProxy service
|
||||
become: true
|
||||
ansible.builtin.systemd:
|
||||
name: haproxy
|
||||
enabled: true
|
||||
state: started
|
||||
|
||||
- name: Reload HAProxy if configuration changed
|
||||
become: true
|
||||
ansible.builtin.systemd:
|
||||
name: haproxy
|
||||
state: reloaded
|
||||
when: haproxy_config.changed
|
||||
114
ansible/haproxy/haproxy.cfg.j2
Normal file
114
ansible/haproxy/haproxy.cfg.j2
Normal file
@@ -0,0 +1,114 @@
|
||||
# HAProxy configuration for Agathos Titania
|
||||
# Managed by Ansible - Red Panda Approved
|
||||
|
||||
global
|
||||
log 127.0.0.1:{{ haproxy_syslog_port }} local0
|
||||
stats timeout 30s
|
||||
|
||||
# Default SSL material locations
|
||||
ca-base /etc/ssl/certs
|
||||
crt-base /etc/ssl/private
|
||||
|
||||
# SSL/TLS configuration
|
||||
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
|
||||
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
|
||||
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
|
||||
|
||||
defaults
|
||||
log global
|
||||
mode http
|
||||
option httplog
|
||||
option dontlognull
|
||||
# Log format with timing information for latency analysis
|
||||
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
|
||||
timeout connect 5s
|
||||
timeout client 50s
|
||||
timeout server 50s
|
||||
|
||||
# Stats page with Prometheus metrics
|
||||
listen stats
|
||||
bind *:{{ haproxy_stats_port }}
|
||||
mode http
|
||||
stats enable
|
||||
stats uri /metrics
|
||||
stats refresh 15s
|
||||
stats show-legends
|
||||
stats show-node
|
||||
|
||||
# Prometheus metrics endpoint
|
||||
http-request use-service prometheus-exporter if { path /metrics }
|
||||
|
||||
# HTTP frontend - redirect all traffic to HTTPS
|
||||
frontend http_frontend
|
||||
bind *:{{ haproxy_http_port }}
|
||||
mode http
|
||||
option httplog
|
||||
http-request redirect scheme https code 301
|
||||
|
||||
# HTTPS frontend with dynamic routing
|
||||
frontend https_frontend
|
||||
bind *:{{ haproxy_https_port }} ssl crt {{ haproxy_cert_path }}
|
||||
mode http
|
||||
option httplog
|
||||
option forwardfor
|
||||
|
||||
# Forward original protocol and host for reverse-proxied services
|
||||
http-request set-header X-Forwarded-Proto https
|
||||
http-request set-header X-Forwarded-Port %[dst_port]
|
||||
|
||||
# Security headers
|
||||
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
http-response set-header X-Frame-Options "SAMEORIGIN"
|
||||
http-response set-header X-Content-Type-Options "nosniff"
|
||||
http-response set-header X-XSS-Protection "1; mode=block"
|
||||
|
||||
{% for backend in haproxy_backends %}
|
||||
{% if backend.subdomain %}
|
||||
# ACL for {{ backend.subdomain }}.{{ haproxy_domain }} (matches with or without port)
|
||||
acl host_{{ backend.subdomain }} hdr_beg(host) -i {{ backend.subdomain }}.{{ haproxy_domain }}
|
||||
{% if backend.redirect_root is defined %}
|
||||
# Redirect root path to {{ backend.redirect_root }} (avoids redirect loop by matching exact path)
|
||||
http-request redirect location {{ backend.redirect_root }} code 302 if host_{{ backend.subdomain }} { path / }
|
||||
{% endif %}
|
||||
use_backend backend_{{ backend.subdomain }} if host_{{ backend.subdomain }}
|
||||
{% else %}
|
||||
# Default backend for root domain
|
||||
default_backend backend_root
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
# Backend definitions
|
||||
{% for backend in haproxy_backends %}
|
||||
{% if backend.subdomain %}
|
||||
backend backend_{{ backend.subdomain }}
|
||||
{% else %}
|
||||
backend backend_root
|
||||
{% endif %}
|
||||
mode http
|
||||
balance roundrobin
|
||||
{% if backend.ssl_backend | default(false) %}
|
||||
option httpchk
|
||||
http-check send meth GET uri {{ backend.health_path }} hdr Host {{ backend.subdomain }}.{{ haproxy_domain }}
|
||||
{% else %}
|
||||
option httpchk GET {{ backend.health_path }}
|
||||
{% endif %}
|
||||
http-check expect status 200
|
||||
{% if backend.timeout_server is defined %}
|
||||
timeout server {{ backend.timeout_server }}
|
||||
{% endif %}
|
||||
server {{ backend.subdomain or 'root' }}_1 {{ backend.backend_host }}:{{ backend.backend_port }} check{% if backend.ssl_backend | default(false) %} ssl verify none{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
{% for tcp_backend in haproxy_tcp_backends | default([]) %}
|
||||
# TCP passthrough: {{ tcp_backend.name }}
|
||||
frontend {{ tcp_backend.name }}_frontend
|
||||
bind *:{{ tcp_backend.listen_port }}
|
||||
mode tcp
|
||||
option tcplog
|
||||
default_backend {{ tcp_backend.name }}_backend
|
||||
|
||||
backend {{ tcp_backend.name }}_backend
|
||||
mode tcp
|
||||
server {{ tcp_backend.name }}_1 {{ tcp_backend.backend_host }}:{{ tcp_backend.backend_port }} check
|
||||
|
||||
{% endfor %}
|
||||
Reference in New Issue
Block a user