Merge pull request #142 from writeas/autocert

Automatic certificates from Let's Encrypt

Resolves T542
pull/153/head
Matt Baer 5 years ago committed by GitHub
commit 3321c750ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 46
      app.go
  2. 1
      config/config.go
  3. 13
      config/setup.go

@ -11,6 +11,7 @@
package writefreely package writefreely
import ( import (
"crypto/tls"
"database/sql" "database/sql"
"fmt" "fmt"
"html/template" "html/template"
@ -39,6 +40,7 @@ import (
"github.com/writeas/writefreely/key" "github.com/writeas/writefreely/key"
"github.com/writeas/writefreely/migrations" "github.com/writeas/writefreely/migrations"
"github.com/writeas/writefreely/page" "github.com/writeas/writefreely/page"
"golang.org/x/crypto/acme/autocert"
) )
const ( const (
@ -380,19 +382,55 @@ func Serve(app *App, r *mux.Router) {
} }
var err error var err error
if app.cfg.IsSecureStandalone() { if app.cfg.IsSecureStandalone() {
if app.cfg.Server.Autocert {
m := &autocert.Manager{
Prompt: autocert.AcceptTOS,
Cache: autocert.DirCache(app.cfg.Server.TLSCertPath),
}
host, err := url.Parse(app.cfg.App.Host)
if err != nil {
log.Error("[WARNING] Unable to parse configured host! %s", err)
log.Error(`[WARNING] ALL hosts are allowed, which can open you to an attack where
clients connect to a server by IP address and pretend to be asking for an
incorrect host name, and cause you to reach the CA's rate limit for certificate
requests. We recommend supplying a valid host name.`)
log.Info("Using autocert on ANY host")
} else {
log.Info("Using autocert on host %s", host.Host)
m.HostPolicy = autocert.HostWhitelist(host.Host)
}
s := &http.Server{
Addr: ":https",
Handler: r,
TLSConfig: &tls.Config{
GetCertificate: m.GetCertificate,
},
}
s.SetKeepAlivesEnabled(false)
go func() {
log.Info("Serving redirects on http://%s:80", bindAddress) log.Info("Serving redirects on http://%s:80", bindAddress)
err = http.ListenAndServe(":80", m.HTTPHandler(nil))
log.Error("Unable to start redirect server: %v", err)
}()
log.Info("Serving on https://%s:443", bindAddress)
log.Info("---")
err = s.ListenAndServeTLS("", "")
} else {
go func() { go func() {
err = http.ListenAndServe( log.Info("Serving redirects on http://%s:80", bindAddress)
fmt.Sprintf("%s:80", bindAddress), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err = http.ListenAndServe(fmt.Sprintf("%s:80", bindAddress), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, app.cfg.App.Host, http.StatusMovedPermanently) http.Redirect(w, r, app.cfg.App.Host, http.StatusMovedPermanently)
})) }))
log.Error("Unable to start redirect server: %v", err) log.Error("Unable to start redirect server: %v", err)
}() }()
log.Info("Serving on https://%s:443", bindAddress) log.Info("Serving on https://%s:443", bindAddress)
log.Info("Using manual certificates")
log.Info("---") log.Info("---")
err = http.ListenAndServeTLS( err = http.ListenAndServeTLS(fmt.Sprintf("%s:443", bindAddress), app.cfg.Server.TLSCertPath, app.cfg.Server.TLSKeyPath, r)
fmt.Sprintf("%s:443", bindAddress), app.cfg.Server.TLSCertPath, app.cfg.Server.TLSKeyPath, r) }
} else { } else {
log.Info("Serving on http://%s:%d\n", bindAddress, app.cfg.Server.Port) log.Info("Serving on http://%s:%d\n", bindAddress, app.cfg.Server.Port)
log.Info("---") log.Info("---")

@ -35,6 +35,7 @@ type (
TLSCertPath string `ini:"tls_cert_path"` TLSCertPath string `ini:"tls_cert_path"`
TLSKeyPath string `ini:"tls_key_path"` TLSKeyPath string `ini:"tls_key_path"`
Autocert bool `ini:"autocert"`
TemplatesParentDir string `ini:"templates_parent_dir"` TemplatesParentDir string `ini:"templates_parent_dir"`
StaticParentDir string `ini:"static_parent_dir"` StaticParentDir string `ini:"static_parent_dir"`

@ -101,19 +101,23 @@ func Configure(fname string, configSections string) (*SetupData, error) {
selPrompt = promptui.Select{ selPrompt = promptui.Select{
Templates: selTmpls, Templates: selTmpls,
Label: "Web server mode", Label: "Web server mode",
Items: []string{"Insecure (port 80)", "Secure (port 443)"}, Items: []string{"Insecure (port 80)", "Secure (port 443), manual certificate", "Secure (port 443), auto certificate"},
} }
sel, _, err := selPrompt.Run() sel, _, err := selPrompt.Run()
if err != nil { if err != nil {
return data, err return data, err
} }
if sel == 0 { if sel == 0 {
data.Config.Server.Autocert = false
data.Config.Server.Port = 80 data.Config.Server.Port = 80
data.Config.Server.TLSCertPath = "" data.Config.Server.TLSCertPath = ""
data.Config.Server.TLSKeyPath = "" data.Config.Server.TLSKeyPath = ""
} else if sel == 1 { } else if sel == 1 || sel == 2 {
data.Config.Server.Port = 443 data.Config.Server.Port = 443
data.Config.Server.Autocert = sel == 2
if sel == 1 {
// Manual certificate configuration
prompt = promptui.Prompt{ prompt = promptui.Prompt{
Templates: tmpls, Templates: tmpls,
Label: "Certificate path", Label: "Certificate path",
@ -135,6 +139,11 @@ func Configure(fname string, configSections string) (*SetupData, error) {
if err != nil { if err != nil {
return data, err return data, err
} }
} else {
// Automatic certificate
data.Config.Server.TLSCertPath = "certs"
data.Config.Server.TLSKeyPath = "certs"
}
} }
} else { } else {
data.Config.Server.TLSCertPath = "" data.Config.Server.TLSCertPath = ""

Loading…
Cancel
Save