From 220372d65a49877a040c515887769b3b87d41a81 Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Sat, 17 Jan 2026 17:51:33 -0500 Subject: [PATCH] Move client config file logic, docs --- client/config.go | 3 ++ client/config_darwin.go | 18 ++++++++++ client/config_unix.go | 18 ++++++++++ client/config_windows.go | 14 ++++++++ cmd/subscribe.go | 54 +++++----------------------- cmd/subscribe_darwin.go | 6 ++-- cmd/subscribe_unix.go | 4 --- cmd/subscribe_windows.go | 6 ++-- docs/config.md | 78 ---------------------------------------- docs/install.md | 35 +++++++----------- 10 files changed, 79 insertions(+), 157 deletions(-) create mode 100644 client/config_darwin.go create mode 100644 client/config_unix.go create mode 100644 client/config_windows.go diff --git a/client/config.go b/client/config.go index 870c835b..444460d6 100644 --- a/client/config.go +++ b/client/config.go @@ -11,6 +11,9 @@ const ( DefaultBaseURL = "https://ntfy.sh" ) +// DefaultConfigFile is the default path to the client config file (set in config_*.go) +var DefaultConfigFile string + // Config is the config struct for a Client type Config struct { DefaultHost string `yaml:"default-host"` diff --git a/client/config_darwin.go b/client/config_darwin.go new file mode 100644 index 00000000..c2488849 --- /dev/null +++ b/client/config_darwin.go @@ -0,0 +1,18 @@ +//go:build darwin + +package client + +import ( + "os" + "os/user" + "path/filepath" +) + +func init() { + u, err := user.Current() + if err == nil && u.Uid == "0" { + DefaultConfigFile = "/etc/ntfy/client.yml" + } else if configDir, err := os.UserConfigDir(); err == nil { + DefaultConfigFile = filepath.Join(configDir, "ntfy", "client.yml") + } +} diff --git a/client/config_unix.go b/client/config_unix.go new file mode 100644 index 00000000..273340e1 --- /dev/null +++ b/client/config_unix.go @@ -0,0 +1,18 @@ +//go:build linux || dragonfly || freebsd || netbsd || openbsd + +package client + +import ( + "os" + "os/user" + "path/filepath" +) + +func init() { + u, err := user.Current() + if err == nil && u.Uid == "0" { + DefaultConfigFile = "/etc/ntfy/client.yml" + } else if configDir, err := os.UserConfigDir(); err == nil { + DefaultConfigFile = filepath.Join(configDir, "ntfy", "client.yml") + } +} diff --git a/client/config_windows.go b/client/config_windows.go new file mode 100644 index 00000000..2ee55328 --- /dev/null +++ b/client/config_windows.go @@ -0,0 +1,14 @@ +//go:build windows + +package client + +import ( + "os" + "path/filepath" +) + +func init() { + if configDir, err := os.UserConfigDir(); err == nil { + DefaultConfigFile = filepath.Join(configDir, "ntfy", "client.yml") + } +} diff --git a/cmd/subscribe.go b/cmd/subscribe.go index 5ebf9627..84450927 100644 --- a/cmd/subscribe.go +++ b/cmd/subscribe.go @@ -3,28 +3,21 @@ package cmd import ( "errors" "fmt" + "os" + "os/exec" + "sort" + "strings" + "github.com/urfave/cli/v2" "heckel.io/ntfy/v2/client" "heckel.io/ntfy/v2/log" "heckel.io/ntfy/v2/util" - "os" - "os/exec" - "os/user" - "path/filepath" - "sort" - "strings" ) func init() { commands = append(commands, cmdSubscribe) } -const ( - clientRootConfigFileUnixAbsolute = "/etc/ntfy/client.yml" - clientUserConfigFileUnixRelative = "ntfy/client.yml" - clientUserConfigFileWindowsRelative = "ntfy\\client.yml" -) - var flagsSubscribe = append( append([]cli.Flag{}, flagsDefault...), &cli.StringFlag{Name: "config", Aliases: []string{"c"}, Usage: "client config file"}, @@ -310,45 +303,16 @@ func loadConfig(c *cli.Context) (*client.Config, error) { if filename != "" { return client.LoadConfig(filename) } - configFile, err := defaultClientConfigFile() - if err != nil { - log.Warn("Could not determine default client config file: %s", err.Error()) - } else { - if s, _ := os.Stat(configFile); s != nil { - return client.LoadConfig(configFile) + if client.DefaultConfigFile != "" { + if s, _ := os.Stat(client.DefaultConfigFile); s != nil { + return client.LoadConfig(client.DefaultConfigFile) } - log.Debug("Config file %s not found", configFile) + log.Debug("Config file %s not found", client.DefaultConfigFile) } log.Debug("Loading default config") return client.NewConfig(), nil } -//lint:ignore U1000 Conditionally used in different builds -func defaultClientConfigFileUnix() (string, error) { - u, err := user.Current() - if err != nil { - return "", fmt.Errorf("could not determine current user: %w", err) - } - configFile := clientRootConfigFileUnixAbsolute - if u.Uid != "0" { - homeDir, err := os.UserConfigDir() - if err != nil { - return "", fmt.Errorf("could not determine user config dir: %w", err) - } - return filepath.Join(homeDir, clientUserConfigFileUnixRelative), nil - } - return configFile, nil -} - -//lint:ignore U1000 Conditionally used in different builds -func defaultClientConfigFileWindows() (string, error) { - homeDir, err := os.UserConfigDir() - if err != nil { - return "", fmt.Errorf("could not determine user config dir: %w", err) - } - return filepath.Join(homeDir, clientUserConfigFileWindowsRelative), nil -} - func logMessagePrefix(m *client.Message) string { return fmt.Sprintf("%s/%s", util.ShortTopicURL(m.TopicURL), m.ID) } diff --git a/cmd/subscribe_darwin.go b/cmd/subscribe_darwin.go index 487f0641..00335540 100644 --- a/cmd/subscribe_darwin.go +++ b/cmd/subscribe_darwin.go @@ -1,3 +1,5 @@ +//go:build darwin + package cmd const ( @@ -10,7 +12,3 @@ or "~/Library/Application Support/ntfy/client.yml" for all other users.` var ( scriptLauncher = []string{"sh", "-c"} ) - -func defaultClientConfigFile() (string, error) { - return defaultClientConfigFileUnix() -} diff --git a/cmd/subscribe_unix.go b/cmd/subscribe_unix.go index 3f5f526f..4c9c6039 100644 --- a/cmd/subscribe_unix.go +++ b/cmd/subscribe_unix.go @@ -12,7 +12,3 @@ or ~/.config/ntfy/client.yml for all other users.` var ( scriptLauncher = []string{"sh", "-c"} ) - -func defaultClientConfigFile() (string, error) { - return defaultClientConfigFileUnix() -} diff --git a/cmd/subscribe_windows.go b/cmd/subscribe_windows.go index 22c07d81..ea5f09f0 100644 --- a/cmd/subscribe_windows.go +++ b/cmd/subscribe_windows.go @@ -1,3 +1,5 @@ +//go:build windows + package cmd const ( @@ -9,7 +11,3 @@ const ( var ( scriptLauncher = []string{"cmd.exe", "/Q", "/C"} ) - -func defaultClientConfigFile() (string, error) { - return defaultClientConfigFileWindows() -} diff --git a/docs/config.md b/docs/config.md index 584f4064..8a125146 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1060,84 +1060,6 @@ or the root domain: } ``` -## Windows service -ntfy can run as a Windows service, allowing it to start automatically on boot and run in the background. -ntfy automatically detects when it is running as a Windows service and adjusts its behavior accordingly. - -### Installing the service -To install ntfy as a Windows service, open an **Administrator** command prompt or PowerShell and run: - -```cmd -sc create ntfy binPath= "C:\path\to\ntfy.exe serve" start= auto -``` - -!!! note - Make sure to replace `C:\path\to\ntfy.exe` with the actual path to your ntfy executable. - The spaces after `binPath=` and `start=` are required. - -You can also specify a config file: - -```cmd -sc create ntfy binPath= "C:\path\to\ntfy.exe serve --config C:\ProgramData\ntfy\server.yml" start= auto -``` - -### Starting and stopping -To start the service: - -```cmd -sc start ntfy -``` - -To stop the service: - -```cmd -sc stop ntfy -``` - -To check the service status: - -```cmd -sc query ntfy -``` - -### Configuring the service -The default configuration file location on Windows is `%ProgramData%\ntfy\server.yml` (typically `C:\ProgramData\ntfy\server.yml`). -Create this directory and file manually if needed. - -Example minimal config: - -```yaml -base-url: "https://ntfy.example.com" -listen-http: ":80" -cache-file: "C:\\ProgramData\\ntfy\\cache.db" -auth-file: "C:\\ProgramData\\ntfy\\auth.db" -``` - -!!! warning - Use double backslashes (`\\`) for paths in YAML files on Windows, or use forward slashes (`/`). - -### Viewing logs -By default, ntfy logs to stderr. When running as a Windows service, you can configure logging to a file: - -```yaml -log-file: "C:\\ProgramData\\ntfy\\ntfy.log" -log-level: info -``` - -### Removing the service -To remove the ntfy service: - -```cmd -sc stop ntfy -sc delete ntfy -``` - -### Limitations on Windows -When running on Windows, the following features are not available: - -- **Unix socket listening**: The `listen-unix` option is not supported on Windows -- **Config hot-reload**: The SIGHUP signal for hot-reloading configuration is not available on Windows; restart the service to apply config changes - ## Firebase (FCM) !!! info Using Firebase is **optional** and only works if you modify and [build your own Android .apk](develop.md#android-app). diff --git a/docs/install.md b/docs/install.md index a437499e..0711fdb2 100644 --- a/docs/install.md +++ b/docs/install.md @@ -229,37 +229,28 @@ brew install ntfy ## Windows The ntfy server and CLI are fully supported on Windows. You can run the ntfy server directly or as a Windows service. +To install, you can either -To install, please [download the latest ZIP](https://github.com/binwiederhier/ntfy/releases/download/v2.15.0/ntfy_2.15.0_windows_amd64.zip), +* [Download the latest ZIP](https://github.com/binwiederhier/ntfy/releases/download/v2.15.0/ntfy_2.15.0_windows_amd64.zip), extract it and place the `ntfy.exe` binary somewhere in your `%Path%`. +* Or install ntfy from the [Scoop](https://scoop.sh) main repository via `scoop install ntfy` -Also available in [Scoop's](https://scoop.sh) Main repository: +Once installed, you can run the ntfy CLI commands like so: -`scoop install ntfy` - -### Running the server -To run the ntfy server directly: ``` -ntfy serve +ntfy.exe -h ``` -The default configuration file location on Windows is `%ProgramData%\ntfy\server.yml` (e.g., `C:\ProgramData\ntfy\server.yml`). -You may need to create the directory and config file manually. +The default configuration file location on Windows is `%ProgramData%\ntfy\server.yml` (e.g., `C:\ProgramData\ntfy\server.yml`) +for the server, and `%AppData%\ntfy\client.yml` for the client. You may need to create the directory and config file manually. -For information on running ntfy as a Windows service, see the [Windows service](config.md#windows-service) section in the configuration documentation. +To install the ntfy server as a Windows service, you can use the built-in `sc` command. For example, run this in an +elevated command prompt (adjust the path to `ntfy.exe` accordingly): -### Client configuration -The default path for the client config file is at `%AppData%\ntfy\client.yml` (not created automatically, sample in the ZIP file). - -!!! info - There is currently no installer for Windows, and the binary is not signed. If this is desired, please create a - [GitHub issue](https://github.com/binwiederhier/ntfy/issues) to let me know. - -!!! note - Some features are not available on Windows: - - - Unix socket listening (`listen-unix`) is not supported - - Config hot-reload via SIGHUP is not available; restart the service to apply config changes +``` +sc create ntfy binPath="C:\path\to\ntfy.exe serve" start=auto +sc start ntfy +``` ## Docker The [ntfy image](https://hub.docker.com/r/binwiederhier/ntfy) is available for amd64, armv6, armv7 and arm64. It should