Add custom SSL certificate data and priority configuration to setup

This commit is contained in:
Théophile Diot 2024-12-31 14:31:02 +00:00
parent 3514d5c3f8
commit 2451ed4048
No known key found for this signature in database
GPG key ID: FA995104A0BA376A
4 changed files with 613 additions and 419 deletions

View file

@ -40,8 +40,11 @@ def setup_page():
"USE_LETS_ENCRYPT_WILDCARD",
"LETS_ENCRYPT_DNS_CREDENTIAL_ITEM",
"USE_CUSTOM_SSL",
"CUSTOM_SSL_CERT_PRIORITY",
"CUSTOM_SSL_CERT",
"CUSTOM_SSL_KEY",
"CUSTOM_SSL_CERT_DATA",
"CUSTOM_SSL_KEY_DATA",
),
)
@ -77,8 +80,11 @@ def setup_page():
"lets_encrypt_dns_propagation",
"lets_encrypt_dns_credential_items",
"use_custom_ssl",
"custom_ssl_cert_priority",
"custom_ssl_cert",
"custom_ssl_key",
"custom_ssl_cert_data",
"custom_ssl_key_data",
]
)
if not admin_user:
@ -171,14 +177,22 @@ def setup_page():
bool(request.form.get("custom_ssl_cert", "")),
bool(request.form.get("custom_ssl_key", "")),
]
) or not all(
[
bool(request.form.get("custom_ssl_cert_data", "")),
bool(request.form.get("custom_ssl_key_data", "")),
]
):
return handle_error("When using a custom SSL certificate, you must set both the certificate and the key.", "setup")
config.update(
{
"USE_CUSTOM_SSL": "yes",
"CUSTOM_SSL_CERT_PRIORITY": request.form.get("custom_ssl_cert_priority", "file"),
"CUSTOM_SSL_CERT": request.form.get("custom_ssl_cert", ""),
"CUSTOM_SSL_KEY": request.form.get("custom_ssl_key", ""),
"CUSTOM_SSL_CERT_DATA": request.form.get("custom_ssl_cert_data", ""),
"CUSTOM_SSL_KEY_DATA": request.form.get("custom_ssl_key_data", ""),
}
)
else:
@ -233,8 +247,11 @@ def setup_page():
lets_encrypt_dns_propagation=db_config.get("LETS_ENCRYPT_DNS_PROPAGATION", getenv("LETS_ENCRYPT_DNS_PROPAGATION", "default")),
lets_encrypt_dns_credential_items=lets_encrypt_dns_credential_items,
use_custom_ssl=db_config.get("USE_CUSTOM_SSL", getenv("USE_CUSTOM_SSL", "no")),
custom_ssl_cert_priority=db_config.get("CUSTOM_SSL_CERT_PRIORITY", getenv("CUSTOM_SSL_CERT_PRIORITY", "file")),
custom_ssl_cert=db_config.get("CUSTOM_SSL_CERT", getenv("CUSTOM_SSL_CERT", "")),
custom_ssl_key=db_config.get("CUSTOM_SSL_KEY", getenv("CUSTOM_SSL_KEY", "")),
custom_ssl_cert_data=db_config.get("CUSTOM_SSL_CERT_DATA", getenv("CUSTOM_SSL_CERT_DATA", "")),
custom_ssl_key_data=db_config.get("CUSTOM_SSL_KEY_DATA", getenv("CUSTOM_SSL_KEY_DATA", "")),
# totp_qr_image=totp_qr_image,
# totp_secret=TOTP.get_totp_pretty_key(session.get("tmp_totp_secret", "")),
)

View file

@ -611,8 +611,14 @@ $(document).ready(() => {
"use_custom_ssl",
$("#USE_CUSTOM_SSL").prop("checked") ? "yes" : "no",
);
formData.append(
"custom_ssl_cert_priority",
$("#CUSTOM_SSL_CERT_PRIORITY").find(":selected").val(),
);
formData.append("custom_ssl_cert", $("#CUSTOM_SSL_CERT").val());
formData.append("custom_ssl_key", $("#CUSTOM_SSL_KEY").val());
formData.append("custom_ssl_cert_data", $("#CUSTOM_SSL_CERT_DATA").val());
formData.append("custom_ssl_key_data", $("#CUSTOM_SSL_KEY_DATA").val());
}
// Remove beforeunload event to prevent prompt on form submission
@ -793,6 +799,21 @@ $(document).ready(() => {
}
});
$("#USE_CUSTOM_SSL").on("change", function () {
const isChecked = $(this).prop("checked");
const $certPriority = $("#CUSTOM_SSL_CERT_PRIORITY");
const $cert = $("#CUSTOM_SSL_CERT");
const $key = $("#CUSTOM_SSL_KEY");
const $certData = $("#CUSTOM_SSL_CERT_DATA");
const $keyData = $("#CUSTOM_SSL_KEY_DATA");
$certPriority.prop("disabled", !isChecked);
$cert.prop("disabled", !isChecked);
$key.prop("disabled", !isChecked);
$certData.prop("disabled", !isChecked);
$keyData.prop("disabled", !isChecked);
});
// Before Unload Event to Warn Users About Unsaved Changes
$window.on("beforeunload", function (e) {
const message =

View file

@ -239,7 +239,12 @@
{% endif %}>
<label for="{{ step_config_id }}" class="form-label fw-semibold fs-6">{{ step_config }}</label>
<textarea id="{{ step_config_id }}-default" class="visually-hidden">{{ template_data["configs"].get(step_config, "") }}</textarea>
<div id="{{ step_config_id }}" aria-labelledby="label-{{ step_config_id }}" data-language="{% if step_config.startswith(('crs', 'modsec')) %}ModSecurity{% else %}NGINX{% endif %}" data-name="CUSTOM_CONF_{{ step_config.split("/")[0] |upper }}_{{ step_config.split("/")[1] .replace(".conf", "") }}" data-method="{% if is_readonly %}readonly{% else %}{{ step_config_method }}{% endif %}" class="ace-editor border rounded position-absolute top-0 start-0 end-0 bottom-0 mt-6">
<div id="{{ step_config_id }}"
aria-labelledby="label-{{ step_config_id }}"
data-language="{% if step_config.startswith(('crs', 'modsec')) %}ModSecurity{% else %}NGINX{% endif %}"
data-name="CUSTOM_CONF_{{ step_config.split("/")[0] |upper }}_{{ step_config.split("/")[1] .replace(".conf", "") }}"
data-method="{% if is_readonly %}readonly{% else %}{{ step_config_method }}{% endif %}"
class="ace-editor border rounded position-absolute top-0 start-0 end-0 bottom-0 mt-6">
{{ step_config_value }}
</div>
</div>

View file

@ -390,428 +390,579 @@
aria-labelledby="label-REVERSE_PROXY_URL"
pattern="^.*$" />
</div>
<h6 class="mt-2 mb-2 fw-bold">Let's Encrypt</h6>
<div class="col-4 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-AUTO_LETS_ENCRYPT"
for="AUTO_LETS_ENCRYPT"
class="form-label fw-semibold text-truncate">
Auto Let's Encrypt
</label>
{% if auto_lets_encrypt == "yes" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<div class="d-flex align-items-center">
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Whether to automatically request a Let's Encrypt certificate">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
<div class="container">
<!-- Nav Tabs -->
<ul class="nav nav-tabs nav-fill">
<li class="nav-item">
<button class="nav-link active"
id="lets-encrypt-tab"
data-bs-toggle="tab"
data-bs-target="#lets-encrypt"
type="button"
role="tab"
aria-controls="lets-encrypt"
aria-selected="true">Let's Encrypt</button>
</li>
<li class="nav-item">
<button class="nav-link"
id="custom-certificate-tab"
data-bs-toggle="tab"
data-bs-target="#custom-certificate"
type="button"
role="tab"
aria-controls="custom-certificate"
aria-selected="false">Custom Certificate</button>
</li>
</ul>
<!-- Tab Content -->
<div class="tab-content">
<!-- Let's Encrypt Tab -->
<div class="tab-pane fade show active"
id="lets-encrypt"
role="tabpanel"
aria-labelledby="lets-encrypt-tab">
<div class="row pb-0">
<h6 class="mt-2 mb-2 fw-bold">Let's Encrypt</h6>
<div class="col-4 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-AUTO_LETS_ENCRYPT"
for="AUTO_LETS_ENCRYPT"
class="form-label fw-semibold text-truncate">
Auto Let's Encrypt
</label>
{% if auto_lets_encrypt == "yes" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<div class="d-flex align-items-center">
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Whether to automatically request a Let's Encrypt certificate">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<div class="form-check form-switch mt-1">
<input id="AUTO_LETS_ENCRYPT"
name="AUTO_LETS_ENCRYPT"
class="form-check-input"
type="checkbox"
role="switch"
aria-labelledby="label-AUTO_LETS_ENCRYPT"
{% if auto_lets_encrypt == "yes" %}checked{% endif %} />
</div>
</div>
<div class="col-4 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-USE_LETS_ENCRYPT_STAGING"
for="USE_LETS_ENCRYPT_STAGING"
class="form-label fw-semibold text-truncate">
Use Let's Encrypt Staging
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_staging == "yes" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Whether to use the Let's Encrypt staging environment">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<div class="form-check form-switch mt-1">
<input id="USE_LETS_ENCRYPT_STAGING"
name="USE_LETS_ENCRYPT_STAGING"
class="form-check-input"
type="checkbox"
role="switch"
aria-labelledby="label-USE_LETS_ENCRYPT_STAGING"
{% if lets_encrypt_staging == "yes" %}checked{% endif %} />
</div>
</div>
<div class="col-4 pb-3"
{% if lets_encrypt_challenge == 'http' %} data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Wildcard certificates are only supported with DNS challenges."{% endif %}>
<div class="d-flex justify-content-between align-items-center">
<label id="label-USE_LETS_ENCRYPT_WILDCARD"
for="USE_LETS_ENCRYPT_WILDCARD"
class="form-label fw-semibold text-truncate">
Wildcard Certificates
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_wildcard == "yes" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Create wildcard certificates for all domains. This allows a single certificate to secure multiple subdomains.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<div class="form-check form-switch mt-1">
<input id="USE_LETS_ENCRYPT_WILDCARD"
name="USE_LETS_ENCRYPT_WILDCARD"
class="form-check-input"
type="checkbox"
role="switch"
aria-labelledby="label-USE_LETS_ENCRYPT_WILDCARD"
{% if lets_encrypt_wildcard == "yes" %}checked{% endif %}
{% if lets_encrypt_challenge == 'http' %}disabled{% endif %} />
</div>
</div>
<div class="col-md-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-EMAIL_LETS_ENCRYPT"
for="EMAIL_LETS_ENCRYPT"
class="form-label fw-semibold text-truncate">
Email for Let's Encrypt
</label>
<div class="d-flex align-items-center">
{% if email_lets_encrypt %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The email address that will be used for Let's Encrypt">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="EMAIL_LETS_ENCRYPT"
name="EMAIL_LETS_ENCRYPT"
type="text"
placeholder="John.doe@example.com"
class="form-control plugin-setting mt-1"
aria-labelledby="label-EMAIL_LETS_ENCRYPT"
pattern="^.*$" />
</div>
<div class="col-md-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-LETS_ENCRYPT_CHALLENGE"
for="LETS_ENCRYPT_CHALLENGE"
class="form-label fw-semibold text-truncate">
Challenge Type
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_challenge == "dns" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The challenge type to use for Let's Encrypt (http or dns).">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<select id="LETS_ENCRYPT_CHALLENGE"
name="LETS_ENCRYPT_CHALLENGE"
class="form-select mt-1"
aria-labelledby="label-LETS_ENCRYPT_CHALLENGE">
<option value="dns"
{% if lets_encrypt_challenge == "dns" %}selected{% endif %}>
dns
</option>
<option value="http"
{% if lets_encrypt_challenge == "http" %}selected{% endif %}>
http
</option>
</select>
</div>
<div class="col-md-6 pb-3"
{% if lets_encrypt_challenge == 'http' %} data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="DNS provider is only supported with DNS challenges."{% endif %}>
<div class="d-flex justify-content-between align-items-center">
<label id="label-LETS_ENCRYPT_DNS_PROVIDER"
for="LETS_ENCRYPT_DNS_PROVIDER"
class="form-label fw-semibold text-truncate">
DNS Provider
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_dns_provider %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The DNS provider to use for DNS challenges.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<select id="LETS_ENCRYPT_DNS_PROVIDER"
name="LETS_ENCRYPT_DNS_PROVIDER"
class="form-select mt-1"
aria-labelledby="label-LETS_ENCRYPT_DNS_PROVIDER"
{% if lets_encrypt_challenge == 'http' %}disabled{% endif %}>
<option value="" {% if not lets_encrypt_dns_provider %}selected{% endif %}></option>
<option value="cloudflare"
{% if lets_encrypt_dns_provider == "cloudflare" %}selected{% endif %}>
cloudflare
</option>
<option value="digitalocean"
{% if lets_encrypt_dns_provider == "digitalocean" %}selected{% endif %}>
digitalocean
</option>
<option value="dnsimple"
{% if lets_encrypt_dns_provider == "dnsimple" %}selected{% endif %}>
dnsimple
</option>
<option value="dnsmadeeasy"
{% if lets_encrypt_dns_provider == "dnsmadeeasy" %}selected{% endif %}>
dnsmadeeasy
</option>
<option value="gehirn"
{% if lets_encrypt_dns_provider == "gehirn" %}selected{% endif %}>
gehirn
</option>
<option value="google"
{% if lets_encrypt_dns_provider == "google" %}selected{% endif %}>
google
</option>
<option value="linode"
{% if lets_encrypt_dns_provider == "linode" %}selected{% endif %}>
linode
</option>
<option value="luadns"
{% if lets_encrypt_dns_provider == "luadns" %}selected{% endif %}>
luadns
</option>
<option value="nsone"
{% if lets_encrypt_dns_provider == "nsone" %}selected{% endif %}>
nsone
</option>
<option value="ovh"
{% if lets_encrypt_dns_provider == "ovh" %}selected{% endif %}>
ovh
</option>
<option value="rfc2136"
{% if lets_encrypt_dns_provider == "rfc2136" %}selected{% endif %}>
rfc2136
</option>
<option value="route53"
{% if lets_encrypt_dns_provider == "route53" %}selected{% endif %}>
route53
</option>
<option value="sakuracloud"
{% if lets_encrypt_dns_provider == "sakuracloud" %}selected{% endif %}>
sakuracloud
</option>
<option value="scaleway"
{% if lets_encrypt_dns_provider == "scaleway" %}selected{% endif %}>
scaleway
</option>
</select>
</div>
<div class="col-md-6 pb-3"
{% if lets_encrypt_challenge == 'http' %} data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="DNS propagation is only supported with DNS challenges."{% endif %}>
<div class="d-flex justify-content-between align-items-center">
<label id="label-LETS_ENCRYPT_DNS_PROPAGATION"
for="LETS_ENCRYPT_DNS_PROPAGATION"
class="form-label fw-semibold text-truncate">
DNS Propagation
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_dns_propagation != "default" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The time to wait for DNS propagation in seconds for DNS challenges.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="LETS_ENCRYPT_DNS_PROPAGATION"
name="LETS_ENCRYPT_DNS_PROPAGATION"
type="text"
value="{{ lets_encrypt_dns_propagation }}"
class="form-control plugin-setting mt-1"
aria-labelledby="label-LETS_ENCRYPT_DNS_PROPAGATION"
pattern="^(default|\d+)$"
{% if lets_encrypt_challenge == 'http' %}disabled{% endif %} />
</div>
<div class="col-12 pb-3"
{% if lets_encrypt_challenge == 'http' %} data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Credentials are only supported with DNS challenges."{% endif %}>
<div class="d-flex justify-content-between align-items-center">
<label id="label-LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
for="LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
class="form-label fw-semibold text-truncate">
Lets encrypt dns credential items
</label>
<div class="d-flex align-items-center">
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Configuration item that will be added to the credentials.ini file for the DNS provider (e.g. 'cloudflare_api_token 123456') for DNS challenges.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<textarea id="LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
name="LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
class="form-control plugin-setting mt-1"
aria-labelledby="label-LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
pattern="^.*$"
{% if lets_encrypt_challenge == 'http' %}disabled{% endif %}>{% for item in lets_encrypt_dns_credential_items %}{{ item }}{% if not loop.last %}\n{% endif %}{% endfor %}</textarea>
</div>
</div>
</div>
<div class="form-check form-switch mt-1">
<input id="AUTO_LETS_ENCRYPT"
name="AUTO_LETS_ENCRYPT"
class="form-check-input"
type="checkbox"
role="switch"
aria-labelledby="label-AUTO_LETS_ENCRYPT"
{% if auto_lets_encrypt == "yes" %}checked{% endif %} />
</div>
</div>
<div class="col-4 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-USE_LETS_ENCRYPT_STAGING"
for="USE_LETS_ENCRYPT_STAGING"
class="form-label fw-semibold text-truncate">
Use Let's Encrypt Staging
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_staging == "yes" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Whether to use the Let's Encrypt staging environment">
<span class="bx bx-question-mark bx-xs"></span>
</span>
<!-- Custom Certificate Tab -->
<div class="tab-pane fade"
id="custom-certificate"
role="tabpanel"
aria-labelledby="custom-certificate-tab">
<div class="row pb-0">
<h6 class="mt-2 mb-2 fw-bold">Custom certificate</h6>
<div class="col-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-USE_CUSTOM_SSL"
for="USE_CUSTOM_SSL"
class="form-label fw-semibold text-truncate">
Use Custom SSL
</label>
{% if use_custom_ssl == "yes" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<div class="d-flex align-items-center">
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Whether to use a custom SSL certificate">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<div class="form-check form-switch mt-1">
<input id="USE_CUSTOM_SSL"
name="USE_CUSTOM_SSL"
class="form-check-input"
type="checkbox"
role="switch"
aria-labelledby="label-USE_CUSTOM_SSL"
{% if use_custom_ssl == "yes" %}checked{% endif %} />
</div>
</div>
<div class="col-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-CUSTOM_SSL_CERT_PRIORITY"
for="CUSTOM_SSL_CERT_PRIORITY"
class="form-label fw-semibold text-truncate">
Certificate priority
</label>
{% if custom_ssl_cert_priority == "data" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<div class="d-flex align-items-center">
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Choose whether to prioritize the certificate from file path or from base64 data.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<select id="CUSTOM_SSL_CERT_PRIORITY"
name="CUSTOM_SSL_CERT_PRIORITY"
class="form-select mt-1"
aria-labelledby="label-CUSTOM_SSL_CERT_PRIORITY"
{% if use_custom_ssl == "no" %}disabled{% endif %}>
<option value="file"
{% if custom_ssl_cert_priority == "file" %}selected{% endif %}>
file
</option>
<option value="data"
{% if custom_ssl_cert_priority == "data" %}selected{% endif %}>
data
</option>
</select>
</div>
<div class="col-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-CUSTOM_SSL_CERT"
for="CUSTOM_SSL_CERT"
class="form-label fw-semibold text-truncate">
Custom SSL Certificate
</label>
<div class="d-flex align-items-center">
{% if custom_ssl_cert %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The custom SSL certificate path">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="CUSTOM_SSL_CERT"
name="CUSTOM_SSL_CERT"
type="text"
placeholder="/tmp/cert.pem"
value="{{ custom_ssl_cert }}"
class="form-control plugin-setting mt-1"
aria-labelledby="label-CUSTOM_SSL_CERT"
pattern="^.*$"
{% if use_custom_ssl == "no" %}disabled{% endif %} />
</div>
<div class="col-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-CUSTOM_SSL_KEY"
for="CUSTOM_SSL_KEY"
class="form-label fw-semibold text-truncate">
Custom SSL Key
</label>
<div class="d-flex align-items-center">
{% if custom_ssl_key %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The custom SSL key path">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="CUSTOM_SSL_KEY"
name="CUSTOM_SSL_KEY"
type="text"
placeholder="/tmp/key.pem"
value="{{ custom_ssl_key }}"
class="form-control plugin-setting mt-1"
aria-labelledby="label-CUSTOM_SSL_KEY"
pattern="^.*$"
{% if use_custom_ssl == "no" %}disabled{% endif %} />
</div>
<div class="col-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-CUSTOM_SSL_CERT_DATA"
for="CUSTOM_SSL_CERT_DATA"
class="form-label fw-semibold text-truncate">
Custom SSL Certificate data (base64)
</label>
<div class="d-flex align-items-center">
{% if custom_ssl_cert_data %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The custom SSL certificate data (base64)">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="CUSTOM_SSL_CERT_DATA"
name="CUSTOM_SSL_CERT_DATA"
type="text"
value="{{ custom_ssl_cert_data }}"
class="form-control plugin-setting mt-1"
aria-labelledby="label-CUSTOM_SSL_CERT_DATA"
pattern="^.*$"
{% if use_custom_ssl == "no" %}disabled{% endif %} />
</div>
<div class="col-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-CUSTOM_SSL_KEY_DATA"
for="CUSTOM_SSL_KEY_DATA"
class="form-label fw-semibold text-truncate">
Custom SSL Key data (base64)
</label>
<div class="d-flex align-items-center">
{% if custom_ssl_key_data %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The custom SSL key data (base64)">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="CUSTOM_SSL_KEY_DATA"
name="CUSTOM_SSL_KEY_DATA"
type="text"
value="{{ custom_ssl_key_data }}"
class="form-control plugin-setting mt-1"
aria-labelledby="label-CUSTOM_SSL_KEY_DATA"
pattern="^.*$"
{% if use_custom_ssl == "no" %}disabled{% endif %} />
</div>
</div>
</div>
<div class="form-check form-switch mt-1">
<input id="USE_LETS_ENCRYPT_STAGING"
name="USE_LETS_ENCRYPT_STAGING"
class="form-check-input"
type="checkbox"
role="switch"
aria-labelledby="label-USE_LETS_ENCRYPT_STAGING"
{% if lets_encrypt_staging == "yes" %}checked{% endif %} />
</div>
</div>
<div class="col-4 pb-3"
{% if lets_encrypt_challenge == 'http' %} data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Wildcard certificates are only supported with DNS challenges."{% endif %}>
<div class="d-flex justify-content-between align-items-center">
<label id="label-USE_LETS_ENCRYPT_WILDCARD"
for="USE_LETS_ENCRYPT_WILDCARD"
class="form-label fw-semibold text-truncate">
Wildcard Certificates
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_wildcard == "yes" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Create wildcard certificates for all domains. This allows a single certificate to secure multiple subdomains.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<div class="form-check form-switch mt-1">
<input id="USE_LETS_ENCRYPT_WILDCARD"
name="USE_LETS_ENCRYPT_WILDCARD"
class="form-check-input"
type="checkbox"
role="switch"
aria-labelledby="label-USE_LETS_ENCRYPT_WILDCARD"
{% if lets_encrypt_wildcard == "yes" %}checked{% endif %}
{% if lets_encrypt_challenge == 'http' %}disabled{% endif %} />
</div>
</div>
<div class="col-md-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-EMAIL_LETS_ENCRYPT"
for="EMAIL_LETS_ENCRYPT"
class="form-label fw-semibold text-truncate">
Email for Let's Encrypt
</label>
<div class="d-flex align-items-center">
{% if email_lets_encrypt %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The email address that will be used for Let's Encrypt">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="EMAIL_LETS_ENCRYPT"
name="EMAIL_LETS_ENCRYPT"
type="text"
placeholder="John.doe@example.com"
class="form-control plugin-setting mt-1"
aria-labelledby="label-EMAIL_LETS_ENCRYPT"
pattern="^.*$" />
</div>
<div class="col-md-6 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-LETS_ENCRYPT_CHALLENGE"
for="LETS_ENCRYPT_CHALLENGE"
class="form-label fw-semibold text-truncate">
Challenge Type
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_challenge == "dns" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The challenge type to use for Let's Encrypt (http or dns).">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<select id="LETS_ENCRYPT_CHALLENGE"
name="LETS_ENCRYPT_CHALLENGE"
class="form-select mt-1"
aria-labelledby="label-LETS_ENCRYPT_CHALLENGE">
<option value="dns"
{% if lets_encrypt_challenge == "dns" %}selected{% endif %}>
dns
</option>
<option value="http"
{% if lets_encrypt_challenge == "http" %}selected{% endif %}>
http
</option>
</select>
</div>
<div class="col-md-6 pb-3"
{% if lets_encrypt_challenge == 'http' %} data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="DNS provider is only supported with DNS challenges."{% endif %}>
<div class="d-flex justify-content-between align-items-center">
<label id="label-LETS_ENCRYPT_DNS_PROVIDER"
for="LETS_ENCRYPT_DNS_PROVIDER"
class="form-label fw-semibold text-truncate">
DNS Provider
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_dns_provider %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The DNS provider to use for DNS challenges.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<select id="LETS_ENCRYPT_DNS_PROVIDER"
name="LETS_ENCRYPT_DNS_PROVIDER"
class="form-select mt-1"
aria-labelledby="label-LETS_ENCRYPT_DNS_PROVIDER"
{% if lets_encrypt_challenge == 'http' %}disabled{% endif %}>
<option value="" {% if not lets_encrypt_dns_provider %}selected{% endif %}></option>
<option value="cloudflare"
{% if lets_encrypt_dns_provider == "cloudflare" %}selected{% endif %}>
cloudflare
</option>
<option value="digitalocean"
{% if lets_encrypt_dns_provider == "digitalocean" %}selected{% endif %}>
digitalocean
</option>
<option value="dnsimple"
{% if lets_encrypt_dns_provider == "dnsimple" %}selected{% endif %}>
dnsimple
</option>
<option value="dnsmadeeasy"
{% if lets_encrypt_dns_provider == "dnsmadeeasy" %}selected{% endif %}>
dnsmadeeasy
</option>
<option value="gehirn"
{% if lets_encrypt_dns_provider == "gehirn" %}selected{% endif %}>
gehirn
</option>
<option value="google"
{% if lets_encrypt_dns_provider == "google" %}selected{% endif %}>
google
</option>
<option value="linode"
{% if lets_encrypt_dns_provider == "linode" %}selected{% endif %}>
linode
</option>
<option value="luadns"
{% if lets_encrypt_dns_provider == "luadns" %}selected{% endif %}>
luadns
</option>
<option value="nsone"
{% if lets_encrypt_dns_provider == "nsone" %}selected{% endif %}>
nsone
</option>
<option value="ovh"
{% if lets_encrypt_dns_provider == "ovh" %}selected{% endif %}>
ovh
</option>
<option value="rfc2136"
{% if lets_encrypt_dns_provider == "rfc2136" %}selected{% endif %}>
rfc2136
</option>
<option value="route53"
{% if lets_encrypt_dns_provider == "route53" %}selected{% endif %}>
route53
</option>
<option value="sakuracloud"
{% if lets_encrypt_dns_provider == "sakuracloud" %}selected{% endif %}>
sakuracloud
</option>
<option value="scaleway"
{% if lets_encrypt_dns_provider == "scaleway" %}selected{% endif %}>
scaleway
</option>
</select>
</div>
<div class="col-md-6 pb-3"
{% if lets_encrypt_challenge == 'http' %} data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="DNS propagation is only supported with DNS challenges."{% endif %}>
<div class="d-flex justify-content-between align-items-center">
<label id="label-LETS_ENCRYPT_DNS_PROPAGATION"
for="LETS_ENCRYPT_DNS_PROPAGATION"
class="form-label fw-semibold text-truncate">
DNS Propagation
</label>
<div class="d-flex align-items-center">
{% if lets_encrypt_dns_propagation != "default" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The time to wait for DNS propagation in seconds for DNS challenges.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="LETS_ENCRYPT_DNS_PROPAGATION"
name="LETS_ENCRYPT_DNS_PROPAGATION"
type="text"
value="{{ lets_encrypt_dns_propagation }}"
class="form-control plugin-setting mt-1"
aria-labelledby="label-LETS_ENCRYPT_DNS_PROPAGATION"
pattern="^(default|\d+)$"
{% if lets_encrypt_challenge == 'http' %}disabled{% endif %} />
</div>
<div class="col-12 pb-3"
{% if lets_encrypt_challenge == 'http' %} data-bs-toggle="tooltip" data-bs-placement="top" data-bs-original-title="Credentials are only supported with DNS challenges."{% endif %}>
<div class="d-flex justify-content-between align-items-center">
<label id="label-LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
for="LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
class="form-label fw-semibold text-truncate">
Lets encrypt dns credential items
</label>
<div class="d-flex align-items-center">
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Configuration item that will be added to the credentials.ini file for the DNS provider (e.g. 'cloudflare_api_token 123456') for DNS challenges.">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<textarea id="LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
name="LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
class="form-control plugin-setting mt-1"
aria-labelledby="label-LETS_ENCRYPT_DNS_CREDENTIAL_ITEMS"
pattern="^.*$"
{% if lets_encrypt_challenge == 'http' %}disabled{% endif %}>{% for item in lets_encrypt_dns_credential_items %}{{ item }}{% if not loop.last %}\n{% endif %}{% endfor %}</textarea>
</div>
<h6 class="mt-2 mb-2 fw-bold">Custom certificate</h6>
<div class="col-12 col-md-2 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-USE_CUSTOM_SSL"
for="USE_CUSTOM_SSL"
class="form-label fw-semibold text-truncate">
Use Custom SSL
</label>
{% if use_custom_ssl == "yes" %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<div class="d-flex align-items-center">
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="Whether to use a custom SSL certificate">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<div class="form-check form-switch mt-1">
<input id="USE_CUSTOM_SSL"
name="USE_CUSTOM_SSL"
class="form-check-input"
type="checkbox"
role="switch"
aria-labelledby="label-USE_CUSTOM_SSL"
{% if use_custom_ssl == "yes" %}checked{% endif %} />
</div>
</div>
<div class="col-6 col-md-5 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-CUSTOM_SSL_CERT"
for="CUSTOM_SSL_CERT"
class="form-label fw-semibold text-truncate">
Custom SSL Certificate
</label>
<div class="d-flex align-items-center">
{% if custom_ssl_cert %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The custom SSL certificate path">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="CUSTOM_SSL_CERT"
name="CUSTOM_SSL_CERT"
type="text"
placeholder="/tmp/cert.pem"
value="{{ custom_ssl_cert }}"
class="form-control plugin-setting mt-1"
aria-labelledby="label-CUSTOM_SSL_CERT"
pattern="^.*$" />
</div>
<div class="col-6 col-md-5 pb-3">
<div class="d-flex justify-content-between align-items-center">
<label id="label-CUSTOM_SSL_KEY"
for="CUSTOM_SSL_KEY"
class="form-label fw-semibold text-truncate">
Custom SSL Key
</label>
<div class="d-flex align-items-center">
{% if custom_ssl_key %}
<span class="badge badge-center rounded-pill bg-primary-subtle text-dark d-flex align-items-center justify-content-center p-1 me-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="From global configuration">
<span class="bx bx-globe bx-xs"></span>
</span>
{% endif %}
<span class="badge rounded-pill bg-secondary-subtle text-dark d-flex align-items-center justify-content-center p-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-original-title="The custom SSL key path">
<span class="bx bx-question-mark bx-xs"></span>
</span>
</div>
</div>
<input id="CUSTOM_SSL_KEY"
name="CUSTOM_SSL_KEY"
type="text"
placeholder="/tmp/key.pem"
value="{{ custom_ssl_key }}"
class="form-control plugin-setting mt-1"
aria-labelledby="label-CUSTOM_SSL_KEY"
pattern="^.*$" />
</div>
</div>
{% else %}