From d777a605920921249ec120c8679f0e50215a0266 Mon Sep 17 00:00:00 2001
From: Monviech <79600909+Monviech@users.noreply.github.com>
Date: Wed, 10 Jul 2024 11:38:46 +0200
Subject: [PATCH] www/caddy: Cleanup model, php (PSR-12), python (PEP 8) and
jinja2 files (#4060)
* www/caddy: Remove unsused code in validation.
* www/caddy: Cleanup Caddyfile template for better readability with improved indentation.
* www/caddy: Cleanup rc.conf.d/caddy
* www/caddy: Cleanup model.
* www/caddy: Cleanup Caddyfile template some more.
* www/caddy: Roll back changes to Caddyfile structure, don't fix what ain't broken.
* www/caddy: Fix caddy_certs.php style warning. A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both.
* www/caddy: Ignore php style warnings for migration scripts, since the class names have to ignore PascalCase.
* www/caddy: Correct style of php files so that no lines exceed 120 characters.
* www/caddy: Refactor caddy_diagnostics.py and caddy_control.py for Python PEP 8. Fix: Shadows name 'action' from outer scope
* www/caddy: Changelog add code cleanup.
* www/caddy: Fix minor regression in refactored caddy_control.py script.
* www/caddy: Fix indentation of Caddyfile template for better code readability. The template gets edited and read a lot so this fix really helps with maintainability.
* www/caddy: Add changelog.
* www/caddy: Fix caddy_certs.php style issue by removing the declared function and execute logic with side effects directly.
* www/caddy: Re-add ValidationMessage to IntegerField because there are custom constraints that are not displayed by the default validation message.
* www/caddy: Add error handling to caddy_control.py when action is empty. Make use of service_action and cmd_action clearer.
* www/caddy: Remove unnecessary variable in caddy_diagnostics.py
* www/caddy: Add validation message since there is a no IP constraint. Add same constraint to subdomains.
* www/caddy: Re-add validation message to ToDomain field since multiple are allowed
* www/caddy: Re-add validation message to clientIps field since multiple are allowed
---
www/caddy/pkg-descr | 6 +-
.../Caddy/Api/DiagnosticsController.php | 4 +-
.../Caddy/Api/ReverseProxyController.php | 30 +-
.../mvc/app/models/OPNsense/Caddy/Caddy.php | 51 ++-
.../mvc/app/models/OPNsense/Caddy/Caddy.xml | 60 +---
.../OPNsense/Caddy/Migrations/M1_1_3.php | 2 +
.../OPNsense/Caddy/Migrations/M1_1_8.php | 2 +
.../scripts/OPNsense/Caddy/caddy_certs.php | 68 ++--
.../scripts/OPNsense/Caddy/caddy_control.py | 51 +--
.../OPNsense/Caddy/caddy_diagnostics.py | 19 +-
.../templates/OPNsense/Caddy/Caddyfile | 334 +++++++++---------
.../templates/OPNsense/Caddy/rc.conf.d/caddy | 11 +-
12 files changed, 331 insertions(+), 307 deletions(-)
diff --git a/www/caddy/pkg-descr b/www/caddy/pkg-descr
index 94e47d2bd..530635276 100644
--- a/www/caddy/pkg-descr
+++ b/www/caddy/pkg-descr
@@ -28,7 +28,11 @@ Plugin Changelog
1.6.0
* Add: New Dashboard widgets for 24.7, showing domain status and certificate validity status.
-* Fix: Caddyfile template fixed for IPv6 addresses and custom port.
+* Cleanup: PHP files refactored for PSR-12, Python files refactored for PEP-8.
+* Cleanup: Templates Caddyfile and rc.conf.d/caddy refactored for maintainability.
+* Cleanup: Spurious keys removed from Caddy.xml model.
+* Cleanup: Unused code removed from Caddy.php.
+* Fix: Caddyfile template fixed when IPv6 addresses and ports are used in Upstream. IPv6 address wraps into brackets now.
* Add: forward_auth directive with Authelia as Authz Provider.
* Add: Default HTTP and HTTPS ports can be changed in general settings.
* Add: Introduce HTTP version to handler. HTTP/1.1, HTTP/2 and HTTP/3 can be chosen.
diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/DiagnosticsController.php b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/DiagnosticsController.php
index bda64cb5e..edcb55389 100644
--- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/DiagnosticsController.php
+++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/DiagnosticsController.php
@@ -50,7 +50,7 @@ class DiagnosticsController extends ApiMutableModelControllerBase
// Decode JSON to PHP array
$responseArray = json_decode($response, true);
- // Since errors are handled by the caddy_diagnostics script and returned as json, check for an error key in the response
+ // Errors are handled by the caddy_diagnostics script and returned, check for an error key in the response
if (isset($responseArray['error'])) {
return ["status" => "failed", "message" => $responseArray['message']];
}
@@ -74,7 +74,6 @@ class DiagnosticsController extends ApiMutableModelControllerBase
// Decode JSON to PHP array
$responseArray = json_decode($response, true);
- // Since errors are handled by the caddy_diagnostics script and returned as json, check for an error key in the response
if (isset($responseArray['error'])) {
return ["status" => "failed", "message" => $responseArray['message']];
}
@@ -94,7 +93,6 @@ class DiagnosticsController extends ApiMutableModelControllerBase
// Decode JSON to PHP array
$responseArray = json_decode($response, true);
- // Since errors are handled by the caddy_diagnostics script and returned as json, check for an error key in the response
if (isset($responseArray['error'])) {
return ["status" => "failed", "message" => $responseArray['message']];
}
diff --git a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/ReverseProxyController.php b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/ReverseProxyController.php
index 5f32443d0..193aa298b 100644
--- a/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/ReverseProxyController.php
+++ b/www/caddy/src/opnsense/mvc/app/controllers/OPNsense/Caddy/Api/ReverseProxyController.php
@@ -26,7 +26,6 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- *
*/
namespace OPNsense\Caddy\Api;
@@ -70,14 +69,15 @@ class ReverseProxyController extends ApiMutableModelControllerBase
}
/**
- * Centralized and generalized helper function for searching across different sections of the reverse proxy setup.
+ * Generalized helper function for searching across different sections of the reverse proxy setup.
* This function mostly helps when model relation fields are used.
* It filters entries based on UUIDs provided as an argument. The section or key used for the UUID
* can be specified, allowing for direct or indirect UUID referencing.
*
- * @param string $modelPath The data model path identifier, pointing to the section of the model being searched.
- * @param string $uuidSearchBase The request parameter name for the comma-separated list of UUIDs to filter the search results.
- * @param string|null $uuidReferenceKey The specific attribute key used to fetch the UUID for filtering. If null, defaults to the item's own UUID.
+ * @param string $modelPath The data model path identifier, pointing to section of model being searched.
+ * @param string $uuidSearchBase The request parameter name for the comma-separated list of UUIDs.
+ * @param string|null $uuidReferenceKey Attribute key used to fetch the UUID for filtering.
+ * If null, uses item's own UUID.
* @return array Filtered search results.
*/
private function searchActionHelper($modelPath, $uuidSearchBase, $uuidReferenceKey = null)
@@ -89,8 +89,12 @@ class ReverseProxyController extends ApiMutableModelControllerBase
// Define a filter function to determine which items to include based on the UUID.
$filterFunction = function ($modelItem) use ($uuidArray, $uuidReferenceKey) {
- // Extract UUID from the item, using the specified UUID key if provided, otherwise default to direct UUID access.
- $modelUUID = ($uuidReferenceKey !== null) ? (string)$modelItem->$uuidReferenceKey : (string)$modelItem->getAttributes()['uuid'];
+ // Extract UUID from the item, using the specified UUID key if provided, else default to direct UUID access.
+ if ($uuidReferenceKey !== null) {
+ $modelUUID = (string)$modelItem->$uuidReferenceKey;
+ } else {
+ $modelUUID = (string)$modelItem->getAttributes()['uuid'];
+ }
// Include the item if the UUID array is empty or if the item's UUID is in the array.
return empty($uuidArray) || in_array($modelUUID, $uuidArray, true);
};
@@ -245,8 +249,10 @@ class ReverseProxyController extends ApiMutableModelControllerBase
{
if ($this->request->isPost()) {
$postData = $this->request->getPost();
-
- if (isset($postData['basicauth']['basicauthpass']) && !empty(trim($postData['basicauth']['basicauthpass']))) {
+ if (
+ isset($postData['basicauth']['basicauthpass'])
+ && !empty(trim($postData['basicauth']['basicauthpass']))
+ ) {
$plainPassword = $postData['basicauth']['basicauthpass'];
$hashedPassword = password_hash($plainPassword, PASSWORD_BCRYPT);
$_POST['basicauth']['basicauthpass'] = $hashedPassword;
@@ -260,8 +266,10 @@ class ReverseProxyController extends ApiMutableModelControllerBase
{
if ($this->request->isPost()) {
$postData = $this->request->getPost();
-
- if (isset($postData['basicauth']['basicauthpass']) && !empty(trim($postData['basicauth']['basicauthpass']))) {
+ if (
+ isset($postData['basicauth']['basicauthpass'])
+ && !empty(trim($postData['basicauth']['basicauthpass']))
+ ) {
$plainPassword = $postData['basicauth']['basicauthpass'];
$hashedPassword = password_hash($plainPassword, PASSWORD_BCRYPT);
$_POST['basicauth']['basicauthpass'] = $hashedPassword;
diff --git a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.php b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.php
index 9f76fe20e..42972f8d1 100644
--- a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.php
+++ b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.php
@@ -59,9 +59,15 @@ class Caddy extends BaseModel
if (isset($combos[$comboKey])) {
// Use dynamic $key for message referencing
$messages->appendMessage(new Message(
- sprintf(gettext("Duplicate entry: The combination of '%s' and port '%s' is already used. Each combination of domain and port must be unique."), $fromDomain, $port),
- $key . ".FromDomain", // Adjusted to use dynamic key
- "DuplicateDomainPort"
+ sprintf(
+ gettext(
+ 'Duplicate entry: The combination of %s and port %s is already used. ' .
+ 'Each combination of domain and port must be unique.'
+ ),
+ $fromDomain,
+ $port
+ ),
+ $key . ".FromDomain"
));
} else {
$combos[$comboKey] = true;
@@ -98,9 +104,14 @@ class Caddy extends BaseModel
if (!$isValid) {
$key = $subdomain->__reference; // Dynamic key based on subdomain reference
$messages->appendMessage(new Message(
- sprintf(gettext("Invalid subdomain configuration: '%s' does not fall under any configured wildcard domain."), $subdomainName),
- $key . ".FromDomain", // Use dynamic key for message referencing
- "InvalidSubdomain"
+ sprintf(
+ gettext(
+ 'Invalid subdomain configuration: %s does not fall ' .
+ 'under any configured wildcard domain.'
+ ),
+ $subdomainName
+ ),
+ $key . ".FromDomain"
));
}
}
@@ -140,7 +151,18 @@ class Caddy extends BaseModel
if (!empty($overlap) && $tlsAutoHttpsSetting !== 'off') {
$portOverlap = implode(', ', $overlap);
$messages->appendMessage(new Message(
- sprintf(gettext('To use "Auto HTTPS", resolve these conflicting ports (%s) that are currently configured for the OPNsense WebGUI. Go to "System - Settings - Administration". To release port 80, enable "Disable web GUI redirect rule". To release port %s, change "TCP port" to a non-standard port, e.g., 8443.'), $portOverlap, $httpsPort),
+ sprintf(
+ gettext(
+ 'To use "Auto HTTPS", resolve these conflicting ports %s ' .
+ 'that are currently configured for the OPNsense WebGUI. ' .
+ 'Go to "System - Settings - Administration". ' .
+ 'To release port 80, enable "Disable web GUI redirect rule". ' .
+ 'To release port %s, change "TCP port" to a non-standard port, ' .
+ 'e.g., 8443.'
+ ),
+ $portOverlap,
+ $httpsPort
+ ),
"general.TlsAutoHttps"
));
}
@@ -193,12 +215,23 @@ class Caddy extends BaseModel
public function performValidation($validateFullModel = false)
{
$messages = parent::performValidation($validateFullModel);
+
// 1. Check domain-port combinations
- $this->checkForUniquePortCombos($this->reverseproxy->reverse->iterateItems(), $messages);
+ $this->checkForUniquePortCombos(
+ $this->reverseproxy->reverse->iterateItems(),
+ $messages
+ );
+
// 2. Check that subdomains are under a wildcard or exact domain
- $this->checkSubdomainsAgainstDomains($this->reverseproxy->subdomain->iterateItems(), $this->reverseproxy->reverse->iterateItems(), $messages);
+ $this->checkSubdomainsAgainstDomains(
+ $this->reverseproxy->subdomain->iterateItems(),
+ $this->reverseproxy->reverse->iterateItems(),
+ $messages
+ );
+
// 3. Check WebGUI conflicts
$this->checkWebGuiSettings($messages);
+
// 4. Check for ACME Email requirement
$this->checkAcmeEmailAutoHttps($messages);
// 5. Check for TLS conflicts in Domain
diff --git a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.xml b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.xml
index 2650cb267..f70f54857 100644
--- a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.xml
+++ b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Caddy.xml
@@ -10,9 +10,7 @@
-
- Please enter a valid email address.
-
+
On (default)
@@ -106,9 +104,7 @@
FATAL
-
- Please enter a valid URL, starting with http or https.
-
+
1
@@ -150,17 +146,11 @@
Y
- Please enter a valid 'from' domain.
N
- Y
Y
- N
+ Please enter a valid domain name.
-
- Please enter a valid 'from' port number.
- Y
- N
-
+
@@ -189,10 +179,7 @@
-
- Please enter a valid 'to' domain or IP address.
- Y
-
+
@@ -213,8 +200,8 @@
Y
- Please enter a valid 'from' Subdomain that is based upon the wildcard domain.
- N
+ N
+ Please enter a valid domain name.
@@ -241,10 +228,7 @@
Y
-
- Please enter a valid 'to' domain or IP address.
- Y
-
+
@@ -282,7 +266,7 @@
/^(\/.*)?$/u
- Please enter a valid 'Handle Path' that starts with '/'.
+ Please enter a valid Path that starts with '/'.
Y
- Please enter a valid 'to' domain or IP address.
- Y
,
Y
+ Please enter one or multiple valid IP addresses, hostnames or FQDNs.
-
- Please enter a valid 'to' port number.
- Y
- N
-
+
/^(\/.*)?$/u
- Please enter a valid 'Backend Path' that starts with '/'.
+ Please enter a valid Path that starts with '/'.
1
@@ -351,30 +330,21 @@
ca
-
- Please enter a valid hostname or IP address.
- Y
- Y
- Y
- N
-
+
Y
-
+
Y
- /^([\t\n\v\f\r 0-9a-zA-Z.,_*-\x{00A0}-\x{FFFF}]){1,255}$/u
- Please provide a valid Access List Name.
Y
- Y
,
Y
Y
- Please enter valid IP address(es) or network(s), separated by commas.
+ Please enter one or multiple valid IP addresses or networks.
diff --git a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Migrations/M1_1_3.php b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Migrations/M1_1_3.php
index c103f8d48..649408dbc 100644
--- a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Migrations/M1_1_3.php
+++ b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Migrations/M1_1_3.php
@@ -31,7 +31,9 @@ namespace OPNsense\Caddy\Migrations;
use OPNsense\Base\BaseModelMigration;
use OPNsense\Core\Config;
+// @codingStandardsIgnoreStart
class M1_1_3 extends BaseModelMigration
+// @codingStandardsIgnoreEnd
{
public function run($model)
{
diff --git a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Migrations/M1_1_8.php b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Migrations/M1_1_8.php
index 0687d49ab..c506375a1 100644
--- a/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Migrations/M1_1_8.php
+++ b/www/caddy/src/opnsense/mvc/app/models/OPNsense/Caddy/Migrations/M1_1_8.php
@@ -31,7 +31,9 @@ namespace OPNsense\Caddy\Migrations;
use OPNsense\Base\BaseModelMigration;
use OPNsense\Core\Config;
+// @codingStandardsIgnoreStart
class M1_1_8 extends BaseModelMigration
+// @codingStandardsIgnoreEnd
{
public function run($model)
{
diff --git a/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_certs.php b/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_certs.php
index 0f6078b46..f65ef168c 100755
--- a/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_certs.php
+++ b/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_certs.php
@@ -2,8 +2,7 @@
object();
$temp_dir = '/var/db/caddy/data/caddy/certificates/temp/';
-function extract_and_save_certificates($configObj, $temp_dir)
-{
- // Traverse through certificates
- foreach ($configObj->cert as $cert) {
- $cert_refid = (string)$cert->refid;
- $cert_content = base64_decode((string)$cert->crt);
- $key_content = base64_decode((string)$cert->prv);
- $cert_chain = $cert_content;
+// Traverse through certificates
+foreach ($configObj->cert as $cert) {
+ $cert_refid = (string) $cert->refid;
+ $cert_content = base64_decode((string) $cert->crt);
+ $key_content = base64_decode((string) $cert->prv);
+ $cert_chain = $cert_content;
- // Handle CA and possible intermediate CA to create a certificate bundle
- if (!empty($cert->caref)) {
- foreach ($configObj->ca as $ca) {
- if ((string)$cert->caref == (string)$ca->refid) {
- $ca_content = base64_decode((string)$ca->crt);
- $cert_chain .= "\n" . $ca_content;
+ // Handle CA and possible intermediate CA to create a certificate bundle
+ if (!empty($cert->caref)) {
+ foreach ($configObj->ca as $ca) {
+ if ((string) $cert->caref === (string) $ca->refid) {
+ $ca_content = base64_decode((string) $ca->crt);
+ $cert_chain .= "\n" . $ca_content;
- if (!empty($ca->caref)) {
- foreach ($configObj->ca as $parent_ca) {
- if ((string)$ca->caref == (string)$parent_ca->refid) {
- $parent_ca_content = base64_decode((string)$parent_ca->crt);
- $cert_chain .= "\n" . $parent_ca_content;
- break;
- }
+ if (!empty($ca->caref)) {
+ foreach ($configObj->ca as $parent_ca) {
+ if ((string) $ca->caref === (string) $parent_ca->refid) {
+ $parent_ca_content = base64_decode((string) $parent_ca->crt);
+ $cert_chain .= "\n" . $parent_ca_content;
+ break;
}
}
}
}
}
-
- // Save the certificate chain and private key
- file_put_contents($temp_dir . $cert_refid . '.pem', $cert_chain);
- file_put_contents($temp_dir . $cert_refid . '.key', $key_content);
}
- // Traverse through CA certificates and save them
- foreach ($configObj->ca as $ca) {
- $ca_refid = (string)$ca->refid;
- $ca_content = base64_decode((string)$ca->crt);
-
- // Save the CA certificate
- file_put_contents($temp_dir . $ca_refid . '.pem', $ca_content);
- }
+ // Save the certificate chain and private key
+ file_put_contents($temp_dir . $cert_refid . '.pem', $cert_chain);
+ file_put_contents($temp_dir . $cert_refid . '.key', $key_content);
}
-extract_and_save_certificates($configObj, $temp_dir);
+// Traverse through CA certificates and save them
+foreach ($configObj->ca as $ca) {
+ $ca_refid = (string) $ca->refid;
+ $ca_content = base64_decode((string) $ca->crt);
+
+ // Save the CA certificate
+ file_put_contents($temp_dir . $ca_refid . '.pem', $ca_content);
+}
diff --git a/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_control.py b/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_control.py
index 79e9a8226..add576358 100755
--- a/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_control.py
+++ b/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_control.py
@@ -30,19 +30,23 @@ import subprocess
import json
import sys
-def run_service_command(action, action_message):
+
+def run_service_command(service_action, action_message):
result = {"message": action_message}
- if action == "validate":
+ if service_action == "validate":
try:
# Validate the Caddyfile with explicit --config flag, capturing both stdout and stderr
- validation_output = subprocess.check_output(["caddy", "validate", "--config", "/usr/local/etc/caddy/Caddyfile"], stderr=subprocess.STDOUT, text=True)
+ validation_output = subprocess.check_output(
+ ["caddy", "validate", "--config", "/usr/local/etc/caddy/Caddyfile"], stderr=subprocess.STDOUT,
+ text=True)
if "Valid configuration" in validation_output:
result["status"] = "ok"
result["message"] = "Caddy configuration is valid."
else:
# Search for the specific error message
- error_msg = next((line for line in validation_output.split('\n') if line.startswith("Error:")), "Caddy configuration is not valid.")
+ error_msg = next((line for line in validation_output.split('\n') if line.startswith("Error:")),
+ "Caddy configuration is not valid.")
result["status"] = "failed"
result["message"] = error_msg
except subprocess.CalledProcessError as e:
@@ -52,7 +56,7 @@ def run_service_command(action, action_message):
result["message"] = error_msg
else:
try:
- subprocess.run(["service", "caddy", action], check=True)
+ subprocess.run(["service", "caddy", service_action], check=True)
result["status"] = "ok"
except subprocess.CalledProcessError as e:
result["status"] = "failed"
@@ -60,29 +64,36 @@ def run_service_command(action, action_message):
return json.dumps(result)
-# Updated actions dictionary
+
+# "cmd_action": "service_action"
actions = {
"start": "start",
"stop": "stop",
"restart": "restart",
- "reload": "reloadssl", # Forces the reload even if the config in the Caddyfile is unchanged, using an extra command of the rc.d script, forcing certificates in the filesystem to reload.
+ "reload": "reloadssl",
+ # Reloadssl reloads even if the config in the Caddyfile is unchanged, using an extra command of the rc.d script,
+ # forcing certificates in the filesystem to be reloaded.
"validate": "validate" # Validate action
}
if __name__ == "__main__":
- action = sys.argv[1] # Get the action from the command-line argument
- if action in actions:
- service_action = actions[action]
- message = f"{action.capitalize()}ing Caddy service" if action != "validate" else "Validating Caddy configuration"
+ if len(sys.argv) > 1:
+ action = sys.argv[1] # Get the action from the command-line argument
+ if action in actions:
+ cmd_action = action
+ service_action = actions[action]
+ message = f"{cmd_action.capitalize()} Caddy service"
- # Call setup script for 'validate' and 'reloadssl' actions
- # This is needed because the setup script triggers the caddy_certs.php script, which exports all certificates into the filesystem.
- # Caddy reloads certificates when reloadssl is used. Because it is a non standard command, the caddy_setup script will not be triggered in /etc/rc.conf.d/caddy.
- # The validate command needs it to make sure all certificates are in the filesystem, because otherwise the validation fails.
- if service_action in ["validate", "reloadssl"]:
- subprocess.run(["/usr/local/opnsense/scripts/OPNsense/Caddy/setup.sh"], check=True)
+ # Call setup script for 'validate' and 'reloadssl' actions. This is needed because the setup script triggers
+ # the caddy_certs.php script, which exports all certificates into the filesystem. Caddy reloads certificates
+ # when reloadssl is used. Because it is a non standard command, the caddy_setup script will not be triggered
+ # in /etc/rc.conf.d/caddy. The validate command needs it to make sure all certificates are in the filesystem,
+ # because otherwise the validation fails.
+ if service_action in ["validate", "reloadssl"]:
+ subprocess.run(["/usr/local/opnsense/scripts/OPNsense/Caddy/setup.sh"], check=True)
- # Continue with the service action
- print(run_service_command(service_action, message))
+ print(run_service_command(service_action, message))
+ else:
+ print(json.dumps({"status": "failed", "message": f"Unknown action: {action}"}))
else:
- print(json.dumps({"status": "failed", "message": f"Unknown action: {action}"}))
+ print(json.dumps({"status": "failed", "message": "No action provided"}))
diff --git a/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_diagnostics.py b/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_diagnostics.py
index f42fd6065..ab55778a6 100755
--- a/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_diagnostics.py
+++ b/www/caddy/src/opnsense/scripts/OPNsense/Caddy/caddy_diagnostics.py
@@ -33,6 +33,7 @@ import subprocess
import asyncio
from datetime import datetime
+
# Function to show the Caddy configuration from a JSON file
def show_caddy_config():
config_path = "/var/db/caddy/config/caddy/autosave.json"
@@ -48,10 +49,12 @@ def show_caddy_config():
except FileNotFoundError:
print(json.dumps({"error": "File not found", "message": "Caddy autosave.json configuration file not found"}))
except json.JSONDecodeError:
- print(json.dumps({"error": "Invalid JSON", "message": "Error decoding the Caddy autosave.json, the file is not valid JSON"}))
+ print(json.dumps(
+ {"error": "Invalid JSON", "message": "Error decoding the Caddy autosave.json, the file is not valid JSON"}))
except Exception as e:
print(json.dumps({"error": "General Error", "message": str(e)}))
+
def show_caddyfile():
caddyfile_path = "/usr/local/etc/caddy/Caddyfile"
@@ -65,6 +68,7 @@ def show_caddyfile():
except Exception as e:
print(json.dumps({"error": "General Error", "message": str(e)}))
+
# Function to extract certificate information using openssl command
async def extract_certificate_info(cert_path):
try:
@@ -105,6 +109,7 @@ async def extract_certificate_info(cert_path):
except Exception as e:
raise RuntimeError(f"Error extracting certificate info for {cert_path}: {str(e)}")
+
# Function to find certificates and create tasks to extract info
async def find_certificates(base_dir):
tasks = []
@@ -123,6 +128,7 @@ async def find_certificates(base_dir):
results = await asyncio.gather(*tasks, return_exceptions=True)
return [result for result in results if not isinstance(result, Exception)]
+
# Function to show certificates, processing all found in the given directory
async def show_certificates():
# Function to show certificates, processing all found in the given directory
@@ -136,25 +142,26 @@ async def show_certificates():
except Exception as e:
print(json.dumps({"error": "General Error", "message": str(e)}))
+
# Action handler
-def perform_action(action):
+def perform_action(cmd_action):
actions = {
"config": show_caddy_config,
"caddyfile": show_caddyfile,
"certificate": lambda: asyncio.run(show_certificates())
}
- action_func = actions.get(action)
+ action_func = actions.get(cmd_action)
if action_func:
action_func()
else:
# Output error details in JSON format if action is unknown
- print(json.dumps({"error": "Unknown Action", "message": f"Unknown action: {action}"}))
+ print(json.dumps({"error": "Unknown Action", "message": f"Unknown action: {cmd_action}"}))
+
if __name__ == "__main__":
if len(sys.argv) > 1:
- action = sys.argv[1]
- perform_action(action)
+ perform_action(sys.argv[1])
else:
# Output error details in JSON format if no action is specified
print(json.dumps({"error": "No Action Specified", "message": "No action specified"}))
diff --git a/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/Caddyfile b/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/Caddyfile
index eb4ce0ad8..c06342fc9 100644
--- a/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/Caddyfile
+++ b/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/Caddyfile
@@ -37,11 +37,11 @@
#}
log {
{% if generalSettings.LogAccessPlain|default("0") == "0" %}
- {% for reverse in helpers.toList('Pischem.caddy.reverseproxy.reverse') %}
- {% if reverse.enabled|default("0") == "1" and reverse.AccessLog|default("0") == "1" %}
- include http.log.access.{{ reverse['@uuid'] }}
- {% endif %}
- {% endfor %}
+ {% for reverse in helpers.toList('Pischem.caddy.reverseproxy.reverse') %}
+ {% if reverse.enabled|default("0") == "1" and reverse.AccessLog|default("0") == "1" %}
+ include http.log.access.{{ reverse['@uuid'] }}
+ {% endif %}
+ {% endfor %}
{% endif %}
output net unixgram//var/caddy/var/run/log {
}
@@ -49,7 +49,7 @@
time_format rfc3339
}
{% if generalSettings.LogLevel %}
- level {{ generalSettings.LogLevel }}
+ level {{ generalSettings.LogLevel }}
{% endif %}
}
@@ -89,10 +89,10 @@
{% if hasAccessList or hasLogCredentials %}
servers {
{% if hasAccessList %}
- trusted_proxies static {{ accessList.clientIps.split(',') | join(' ') }}
+ trusted_proxies static {{ accessList.clientIps.split(',') | join(' ') }}
{% endif %}
{% if hasLogCredentials %}
- log_credentials
+ log_credentials
{% endif %}
}
{% endif %}
@@ -175,11 +175,11 @@
{% endif %}
domains {
{% for domain in dynDnsDomains %}
- {{ domain }}
+ {{ domain }}
{% endfor %}
}
{% if dynDnsSimpleHttp %}
- ip_source simple_http {{ dynDnsSimpleHttp }}
+ ip_source simple_http {{ dynDnsSimpleHttp }}
{% endif %}
{% if dynDnsInterface %}
{% set physicalInterfaceNames = [] %}
@@ -189,16 +189,16 @@
ip_source interface {{ physicalInterfaceNames | join(',') }}
{% endif %}
{% if dynDnsCheckInterval %}
- check_interval {{ dynDnsCheckInterval }}s
+ check_interval {{ dynDnsCheckInterval }}s
{% endif %}
{% if dynDnsIpVersions %}
- versions {{ dynDnsIpVersions }}
+ versions {{ dynDnsIpVersions }}
{% endif %}
{% if dynDnsTtl %}
- ttl {{ dynDnsTtl }}s
+ ttl {{ dynDnsTtl }}s
{% endif %}
{% if dynDnsUpdateOnly|default("0") == "1" %}
- update_only
+ update_only
{% endif %}
}
{% endif %}
@@ -211,11 +211,11 @@
#}
{% set emailValue = helpers.toList('Pischem.caddy.general.TlsEmail') | first %}
{% if emailValue %}
- email {{ emailValue }}
+ email {{ emailValue }}
{% endif %}
{% set autoHttpsValue = helpers.toList('Pischem.caddy.general.TlsAutoHttps') | first %}
{% if autoHttpsValue %}
- auto_https {{ autoHttpsValue }}
+ auto_https {{ autoHttpsValue }}
{% endif %}
{#
# Important: Grace Period influences how fast the server can finish reloads with open connections, by forcing termination.
@@ -299,8 +299,8 @@
# It uses a 'handle' object that specifies which headers to manipulate based on their @UUIDs.
# Each handle can have multiple of these HTTP headers assigned.
# Parameters:
-# @param handle (@object):
-# - @uuid (@string)
+# @param handle (object):
+# - @uuid (string)
# - HeaderUpDown (string): Determines the direction of the header.
# - HeaderType (string): Specifies the name of the header.
# - HeaderValue (string, optional): The new value to set for the header, if any.
@@ -341,15 +341,15 @@
# Purpose: Sets up the handle with the reverse proxy configurations. The TLS Settings are generated here for the Upstream.
# Integrated Macros: header_manipulation
# Parameters:
-# @param handle (@object):
-# - @uuid (@string)
+# @param handle (object):
+# - @uuid (string)
# - HandleType (string): Specifies the handling strategy.
# - HandlePath (string, optional): The path the handle should match on.
# - ToDomain (string): Target domain for the reverse proxy.
# - ToPort (string, optional): Target port on the ToDomain.
# - ToPath (string, optional): Destination path on the ToDomain.
# - HttpTls (boolean, optional): Enable TLS for the connection.
-# - HttpNtlm (boolean, optional): Enable NTLM authentication for the connection.
+# - HttpNtlm (boolean, optional): Enable NTLM authentication for the connection. Not all HTTP options apply to NTLM.
# - 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.
@@ -363,7 +363,7 @@
{% include "OPNsense/Caddy/includeAuthProvider" %}
{% endif %}
{% if handle.ToPath|default("") != "" %}
- rewrite * {{ handle.ToPath }}{uri}
+ rewrite * {{ handle.ToPath }}{uri}
{% endif %}
reverse_proxy {% for domain in handle.ToDomain.split(',') %}
{# Check if the domain is IPv6 and wrap in square brackets if necessary #}
@@ -373,22 +373,22 @@
{% endfor %} {
{{ header_manipulation(handle) }}
{% if handle.PassiveHealthFailDuration|default("") %}
- fail_duration {{ handle.PassiveHealthFailDuration }}s
+ fail_duration {{ handle.PassiveHealthFailDuration }}s
{% endif %}
{% if handle.HttpTls|default("0") == "1" or handle.HttpTlsInsecureSkipVerify|default("0") == "1" or handle.HttpTlsTrustedCaCerts or handle.HttpTlsServerName or handle.HttpVersion or handle.HttpKeepalive %}
{% if handle.HttpNtlm|default("0") == "1" %}
transport http_ntlm {
{% if handle.HttpTls|default("0") == "1" %}
- tls
+ tls
{% endif %}
{% if handle.HttpTlsInsecureSkipVerify|default("0") == "1" %}
- tls_insecure_skip_verify
+ tls_insecure_skip_verify
{% endif %}
{% if handle.HttpTlsTrustedCaCerts %}
- tls_trust_pool file /var/db/caddy/data/caddy/certificates/temp/{{ handle.HttpTlsTrustedCaCerts }}.pem
+ tls_trust_pool file /var/db/caddy/data/caddy/certificates/temp/{{ handle.HttpTlsTrustedCaCerts }}.pem
{% endif %}
{% if handle.HttpTlsServerName %}
- tls_server_name {{ handle.HttpTlsServerName }}
+ tls_server_name {{ handle.HttpTlsServerName }}
{% endif %}
}
{% else %}
@@ -406,16 +406,16 @@
{% endif %}
{% endif %}
{% if handle.HttpTls|default("0") == "1" %}
- tls
+ tls
{% endif %}
{% if handle.HttpTlsInsecureSkipVerify|default("0") == "1" %}
- tls_insecure_skip_verify
+ tls_insecure_skip_verify
{% endif %}
{% if handle.HttpTlsTrustedCaCerts %}
- tls_trust_pool file /var/db/caddy/data/caddy/certificates/temp/{{ handle.HttpTlsTrustedCaCerts }}.pem
+ tls_trust_pool file /var/db/caddy/data/caddy/certificates/temp/{{ handle.HttpTlsTrustedCaCerts }}.pem
{% endif %}
{% if handle.HttpTlsServerName %}
- tls_server_name {{ handle.HttpTlsServerName }}
+ tls_server_name {{ handle.HttpTlsServerName }}
{% endif %}
}
{% endif %}
@@ -431,10 +431,10 @@
# only get to the reverse proxy, when the access list matches. Invert is also possible, to explicitely deny IPs.
# The assembly is handled by the "Section: Reverse Proxy Configurations".
# Parameters:
-# @param accesslist (@object):
-# - @uuid (@string)
-# - clientIps (@string): A comma-separated list of client IP addresses
-# - invert (@boolean): A flag that inverts the logic of the access list
+# @param accesslist (object):
+# - uuid (string)
+# - clientIps (string): A comma-separated list of client IP addresses
+# - invert (boolean): A flag that inverts the logic of the access list
#}
{% macro access_list_configuration(accesslist, invert) %}
{% set client_ips = accesslist.clientIps.split(',') %}
@@ -448,11 +448,11 @@
# Macro: basicauth_configuration
# Purpose: Implements basic authentication with a username and password for access.
# Parameters:
-# @param basicauth_uuids (@string): A comma-separated list of UUIDs, each UUID corresponding to
+# @param basicauth_uuids (string): A comma-separated list of UUIDs, each UUID corresponding to
# a specific user credentials (username and password).
-# - @uuid (@string)
-# - basicauthuser (@string): The username required for authentication.
-# - basicauthpass (@string): The password associated with the username.
+# - @uuid (string)
+# - basicauthuser (string): The username required for authentication.
+# - basicauthpass (string): The password associated with the username.
#}
{% macro basicauth_configuration(basicauth_uuids) %}
{% if basicauth_uuids %}
@@ -482,139 +482,139 @@
# - Order of Wildcard Domains and Subdomains: Handles for wildcard domains come after all subdomains.
#}
{% for reverse in helpers.toList('Pischem.caddy.reverseproxy.reverse') %}
-{% if reverse.enabled|default("0") == "1" %}
-# Reverse Proxy Domain: "{{ reverse['@uuid'] }}"
-{# The default are encrypted connections, uncencrypted connections have to render http:// #}
-{% if reverse.DisableTls|default("0") == "1" %}http://{% endif %}{{ reverse.FromDomain|default("") }}{% if reverse.FromPort %}:{{ reverse.FromPort }}{% endif %} {
- {% if reverse.AccessLog|default("0") == "1" %}
- {% if generalSettings.LogAccessPlain|default("0") == "0" %}
- log {{ reverse['@uuid'] }}
- {% else %}
- log {
- output file /var/log/caddy/access/{{ reverse['@uuid'] }}.log {
- roll_keep_for {{ generalSettings.LogAccessPlainKeep|default("10") }}d
- }
- }
- {% endif %}
- {% endif %}
- {% set customCert = reverse.CustomCertificate|default("") %}
- {% set dnsChallenge = reverse.DnsChallenge|default("0") %}
- {{ tls_configuration(dnsProvider, dnsApiKey, customCert, dnsChallenge, dnsSecretApiKey, TlsDnsOptionalField1, TlsDnsOptionalField2, TlsDnsOptionalField3, TlsDnsOptionalField4) }}
-
- {% if not reverse.accesslist %}
- {% set basicauth_uuids = reverse.basicauth %}
- {{ basicauth_configuration(basicauth_uuids) }}
- {% endif %}
-
- {% for subdomain in helpers.toList('Pischem.caddy.reverseproxy.subdomain') %}
- {% if subdomain.enabled|default("0") == "1" and subdomain.reverse == reverse['@uuid'] %}
- @{{ subdomain['@uuid'] }} {
- host {{ subdomain.FromDomain }}
- }
- handle @{{ subdomain['@uuid'] }} {
-
- {% if not subdomain.accesslist %}
- {% set subdomain_basicauth_uuids = subdomain.basicauth %}
- {{ basicauth_configuration(subdomain_basicauth_uuids) }}
- {% endif %}
-
- {% if subdomain.accesslist %}
- {% set accesslist = helpers.toList('Pischem.caddy.reverseproxy.accesslist') | selectattr('@uuid', 'equalto', subdomain.accesslist) | first %}
- {{ access_list_configuration(accesslist, accesslist.accesslistInvert|default("0") == "1") }}
- handle @{{ accesslist['@uuid'] }} {
-
- {% set subdomain_basicauth_uuids = subdomain.basicauth %}
- {{ basicauth_configuration(subdomain_basicauth_uuids) }}
-
- {% set subdomain_handles = helpers.toList('Pischem.caddy.reverseproxy.handle') | selectattr('subdomain', 'equalto', subdomain['@uuid']) | list %}
- {% for handle in subdomain_handles %}
- {% if handle.enabled|default("0") == "1" and handle.HandlePath %}
- {{ reverse_proxy_configuration(handle) }}
+ {% if reverse.enabled|default("0") == "1" %}
+ # Reverse Proxy Domain: "{{ reverse['@uuid'] }}"
+ {# The default are encrypted connections, uncencrypted connections have to render http:// #}
+ {% if reverse.DisableTls|default("0") == "1" %}http://{% endif %}{{ reverse.FromDomain|default("") }}{% if reverse.FromPort %}:{{ reverse.FromPort }}{% endif %} {
+ {% if reverse.AccessLog|default("0") == "1" %}
+ {% if generalSettings.LogAccessPlain|default("0") == "0" %}
+ log {{ reverse['@uuid'] }}
+ {% else %}
+ log {
+ output file /var/log/caddy/access/{{ reverse['@uuid'] }}.log {
+ roll_keep_for {{ generalSettings.LogAccessPlainKeep|default("10") }}d
+ }
+ }
+ {% endif %}
{% endif %}
+ {% set customCert = reverse.CustomCertificate|default("") %}
+ {% set dnsChallenge = reverse.DnsChallenge|default("0") %}
+ {{ tls_configuration(dnsProvider, dnsApiKey, customCert, dnsChallenge, dnsSecretApiKey, TlsDnsOptionalField1, TlsDnsOptionalField2, TlsDnsOptionalField3, TlsDnsOptionalField4) }}
+
+ {% if not reverse.accesslist %}
+ {% set basicauth_uuids = reverse.basicauth %}
+ {{ basicauth_configuration(basicauth_uuids) }}
+ {% endif %}
+
+ {% for subdomain in helpers.toList('Pischem.caddy.reverseproxy.subdomain') %}
+ {% if subdomain.enabled|default("0") == "1" and subdomain.reverse == reverse['@uuid'] %}
+ @{{ subdomain['@uuid'] }} {
+ host {{ subdomain.FromDomain }}
+ }
+ handle @{{ subdomain['@uuid'] }} {
+
+ {% if not subdomain.accesslist %}
+ {% set subdomain_basicauth_uuids = subdomain.basicauth %}
+ {{ basicauth_configuration(subdomain_basicauth_uuids) }}
+ {% endif %}
+
+ {% if subdomain.accesslist %}
+ {% set accesslist = helpers.toList('Pischem.caddy.reverseproxy.accesslist') | selectattr('@uuid', 'equalto', subdomain.accesslist) | first %}
+ {{ access_list_configuration(accesslist, accesslist.accesslistInvert|default("0") == "1") }}
+ handle @{{ accesslist['@uuid'] }} {
+
+ {% set subdomain_basicauth_uuids = subdomain.basicauth %}
+ {{ basicauth_configuration(subdomain_basicauth_uuids) }}
+
+ {% set subdomain_handles = helpers.toList('Pischem.caddy.reverseproxy.handle') | selectattr('subdomain', 'equalto', subdomain['@uuid']) | list %}
+ {% for handle in subdomain_handles %}
+ {% if handle.enabled|default("0") == "1" and handle.HandlePath %}
+ {{ reverse_proxy_configuration(handle) }}
+ {% endif %}
+ {% endfor %}
+ {% for handle in subdomain_handles %}
+ {% if handle.enabled|default("0") == "1" and not handle.HandlePath %}
+ {{ reverse_proxy_configuration(handle) }}
+ {% endif %}
+ {% endfor %}
+ }
+ {% else %}
+ {% set subdomain_handles = helpers.toList('Pischem.caddy.reverseproxy.handle') | selectattr('subdomain', 'equalto', subdomain['@uuid']) | list %}
+ {% for handle in subdomain_handles %}
+ {% if handle.enabled|default("0") == "1" and handle.HandlePath %}
+ {{ reverse_proxy_configuration(handle) }}
+ {% endif %}
+ {% endfor %}
+ {% for handle in subdomain_handles %}
+ {% if handle.enabled|default("0") == "1" and not handle.HandlePath %}
+ {{ reverse_proxy_configuration(handle) }}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+
+ {% if subdomain.accesslist %}
+ {% if accesslist.HttpResponseCode or accesslist.HttpResponseMessage %}
+ respond {{ '"' + accesslist.HttpResponseMessage|default('') + '"' if accesslist.HttpResponseMessage else '' }} {{ accesslist.HttpResponseCode|default(403) }}
+ {% elif Pischem.caddy.general.abort|default("0") == "1" %}
+ abort
+ {% endif %}
+ {% else %}
+ {% if Pischem.caddy.general.abort|default("0") == "1" %}
+ abort
+ {% endif %}
+ {% endif %}
+ }
+ {% endif %}
{% endfor %}
- {% for handle in subdomain_handles %}
- {% if handle.enabled|default("0") == "1" and not handle.HandlePath %}
- {{ reverse_proxy_configuration(handle) }}
+
+ {% if reverse.accesslist %}
+ {% set accesslist = helpers.toList('Pischem.caddy.reverseproxy.accesslist') | selectattr('@uuid', 'equalto', reverse.accesslist) | first %}
+ {{ access_list_configuration(accesslist, accesslist.accesslistInvert|default("0") == "1") }}
+ handle @{{ accesslist['@uuid'] }} {
+
+ {% set basicauth_uuids = reverse.basicauth %}
+ {{ basicauth_configuration(basicauth_uuids) }}
+
+ {% set wildcard_handles = helpers.toList('Pischem.caddy.reverseproxy.handle') | selectattr('reverse', 'equalto', reverse['@uuid']) | selectattr('subdomain', 'undefined') | list %}
+ {% for handle in wildcard_handles %}
+ {% if handle.enabled|default("0") == "1" and handle.HandlePath %}
+ {{ reverse_proxy_configuration(handle) }}
+ {% endif %}
+ {% endfor %}
+ {% for handle in wildcard_handles %}
+ {% if handle.enabled|default("0") == "1" and not handle.HandlePath %}
+ {{ reverse_proxy_configuration(handle) }}
+ {% endif %}
+ {% endfor %}
+ }
+ {% else %}
+ {% set wildcard_handles = helpers.toList('Pischem.caddy.reverseproxy.handle') | selectattr('reverse', 'equalto', reverse['@uuid']) | selectattr('subdomain', 'undefined') | list %}
+ {% for handle in wildcard_handles %}
+ {% if handle.enabled|default("0") == "1" and handle.HandlePath %}
+ {{ reverse_proxy_configuration(handle) }}
+ {% endif %}
+ {% endfor %}
+ {% for handle in wildcard_handles %}
+ {% if handle.enabled|default("0") == "1" and not handle.HandlePath %}
+ {{ reverse_proxy_configuration(handle) }}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+
+ {% set accesslist = helpers.toList('Pischem.caddy.reverseproxy.accesslist') | selectattr('@uuid', 'equalto', reverse.accesslist) | first %}
+ {% if accesslist %}
+ {% if accesslist.HttpResponseCode or accesslist.HttpResponseMessage %}
+ respond {{ '"' + accesslist.HttpResponseMessage|default('') + '"' if accesslist.HttpResponseMessage else '' }} {{ accesslist.HttpResponseCode|default(403) }}
+ {% elif Pischem.caddy.general.abort|default("0") == "1" %}
+ abort
+ {% endif %}
+ {% else %}
+ {% if Pischem.caddy.general.abort|default("0") == "1" %}
+ abort
+ {% endif %}
{% endif %}
- {% endfor %}
}
- {% else %}
- {% set subdomain_handles = helpers.toList('Pischem.caddy.reverseproxy.handle') | selectattr('subdomain', 'equalto', subdomain['@uuid']) | list %}
- {% for handle in subdomain_handles %}
- {% if handle.enabled|default("0") == "1" and handle.HandlePath %}
- {{ reverse_proxy_configuration(handle) }}
- {% endif %}
- {% endfor %}
- {% for handle in subdomain_handles %}
- {% if handle.enabled|default("0") == "1" and not handle.HandlePath %}
- {{ reverse_proxy_configuration(handle) }}
- {% endif %}
- {% endfor %}
- {% endif %}
-
- {% if subdomain.accesslist %}
- {% if accesslist.HttpResponseCode or accesslist.HttpResponseMessage %}
- respond {{ '"' + accesslist.HttpResponseMessage|default('') + '"' if accesslist.HttpResponseMessage else '' }} {{ accesslist.HttpResponseCode|default(403) }}
- {% elif Pischem.caddy.general.abort|default("0") == "1" %}
- abort
- {% endif %}
- {% else %}
- {% if Pischem.caddy.general.abort|default("0") == "1" %}
- abort
- {% endif %}
- {% endif %}
- }
{% endif %}
- {% endfor %}
-
- {% if reverse.accesslist %}
- {% set accesslist = helpers.toList('Pischem.caddy.reverseproxy.accesslist') | selectattr('@uuid', 'equalto', reverse.accesslist) | first %}
- {{ access_list_configuration(accesslist, accesslist.accesslistInvert|default("0") == "1") }}
- handle @{{ accesslist['@uuid'] }} {
-
- {% set basicauth_uuids = reverse.basicauth %}
- {{ basicauth_configuration(basicauth_uuids) }}
-
- {% set wildcard_handles = helpers.toList('Pischem.caddy.reverseproxy.handle') | selectattr('reverse', 'equalto', reverse['@uuid']) | selectattr('subdomain', 'undefined') | list %}
- {% for handle in wildcard_handles %}
- {% if handle.enabled|default("0") == "1" and handle.HandlePath %}
- {{ reverse_proxy_configuration(handle) }}
- {% endif %}
- {% endfor %}
- {% for handle in wildcard_handles %}
- {% if handle.enabled|default("0") == "1" and not handle.HandlePath %}
- {{ reverse_proxy_configuration(handle) }}
- {% endif %}
- {% endfor %}
- }
- {% else %}
- {% set wildcard_handles = helpers.toList('Pischem.caddy.reverseproxy.handle') | selectattr('reverse', 'equalto', reverse['@uuid']) | selectattr('subdomain', 'undefined') | list %}
- {% for handle in wildcard_handles %}
- {% if handle.enabled|default("0") == "1" and handle.HandlePath %}
- {{ reverse_proxy_configuration(handle) }}
- {% endif %}
- {% endfor %}
- {% for handle in wildcard_handles %}
- {% if handle.enabled|default("0") == "1" and not handle.HandlePath %}
- {{ reverse_proxy_configuration(handle) }}
- {% endif %}
- {% endfor %}
- {% endif %}
-
- {% set accesslist = helpers.toList('Pischem.caddy.reverseproxy.accesslist') | selectattr('@uuid', 'equalto', reverse.accesslist) | first %}
- {% if accesslist %}
- {% if accesslist.HttpResponseCode or accesslist.HttpResponseMessage %}
- respond {{ '"' + accesslist.HttpResponseMessage|default('') + '"' if accesslist.HttpResponseMessage else '' }} {{ accesslist.HttpResponseCode|default(403) }}
- {% elif Pischem.caddy.general.abort|default("0") == "1" %}
- abort
- {% endif %}
- {% else %}
- {% if Pischem.caddy.general.abort|default("0") == "1" %}
- abort
- {% endif %}
- {% endif %}
-}
-{% endif %}
{% endfor %}
import /usr/local/etc/caddy/caddy.d/*.conf
diff --git a/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/rc.conf.d/caddy b/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/rc.conf.d/caddy
index 503f7da6f..d8ab2eda2 100644
--- a/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/rc.conf.d/caddy
+++ b/www/caddy/src/opnsense/service/templates/OPNsense/Caddy/rc.conf.d/caddy
@@ -1,13 +1,8 @@
# DO NOT EDIT THIS FILE -- OPNsense auto-generated file
-{% if helpers.exists('Pischem.caddy.general.enabled') %}
- {%- set general_enabled = helpers.toList('Pischem.caddy.general.enabled') | first %}
- {%- if general_enabled == '1' %}
+{% set generalSettings = helpers.getNodeByTag('Pischem.caddy.general') %}
+{% if generalSettings.enabled|default("0") == "1" %}
caddy_enable="YES"
-# Path to the Caddy setup script
caddy_setup="/usr/local/opnsense/scripts/OPNsense/Caddy/setup.sh"
- {%- else %}
-caddy_enable="NO"
- {%- endif %}
-{%- else %}
+{% else %}
caddy_enable="NO"
{% endif %}