From b6a0a7a96fa3605703f4707075af00bf05ed723d Mon Sep 17 00:00:00 2001 From: Simon Skoczylas Date: Tue, 30 Jun 2026 14:31:57 +0200 Subject: [PATCH 1/2] Add config file support --- README.md | 26 ++++++++++++++++++++ cmd/fail2ban-dashboard/fail2ban-dashboard.go | 14 +++++++++++ 2 files changed, 40 insertions(+) diff --git a/README.md b/README.md index f663b34..d644508 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,32 @@ Environment variables can be used to set parameters without using command line f | `F2BD_SOCKET` | `-s, --socket` | Fail2ban socket path | `/var/run/fail2ban/fail2ban.sock` | | `F2BD_TRUST_PROXY_HEADERS` | `--trust-proxy-headers` | Trust proxy headers like X-Forwarded-For | `false` | +### Config file + +It is also possible to configure the application using a config file. +Supported config file formats are the ones supported by the [viper](https://github.com/spf13/viper) library. + +The config file can be located at `/etc/fail2ban-dashboard/`, the user home directory `~/.config/fail2ban-dashboard/` or the current working directory. + +For example, for a TOML file located at `/etc/fail2ban-dashboard/config.toml` the chaning the address is like + +```toml +address="127.0.0.1:4000" +``` + +Supported configurations are + +| Configuration | +|-----------------| +| socket | +| address | +| auth-user | +| auth-password | +| cache-dir | +| log-level | +| base-path | +| metrics-address | + ## Dashboard ### Web application diff --git a/cmd/fail2ban-dashboard/fail2ban-dashboard.go b/cmd/fail2ban-dashboard/fail2ban-dashboard.go index ff605a6..52fa5dc 100644 --- a/cmd/fail2ban-dashboard/fail2ban-dashboard.go +++ b/cmd/fail2ban-dashboard/fail2ban-dashboard.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "os" "strings" @@ -36,6 +37,19 @@ var versionCmd = &cobra.Command{ } func setupRootCommand() { + // Add search paths to find the file + viper.SetConfigName("config") + viper.AddConfigPath("/etc/fail2ban-dashboard/") + viper.AddConfigPath("$HOME/.config/fail2ban-dashboard") + viper.AddConfigPath(".") + + if err := viper.ReadInConfig(); err != nil { + if _, ok := errors.AsType[viper.ConfigFileNotFoundError](err); !ok { + fmt.Printf("Could not parse config file: %s\n", err) + os.Exit(1) + } + } + viper.AutomaticEnv() viper.SetEnvPrefix("F2BD") viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) From 5bc3d8931416d0535e38b8c5b1380369e86d4261 Mon Sep 17 00:00:00 2001 From: Simon Skoczylas Date: Tue, 30 Jun 2026 14:33:37 +0200 Subject: [PATCH 2/2] Fix password generation --- server/server.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/server/server.go b/server/server.go index e659742..9dd4e32 100644 --- a/server/server.go +++ b/server/server.go @@ -4,6 +4,7 @@ import ( "crypto/rand" _ "embed" "encoding/binary" + "encoding/hex" "fmt" "html/template" "net" @@ -103,6 +104,14 @@ type detailData struct { Jail store.Jail } +func generateRandomPassword() string { + b := make([]byte, 16) + if _, err := rand.Read(b); err != nil { + return "default-password-change-me" + } + return hex.EncodeToString(b) +} + func RegisterDashboardEndpoints(app *fiber.App, dataStore *store.DataStore, geoIP *geoip.GeoIP, configuration *Configuration) error { templateFunctions := template.FuncMap{ @@ -197,13 +206,13 @@ func RegisterDashboardEndpoints(app *fiber.App, dataStore *store.DataStore, geoI } log.Infof("Basic authentication username set to %s", configuration.AuthUser) if configuration.AuthPassword == "" { - configuration.AuthPassword = rand.Text() + configuration.AuthPassword = generateRandomPassword() log.Infof("Basic authentication password set to %s", configuration.AuthPassword) } app.Use(basicauth.New(basicauth.Config{ - Users: map[string]string{ - configuration.AuthUser: configuration.AuthPassword, + Authorizer: func(user, password string, c fiber.Ctx) bool { + return user == configuration.AuthUser && password == configuration.AuthPassword }, })) }