Add TLS/HTTPS

pull/29/head
Philipp Heckel 2021-12-02 08:52:48 -05:00
parent 1e7ae885b4
commit 07a1fe3acb
4 changed files with 52 additions and 6 deletions

View File

@ -18,7 +18,10 @@ import (
func New() *cli.App { func New() *cli.App {
flags := []cli.Flag{ flags := []cli.Flag{
&cli.StringFlag{Name: "config", Aliases: []string{"c"}, EnvVars: []string{"NTFY_CONFIG_FILE"}, Value: "/etc/ntfy/config.yml", DefaultText: "/etc/ntfy/config.yml", Usage: "config file"}, &cli.StringFlag{Name: "config", Aliases: []string{"c"}, EnvVars: []string{"NTFY_CONFIG_FILE"}, Value: "/etc/ntfy/config.yml", DefaultText: "/etc/ntfy/config.yml", Usage: "config file"},
altsrc.NewStringFlag(&cli.StringFlag{Name: "listen-http", Aliases: []string{"l"}, EnvVars: []string{"NTFY_LISTEN_HTTP"}, Value: config.DefaultListenHTTP, Usage: "ip:port used to as listen address"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "listen-http", Aliases: []string{"l"}, EnvVars: []string{"NTFY_LISTEN_HTTP"}, Value: config.DefaultListenHTTP, Usage: "ip:port used to as HTTP listen address"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "listen-https", Aliases: []string{"L"}, EnvVars: []string{"NTFY_LISTEN_HTTPS"}, Usage: "ip:port used to as HTTPS listen address"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "key-file", Aliases: []string{"K"}, EnvVars: []string{"NTFY_KEY_FILE"}, Usage: "private key file, if listen-https is set"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "cert-file", Aliases: []string{"E"}, EnvVars: []string{"NTFY_CERT_FILE"}, Usage: "certificate file, if listen-https is set"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "firebase-key-file", Aliases: []string{"F"}, EnvVars: []string{"NTFY_FIREBASE_KEY_FILE"}, Usage: "Firebase credentials file; if set additionally publish to FCM topic"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "firebase-key-file", Aliases: []string{"F"}, EnvVars: []string{"NTFY_FIREBASE_KEY_FILE"}, Usage: "Firebase credentials file; if set additionally publish to FCM topic"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-file", Aliases: []string{"C"}, EnvVars: []string{"NTFY_CACHE_FILE"}, Usage: "cache file used for message caching"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-file", Aliases: []string{"C"}, EnvVars: []string{"NTFY_CACHE_FILE"}, Usage: "cache file used for message caching"}),
altsrc.NewDurationFlag(&cli.DurationFlag{Name: "cache-duration", Aliases: []string{"b"}, EnvVars: []string{"NTFY_CACHE_DURATION"}, Value: config.DefaultCacheDuration, Usage: "buffer messages for this time to allow `since` requests"}), altsrc.NewDurationFlag(&cli.DurationFlag{Name: "cache-duration", Aliases: []string{"b"}, EnvVars: []string{"NTFY_CACHE_DURATION"}, Value: config.DefaultCacheDuration, Usage: "buffer messages for this time to allow `since` requests"}),
@ -50,6 +53,9 @@ func New() *cli.App {
func execRun(c *cli.Context) error { func execRun(c *cli.Context) error {
// Read all the options // Read all the options
listenHTTP := c.String("listen-http") listenHTTP := c.String("listen-http")
listenHTTPS := c.String("listen-https")
keyFile := c.String("key-file")
certFile := c.String("cert-file")
firebaseKeyFile := c.String("firebase-key-file") firebaseKeyFile := c.String("firebase-key-file")
cacheFile := c.String("cache-file") cacheFile := c.String("cache-file")
cacheDuration := c.Duration("cache-duration") cacheDuration := c.Duration("cache-duration")
@ -70,10 +76,19 @@ func execRun(c *cli.Context) error {
return errors.New("manager interval cannot be lower than five seconds") return errors.New("manager interval cannot be lower than five seconds")
} else if cacheDuration < managerInterval { } else if cacheDuration < managerInterval {
return errors.New("cache duration cannot be lower than manager interval") return errors.New("cache duration cannot be lower than manager interval")
} else if keyFile != "" && !util.FileExists(keyFile) {
return errors.New("if set, key file must exist")
} else if certFile != "" && !util.FileExists(certFile) {
return errors.New("if set, certificate file must exist")
} else if listenHTTPS != "" && (keyFile == "" || certFile == "") {
return errors.New("if listen-https is set, both key-file and cert-file must be set")
} }
// Run server // Run server
conf := config.New(listenHTTP) conf := config.New(listenHTTP)
conf.ListenHTTPS = listenHTTPS
conf.KeyFile = keyFile
conf.CertFile = certFile
conf.FirebaseKeyFile = firebaseKeyFile conf.FirebaseKeyFile = firebaseKeyFile
conf.CacheFile = cacheFile conf.CacheFile = cacheFile
conf.CacheDuration = cacheDuration conf.CacheDuration = cacheDuration

View File

@ -27,6 +27,9 @@ const (
// Config is the main config struct for the application. Use New to instantiate a default config struct. // Config is the main config struct for the application. Use New to instantiate a default config struct.
type Config struct { type Config struct {
ListenHTTP string ListenHTTP string
ListenHTTPS string
KeyFile string
CertFile string
FirebaseKeyFile string FirebaseKeyFile string
CacheFile string CacheFile string
CacheDuration time.Duration CacheDuration time.Duration
@ -43,6 +46,9 @@ type Config struct {
func New(listenHTTP string) *Config { func New(listenHTTP string) *Config {
return &Config{ return &Config{
ListenHTTP: listenHTTP, ListenHTTP: listenHTTP,
ListenHTTPS: "",
KeyFile: "",
CertFile: "",
FirebaseKeyFile: "", FirebaseKeyFile: "",
CacheFile: "", CacheFile: "",
CacheDuration: DefaultCacheDuration, CacheDuration: DefaultCacheDuration,

View File

@ -5,6 +5,21 @@
# #
# listen-http: ":80" # listen-http: ":80"
# Listen address for the HTTPS web server. If set, you must also set "key-file" and "cert-file".
# Format: <hostname>:<port>
#
# listen-https:
# Path to the private key file for the HTTPS web server. Not used if "listen-https" is not set.
# Format: <filename>
#
# key-file:
# Path to the cert file for the HTTPS web server. Not used if "listen-https" is not set.
# Format: <filename>
#
# cert-file:
# If set, also publish messages to a Firebase Cloud Messaging (FCM) topic for your app. # If set, also publish messages to a Firebase Cloud Messaging (FCM) topic for your app.
# This is optional and only required to support Android apps (which don't allow background services anymore). # This is optional and only required to support Android apps (which don't allow background services anymore).
# #

View File

@ -173,13 +173,23 @@ func (s *Server) Run() error {
s.updateStatsAndExpire() s.updateStatsAndExpire()
} }
}() }()
return s.listenAndServe() listenStr := fmt.Sprintf("%s/http", s.config.ListenHTTP)
} if s.config.ListenHTTPS != "" {
listenStr += fmt.Sprintf(" %s/https", s.config.ListenHTTPS)
}
log.Printf("Listening on %s", listenStr)
func (s *Server) listenAndServe() error {
log.Printf("Listening on %s", s.config.ListenHTTP)
http.HandleFunc("/", s.handle) http.HandleFunc("/", s.handle)
return http.ListenAndServe(s.config.ListenHTTP, nil) errChan := make(chan error)
go func() {
errChan <- http.ListenAndServe(s.config.ListenHTTP, nil)
}()
if s.config.ListenHTTPS != "" {
go func() {
errChan <- http.ListenAndServeTLS(s.config.ListenHTTPS, s.config.CertFile, s.config.KeyFile, nil)
}()
}
return <-errChan
} }
func (s *Server) handle(w http.ResponseWriter, r *http.Request) { func (s *Server) handle(w http.ResponseWriter, r *http.Request) {