backend-haproxy.cfg.in 4.86 KB
global
  pidfile {{ configuration['pid-file'] }}
  # master-worker is compatible with foreground with process management
  master-worker

log {{ configuration['log-socket'] }} local0
defaults
  log global
  mode http
  option httplog
  timeout queue 60s
  timeout server {{ configuration['request-timeout'] }}s
  timeout client {{ configuration['request-timeout'] }}s
  timeout connect {{ configuration['backend-connect-timeout'] }}s
  retries {{ configuration['backend-connect-retries'] }}

{%- set SCHEME_PREFIX_MAPPING = { 'http': 'http_backend', 'https': 'https_backend'} %}
{%- macro frontend_entry(slave_instance, scheme, wildcard) %}
{#-   wildcard switch allows to put dangerous entries in the end, as haproxy parses with first match #}
{%-   if slave_instance[SCHEME_PREFIX_MAPPING[scheme]]['hostname'] and slave_instance[SCHEME_PREFIX_MAPPING[scheme]]['port'] %}
{%-     set host_list = (slave_instance.get('server-alias') or  '').split() %}
{%-     if slave_instance.get('custom_domain') not in host_list %}
{%-       do host_list.append(slave_instance.get('custom_domain')) %}
{%-     endif %}
{%-     set matched = {'count': 0} %}
{%-     for host in host_list %}
{#-       Match up to the end or optional port (starting with ':') #}
{#-       Please note that this matching is quite sensitive to changes and hard to test, so avoid needless changes #}
{%-       if wildcard and host.startswith('*.') %}
{%-         do matched.__setitem__('count', matched['count'] + 1) %}
# match wildcard {{ host }}
  acl is_{{ slave_instance['slave_reference'] }} hdr_reg(host) -i {{ host[2:] }}($|:.*)
{%-       elif not wildcard and not host.startswith('*.') %}
{%-         do matched.__setitem__('count', matched['count'] + 1) %}
  acl is_{{ slave_instance['slave_reference'] }} hdr_reg(host) -i ^{{ host }}($|:.*)
{%-       endif %}
{%-     endfor %}
{%-     if matched['count'] > 0 %}
  use_backend {{ slave_instance['slave_reference'] }}-{{ scheme }} if is_{{ slave_instance['slave_reference'] }}
{%-     endif %}
{%-   endif %}
{%- endmacro %}

# statistic
frontend statistic
  bind {{ configuration['global-ipv6']}}:{{ configuration['statistic-port'] }} ssl crt {{ configuration['statistic-certificate'] }}
  stats enable
  stats uri /
  stats show-desc {{ configuration['statistic-identification'] }}
  stats auth {{ configuration['statistic-username'] }}:{{ configuration['statistic-password'] }}
  stats realm {{ configuration['statistic-identification'] }}

frontend http-backend
  bind {{ configuration['local-ipv4'] }}:{{ configuration['http-port'] }}
{%- for slave_instance in backend_slave_list -%}
{{ frontend_entry(slave_instance, 'http', False) }}
{%- endfor %}
{%- for slave_instance in backend_slave_list -%}
{{ frontend_entry(slave_instance, 'http', True) }}
{%- endfor %}

frontend https-backend
  bind {{ configuration['local-ipv4'] }}:{{ configuration['https-port'] }}
{%- for slave_instance in backend_slave_list -%}
{{ frontend_entry(slave_instance, 'https', False) }}
{%- endfor %}
{%- for slave_instance in backend_slave_list -%}
{{ frontend_entry(slave_instance, 'https', True) }}
{%- endfor %}

{%- for slave_instance in backend_slave_list %}
{%-   for (scheme, prefix) in SCHEME_PREFIX_MAPPING.items() %}
{%-     set info_dict = slave_instance[prefix] %}
{%-     if info_dict['hostname'] and info_dict['port'] %}
{%-       set ssl_list = [] %}
{%-       if info_dict['scheme'] == 'https' %}
{%-         if slave_instance['authenticate-to-backend'] %}
{%-           do ssl_list.append('crt %s' % (configuration['certificate'],)) %}
{%-         endif %}
{%-         do ssl_list.append('ssl verify') %}
{%-         set path_to_ssl_proxy_ca_crt = slave_instance.get('path_to_ssl_proxy_ca_crt') %}
{%-         if slave_instance['ssl_proxy_verify'] %}
{%-           if path_to_ssl_proxy_ca_crt %}
{%-             do ssl_list.append('required ca-file %s' % (path_to_ssl_proxy_ca_crt,)) %}
{%-           else %}
{#-           Backend SSL shall be verified, but not CA provided, disallow connection #}
{#-           Simply dropping hostname from the dict will result with ignoring it... #}
{%-           do info_dict.__setitem__('hostname', '') %}
{%-           endif %}
{%-         else %}
{%-           do ssl_list.append('none') %}
{%-         endif %}
{%-       endif %}

backend {{ slave_instance['slave_reference'] }}-{{ scheme }}
{%-       set hostname = info_dict['hostname'] %}
{%-       set port = info_dict['port'] %}
{%-       set path = info_dict['path'].rstrip('/') %}
{%-       if hostname and port %}
  timeout server {{ slave_instance['request-timeout'] }}s
  timeout connect {{ slave_instance['backend-connect-timeout'] }}s
  retries {{ slave_instance['backend-connect-retries'] }}
  server {{ slave_instance['slave_reference'] }}-backend {{ hostname }}:{{ port }} {{ ' '.join(ssl_list) }}
{%-         if path %}
  http-request set-path {{ path }}%[path]
{%-         endif %}
{%-       endif %}
{%-     endif %}
{%-   endfor %}
{%- endfor %}