www/caddy: Add simple load balancing (#3911)

* Add: Simple Load Balancing support of Upstreams with the random policy, by allowing multiple Upstream Domains in Handlers.

* Add passive health fail duration test. It enables unhealthy upstreams to be sorted when simple load balancing is enabled.

* Update pkg-descr
This commit is contained in:
Monviech
2024-04-13 14:58:42 +02:00
committed by GitHub
parent 74c1c75491
commit 7a5c968dc5
5 changed files with 30 additions and 3 deletions
+3
View File
@@ -19,6 +19,7 @@ Main features of this plugin:
* Syslog-ng integration and HTTP Access Log
* NTLM Transport
* Header manipulation with header_up and header_down
* Simple load balancing with passive health check
DOC: https://docs.opnsense.org/manual/how-tos/caddy.html
@@ -34,6 +35,8 @@ Plugin Changelog
* Add: Header functionality added. Multiple header manipulations can be set per handler.
* Cleanup: Update searchBase() in ReverseProxyController.php for easier maintainability.
* Fix: Move selectpicker empty option to model in general.volt, using BlankDesc. This fixes the option IPv4+IPv6 not appearing in Dynamic DNS.
* Add: Simple Load Balancing support with the default random policy, by allowing to add multiple Upstream Domains in Handlers.
* Add: Passive Health check for load balancing (Upstream Fail Duration) in Handlers.
1.5.3
@@ -56,9 +56,11 @@
<field>
<id>handle.ToDomain</id>
<label>Upstream Domain</label>
<type>text</type>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
<hint>192.168.1.1</hint>
<help><![CDATA[Enter the internal domain name or IP address of the upstream destination for this handler.]]></help>
<help><![CDATA[Enter the internal domain name or IP address of the upstream destination for this handler. If multiple upstream destinations are chosen, they will be load balanced with the default random policy.]]></help>
</field>
<field>
<id>handle.ToPort</id>
@@ -74,6 +76,13 @@
<help><![CDATA[Enter a path prefix like '/guacamole' that should be prepended to the upstream request because the application demands it.]]></help>
<advanced>true</advanced>
</field>
<field>
<id>handle.PassiveHealthFailDuration</id>
<label>Upstream Fail Duration</label>
<type>text</type>
<help><![CDATA[Enables a passive health check when multiple upstream destinations have been defined for load balancing. "fail_duration" is a duration value that defines how long to remember a failed request. A duration of 1 or more seconds enables passive health checking; the default is empty (off). A reasonable starting point might be 30s to balance error rates with responsiveness when bringing an unhealthy upstream back online.]]></help>
<advanced>true</advanced>
</field>
<field>
<type>header</type>
<label>Trust</label>
@@ -256,6 +256,8 @@
<Required>Y</Required>
<ValidationMessage>Please enter a valid 'to' domain or IP address.</ValidationMessage>
<IpAllowed>Y</IpAllowed>
<FieldSeparator>,</FieldSeparator>
<AsList>Y</AsList>
</ToDomain>
<ToPort type="PortField">
<ValidationMessage>Please enter a valid 'to' port number.</ValidationMessage>
@@ -266,6 +268,11 @@
<Mask>/^(\/.*)?$/u</Mask>
<ValidationMessage>Please enter a valid 'Backend Path' that starts with '/'.</ValidationMessage>
</ToPath>
<PassiveHealthFailDuration type="IntegerField">
<MinimumValue>1</MinimumValue>
<MaximumValue>100</MaximumValue>
<ValidationMessage>Please enter a value between 1 to 100.</ValidationMessage>
</PassiveHealthFailDuration>
<HttpTls type="BooleanField"/>
<HttpNtlm type="BooleanField"/>
<HttpTlsInsecureSkipVerify type="BooleanField"/>
@@ -247,6 +247,7 @@
<th data-column-id="ToDomain" data-type="string">Upstream Domain</th>
<th data-column-id="ToPort" data-type="string">Upstream Port</th>
<th data-column-id="ToPath" data-type="string" data-visible="false">Upstream Path</th>
<th data-column-id="PassiveHealthFailDuration" data-type="string" data-visible="false">Fail Duration</th>
<th data-column-id="HttpTls" data-type="boolean" data-formatter="boolean" data-visible="false">TLS</th>
<th data-column-id="HttpTlsTrustedCaCerts" data-type="string" data-visible="false">TLS CA</th>
<th data-column-id="HttpTlsServerName" data-type="string" data-visible="false">TLS Server Name</th>
@@ -500,14 +500,21 @@
# - HttpTlsInsecureSkipVerify (boolean, optional): If true, the server's SSL certificate is not verified.
# - HttpTlsTrustedCaCerts (string, optional): The config extracted name of a CA certificate.
# - HttpTlsServerName (string, optional): Specifies the server name for the TLS handshake.
# - PassiveHealthFailDuration (integer, optional): Enables passive health checks when set > 0.
#}
{% macro reverse_proxy_configuration(handle) %}
{{ handle.HandleType }} {{ handle.HandlePath|default("") }} {
{% if handle.ToPath|default("") != "" %}
rewrite * {{ handle.ToPath }}{uri}
{% endif %}
reverse_proxy {{ handle.ToDomain }}{% if handle.ToPort %}:{{ handle.ToPort }}{% endif %} {
reverse_proxy {% for domain in handle.ToDomain.split(',') %}
{# For each domain/IP, append the port if it's specified, followed by a space #}
{{- domain -}}{% if handle.ToPort %}:{{ handle.ToPort }}{% endif %}{% if not loop.last %} {% endif %}
{% endfor %}{
{{ header_manipulation(handle) }}
{% if handle.PassiveHealthFailDuration|default("") %}
fail_duration {{ handle.PassiveHealthFailDuration }}s
{% endif %}
{% if handle.HttpTls|default("0") == "1" or handle.HttpTlsInsecureSkipVerify|default("0") == "1" %}
{% if handle.HttpNtlm|default("0") == "1" %}
transport http_ntlm {