diff --git a/conf/configuration.go b/conf/configuration.go
index e8cdeccf3..dd5badeda 100644
--- a/conf/configuration.go
+++ b/conf/configuration.go
@@ -115,7 +115,9 @@ func Load() {
 		os.Exit(1)
 	}
 
-	log.Debug(pretty.Sprintf("Loaded configuration from '%s': %# v\n", Server.ConfigFile, Server))
+	if log.CurrentLevel() >= log.LevelDebug {
+		fmt.Println(log.Redact(pretty.Sprintf("Loaded configuration from '%s': %# v", Server.ConfigFile, Server)))
+	}
 
 	// Call init hooks
 	for _, hook := range hooks {
diff --git a/log/log.go b/log/log.go
index 3d2e7d6c5..bb79f7edb 100644
--- a/log/log.go
+++ b/log/log.go
@@ -87,6 +87,12 @@ func SetRedacting(enabled bool) {
 	}
 }
 
+// Redact applies redaction to a single string
+func Redact(msg string) string {
+	r, _ := redacted.redact(msg)
+	return r
+}
+
 func NewContext(ctx context.Context, keyValuePairs ...interface{}) context.Context {
 	if ctx == nil {
 		ctx = context.Background()
diff --git a/log/log_test.go b/log/log_test.go
index 146baee3b..bb7c7f8c1 100644
--- a/log/log_test.go
+++ b/log/log_test.go
@@ -28,7 +28,7 @@ var _ = Describe("Logger", func() {
 		SetDefaultLogger(l)
 	})
 
-	Context("Logging", func() {
+	Describe("Logging", func() {
 		It("logs a simple message", func() {
 			Error("Simple Message")
 			Expect(hook.LastEntry().Message).To(Equal("Simple Message"))
@@ -96,7 +96,7 @@ var _ = Describe("Logger", func() {
 		})
 	})
 
-	Context("Levels", func() {
+	Describe("Levels", func() {
 		BeforeEach(func() {
 			SetLevel(LevelTrace)
 		})
@@ -122,7 +122,7 @@ var _ = Describe("Logger", func() {
 		})
 	})
 
-	Context("extractLogger", func() {
+	Describe("extractLogger", func() {
 		It("returns an error if the context is nil", func() {
 			_, err := extractLogger(nil)
 			Expect(err).ToNot(BeNil())
@@ -151,7 +151,7 @@ var _ = Describe("Logger", func() {
 		})
 	})
 
-	Context("SetLevelString", func() {
+	Describe("SetLevelString", func() {
 		It("converts Critical level", func() {
 			SetLevelString("Critical")
 			Expect(CurrentLevel()).To(Equal(LevelCritical))
@@ -177,4 +177,11 @@ var _ = Describe("Logger", func() {
 			Expect(CurrentLevel()).To(Equal(LevelTrace))
 		})
 	})
+
+	Describe("Redact", func() {
+		Describe("Subsonic API password", func() {
+			msg := "getLyrics.view?v=1.2.0&c=iSub&u=user_name&p=first%20and%20other%20words&title=Title"
+			Expect(Redact(msg)).To(Equal("getLyrics.view?v=1.2.0&c=iSub&u=user_name&p=[REDACTED]&title=Title"))
+		})
+	})
 })
diff --git a/log/redactrus.go b/log/redactrus.go
index ba82da202..8c0d2ace9 100755
--- a/log/redactrus.go
+++ b/log/redactrus.go
@@ -16,6 +16,7 @@ type Hook struct {
 	// will not be dispatched. If empty, all messages will be dispatched.
 	AcceptedLevels []logrus.Level
 	RedactionList  []string
+	redactionKeys  []*regexp.Regexp
 }
 
 // Levels returns the user defined AcceptedLevels
@@ -27,26 +28,13 @@ func (h *Hook) Levels() []logrus.Level {
 	return h.AcceptedLevels
 }
 
-// LevelThreshold returns a []logrus.Level including all levels
-// above and including the level given. If the provided level does not exit,
-// an empty slice is returned.
-func LevelThreshold(l logrus.Level) []logrus.Level {
-	//nolint
-	if l < 0 || int(l) > len(logrus.AllLevels) {
-		return []logrus.Level{}
-	}
-	return logrus.AllLevels[:l+1]
-}
-
 // Fire redacts values in an log Entry that match
 // with keys defined in the RedactionList
 func (h *Hook) Fire(e *logrus.Entry) error {
-	for _, redactionKey := range h.RedactionList {
-		re, err := regexp.Compile(redactionKey)
-		if err != nil {
-			return err
-		}
-
+	if err := h.initRedaction(); err != nil {
+		return err
+	}
+	for _, re := range h.redactionKeys {
 		// Redact based on key matching in Data fields
 		for k, v := range e.Data {
 			if re.MatchString(k) {
@@ -68,3 +56,27 @@ func (h *Hook) Fire(e *logrus.Entry) error {
 
 	return nil
 }
+
+func (h *Hook) initRedaction() error {
+	if len(h.redactionKeys) == 0 {
+		for _, redactionKey := range h.RedactionList {
+			re, err := regexp.Compile(redactionKey)
+			if err != nil {
+				return err
+			}
+			h.redactionKeys = append(h.redactionKeys, re)
+		}
+	}
+	return nil
+}
+
+func (h *Hook) redact(msg string) (string, error) {
+	if err := h.initRedaction(); err != nil {
+		return msg, err
+	}
+	for _, re := range h.redactionKeys {
+		msg = re.ReplaceAllString(msg, "$1[REDACTED]$2")
+	}
+
+	return msg, nil
+}
diff --git a/log/redactrus_test.go b/log/redactrus_test.go
index 8fcc2e8e1..c06987b10 100755
--- a/log/redactrus_test.go
+++ b/log/redactrus_test.go
@@ -50,6 +50,17 @@ type levelThresholdTest struct {
 	description string
 }
 
+// levelThreshold returns a []logrus.Level including all levels
+// above and including the level given. If the provided level does not exit,
+// an empty slice is returned.
+func levelThreshold(l logrus.Level) []logrus.Level {
+	//nolint
+	if l < 0 || int(l) > len(logrus.AllLevels) {
+		return []logrus.Level{}
+	}
+	return logrus.AllLevels[:l+1]
+}
+
 func TestLevelThreshold(t *testing.T) {
 	tests := []levelThresholdTest{
 		{
@@ -68,7 +79,7 @@ func TestLevelThreshold(t *testing.T) {
 
 	for _, test := range tests {
 		fn := func(t *testing.T) {
-			levels := LevelThreshold(test.level)
+			levels := levelThreshold(test.level)
 			assert.Equal(t, test.expected, levels, test.description)
 		}