diff --git a/states/haproxy/defaults.yaml b/states/haproxy/defaults.yaml index 59ba14e..0fdd63f 100644 --- a/states/haproxy/defaults.yaml +++ b/states/haproxy/defaults.yaml @@ -14,8 +14,10 @@ haproxy: lib: false maps: - access + - redirects + - vhosts config: - servername: "PaulBSD WebServer 1.0" + servername: "High-performance Web Server" http2: true defaults: #log: global @@ -58,5 +60,16 @@ haproxy: ssl_options: - no-sslv3 - no-tls-tickets + gzip_mime_types: + - text/html + - text/plain + - text/css + - text/javascript + - application/javascript + cache_file_types: + - .css + - .js + - .png + - .jpg vhosts: {} services: {} diff --git a/states/haproxy/install.sls b/states/haproxy/install.sls index 757f258..39dfe48 100644 --- a/states/haproxy/install.sls +++ b/states/haproxy/install.sls @@ -1,17 +1,24 @@ --- {%- from "haproxy/map.jinja" import haproxy with context %} haproxy-pkg: - pkg.installed: + pkg.latest: - pkgs: {{ haproxy.packages }} -haproxy-maps-dir: +haproxy-config-dir: + file.directory: + - name: {{ haproxy.config.dir }} + - user: {{ haproxy.config.user }} + - group: {{ haproxy.config.group }} + - mode: "0700" + +haproxy-config-maps-dir: file.directory: - name: {{ haproxy.config.dir }}/maps - user: {{ haproxy.config.user }} - group: {{ haproxy.config.group }} - mode: "0700" -haproxy-script-dir: +haproxy-config-script-dir: file.directory: - name: {{ haproxy.config.dir }}/scripts - user: {{ haproxy.config.user }} @@ -34,7 +41,7 @@ haproxy-script-{{ file.name }}: haproxy-maps-{{ filename }}: file.managed: - name: {{ haproxy.config.dir }}/maps/{{ filename }} - - source: salt://haproxy/templates/{{ filename }}.j2 + - source: salt://haproxy/maps/{{ filename }}.j2 - user: {{ haproxy.config.user }} - group: {{ haproxy.config.group }} - mode: "0600" diff --git a/states/haproxy/templates/access.j2 b/states/haproxy/maps/access.j2 similarity index 100% rename from states/haproxy/templates/access.j2 rename to states/haproxy/maps/access.j2 diff --git a/states/haproxy/maps/redirects.j2 b/states/haproxy/maps/redirects.j2 new file mode 100644 index 0000000..507a1bf --- /dev/null +++ b/states/haproxy/maps/redirects.j2 @@ -0,0 +1,7 @@ +## {{ salt['pillar.get']('salt_managed', default='Salt Managed') }} +{%- from "haproxy/map.jinja" import haproxy with context %} +{%- for name, values in haproxy.config.vhosts.items() %} +{%- if values.redirect|default(false) %} +{{ values.host }} {{ values.redirect }} +{%- endif %} +{%- endfor %} diff --git a/states/haproxy/maps/vhosts.j2 b/states/haproxy/maps/vhosts.j2 new file mode 100644 index 0000000..f0643c3 --- /dev/null +++ b/states/haproxy/maps/vhosts.j2 @@ -0,0 +1,7 @@ +## {{ salt['pillar.get']('salt_managed', default='Salt Managed') }} +{%- from "haproxy/map.jinja" import haproxy with context %} +{%- for name, values in haproxy.config.vhosts.items() %} +{%- if not values.redirect|default(false) %} +{{ values.host }} {{ name }} +{%- endif %} +{%- endfor %} diff --git a/states/haproxy/scripts/weight_by_latency.lua b/states/haproxy/scripts/weight_by_latency.lua index 0160a95..e88fc4f 100644 --- a/states/haproxy/scripts/weight_by_latency.lua +++ b/states/haproxy/scripts/weight_by_latency.lua @@ -14,17 +14,19 @@ local function getmax(t) end local function arrange_backends() - local results = {} while true do for _, backend in pairs(core.backends) do - results = {} + local results = {} for n,server in pairs(backend.servers) do - if server:get_stats()["check_status"] == "L4OK" then - local svname = server:get_stats()["svname"] - local latency = server:get_stats()["check_duration"] - results[svname] = latency + if server:get_stats()["check_status"] ~= nil then + if string.find(server:get_stats()["check_status"],"OK") ~= nil then + local svname = server:get_stats()["svname"] + local latency = server:get_stats()["check_duration"] + results[svname] = latency + end end end + local b,c = getmax(results) if b ~= nil then for n,server in pairs(backend.servers) do diff --git a/states/haproxy/templates/haproxy.cfg.j2 b/states/haproxy/templates/haproxy.cfg.j2 index deee9cc..5f20304 100644 --- a/states/haproxy/templates/haproxy.cfg.j2 +++ b/states/haproxy/templates/haproxy.cfg.j2 @@ -16,35 +16,37 @@ {%- macro endpoints(servers, check, ssl) -%} {%- for server in servers %} - server {{ server.name }} {{ server.name }}:{{ server.port }}{{ " check observe layer7 inter 1s fall 5 rise 5 " if check|default(true) }}{{ " ssl verify none " if ssl|default(false) }} + server {{ server.name }} {{ server.name }}:{{ server.port }}{{ " check observe layer7 inter 2s fall 5 rise 5 " if check|default(true) }}{{ " ssl verify none " if ssl|default(false) }} {%- endfor %} {%- endmacro -%} {%- macro cache() -%} - http-request cache-use static if { path_end .css .js .png .jpg } + http-request cache-use static if { path_end {{ haproxy.config.cache_file_types|join(" ") }} } http-response cache-store static {%- endmacro -%} {%- macro compression() -%} compression algo gzip - compression type text/html text/plain text/css text/javascript application/javascript + compression type {{ haproxy.config.gzip_mime_types|join(' ') }} {%- endmacro -%} {%- macro admin() -%} +# Stats listen stats mode http - bind *:7000 v4v6 + bind *:7000,:::7000 v4v6 stats enable stats refresh 5s stats uri / {%- endmacro -%} {%- macro api() -%} - stats socket ipv4@127.0.0.1:9990 level admin - stats socket /var/run/hap-lb.sock mode 666 level admin - stats timeout 2m +# Runtime API + stats socket {{ haproxy.config.api.tcpsocket }} level admin + stats socket {{ haproxy.config.api.filesocket }} mode 666 level admin {%- endmacro %} +# Global config global lua-prepend-path {{ haproxy.config.dir }}/scripts/?.lua {%- for file in haproxy.scripts %} @@ -52,10 +54,10 @@ global lua-load {{ haproxy.config.dir }}/{{ file.name }} {%- endif %} {%- endfor %} - maxconn 1000 {%- if haproxy.config.api.enable %} {{ api() }} {%- endif %} + maxconn 1000 ssl-default-bind-ciphers {{ haproxy.config.ssl_ciphers|join(":") }} ssl-default-bind-options {{ haproxy.config.ssl_options|join(" ") }} ssl-default-server-ciphers {{ haproxy.config.ssl_ciphers|join(":") }} @@ -63,6 +65,7 @@ global crt-base {{ haproxy.config.acme_fullchains_dir }} ssl-dh-param-file {{ haproxy.config.acme_dh_dir }}/dh.pem +# Defaults values defaults {%- for key, value in haproxy.config.defaults.items() %} {{ key }} {{ value }} @@ -72,42 +75,58 @@ defaults {{ admin() }} {%- endif %} +# Cache cache static total-max-size 256 max-object-size 50000 max-age 120 +# Per IP rates stick table backend per_ip_rates stick-table type string size 1m expire 10s store http_req_rate(10s) +# Default HTTP frontend frontend http bind *:80,:::80 v4v6 mode http acl http ssl_fc,not http-request redirect scheme https if http +# Default HTTPS frontend frontend https bind *:443,:::443 v4v6 ssl crt {{ haproxy.config.acme_fullchains_dir }}{% if haproxy.config.http2 %} alpn h2,http/1.1{% endif %} mode http option httplog - {%- for name, values in haproxy.config.vhosts.items() %} - use_backend {{ name }} if { hdr(Host) -i {{ values.host }} } - {%- endfor %} - http-request track-sc0 src table per_ip_rates + acl internal src -f {{ haproxy.config.dir }}/maps/access + http-request set-var(req.src) src + http-request set-var(req.host) req.hdr(host) + http-request set-var(req.accesshash) str(),concat(,req.src,),concat(-,req.host,) + http-request track-sc0 var(req.accesshash) table per_ip_rates http-request capture req.hdr(User-Agent) len 200 http-request capture req.hdr(Content-Type) len 200 http-request capture req.hdr(Referer) len 200 http-request capture sc_http_req_rate(0) len 4 - http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 } - http-request set-header x-proxy-id "{{ salt["grains.get"]("host") }}" + http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 } !internal + http-request set-header X-Proxy-Id "{{ salt["grains.get"]("host") }}" + http-request set-header X-Proto https if { ssl_fc } 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" + http-request redirect location %[req.hdr(host),map_dom({{ haproxy.config.dir }}/maps/redirects)] code 301 if { req.hdr(host),map_dom(/etc/haproxy/maps/redirects) -m found } + use_backend %[req.hdr(Host),lower,map({{ haproxy.config.dir }}/maps/vhosts,nginx)] default_backend nginx +# HTTP Backends {% for name, values in haproxy.config.vhosts.items() %} +{%- if not values.redirect|default(false) %} backend {{ name }} balance {{ values.balance|default("roundrobin") }} mode http option forwardfor +{%- if values.check|default(false) %} + option httpchk +{%- for step in values.check_steps|default([]) %} + http-check {{ step }} +{%- endfor %} +{%- endif %} {%- if values.head|default(false) %} {{ head() }} {%- endif %} @@ -128,11 +147,13 @@ backend {{ name }} {{ internal() }} {%- endif %} {{- endpoints(values.servers, values.check, values.ssl) }} -{% endfor -%} +{%- endif %} +{% endfor %} +# TCP services {% for name, values in haproxy.config.services.items() %} listen {{ name }} - bind :::{{ values.port }} v4v6 + bind *:{{ values.port }},:::{{ values.port }} v4v6 mode tcp option tcplog {%- if values.type == "postgres" %}