summaryrefslogtreecommitdiff
path: root/data/templates/load-balancing/haproxy.cfg.j2
blob: 5137966c1cc934dfec0e9c1dbbc407e7ea3f2b23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
### Autogenerated by load-balancing_reverse-proxy.py ###

global
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

{% if global_parameters is vyos_defined %}
{%     if global_parameters.logging is vyos_defined %}
{%         for facility, facility_config in global_parameters.logging.facility.items() %}
    log /dev/log {{ facility }} {{ facility_config.level }}
{%         endfor %}
{%     endif %}
{%     if global_parameters.max_connections is vyos_defined %}
    maxconn {{ global_parameters.max_connections }}
{%     endif %}

    # Default SSL material locations
    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

{%     if global_parameters.ssl_bind_ciphers is vyos_defined %}
    # https://ssl-config.mozilla.org/#server=haproxy&version=2.6.12-1&config=intermediate&openssl=3.0.8-1&guideline=5.6
    ssl-default-bind-ciphers {{ global_parameters.ssl_bind_ciphers | join(':') | upper }}
{%     endif %}
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
{%     if global_parameters.tls_version_min is vyos_defined('1.3') %}
    ssl-default-bind-options force-tlsv13
{%     else %}
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
{%     endif %}
{% endif %}

defaults
    log     global
    mode    http
    option  dontlognull
    timeout connect 10s
    timeout client  50s
    timeout server  50s
    errorfile 400 /etc/haproxy/errors/400.http
    errorfile 403 /etc/haproxy/errors/403.http
    errorfile 408 /etc/haproxy/errors/408.http
    errorfile 500 /etc/haproxy/errors/500.http
    errorfile 502 /etc/haproxy/errors/502.http
    errorfile 503 /etc/haproxy/errors/503.http
    errorfile 504 /etc/haproxy/errors/504.http

# Frontend
{% if service is vyos_defined %}
{%     for front, front_config in service.items() %}
frontend {{ front }}
{%         set ssl_front = [] %}
{%         if front_config.ssl.certificate is vyos_defined and front_config.ssl.certificate is iterable %}
{%             for cert in front_config.ssl.certificate %}
{%                 set _ = ssl_front.append('crt /run/haproxy/' ~ cert ~ '.pem') %}
{%             endfor %}
{%         endif %}
{%         set ssl_directive = 'ssl' if ssl_front else '' %}
{%         if front_config.listen_address is vyos_defined %}
{%             for address in front_config.listen_address %}
    bind {{ address | bracketize_ipv6 }}:{{ front_config.port }} {{ ssl_directive }} {{ ssl_front | join(' ') }}
{%             endfor %}
{%         else %}
    bind [::]:{{ front_config.port }} v4v6 {{ ssl_directive }} {{ ssl_front | join(' ') }}
{%         endif %}
{%         if front_config.redirect_http_to_https is vyos_defined %}
    http-request redirect scheme https unless { ssl_fc }
{%         endif %}
{%         if front_config.logging is vyos_defined %}
{%             for facility, facility_config in front_config.logging.facility.items() %}
    log /dev/log {{ facility }} {{ facility_config.level }}
{%             endfor %}
{%         endif %}
    mode {{ front_config.mode }}
{%         if front_config.tcp_request.inspect_delay is vyos_defined %}
    tcp-request inspect-delay {{ front_config.tcp_request.inspect_delay }}
{%         endif %}
{# add tcp-request related directive if ssl is configured #}
{%         if front_config.mode == 'tcp' and front_config.rule is vyos_defined %}
{%             for rule, rule_config in front_config.rule.items() %}
{%                 if rule_config.ssl is vyos_defined %}
    tcp-request content accept if { req_ssl_hello_type 1 }
{%                     break %}
{%                 endif %}
{%             endfor %}
{%         endif %}
{%         if front_config.http_response_headers is vyos_defined %}
{%             for header, header_config in front_config.http_response_headers.items() %}
    http-response set-header {{ header }} '{{ header_config['value'] }}'
{%             endfor %}
{%         endif %}
{%         if front_config.rule is vyos_defined %}
{%             for rule, rule_config in front_config.rule.items() %}
    # rule {{ rule }}
{%                 if rule_config.domain_name is vyos_defined %}
{%                     set rule_options = 'hdr(host)' %}
{%                     if rule_config.ssl is vyos_defined %}
{%                         set ssl_rule_translate = {'req-ssl-sni': 'req_ssl_sni', 'ssl-fc-sni': 'ssl_fc_sni', 'ssl-fc-sni-end': 'ssl_fc_sni_end'} %}
{%                         set rule_options = ssl_rule_translate[rule_config.ssl] %}
{%                     endif %}
{%                     for domain in rule_config.domain_name %}
    acl {{ rule }} {{ rule_options }} -i {{ domain }}
{%                     endfor %}
{%                 endif %}
{# path url #}
{%                 if rule_config.url_path is vyos_defined %}
{%                     set path_mod_translate = {'begin': '-i -m beg', 'end': '-i -m end', 'exact': ''} %}
{%                     for path, path_config in rule_config.url_path.items() %}
{%                         for url in path_config %}
    acl {{ rule }} path {{ path_mod_translate[path] }} {{ url }}
{%                         endfor %}
{%                     endfor %}
{%                 endif %}
{%                 if rule_config.set.backend is vyos_defined %}
    use_backend {{ rule_config.set.backend }} if {{ rule }}
{%                 endif %}
{%                 if rule_config.set.redirect_location is vyos_defined %}
    http-request redirect location {{ rule_config.set.redirect_location }} code 301 if {{ rule }}
{%                 endif %}
{# endpath #}
{%             endfor %}
{%         endif %}
{%         if front_config.backend is vyos_defined %}
{%             for backend in front_config.backend %}
    default_backend {{ backend }}
{%             endfor %}
{%         endif %}

{%     endfor %}
{% endif %}

# Backend
{% if backend is vyos_defined %}
{%     for back, back_config in backend.items() %}
backend {{ back }}
{%         if back_config.health_check is vyos_defined %}
{%             if back_config.health_check == 'smtp' %}
    option smtpchk
{%             else  %}
    option {{ back_config.health_check }}-check
{%             endif %}
{%         endif %}
{%         if back_config.http_check is vyos_defined %}
    option httpchk
{%         endif %}
{%         set send = '' %}
{%         if back_config.http_check.method is vyos_defined %}
{%             set send = send + ' meth ' + back_config.http_check.method | upper %}
{%         endif %}
{%         if back_config.http_check.uri is vyos_defined %}
{%             set send = send + ' uri ' + back_config.http_check.uri %}
{%         endif %}
{%         if send != '' %}
    http-check send{{ send }}
{%         endif %}
{%         if back_config.http_check.expect is vyos_defined %}
{%             if back_config.http_check.expect.status is vyos_defined %}
    http-check expect status {{ back_config.http_check.expect.status }}
{%             elif back_config.http_check.expect.string is vyos_defined %}
    http-check expect string {{ back_config.http_check.expect.string }}
{%             endif %}
{%         endif %}
{%         if back_config.balance is vyos_defined %}
{%             set balance_translate = {'least-connection': 'leastconn', 'round-robin': 'roundrobin', 'source-address': 'source'} %}
    balance {{ balance_translate[back_config.balance] }}
{%         endif %}
{# If mode is HTTP add X-Forwarded headers #}
{%         if back_config.mode == 'http' %}
    option forwardfor
    http-request set-header X-Forwarded-Port %[dst_port]
    http-request add-header X-Forwarded-Proto https if { ssl_fc }
{%         endif %}
{%         if back_config.logging is vyos_defined %}
{%             for facility, facility_config in back_config.logging.facility.items() %}
    log /dev/log {{ facility }} {{ facility_config.level }}
{%             endfor %}
{%         endif %}
    mode {{ back_config.mode }}
{%         if back_config.http_response_headers is vyos_defined %}
{%             for header, header_config in back_config.http_response_headers.items() %}
    http-response set-header {{ header }} '{{ header_config['value'] }}'
{%             endfor %}
{%         endif %}
{%         if back_config.rule is vyos_defined %}
{%             for rule, rule_config in back_config.rule.items() %}
{%                 if rule_config.domain_name is vyos_defined and rule_config.set.server is vyos_defined %}
{%                     set rule_options = 'hdr(host)' %}
{%                     if rule_config.ssl is vyos_defined %}
{%                         set ssl_rule_translate = {'req-ssl-sni': 'req_ssl_sni', 'ssl-fc-sni': 'ssl_fc_sni', 'ssl-fc-sni-end': 'ssl_fc_sni_end'} %}
{%                         set rule_options = ssl_rule_translate[rule_config.ssl] %}
{%                     endif %}
{%                     for domain in rule_config.domain_name %}
    acl {{ rule }} {{ rule_options }} -i {{ domain }}
{%                     endfor %}
    use-server {{ rule_config.set.server }} if {{ rule }}
{%                 endif %}
{# path url #}
{%                 if rule_config.url_path is vyos_defined and rule_config.set.redirect_location is vyos_defined %}
{%                     set path_mod_translate = {'begin': '-i -m beg', 'end': '-i -m end', 'exact': ''} %}
{%                     for path, path_config in rule_config.url_path.items() %}
{%                         for url in path_config %}
    acl {{ rule }} path {{ path_mod_translate[path] }} {{ url }}
{%                         endfor %}
{%                     endfor %}
    http-request redirect location {{ rule_config.set.redirect_location }} code 301 if {{ rule }}
{%                 endif %}
{# endpath #}
{%             endfor %}
{%         endif %}
{%         if back_config.server is vyos_defined %}
{%             set ssl_back =  'ssl ca-file /run/haproxy/' ~ back_config.ssl.ca_certificate ~ '.pem' if back_config.ssl.ca_certificate is vyos_defined else ('ssl verify none' if back_config.ssl.no_verify is vyos_defined else '') %}
{%             for server, server_config in back_config.server.items() %}
    server {{ server }} {{ server_config.address }}:{{ server_config.port }}{{ ' check' if server_config.check is vyos_defined }}{{ ' backup' if server_config.backup is vyos_defined }}{{ ' send-proxy' if server_config.send_proxy is vyos_defined }}{{ ' send-proxy-v2' if server_config.send_proxy_v2 is vyos_defined }} {{ ssl_back }}
{%             endfor %}
{%         endif %}
{%         if back_config.timeout.check is vyos_defined %}
    timeout check {{ back_config.timeout.check }}s
{%         endif %}
{%         if back_config.timeout.connect is vyos_defined %}
    timeout connect {{ back_config.timeout.connect }}s
{%         endif %}
{%         if back_config.timeout.server is vyos_defined %}
    timeout server {{ back_config.timeout.server }}s
{%         endif %}

{%     endfor %}
{% endif %}