initial commit

This commit is contained in:
Ludovic Cartier 2024-12-20 17:15:44 +01:00
parent e08ff94203
commit 55c5833ad4
8 changed files with 278 additions and 0 deletions

11
defaults/main.yml Normal file
View File

@ -0,0 +1,11 @@
---
haproxy_ssl_certs_dir: /etc/haproxy/ssl/certs
haproxy_ssl_self_dir: /etc/haproxy/ssl/self
haproxy_ssl_self_signed_subj: '/C=FR/ST=France/L=Marseille/O={{ inventory_hostname }}'
haproxy_ssl_self_signed_days: 3650
haproxy_ssl_self_signed_domains:
- '{{ inventory_hostname }}'
haproxy_accept_warnings: yes
haproxy_bind_ip: '*'

10
handlers/main.yml Normal file
View File

@ -0,0 +1,10 @@
---
- name: haproxy restart
systemd_service:
name: haproxy
state: restarted
- name: haproxy reload
systemd_service:
name: haproxy
state: reloaded

9
meta/main.yml Normal file
View File

@ -0,0 +1,9 @@
---
galaxy_info:
author: Ludovic Cartier
description: install & configure haproxy
company: brainsys
license: MIT
min_ansible_version: 2.8
issue_tracker_url: https://git.brainsys.io/ansible-roles/haproxy/issues
github_branch: main

34
tasks/configure.yml Normal file
View File

@ -0,0 +1,34 @@
---
- name: haproxy | ensure certs directory
file:
path: '{{ item }}'
state: directory
mode: '0755'
owner: root
group: root
with_items:
- '/etc/haproxy/ssl/certs'
- '/etc/haproxy/ssl/self'
- name: haproxy | create default self-signed certificate
shell: |
openssl req -newkey rsa:2048 -nodes -sha256 -x509 -subj "{{ haproxy_ssl_self_signed_subj }}/CN={{ item }}" -days {{ haproxy_ssl_self_signed_days }} -keyout "{{ item }}.key" -out "{{ item }}.crt" -extensions v3_ca
cat {{ item }}.crt {{ item }}.key >> {{ haproxy_ssl_certs_dir }}/{{ item }}.pem
chmod 0600 {{ item }}.crt {{ item }}.key {{ haproxy_ssl_certs_dir }}/{{ item }}.pem
args:
chdir: '{{ haproxy_ssl_self_dir }}'
creates: '{{ haproxy_ssl_certs_dir }}/{{ item }}.pem'
with_items: '{{ haproxy_ssl_self_signed_domains }}'
notify:
- haproxy restarted
- name: haproxy | copy configuration file
template:
src: haproxy.cfg.j2
dest: '/etc/haproxy/haproxy.cfg'
owner: root
group: root
mode: '0440'
validate: 'haproxy -f %s -c {% if haproxy_accept_warnings %}-q{% endif %}'
notify:
- haproxy reloaded

7
tasks/install.yml Normal file
View File

@ -0,0 +1,7 @@
---
- name: haproxy | installation
apt:
name: haproxy
state: present
default_release: {{ ansible_distribution_release }}-backports

10
tasks/main.yml Normal file
View File

@ -0,0 +1,10 @@
---
- name: haproxy | requirements
include_tasks: requirements.yml
- name: haproxy | installation
include_tasks: install.yml
- name: haproxy | configuration
include_tasks: configure.yml

11
tasks/requirements.yml Normal file
View File

@ -0,0 +1,11 @@
---
- name: haproxy | add backports repository
apt_repository:
repo: deb http://deb.debian.org/debian {{ ansible_distribution_release }}-backports main
state: present
filename: "{{ ansible_distribution_release }}-backports"
- name: haproxy | update apt cache
apt:
update_cache: yes
cache_valid_time: 86400

186
templates/haproxy.cfg.j2 Normal file
View File

@ -0,0 +1,186 @@
# {{ ansible_managed }}
##########
# Global #
##########
global
ca-base /etc/ssl/certs
chroot /var/lib/haproxy
crt-base /etc/ssl/private
log /dev/log local0 info
log /dev/log local1 notice
log-tag haproxy
maxconn 20000
pidfile /var/run/haproxy.pid
spread-checks 8
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-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 prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-HA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-server-verify none
stats socket /var/lib/haproxy/stats mode 600 level admin
tune.bufsize 65536
tune.maxrewrite 32768
tune.ssl.cachesize 100000
tune.ssl.default-dh-param 2048
tune.ssl.lifetime 600
tune.ssl.maxrecord 1460
############
# Defaults #
############
defaults 000-main
compression algo gzip
compression type text/html text/plain text/xml text/css text/javascript application/javascript application/json text/json image/svg+xml
log global
mode http
option httplog
option http-server-close
option dontlognull
option forwardfor
option redispatch
retries 3
stats realm Haproxy\ Statistics
stats show-desc Haproxy\ Statistics
stats show-node {{ ansible_hostname }}
stats uri /haproxy-stats
stats refresh 5s
stats hide-version
stats show-legends
timeout http-request 60s
timeout queue 60s
timeout connect 60s
timeout client 60s
timeout server 60s
timeout check 10s
############
# Userlist #
############
userlist prod
group ADMIN
user brainsys password $6$whKvhQcRLecqnNlC$CZS.p3EHfJDmC9H6KDeLkwOddLOPvPuEUDsaR3iLGbXU3eJ9kKcGDfq.Y59qgX2Q10x2Q2QuJ0lAcs0T2eAfa. groups ADMIN
#############
# Frontends #
#############
frontend stats
bind *:8404
option httpclose
stats enable
stats uri /stats
stats refresh 10s
http-request use-service prometheus-exporter if { path /metrics }
frontend prd_frontend1
bind {{ haproxy_bind_ip }}:80
bind {{ haproxy_bind_ip }}:443 ssl crt /etc/haproxy/ssl/certs
mode http
option http-server-close
option forwardfor
log-format %ci\ -\ [%Tl]\ %{+Q}r\ %ST\ %B\ %{+Q}hrl\ ---\ %{+Q}[var(txn.SCHEME)]\ %{+Q}[var(txn.COUNTRY)]\ %b\ %s\ %{+Q}hsl\ %Tq/%Tw/%Tc/%Tr/%Tt
## acl ##
acl has_DEBUG always_false
acl has_SCHEME_HTTPS ssl_fc
acl has_BYPASS_MAINTENANCE always_false
acl has_MAINTENANCE always_false
acl has_BYPASS_CACHE hdr_sub(X-Requested-With) XMLHttpRequest
acl has_BYPASS_CACHE method POST
acl has_AUTHORIZATION always_false
acl has_HEADER_X_FORWARDED_FOR hdr(X-Forwarded-For) -m found
acl has_HEADER_CF_CONNECTING_IP hdr(CF-Connecting-IP) -m found
acl has_HEADER_CF_TRUE_CLIENT_IP hdr(True-Client-IP) -m found # was cf_hdr_found
acl to_RESTRICTED_AREA path_beg -i /haproxy-stats
acl to_ACME_CHALLENGE path_beg /.well-known/acme-challenge/
acl is_auth_ok http_auth(prod)
acl is_HAPROXY_STATS path_beg -i /haproxy
acl is_localhost hdr(host) -i localhost
acl is_POST method POST
acl is_DELETE method DELETE
acl disable_AUTH_to_RESTRICTED_AREA always_false
acl disable_REDIRECT_TO_HTTPS always_false
acl disable_REDIRECT_TO_HTTPS hdr(host) -i localhost {{ ansible_hostname }}
acl disable_REDIRECT_TO_HTTPS path_beg -i /.well-known/acme-challenge/
## capture ##
capture request header X-Forwarded-For len 64
capture request header CF-Connecting-IP len 64
capture request header Referer len 64
capture request header User-Agent len 512
capture request header Host len 128
capture response header Content-Length len 10
capture response header X-Cache len 4
capture response header X-Cache-Hits len 8
capture response header Cache-Control len 64
capture response header X-UA-Device len 8
## http-response ##
http-response add-header Strict-Transport-Security max-age=15768000
http-response add-header Referrer-Policy no-referrer-when-downgrade
http-response del-header Server if !has_DEBUG
http-response del-header X-Generator if !has_DEBUG
http-response del-header X-Apache-Server-ID if !has_DEBUG
http-response del-header X-Vhost-ID if !has_DEBUG
http-response del-header x-url if !has_DEBUG
http-response del-header X-UA-Device if !has_DEBUG
http-response del-header X-Cache-Hits if !has_DEBUG
http-response del-header X-Powered-By if !has_DEBUG
http-response del-header X-Served-By if !has_DEBUG
http-response del-header X-Varnish-Ip if !has_DEBUG
http-response del-header X-Varnish-Port if !has_DEBUG
http-response del-header via if !has_DEBUG
http-response set-header X-XSS-Protection "1; mode=block"
http-response set-header X-Content-Type-Options nosniff
http-response del-header content-security-policy-report-only
# no follow / no index !!!
http-response set-header X-Robots-Tag "noindex, nofollow"
## http-request ##
http-request set-src hdr_ip(CF-Connecting-IP) if has_HEADER_CF_CONNECTING_IP
http-request set-src hdr_ip(X-Forwarded-For) if has_HEADER_X_FORWARDED_FOR
http-request set-src hdr(True-Client-IP) if has_HEADER_CF_TRUE_CLIENT_IP
http-request set-header X-Client-IP %[src]
http-request set-header X-Forwarded-For %[src]
http-request set-header X-Forwarded-Proto https if has_SCHEME_HTTPS
http-request set-header X-Forwarded-Port 443 if has_SCHEME_HTTPS
http-request set-header X-Forwarded-Port 80 if !has_SCHEME_HTTPS
http-request set-var(txn.SCHEME) hdr(X-Forwarded-Proto)
http-request set-var(txn.host) hdr(Host)
http-request set-var(txn.path) path
http-request redirect code 301 scheme https if !has_SCHEME_HTTPS !disable_REDIRECT_TO_HTTPS
http-request del-header authorization if to_RESTRICTED_AREA has_AUTHORIZATION
http-request del-header user-agent if { hdr(user-agent) -i HAPROXY-LB-Check VARNISH-LB-Check }
http-request del-header Authorization if is_auth_ok
http-request deny if to_RESTRICTED_AREA !has_AUTHORIZATION
http-request deny if is_HAPROXY_STATS !is_localhost
http-request auth realm "haproxy statistics - Limited access" if !is_auth_ok is_HAPROXY_STATS
http-request auth realm "You need a valid user and password to access this content. Unauthorized access to this system is forbidden and will be prosecuted by law. By accessing this system, you agree that your actions may be monitored if unauthorized usage is suspected" if to_RESTRICTED_AREA !has_AUTHORIZATION !disable_AUTH_to_RESTRICTED_AREA
## end http-request ##
## use backends ##
default_backend prd_backend
############
# Backends #
############
backend prd_backend
mode http
server nginx 127.0.0.1:80 check inter 3s