Add option to load TLS cert/key, and use HTTPS

This commit is contained in:
Deluan 2023-03-17 16:07:01 -04:00
parent 7ea111322b
commit 673880d661
3 changed files with 50 additions and 13 deletions

View File

@ -103,7 +103,7 @@ func startServer(ctx context.Context) func() error {
if strings.HasPrefix(conf.Server.UILoginBackgroundURL, "/") {
a.MountRouter("Background images", consts.DefaultUILoginBackgroundURL, backgrounds.NewHandler())
}
return a.Run(ctx, fmt.Sprintf("%s:%d", conf.Server.Address, conf.Server.Port))
return a.Run(ctx, fmt.Sprintf("%s:%d", conf.Server.Address, conf.Server.Port), conf.Server.TLSCert, conf.Server.TLSKey)
}
}
@ -162,11 +162,14 @@ func init() {
_ = viper.BindPFlag("datafolder", rootCmd.PersistentFlags().Lookup("datafolder"))
_ = viper.BindPFlag("loglevel", rootCmd.PersistentFlags().Lookup("loglevel"))
rootCmd.Flags().StringP("address", "a", viper.GetString("address"), "IP address to bind")
rootCmd.Flags().IntP("port", "p", viper.GetInt("port"), "HTTP port Navidrome will use")
rootCmd.Flags().StringP("address", "a", viper.GetString("address"), "IP address to bind to")
rootCmd.Flags().IntP("port", "p", viper.GetInt("port"), "HTTP port Navidrome will listen to")
rootCmd.Flags().String("baseurl", viper.GetString("baseurl"), "base URL to configure Navidrome behind a proxy (ex: /music or http://my.server.com)")
rootCmd.Flags().String("tlscert", viper.GetString("tlscert"), "optional path to a TLS cert file (enables HTTPS listening)")
rootCmd.Flags().String("tlskey", viper.GetString("tlskey"), "optional path to a TLS key file (enables HTTPS listening)")
rootCmd.Flags().Duration("sessiontimeout", viper.GetDuration("sessiontimeout"), "how long Navidrome will wait before closing web ui idle sessions")
rootCmd.Flags().Duration("scaninterval", viper.GetDuration("scaninterval"), "how frequently to scan for changes in your music library")
rootCmd.Flags().String("baseurl", viper.GetString("baseurl"), "base URL (only the path part) to configure Navidrome behind a proxy (ex: /music)")
rootCmd.Flags().String("uiloginbackgroundurl", viper.GetString("uiloginbackgroundurl"), "URL to a backaground image used in the Login page")
rootCmd.Flags().Bool("enabletranscodingconfig", viper.GetBool("enabletranscodingconfig"), "enables transcoding configuration in the UI")
rootCmd.Flags().String("transcodingcachesize", viper.GetString("transcodingcachesize"), "size of transcoding cache")
@ -178,9 +181,12 @@ func init() {
_ = viper.BindPFlag("address", rootCmd.Flags().Lookup("address"))
_ = viper.BindPFlag("port", rootCmd.Flags().Lookup("port"))
_ = viper.BindPFlag("tlscert", rootCmd.Flags().Lookup("tlscert"))
_ = viper.BindPFlag("tlskey", rootCmd.Flags().Lookup("tlskey"))
_ = viper.BindPFlag("baseurl", rootCmd.Flags().Lookup("baseurl"))
_ = viper.BindPFlag("sessiontimeout", rootCmd.Flags().Lookup("sessiontimeout"))
_ = viper.BindPFlag("scaninterval", rootCmd.Flags().Lookup("scaninterval"))
_ = viper.BindPFlag("baseurl", rootCmd.Flags().Lookup("baseurl"))
_ = viper.BindPFlag("uiloginbackgroundurl", rootCmd.Flags().Lookup("uiloginbackgroundurl"))
_ = viper.BindPFlag("prometheus.enabled", rootCmd.Flags().Lookup("prometheus.enabled"))

View File

@ -32,6 +32,8 @@ type configOptions struct {
BasePath string
BaseHost string
BaseScheme string
TLSCert string
TLSKey string
UILoginBackgroundURL string
UIWelcomeMessage string
MaxSidebarPlaylists int
@ -246,6 +248,8 @@ func init() {
viper.SetDefault("scaninterval", -1)
viper.SetDefault("scanschedule", "@every 1m")
viper.SetDefault("baseurl", "")
viper.SetDefault("tlscert", "")
viper.SetDefault("tlskey", "")
viper.SetDefault("uiloginbackgroundurl", consts.DefaultUILoginBackgroundURL)
viper.SetDefault("uiwelcomemessage", "")
viper.SetDefault("maxsidebarplaylists", consts.DefaultMaxSidebarPlaylists)

View File

@ -46,30 +46,57 @@ func (s *Server) MountRouter(description, urlPath string, subRouter http.Handler
})
}
func (s *Server) Run(ctx context.Context, addr string) error {
// Run starts the server with the given address, and if specified, with TLS enabled.
func (s *Server) Run(ctx context.Context, addr string, tlsCert string, tlsKey string) error {
// Mount the router for the frontend assets
s.MountRouter("WebUI", consts.URLPathUI, s.frontendAssetsHandler())
// Create a new http.Server with the specified address and read header timeout
server := &http.Server{
Addr: addr,
ReadHeaderTimeout: consts.ServerReadHeaderTimeout,
Handler: s.router,
}
// Start HTTP server in its own goroutine, send a signal (errC) if failed to start
// Determine if TLS is enabled
tlsEnabled := tlsCert != "" && tlsKey != ""
// Start the server in a new goroutine and send an error signal to errC if there's an error
errC := make(chan error)
go func() {
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
log.Error(ctx, "Could not start server. Aborting", err)
errC <- err
if tlsEnabled {
// Start the HTTPS server
log.Info("Starting server with TLS (HTTPS) enabled", "tlsCert", tlsCert, "tlsKey", tlsKey)
if err := server.ListenAndServeTLS(tlsCert, tlsKey); !errors.Is(err, http.ErrServerClosed) {
errC <- err
}
} else {
// Start the HTTP server
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
errC <- err
}
}
}()
log.Info(ctx, "Navidrome server is ready!", "address", addr, "startupTime", time.Since(consts.ServerStart))
// Measure server startup time
startupTime := time.Since(consts.ServerStart)
// Wait for a signal to terminate (or an error during startup)
// Wait a short time before checking if the server has started successfully
time.Sleep(50 * time.Millisecond)
select {
case err := <-errC:
return err
log.Error(ctx, "Could not start server. Aborting", err)
return fmt.Errorf("error starting server: %w", err)
default:
log.Info(ctx, "----> Navidrome server is ready!", "address", addr, "startupTime", startupTime, "tlsEnabled", tlsEnabled)
}
// Wait for a signal to terminate
select {
case err := <-errC:
return fmt.Errorf("error running server: %w", err)
case <-ctx.Done():
// If the context is done (i.e. the server should stop), proceed to shutting down the server
}
// Try to stop the HTTP server gracefully