forked from haproxytech/haproxy-pygments-lexer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
haproxy.cfg
853 lines (667 loc) · 28.2 KB
/
haproxy.cfg
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
#
# All configuration examples used bellow can be found on
# https://github.com/haproxytech/ultimate-configs/tree/2.2
#
#
# This is the ultimate HAProxy 2.2 "Getting Started" config
# It demonstrates many of the features available which are now available
# While you may not need all of these things, this can serve
# as a reference for your own configurations.
#
# Have questions? Check out our community Slack:
# https://slack.haproxy.org/
#
global
# master-worker required for `program` section
# enable here or start with -Ws
master-worker
mworker-max-reloads 3
daemon
zero-warning
# enable core dumps
set-dumpable
user haproxy
group haproxy
# Used with peers syncing
localpeer haproxy1
# For Docker or logs over stdout
# uncomment the below and comment ring@
# log stdout local1 info
# For syslog over TCP
# + ring buffer log
log ring@requests local1 info
log ring@admin local1 notice
log ring@security local2 warning
# Runtime API
stats socket 127.0.0.1:9999 level admin expose-fd listeners
tune.bufsize 32000
ssl-load-extra-files all
issuers-chain-path certs/issuers/
ssl-default-bind-curves X25519:P-256
# intermediate 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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:!MD5:!aNULL:!DH:!RC4
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options 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-SHA384: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
defaults
mode http
log global
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
resolvers dns
parse-resolv-conf
resolve_retries 3
timeout resolve 1s
timeout retry 1s
hold other 30s
hold refused 30s
hold nx 30s
hold timeout 30s
hold valid 10s
hold obsolete 30s
http-errors haproxy.local
errorfile 400 files/errorfiles/haproxy.local/400.http
errorfile 401 files/errorfiles/haproxy.local/401.http
errorfile 403 files/errorfiles/haproxy.local/403.http
errorfile 404 files/errorfiles/haproxy.local/404.http
errorfile 503 files/errorfiles/haproxy.local/503.http
http-errors haproxy.local-json
errorfile 400 files/errorfiles/haproxy.local-json/400.http
errorfile 401 files/errorfiles/haproxy.local-json/401.http
errorfile 403 files/errorfiles/haproxy.local-json/403.http
errorfile 404 files/errorfiles/haproxy.local-json/404.http
errorfile 503 files/errorfiles/haproxy.local-json/503.http
fcgi-app php-fpm
log-stderr global
option keep-conn
docroot /var/www/html
index app.php
path-info ^(/.+\.php)(/.*)?$
frontend stats
bind :20212
# Enable Prometheus Exporter
# make TARGET=linux-glibc EXTRA_OBJS="contrib/prometheus-exporter/service-prometheus.o"
# http-request use-service prometheus-exporter if { path /metrics }
http-after-response set-header Via "%[res.ver] haproxy"
stats enable
stats uri /stats
stats refresh 10s
ring requests
description "request logs"
format rfc3164
maxlen 1200
size 32764
timeout connect 5s
timeout server 10s
server request-log 127.0.0.1:6514 log-proto octet-count
ring admin
description "admin logs"
format rfc3164
maxlen 1200
size 32764
timeout connect 5s
timeout server 10s
server admin-log 127.0.0.1:6515 log-proto octet-count
ring security
description "security"
format rfc3164
maxlen 1200
size 32764
timeout connect 5s
timeout server 10s
server security-log 127.0.0.1:6516 log-proto octet-count
peers security
bind :20217
server haproxy1 #local peer
table src_req_tracking type ip size 1m expire 1h store http_req_rate(10s),http_req_cnt,http_err_rate(10s),http_err_cnt
table key_req_tracking type string len 32 size 1m expire 1h store http_req_rate(10s),http_req_cnt,http_err_rate(10s),http_err_cnt
peers admin
bind :20214
server haproxy1 #local peer
table fe_req_tracking type string type string len 32 size 1m expire 1h store http_req_rate(10s),http_req_cnt,http_err_rate(10s),http_err_cnt
frontend fe_main
bind :::80 name http
bind :::443 name https alpn h2,http1.1 tfo ssl crt certs/
unique-id-format %{+X}o\ %[uuid(4)]
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 %[unique-id] %{+Q}[var(txn.actionreason)]"
acl is_digest path /api/tools/digest
acl is_whoami path /api/tools/whoami
acl is_elephant path /api/tools/elephantfacts
# gRPC path matching
acl is_grpc_codename path_beg /CodenameCreator
# API Path
acl api_path path_beg /api/tools/
# Allowed extensions
acl static_extensions path_end .css .ico #.php
# Begin tracking
tcp-request connection track-sc0 src,debug(track-sc-src) table security/src_req_tracking
http-request track-sc1 var(txn.key),debug(track-sc-key) table security/key_req_tracking
http-request track-sc2 fe_name table admin/fe_req_tracking
# Capture unique id for logs
http-request capture unique-id len 256
# Get/SetAPI key
http-request set-var(txn.key) src,digest(md5),hex,lower
http-request set-var(txn.key) req.hdr(x-api-key) if { req.hdr(x-api-key) -m found } { req.hdr(x-api-key) -m len 32 }
# HTTP security headers
http-request set-header x-frame-options DENY
http-request set-header x-xss-protection 1
http-request strict-mode on
#http-request redirect location '/rand[url,regsub("(foo|bar)([0-9]+)?","\2\1",i)]'
http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ }
# Reasons why we may rejeect this request
# No action is taken at this point
# This is only for logging purposes
http-request set-var(txn.reason) 'str(Invalid path)' if !api_path !is_grpc_codename !static_extensions !{ path / } !{ path_end .php } !{ path /slack }
http-request set-var(txn.reason) 'str(Invalid API Key)' if api_path !{ url_param(key) -m found } || !{ req.body_param(x-api-key) -m found }
# Set log level to warning if any action will be taken
http-request set-log-level warning if { var(txn.reason) -m len gt 1 }
# Potential actions to take
#
# Return 404 to those paths that do not match URLs defined as allowed
# http-request deny deny_status 404 errorfiles haproxy.local if !api_path !is_grpc_codename !static_extensions !{ path / } !{ path_end .php } !{ path /test }
# http-request deny deny_status 404 errorfiles haproxy.local-json if !api_path !is_grpc_codename !static_extensions !{ path / } !{ path_end .php } !{ path /test } { req.hdr(content-type) application/json }
#
# Return 401 for any client accessing without an API key specifieid
# in either the query string "key" parameter or a request header 'x-api-key'
http-request deny deny_status 401 errorfiles haproxy.local-json if api_path !{ url_param(key) -m found } !{ req.hdr(x-api-key) -m found } { req.hdr(content-type) application/json }
http-request deny deny_status 401 errorfiles haproxy.local if api_path !{ url_param(key) -m found } !{ req.hdr(x-api-key) -m found }
http-after-response set-header Via "%[res.ver] haproxy"
# Backend selection
# gRPC
# use_backend be_grpc if is_grpc_codename
# FastCGI
#use_backend be_fastcgi if { path_reg ^/.+\.php(/.*)?$ }
# Stats
use_backend be_stats if { path /stats }
# Builtin API endpoints
use_backend be_digest-service if is_digest
use_backend be_eleph-service if is_elephant
use_backend be_whatismyip-service if is_whoami
# Default HTML page
default_backend be_haproxy-html
backend be_stats
server stats 127.0.0.1:20212
backend be_whatismyip-service
# What is my ip? service
errorfiles haproxy.local-json
# Return JSON response
http-request return status 200 content-type "application/json" lf-string '{"ip":"%[src]"}' if { url_param(json) -m found }
# Return text response
http-request return status 200 content-type "text/plain; charset=utf-8" lf-string "%[src]"
backend be_eleph-service
# 🐘 Elephant fact service
errorfiles haproxy.local-json
# Set the default variable txn.elephant_fact in case of lookup failure
http-request set-var(txn.elephant_fact) 'str(Elephants have around 150000 muscle units in their trunk.)'
# Grab random entry based on the length of the current map file
# Set rand(<int>) according to the length of your current elephants.map file
http-request set-var(txn.elephant_fact) rand(35),map(files/maps/elephants.map)
# Return JSON response
http-request return status 200 content-type "application/json" lf-string '{"fact":"%[var(txn.elephant_fact)]"}' if { url_param(json) -m found }
# Return text response
http-request return status 200 content-type "text/plain" lf-string %[var(txn.elephant_fact)]
backend be_digest-service
# Digest service
errorfiles haproxy.local-json
# Return HTTP/400 if API request is missing "str" parameter
# If the client sends a content-type with application/json we
# will return a json based response
http-request return status 400 errorfiles haproxy.local-json if !{ url_param(str) -m found } { req.hdr(content-type) application/json }
http-request return status 400 errorfiles haproxy.local if !{ url_param(str) -m found }
# Generate hash
# defaults to md5
http-request set-var(txn.digest) str(md5) if !{ url_param(digest) -m found }
http-request set-var(txn.defaultstr) str(haproxy) if !{ url_param(str) -m found }
http-request set-var(txn.hash) url_param(str),digest(md5),hex,lower
http-request set-var(txn.hash) url_param(str),digest(sha256),hex,lower if { url_param(digest) sha256 }
http-request set-var(txn.hash) url_param(str),digest(sha512),hex,lower if { url_param(digest) sha512 }
http-request set-var(txn.hash) url_param(str),digest(blake2s256),hex,lower if { url_param(digest) blake2s256 }
http-request set-var(txn.hash) url_param(str),digest(blake2b512),hex,lower if { url_param(digest) blake2b512 }
# Validate hash
http-request set-var(txn.hashvalidation) str(NoMatch-\xE2\x9D\x8C)
http-request set-var(txn.hashvalidation) str(Success-\xE2\x9C\x85) if { url_param(hash),secure_memcmp(txn.hash) }
# Return validated hash
http-request return status 200 content-type "text/plain" lf-string "%[var(txn.hashvalidation)]\n" if { url_param(str) -m found } { url_param(hash) -m found }
# Return JSON response
http-request return status 200 content-type "application/json" lf-string '{"hash":"%[var(txn.hash)]"}' if { url_param(str) -m found } { url_param(json) -m found }
# Return text response
http-request return status 200 content-type "text/plain" lf-string "%[var(txn.hash)]\n" if { url_param(str) -m found }
backend be_main
#default-server ssl verify none alpn h2 check maxconn 50
unique-id-header unique_id
errorfiles haproxy.local
# Enable Power of Two Random Choices Algorithm
balance random(2)
# Enable Layer 7 retries
retry-on all-retryable-errors
retries 3
option httpchk
http-check send meth HEAD uri / ver HTTP/1.1 hdr Host slack.haproxy.org hdr user-agent haproxy comment "HTTP Check Failed: HEAD /"
http-check expect status 200
# retrying POST requests can be dangerous
# make sure you understand the implications before removing
http-request disable-l7-retry if METH_POST
use-server %[hdr(srv)] if { hdr(srv) -m found }
server app1 172.31.31.151:10000 check cookie 000
server app2 172.31.31.174:10000 check cookie 111 ssl verify none alpn h2,http/1.1 maxconn 50
server app3 172.31.31.184:10000 check cookie 222 send-proxy-v2 proxy-v2-options unique-id
backend be_fastcgi
mode http
use-fcgi-app php-fpm
option httpchk
http-check connect proto fcgi
http-check send meth GET uri /ping
http-check expect string pong
# Use DNS service discovery to check for pool of fastcgi servers
# defaults to fastcgi.example.com on port 9000
server-template php-fpm-pool 10 fastcgi.example.local:9000 check resolvers dns init-addr none
# define a static pool
server php-fpm1 172.31.31.151:18081 proto fcgi
server php-fpm2 172.31.31.174:18081 proto fcgi
backend be_grpc
default-server ssl verify none alpn h2 check maxconn 50
option httpchk
timeout check 5s
# Use DNS service discovery to check for pool of fastcgi servers
# defaults to fastcgi.example.com on port 9000
server-template grpc-pool 10 grpc.example.local:3000 check resolvers dns init-addr none
# define a static pool
server grpc1 127.0.0.1:3000 check
server grpc2 10.1.0.12:3000 check
backend be_haproxy-html
errorfiles haproxy.local
# Title
http-request set-var(txn.title) str(HAProxy\ 2.2)
# Set lock/unlock emoji if connection over http/https
http-request set-var(txn.lock_emoji) str(\xF0\x9F\x94\x92)
http-request set-var(txn.lock_emoji) str(\xF0\x9F\x94\x93) if !{ ssl_fc }
# Favicon
http-request return status 200 content-type "image/x-icon" string " " if { path /favicon.ico }
# CSS
http-request return status 200 content-type "text/css" file files/css/style.css if { path /css/style.css }
# Set current tab
http-request set-query overview=checked if !{ url_param(ip) -m found } !{ url_param(digest) -m found }
# Digest
# These variables will be used in the template
http-request set-var(txn.digest) str(md5) if !{ url_param(digest) -m found }
http-request set-var(txn.defaultstr) str(haproxy) if !{ url_param(str) -m found }
http-request set-var(txn.hash) url_param(str),digest(md5),hex,lower
http-request set-var(txn.hash) url_param(str),digest(sha256),hex,lower if { url_param(digest) sha256 }
http-request set-var(txn.hash) url_param(str),digest(sha512),hex,lower if { url_param(digest) sha512 }
http-request set-var(txn.hash) url_param(str),digest(blake2s256),hex,lower if { url_param(digest) blake2s256 }
http-request set-var(txn.hash) url_param(str),digest(blake2b512),hex,lower if { url_param(digest) blake2b512 }
# 🐘 Elephant fact
# This is for the template
http-request set-var(txn.elephant_fact) 'str(Elephants have around 150000 muscle units in their trunk.)'
http-request set-var(txn.elephant_fact) rand(35),map(files/maps/elephants.map)
# Plain text response
http-request return status 200 content-type "text/plain; charset=utf-8" lf-file files/responses/haproxy.resp if { req.hdr(user-agent) -m beg curl }
# HTML minified response
http-request return status 200 content-type "text/html; charset=utf-8" lf-file files/responses/haproxy.html.min.resp if { url_param(min) -m found }
# HTML response
http-request return status 200 content-type "text/html; charset=utf-8" lf-file files/responses/haproxy.html.resp
global
master-worker
# log messages to stdout so that it can be seen with 'docker logs'
log stdout format raw local0 info
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
# standard default settings...
log global
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
frontend fe_sitea
bind :80
bind :443 ssl crt /etc/haproxy/certs/site.pem
default_backend be_main
backend be_main
server s1 172.25.0.10:8080 check
global
master-worker
# log messages to stdout so that it can be seen with 'docker logs'
log stdout format raw local0 info
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
# standard default settings...
log global
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
http-errors siteA
errorfile 503 /etc/haproxy/errors/sitea/503.http
errorfile 403 /etc/haproxy/errors/sitea/403.http
http-errors siteB
errorfile 503 /etc/haproxy/errors/siteb/503.http
errorfile 403 /etc/haproxy/errors/siteb/403.http
# This errorfiles returns back JSON:
http-errors api
errorfile 503 /etc/haproxy/errors/api/503.http
frontend fe_sitea
bind :80
default_backend be_main
# Use the errorsfiles from the 'http-errors siteA' section
# This only shows these errors if HAProxy triggered the error (not the backend site)
# e.g. it could not connect to the backend server = 503 Service Unavailable
errorfiles siteA
# Optional: If the server returns 403, replace it with our custom 403 errorfile
http-response deny deny_status 403 errorfiles siteA if { status 403 }
frontend fe_siteb
bind :8080
default_backend be_main
# Use the errorsfiles from the 'http-errors siteB' section
# This only shows these errors if HAProxy triggered the error (not the backend site)
# e.g. it could not connect to the backend server = 503 Service Unavailable
errorfiles siteB
# Optional: If the server returns 403, replace it with our custom 403 errorfile
http-response deny deny_status 403 errorfiles siteB if { status 403 }
frontend api
bind :8081
default_backend be_main
errorfiles api
http-response deny deny_status 503
backend be_main
server s1 172.25.0.10:8080 check
global
master-worker
# log messages to stdout so that it can be seen with 'docker logs'
log stdout format raw local0 info
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
# standard default settings...
log global
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
frontend fe_main
bind :80
default_backend be_main
backend be_main
# ---------------------------
# Health check configuration
# ---------------------------
# Enable HTTP health checks
option httpchk
# Connect to the server for HTTP health checks. It is possible to add 'ssl' here.
http-check connect
# Send the X-Haproxy-Server-State header to the server
http-check send-state
# Send the health check
# Includes request headers and a POST body
http-check send meth POST uri /healthz hdr MyHeader1 foo hdr Content-Type application/json body "{ \"foo\": \"bar\" }"
# Expect the header 'X-Health-Status: OK' in the response
http-check expect hdr name -m str "X-Health-Status" value -m str "OK"
# ---------------------------
# Add these parameters to include this server in the health checks
# 'check' - enable checks
# 'inter' - how often to do a check
# 'fall' - how many check can fail before removing the server from the pool
# 'rise' - how many checks must pass after the server went down
server s1 172.25.0.10:8080 check inter 10s fall 2 rise 4
global
master-worker
# log messages to stdout so that it can be seen with 'docker logs'
log stdout format raw local0 info
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
# standard default settings...
log global
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
frontend fe_main
bind :80
bind :443 ssl crt /etc/haproxy/certs/site.pem
# Show a locked / unlocked emoji depending on if the connection is HTTPS
http-request set-var(txn.lock_emoji) str(\xF0\x9F\x94\x92)
http-request set-var(txn.lock_emoji) str(\xF0\x9F\x94\x93) if !{ ssl_fc }
http-request set-var(txn.other_protocol) str(http://) if { ssl_fc }
http-request set-var(txn.other_protocol) str(https://) if !{ ssl_fc }
http-request return status 200 content-type "image/x-icon" file /etc/haproxy/content/favicon.ico if { path /favicon.ico }
http-request return status 200 content-type "text/css" file /etc/haproxy/content/css/style.min.css if { path /css/style.css }
http-request return status 200 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/content/index.html
# NOTE: There is no 'backend' defined in this configuration.
global
master-worker
# log messages to stdout so that it can be seen with 'docker logs'
log stdout format raw local0 info
# log messages to the external rsyslog server over TCP
log ring@rsyslog_server local0
# Runtime API
stats socket :9999 level admin expose-fd listeners
# Configure ring buffer to store log messages and where to send them
ring rsyslog_server
description "request logs"
format rfc3164
maxlen 1200
size 32764
timeout connect 5s
timeout server 10s
server rsyslog 172.25.0.12:514
defaults
# standard default settings...
log global
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
frontend fe_main
bind :80
default_backend be_main
backend be_main
server s1 172.25.0.10:8080 check
global
master-worker
# log all info to stdout so that it can be seen with 'docker logs'
log stdout format raw local0 info
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
# apply log from 'global' section to all of the following 'frontend' and 'backend' sections
log global
# standard default settings...
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
frontend fe_main
bind :80
default_backend be_main
backend be_main
server s1 172.25.0.10:8080 check
global
master-worker
log stdout format raw local0 info
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
# standard default settings...
log global
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
resolvers dnsprod
nameserver ns1 172.25.0.12:53
resolvers dnsdev
nameserver ns1 172.25.0.13:53
frontend prod
bind :80
# Resolve the DNS name found in the Host header and store it in the variable
http-request do-resolve(txn.prodip,dnsprod) hdr(Host),lower
http-request do-resolve(txn.devip,dnsdev) hdr(Host),lower
# Log the resolved IP address
http-request capture var(txn.prodip) len 40
http-request capture var(txn.devip) len 40
default_backend be_main
backend be_main
# Dynamically set the server IP address
http-request set-dst var(txn.prodip) unless { url_param(env) -m str dev } # Use Prod server if no "env" URL param
http-request set-dst var(txn.devip) if { url_param(env) -m str dev } # Use Dev server if "env" URL param
server clear 0.0.0.0:8080
global
master-worker
log stdout local0
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
log global
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
frontend fe_main
# HTTP/2 from the client to HAProxy
bind :443 ssl crt /etc/haproxy/certs/mycert.pem alpn h2,http/1.1
default_backend be_main
backend be_main
# HTTP/2 from HAProxy to the backend web server
server s1 172.25.0.10:443 check ssl verify none alpn h2
global
master-worker
log stdout local0
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
log global
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option httplog
frontend fe_main
bind :80
default_backend be_main
backend be_main
retries 3 # How many times to retry
option redispatch # try another server if the first fails
# COMMENT OUT THE NEXT LINE TO STOP LAYER 7 RETRIES:
retry-on 500 # retry if there's an HTTP 500 error.
# Do not retry POST requests
http-request disable-l7-retry if METH_POST
server s1 172.25.0.8:8080 check
server s2 172.25.0.10:8080 check # muxy server, causes HTTP errors intentionally en route to server2
global
master-worker
# log all info to stdout so that it can be seen with 'docker logs'
log stdout format raw local0 info
# log 1/3 of the messages to the external rsyslog server
log 172.25.0.12:514 sample 1:3 local0
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
# apply log from 'global' section to all of the following 'frontend' and 'backend' sections
log global
# standard default settings...
mode http
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
frontend fe_main
bind :80
default_backend be_main
backend be_main
server s1 172.25.0.10:8080 check
global
master-worker
log stdout local0
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
mode http
log global
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
# Shows that you can define a 'table' inside a 'peers' section.
peers peerslist1
peer haproxy1 172.25.0.11:10000 # NOTE: I am using the Docker-Compose hostname 'haproxy1', but you can use an IP/port too
peer haproxy2 172.25.0.12:10000
table global_req_rate type ip size 1m expire 10m store http_req_rate(10m)
# Another peers section that shows that you can use 'bind' and 'server' lines to define listening and remote endpoings
# for the peers protocol, instead of the older 'peer' line. The benefit is the ability to use server arguments like 'ssl'.
peers peerslist2
bind :10001 ssl crt /etc/haproxy/certs/mycert.pem
default-server ssl verify none
server haproxy1 #local peer - it is an error to give an address here.
server haproxy2 172.25.0.12:10000
table login_req_rate type ip size 1m expire 10m store http_req_rate(10m)
table api_req_rate type ip size 1m expire 10m store http_req_rate(10m)
# Reference the peers section and table with 'track-scX' lines.
frontend fe_main
bind :80
http-request track-sc0 src table peerslist1/global_req_rate
http-request track-sc1 src table peerslist2/login_req_rate if { path_beg /login }
http-request track-sc1 src table peerslist2/api_req_rate if { path_beg /api }
default_backend be_main
backend be_main
server s1 172.25.0.10:8080 check
global
master-worker
log stdout local0
# Runtime API
stats socket :9999 level admin expose-fd listeners
defaults
mode http
log global
timeout client 5s
timeout server 5s
timeout connect 5s
option redispatch
option httplog
# Shows that you can define a 'table' inside a 'peers' section.
peers peerslist1
peer haproxy1 172.25.0.11:10000 # NOTE: I am using the Docker-Compose hostname 'haproxy1', but you can use an IP/port too
peer haproxy2 172.25.0.12:10000
table global_req_rate type ip size 1m expire 10m store http_req_rate(10m)
# Another peers section that shows that you can use 'bind' and 'server' lines to define listening and remote endpoings
# for the peers protocol, instead of the older 'peer' line. The benefit is the ability to use server arguments like 'ssl'.
peers peerslist2
bind :10001 ssl crt /etc/haproxy/certs/mycert.pem
default-server ssl verify none
server haproxy1 172.25.0.11:10000
server haproxy2 #local peer - it is an error to give an address here
table login_req_rate type ip size 1m expire 10m store http_req_rate(10m)
table api_req_rate type ip size 1m expire 10m store http_req_rate(10m)
# Reference the peers section and table with a 'track-sc0' line.
frontend fe_main
bind :80
http-request track-sc0 src table peerslist1/global_req_rate
http-request track-sc1 src table peerslist2/login_req_rate if { path_beg /login }
http-request track-sc1 src table peerslist2/api_req_rate if { path_beg /api }
default_backend be_main
backend be_main
server s1 172.25.0.10:8080 check