mirror of
https://github.com/swissmakers/fail2ban-ui.git
synced 2026-04-11 13:47:05 +02:00
Add documentation for callback-URL, move css for fail2ban-ui into seperate file. Fix some settings-options
This commit is contained in:
31
README.md
31
README.md
@@ -386,6 +386,37 @@ go build -o fail2ban-ui ./cmd/server/main.go
|
||||
|
||||
### Configuration
|
||||
|
||||
#### Fail2Ban Callback URL
|
||||
|
||||
The **Fail2Ban Callback URL** is a critical setting that determines how Fail2Ban instances send ban alerts back to Fail2Ban UI. This URL is embedded in a custom Fail2Ban action file that gets deployed to all managed Fail2Ban instances (local, SSH, and API agent connections).
|
||||
|
||||
**How it works:**
|
||||
- When a Fail2Ban instance bans an IP, it executes the custom action which sends a POST request to the callback URL (`/api/ban` endpoint)
|
||||
- Fail2Ban UI receives these notifications and stores them in the database for monitoring and analysis
|
||||
- The callback URL is automatically synchronized with the server port when using the default localhost pattern
|
||||
|
||||
**Configuration Guidelines:**
|
||||
|
||||
1. **Local Deployments:**
|
||||
- Use the same port as Fail2Ban UI: `http://127.0.0.1:8080` (or your configured port)
|
||||
- The callback URL automatically updates when you change the server port
|
||||
- Example: If Fail2Ban UI runs on port `3080`, use `http://127.0.0.1:3080`
|
||||
|
||||
2. **Reverse Proxy Setups:**
|
||||
- Use your TLS-encrypted endpoint: `https://fail2ban.example.com`
|
||||
- Ensure the reverse proxy forwards requests to the correct Fail2Ban UI port
|
||||
- The callback URL must be accessible from all Fail2Ban instances (local and remote)
|
||||
|
||||
3. **Port Changes:**
|
||||
- When you change the Fail2Ban UI port (via `PORT` environment variable or UI settings), the callback URL automatically updates if it's using the default localhost pattern
|
||||
- For custom callback URLs (e.g., reverse proxy or custom IP), you must manually update them to match your setup
|
||||
|
||||
**Important Notes:**
|
||||
- The callback URL must be accessible from all Fail2Ban instances that need to send alerts
|
||||
- For remote Fail2Ban instances, ensure network connectivity to the callback URL
|
||||
- If using a reverse proxy, configure it to forward `/api/ban` requests to Fail2Ban UI
|
||||
- The callback URL is stored in `/etc/fail2ban/action.d/ui-custom-action.conf` on each managed Fail2Ban instance
|
||||
|
||||
#### Adding a Local Server
|
||||
|
||||
The local connector allows managing Fail2Ban on the same host where Fail2Ban UI runs.
|
||||
|
||||
@@ -242,12 +242,18 @@ After starting the container, access the web interface and configure your first
|
||||
- **Remote Server**: Add via SSH or API agent connection
|
||||
|
||||
3. **Configure Settings**
|
||||
- **Fail2Ban Callback URL**: This URL is used by all Fail2Ban instances to send ban alerts back to Fail2Ban UI
|
||||
- For local deployments: Use the same port as Fail2Ban UI (e.g., `http://127.0.0.1:8080` or your configured port)
|
||||
- For reverse proxy setups: Use your TLS-encrypted endpoint (e.g., `https://fail2ban.example.com`)
|
||||
- The callback URL automatically updates when you change the server port (if using the default localhost pattern)
|
||||
- Set up email alerts (optional)
|
||||
- Configure language preferences
|
||||
- Adjust security settings
|
||||
|
||||
> **Note:** The local Fail2Ban service is optional. Fail2Ban UI can manage remote Fail2Ban servers via SSH or API agents without requiring a local Fail2Ban installation in the container.
|
||||
|
||||
> **Important:** The Fail2Ban Callback URL must be accessible from all Fail2Ban instances (local and remote) that need to send alerts. If you change the Fail2Ban UI port, ensure the callback URL is updated accordingly.
|
||||
|
||||
---
|
||||
|
||||
## Docker Compose
|
||||
|
||||
@@ -495,8 +495,15 @@ func setDefaultsLocked() {
|
||||
} else if currentSettings.Port == 0 {
|
||||
currentSettings.Port = 8080
|
||||
}
|
||||
// Auto-update callback URL if it's empty or still using the old default localhost pattern
|
||||
if currentSettings.CallbackURL == "" {
|
||||
currentSettings.CallbackURL = fmt.Sprintf("http://127.0.0.1:%d", currentSettings.Port)
|
||||
} else {
|
||||
// If callback URL matches the old default pattern, update it to match the current port
|
||||
oldPattern := regexp.MustCompile(`^http://127\.0\.0\.1:\d+$`)
|
||||
if oldPattern.MatchString(currentSettings.CallbackURL) {
|
||||
currentSettings.CallbackURL = fmt.Sprintf("http://127.0.0.1:%d", currentSettings.Port)
|
||||
}
|
||||
}
|
||||
if currentSettings.AlertCountries == nil {
|
||||
currentSettings.AlertCountries = []string{"ALL"}
|
||||
@@ -1190,6 +1197,18 @@ func UpdateSettings(new AppSettings) (AppSettings, error) {
|
||||
}
|
||||
|
||||
new.CallbackURL = strings.TrimSpace(new.CallbackURL)
|
||||
|
||||
// Auto-update callback URL if port changed and callback URL is still using default localhost pattern
|
||||
oldPort := currentSettings.Port
|
||||
if new.Port != oldPort && new.Port > 0 {
|
||||
// Check if callback URL matches the default localhost pattern
|
||||
oldPattern := regexp.MustCompile(`^http://127\.0\.0\.1:\d+$`)
|
||||
if oldPattern.MatchString(new.CallbackURL) || new.CallbackURL == "" {
|
||||
// Update to match new port
|
||||
new.CallbackURL = fmt.Sprintf("http://127.0.0.1:%d", new.Port)
|
||||
}
|
||||
}
|
||||
|
||||
if len(new.Servers) == 0 && len(currentSettings.Servers) > 0 {
|
||||
new.Servers = make([]Fail2banServer, len(currentSettings.Servers))
|
||||
for i, srv := range currentSettings.Servers {
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
"settings.alert": "Alarm-Einstellungen",
|
||||
"settings.callback_url": "Fail2ban Callback-URL",
|
||||
"settings.callback_url_placeholder": "http://127.0.0.1:8080",
|
||||
"settings.callback_url_hint": "Diese URL wird von allen Fail2Ban-Instanzen verwendet, um die Ban-Payloads an Fail2Ban UI zu senden. Für lokale Installationen verwenden Sie denselben Port wie Fail2Ban UI (z.B. http://127.0.0.1:8080). Für Reverse-Proxy-Setups verwenden Sie falls möglich den TLS-verschlüsselten Endpunkt (z.B. https://fail2ban.example.com).",
|
||||
"settings.destination_email": "Ziel-E-Mail (Alarmempfänger)",
|
||||
"settings.destination_email_placeholder": "alerts@swissmakers.ch",
|
||||
"settings.alert_countries": "Alarm-Länder",
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
"settings.alert": "Alarm-Istellige",
|
||||
"settings.callback_url": "Fail2ban Callback-URL",
|
||||
"settings.callback_url_placeholder": "http://127.0.0.1:8080",
|
||||
"settings.callback_url_hint": "Diä URL wird vo aune Fail2Ban-Instanze brucht, zum Ban-Payloads a Fail2Ban UI z sende. Für lokali Installatione bruchts de gliich Port wie z Fail2Ban UI (z.B. http://127.0.0.1:8080). Für Reverse-Proxy-Setups sött dr TLS-verschlüssleti Endpunkt wenn müglech brücht wärde (auso z.B. https://fail2ban.example.com).",
|
||||
"settings.destination_email": "Ziiu-Email (Alarmempfänger)",
|
||||
"settings.destination_email_placeholder": "alerts@swissmakers.ch",
|
||||
"settings.alert_countries": "Alarm-Länder",
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
"settings.alert": "Alert Settings",
|
||||
"settings.callback_url": "Fail2ban Callback URL",
|
||||
"settings.callback_url_placeholder": "http://127.0.0.1:8080",
|
||||
"settings.callback_url_hint": "This URL is used by all Fail2Ban instances to send ban alerts back to Fail2Ban UI. For local deployments, use the same port as Fail2Ban UI (e.g., http://127.0.0.1:8080). For reverse proxy setups, use your TLS-encrypted endpoint (e.g., https://fail2ban.example.com).",
|
||||
"settings.destination_email": "Destination Email (Alerts Receiver)",
|
||||
"settings.destination_email_placeholder": "alerts@swissmakers.ch",
|
||||
"settings.alert_countries": "Alert Countries",
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
"settings.alert": "Configuración de alertas",
|
||||
"settings.callback_url": "URL de retorno de Fail2ban",
|
||||
"settings.callback_url_placeholder": "http://127.0.0.1:8080",
|
||||
"settings.callback_url_hint": "Esta URL es utilizada por todas las instancias de Fail2Ban para enviar alertas de bloqueo a Fail2Ban UI. Para implementaciones locales, use el mismo puerto que Fail2Ban UI (ej. http://127.0.0.1:8080). Para configuraciones de proxy inverso, use su endpoint cifrado TLS (ej. https://fail2ban.example.com).",
|
||||
"settings.destination_email": "Correo electrónico de destino (receptor de alertas)",
|
||||
"settings.destination_email_placeholder": "alerts@swissmakers.ch",
|
||||
"settings.alert_countries": "Países para alerta",
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
"settings.alert": "Paramètres d'alerte",
|
||||
"settings.callback_url": "URL de rappel Fail2ban",
|
||||
"settings.callback_url_placeholder": "http://127.0.0.1:8080",
|
||||
"settings.callback_url_hint": "Cette URL est utilisée par toutes les instances Fail2Ban pour envoyer les alertes de bannissement à Fail2Ban UI. Pour les déploiements locaux, utilisez le même port que Fail2Ban UI (p. ex. http://127.0.0.1:8080). Pour les configurations de reverse proxy, utilisez votre point de terminaison chiffré TLS (p. ex. https://fail2ban.example.com).",
|
||||
"settings.destination_email": "Email de destination (récepteur des alertes)",
|
||||
"settings.destination_email_placeholder": "alerts@swissmakers.ch",
|
||||
"settings.alert_countries": "Pays d'alerte",
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
"settings.alert": "Impostazioni di allarme",
|
||||
"settings.callback_url": "URL di callback Fail2ban",
|
||||
"settings.callback_url_placeholder": "http://127.0.0.1:8080",
|
||||
"settings.callback_url_hint": "Questo URL viene utilizzato da tutte le istanze Fail2Ban per inviare gli avvisi di ban a Fail2Ban UI. Per le distribuzioni locali, utilizzare la stessa porta di Fail2Ban UI (es. http://127.0.0.1:8080). Per le configurazioni di reverse proxy, utilizzare il proprio endpoint crittografato TLS (es. https://fail2ban.example.com).",
|
||||
"settings.destination_email": "Email di destinazione (ricevente allarmi)",
|
||||
"settings.destination_email_placeholder": "alerts@swissmakers.ch",
|
||||
"settings.alert_countries": "Paesi per allarme",
|
||||
|
||||
157
pkg/web/static/fail2ban-ui.css
Normal file
157
pkg/web/static/fail2ban-ui.css
Normal file
@@ -0,0 +1,157 @@
|
||||
/* Loading overlay styling */
|
||||
#loading-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 9999;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
backdrop-filter: blur(4px);
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s ease;
|
||||
}
|
||||
|
||||
#loading-overlay.show {
|
||||
display: flex;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Restart banner */
|
||||
#restartBanner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Custom scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
/* Custom select2 styling to match Tailwind */
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
min-height: 42px;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #3b82f6;
|
||||
border: 1px solid #3b82f6;
|
||||
color: white;
|
||||
border-radius: 0.25rem;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: white;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
/* Custom modal styling */
|
||||
.modal-content {
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
body.modal-open {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
/* Custom tooltip styling */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip .tooltip-text {
|
||||
visibility: hidden;
|
||||
width: 200px;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltip-text {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Custom mark styling for search highlights */
|
||||
mark {
|
||||
background-color: #fef08a;
|
||||
padding: 0.1em 0em 0.1em 0.2em;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
/* Toast notifications */
|
||||
#toast-container {
|
||||
position: fixed;
|
||||
top: 1.5rem;
|
||||
right: 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
z-index: 10000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toast {
|
||||
min-width: 240px;
|
||||
max-width: 360px;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
opacity: 0;
|
||||
transform: translateY(-6px);
|
||||
transition: opacity 0.25s ease, transform 0.25s ease;
|
||||
}
|
||||
|
||||
.toast.show {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.toast-success {
|
||||
background-color: #047857;
|
||||
}
|
||||
|
||||
.toast-error {
|
||||
background-color: #b91c1c;
|
||||
}
|
||||
|
||||
.toast-info {
|
||||
background-color: #1d4ed8;
|
||||
}
|
||||
|
||||
#advancedMikrotikFields, #advancedPfSenseFields {
|
||||
padding: 10px;
|
||||
}
|
||||
@@ -33,162 +33,9 @@
|
||||
<!-- Font Awesome for icons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<!-- Select2 CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet" />
|
||||
<style>
|
||||
/* Loading overlay styling */
|
||||
#loading-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 9999;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
backdrop-filter: blur(4px);
|
||||
-webkit-backdrop-filter: blur(4px);
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s ease;
|
||||
}
|
||||
|
||||
#loading-overlay.show {
|
||||
display: flex;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Restart banner */
|
||||
#restartBanner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Custom scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
/* Custom select2 styling to match Tailwind */
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
min-height: 42px;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #3b82f6;
|
||||
border: 1px solid #3b82f6;
|
||||
color: white;
|
||||
border-radius: 0.25rem;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: white;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
/* Custom modal styling */
|
||||
.modal-content {
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
body.modal-open {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
/* Custom tooltip styling */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip .tooltip-text {
|
||||
visibility: hidden;
|
||||
width: 200px;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltip-text {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Custom mark styling for search highlights */
|
||||
mark {
|
||||
background-color: #fef08a;
|
||||
padding: 0.1em 0em 0.1em 0.2em;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
/* Toast notifications */
|
||||
#toast-container {
|
||||
position: fixed;
|
||||
top: 1.5rem;
|
||||
right: 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
z-index: 10000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toast {
|
||||
min-width: 240px;
|
||||
max-width: 360px;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
||||
opacity: 0;
|
||||
transform: translateY(-6px);
|
||||
transition: opacity 0.25s ease, transform 0.25s ease;
|
||||
}
|
||||
|
||||
.toast.show {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.toast-success {
|
||||
background-color: #047857;
|
||||
}
|
||||
|
||||
.toast-error {
|
||||
background-color: #b91c1c;
|
||||
}
|
||||
|
||||
.toast-info {
|
||||
background-color: #1d4ed8;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" />
|
||||
<!-- Fail2ban UI CSS -->
|
||||
<link rel="stylesheet" href="/static/fail2ban-ui.css">
|
||||
</head>
|
||||
|
||||
<body class="bg-gray-50 overflow-y-scroll">
|
||||
@@ -344,18 +191,20 @@
|
||||
<input type="number" class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" id="uiPort"
|
||||
data-i18n-placeholder="settings.server_port_placeholder" placeholder="e.g., 8080" required min="80" max="65535" />
|
||||
<p class="mt-1 text-sm text-gray-500" id="portEnvHint" style="display: none;">
|
||||
<span data-i18n="settings.port_env_set">Port is set via PORT environment variable:</span> <span id="portEnvValue"></span>. <span data-i18n="settings.port_env_hint">To change the port via Web UI, remove the PORT environment variable and restart the container.</span>
|
||||
<span data-i18n="settings.port_env_set">Port is set via PORT environment variable:</span>
|
||||
<span id="portEnvValue"></span>. <span data-i18n="settings.port_env_hint">To change the port via Web UI, remove the PORT environment variable and restart the container.</span>
|
||||
</p>
|
||||
<p class="mt-1 text-sm text-amber-600" id="portRestartHint" style="display: none;" data-i18n="settings.port_restart_hint">⚠️ Port changes require a container restart to take effect.</p>
|
||||
<p class="text-xs text-gray-500 mt-1" id="portRestartHint" style="display: none;" data-i18n="settings.port_restart_hint">⚠️ Port changes require a container restart to take effect.</p>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="callbackURL" class="block text-sm font-medium text-gray-700 mb-2" data-i18n="settings.callback_url">Fail2ban Callback URL</label>
|
||||
<input type="text" class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500" id="callbackURL"
|
||||
data-i18n-placeholder="settings.callback_url_placeholder" placeholder="http://127.0.0.1:8080" />
|
||||
<p class="text-xs text-gray-500 mt-1" data-i18n="settings.callback_url_hint">This URL is used by all Fail2Ban instances to send ban alerts back to Fail2Ban UI. For local deployments, use the same port as Fail2Ban UI (e.g., http://127.0.0.1:8080). For reverse proxy setups, use your TLS-encrypted endpoint (e.g., https://fail2ban.example.com).</p>
|
||||
</div>
|
||||
|
||||
<!-- Debug Log Output -->
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center border border-gray-200 rounded-lg p-2 overflow-x-auto bg-gray-50">
|
||||
<input type="checkbox" id="debugMode" class="h-4 w-7 text-blue-600 transition duration-150 ease-in-out">
|
||||
<label for="debugMode" class="ml-2 block text-sm text-gray-700" data-i18n="settings.enable_debug">Enable Debug Log</label>
|
||||
</div>
|
||||
@@ -396,7 +245,7 @@
|
||||
<p class="text-xs text-gray-500 mt-1" data-i18n="settings.advanced.integration_hint">Choose where permanent bans should be synchronized.</p>
|
||||
</div>
|
||||
|
||||
<div id="advancedMikrotikFields" class="hidden space-y-4">
|
||||
<div id="advancedMikrotikFields" class="hidden border border-gray-200 rounded-lg p-4 overflow-x-auto bg-gray-50">
|
||||
<p class="text-sm text-gray-500" data-i18n="settings.advanced.mikrotik.note">Provide SSH credentials and the address list where IPs should be added.</p>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
@@ -426,7 +275,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="advancedPfSenseFields" class="hidden space-y-4">
|
||||
<div id="advancedPfSenseFields" class="hidden border border-gray-200 rounded-lg p-4 overflow-x-auto bg-gray-50">
|
||||
<p class="text-sm text-gray-500" data-i18n="settings.advanced.pfsense.note">Requires the pfSense API package. Enter the API credentials and alias to manage.</p>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="md:col-span-2">
|
||||
@@ -3178,7 +3027,24 @@
|
||||
}
|
||||
|
||||
document.getElementById('debugMode').checked = data.debug || false;
|
||||
document.getElementById('callbackURL').value = data.callbackUrl || '';
|
||||
|
||||
// Set callback URL and add auto-update listener for port changes
|
||||
const callbackURLInput = document.getElementById('callbackURL');
|
||||
callbackURLInput.value = data.callbackUrl || '';
|
||||
|
||||
// Auto-update callback URL when port changes (if using default localhost pattern)
|
||||
function updateCallbackURLIfDefault() {
|
||||
const currentPort = parseInt(uiPortInput.value, 10) || 8080;
|
||||
const currentCallbackURL = callbackURLInput.value.trim();
|
||||
// Check if callback URL matches default localhost pattern
|
||||
const defaultPattern = /^http:\/\/127\.0\.0\.1:\d+$/;
|
||||
if (currentCallbackURL === '' || defaultPattern.test(currentCallbackURL)) {
|
||||
callbackURLInput.value = `http://127.0.0.1:${currentPort}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Add listener to port input to auto-update callback URL
|
||||
uiPortInput.addEventListener('input', updateCallbackURLIfDefault);
|
||||
|
||||
document.getElementById('destEmail').value = data.destemail || '';
|
||||
|
||||
@@ -3241,12 +3107,21 @@
|
||||
|
||||
const selectedCountries = Array.from(document.getElementById('alertCountries').selectedOptions).map(opt => opt.value);
|
||||
|
||||
// Auto-update callback URL if using default localhost pattern and port changed
|
||||
const callbackURLInput = document.getElementById('callbackURL');
|
||||
let callbackUrl = callbackURLInput.value.trim();
|
||||
const currentPort = parseInt(document.getElementById('uiPort').value, 10) || 8080;
|
||||
const defaultPattern = /^http:\/\/127\.0\.0\.1:\d+$/;
|
||||
if (callbackUrl === '' || defaultPattern.test(callbackUrl)) {
|
||||
callbackUrl = `http://127.0.0.1:${currentPort}`;
|
||||
}
|
||||
|
||||
const settingsData = {
|
||||
language: document.getElementById('languageSelect').value,
|
||||
port: parseInt(document.getElementById('uiPort').value, 10) || 8080,
|
||||
port: currentPort,
|
||||
debug: document.getElementById('debugMode').checked,
|
||||
destemail: document.getElementById('destEmail').value.trim(),
|
||||
callbackUrl: document.getElementById('callbackURL').value.trim(),
|
||||
callbackUrl: callbackUrl,
|
||||
alertCountries: selectedCountries.length > 0 ? selectedCountries : ["ALL"],
|
||||
bantimeIncrement: document.getElementById('bantimeIncrement').checked,
|
||||
bantime: document.getElementById('banTime').value.trim(),
|
||||
|
||||
Reference in New Issue
Block a user