Work as a standalone server, including TLS

This supports running the server on port 443, serving secure pages, with
automatic redirects from the insecure site. It also modifies the
configuration process to better guide users through configuring for
running behind a reverse proxy or as a standalone server.

This closes T537
This commit is contained in:
Matt Baer 2018-11-21 18:26:19 -05:00
parent 77e79acd06
commit 09f5953431
3 changed files with 97 additions and 12 deletions

23
app.go
View file

@ -401,11 +401,26 @@ func Serve() {
os.Exit(0)
}()
// Start web application server
http.Handle("/", r)
log.Info("Serving on http://localhost:%d\n", app.cfg.Server.Port)
log.Info("---")
err = http.ListenAndServe(fmt.Sprintf(":%d", app.cfg.Server.Port), nil)
// Start web application server
if app.cfg.IsSecureStandalone() {
log.Info("Serving redirects on http://localhost:80")
go func() {
err = http.ListenAndServe(":80", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, app.cfg.App.Host, http.StatusMovedPermanently)
}))
log.Error("Unable to start redirect server: %v", err)
}()
log.Info("Serving on https://localhost:443")
log.Info("---")
err = http.ListenAndServeTLS(":443", app.cfg.Server.TLSCertPath, app.cfg.Server.TLSKeyPath, nil)
} else {
log.Info("Serving on http://localhost:%d\n", app.cfg.Server.Port)
log.Info("---")
err = http.ListenAndServe(fmt.Sprintf(":%d", app.cfg.Server.Port), nil)
}
if err != nil {
log.Error("Unable to start: %v", err)
os.Exit(1)

View file

@ -13,6 +13,9 @@ type (
HiddenHost string `ini:"hidden_host"`
Port int `ini:"port"`
TLSCertPath string `ini:"tls_cert_path"`
TLSKeyPath string `ini:"tls_key_path"`
Dev bool `ini:"-"`
}
@ -76,6 +79,10 @@ func New() *Config {
}
}
func (cfg *Config) IsSecureStandalone() bool {
return cfg.Server.Port == 443 && cfg.Server.TLSCertPath != "" && cfg.Server.TLSKeyPath != ""
}
func Load() (*Config, error) {
cfg, err := ini.Load(FileName)
if err != nil {

View file

@ -47,17 +47,80 @@ func Configure() (*SetupData, error) {
Selected: fmt.Sprintf(`{{.Label}} {{ . | faint }}`),
}
prompt := promptui.Prompt{
Templates: tmpls,
Label: "Local port",
Validate: validatePort,
Default: fmt.Sprintf("%d", data.Config.Server.Port),
// Environment selection
selPrompt := promptui.Select{
Templates: selTmpls,
Label: "Environment",
Items: []string{"Development", "Production, standalone", "Production, behind reverse proxy"},
}
port, err := prompt.Run()
_, envType, err := selPrompt.Run()
if err != nil {
return data, err
}
data.Config.Server.Port, _ = strconv.Atoi(port) // Ignore error, as we've already validated number
isDevEnv := envType == "Development"
isStandalone := envType == "Production, standalone"
data.Config.Server.Dev = isDevEnv
var prompt promptui.Prompt
if isDevEnv || !isStandalone {
// Running in dev environment or behind reverse proxy; ask for port
prompt = promptui.Prompt{
Templates: tmpls,
Label: "Local port",
Validate: validatePort,
Default: fmt.Sprintf("%d", data.Config.Server.Port),
}
port, err := prompt.Run()
if err != nil {
return data, err
}
data.Config.Server.Port, _ = strconv.Atoi(port) // Ignore error, as we've already validated number
}
if isStandalone {
selPrompt = promptui.Select{
Templates: selTmpls,
Label: "Web server mode",
Items: []string{"Insecure (port 80)", "Secure (port 443)"},
}
sel, _, err := selPrompt.Run()
if err != nil {
return data, err
}
if sel == 0 {
data.Config.Server.Port = 80
data.Config.Server.TLSCertPath = ""
data.Config.Server.TLSKeyPath = ""
} else if sel == 1 {
data.Config.Server.Port = 443
prompt = promptui.Prompt{
Templates: tmpls,
Label: "Certificate path",
Validate: validateNonEmpty,
Default: data.Config.Server.TLSCertPath,
}
data.Config.Server.TLSCertPath, err = prompt.Run()
if err != nil {
return data, err
}
prompt = promptui.Prompt{
Templates: tmpls,
Label: "Key path",
Validate: validateNonEmpty,
Default: data.Config.Server.TLSKeyPath,
}
data.Config.Server.TLSKeyPath, err = prompt.Run()
if err != nil {
return data, err
}
}
} else {
data.Config.Server.TLSCertPath = ""
data.Config.Server.TLSKeyPath = ""
}
fmt.Println()
title(" Database setup ")
@ -124,7 +187,7 @@ func Configure() (*SetupData, error) {
title(" App setup ")
fmt.Println()
selPrompt := promptui.Select{
selPrompt = promptui.Select{
Templates: selTmpls,
Label: "Site type",
Items: []string{"Single user blog", "Multi-user instance"},