From 23e88a5555d37179546717857a8f1388490c971a Mon Sep 17 00:00:00 2001
From: Filipp Bondarenko <extracomplex@gmail.com>
Date: Tue, 28 May 2024 09:34:26 +0300
Subject: [PATCH] Add logrotate support: reopen log file on SIGHUP

---
 cmd/serve.go | 18 +++++++++++-------
 log/log.go   | 17 +++++++++++++++++
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/cmd/serve.go b/cmd/serve.go
index 62e0a14a..e546b82f 100644
--- a/cmd/serve.go
+++ b/cmd/serve.go
@@ -5,13 +5,6 @@ package cmd
 import (
 	"errors"
 	"fmt"
-	"github.com/stripe/stripe-go/v74"
-	"github.com/urfave/cli/v2"
-	"github.com/urfave/cli/v2/altsrc"
-	"heckel.io/ntfy/v2/log"
-	"heckel.io/ntfy/v2/server"
-	"heckel.io/ntfy/v2/user"
-	"heckel.io/ntfy/v2/util"
 	"io/fs"
 	"math"
 	"net"
@@ -22,6 +15,14 @@ import (
 	"strings"
 	"syscall"
 	"time"
+
+	"github.com/stripe/stripe-go/v74"
+	"github.com/urfave/cli/v2"
+	"github.com/urfave/cli/v2/altsrc"
+	"heckel.io/ntfy/v2/log"
+	"heckel.io/ntfy/v2/server"
+	"heckel.io/ntfy/v2/user"
+	"heckel.io/ntfy/v2/util"
 )
 
 func init() {
@@ -492,5 +493,8 @@ func reloadLogLevel(inputSource altsrc.InputSourceContext) error {
 	} else {
 		log.Info("Log level is %v", strings.ToUpper(newLevelStr))
 	}
+	if err := log.Reopen(); err != nil {
+		return fmt.Errorf("cannot reopen log file: %s", err.Error())
+	}
 	return nil
 }
diff --git a/log/log.go b/log/log.go
index 20ad6151..c8e26d48 100644
--- a/log/log.go
+++ b/log/log.go
@@ -154,6 +154,23 @@ func SetOutput(w io.Writer) {
 	log.SetOutput(output)
 }
 
+func Reopen() error {
+	mu.Lock()
+	defer mu.Unlock()
+	if f, ok := output.(*os.File); ok {
+		logFile := f.Name()
+		f.Close()
+
+		w, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
+		if err != nil {
+			return err
+		}
+		output = &peekLogWriter{w}
+		log.SetOutput(output)
+	}
+	return nil
+}
+
 // File returns the log file, if any, or an empty string otherwise
 func File() string {
 	mu.RLock()