mirror of
https://github.com/foomo/simplecert.git
synced 2025-10-16 12:35:34 +00:00
added common container pitfalls to readme
This commit is contained in:
parent
8faf537327
commit
c45ebd3450
@ -283,6 +283,15 @@ The LEGO package imports various api clients for providing the DNS challenges -
|
|||||||
In case this happens usually googling the error message is sufficient to find the go module replace directive that pins the needed version.
|
In case this happens usually googling the error message is sufficient to find the go module replace directive that pins the needed version.
|
||||||
Please open an issue if you could not fix a dependency error on your own.
|
Please open an issue if you could not fix a dependency error on your own.
|
||||||
|
|
||||||
|
- Container Pitfalls
|
||||||
|
|
||||||
|
Be careful with containers that are configured to automatically restart on errors!
|
||||||
|
When obtaining (or storing) a certificate fails for whatever reason, and your container will crash and restart automatically, you might get blocked due to the letsencrypt APIs rate limits.
|
||||||
|
|
||||||
|
Another common pitfall is to forget mounting the cache directory into your container, this way simplecert will obtain a new cert on every deployment, which will also likely cause rate limit issues after a while.
|
||||||
|
|
||||||
|
You can read more about the letsencrypt API rate limits here: https://letsencrypt.org/docs/rate-limits/
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
MIT
|
||||||
@ -1,65 +0,0 @@
|
|||||||
//
|
|
||||||
// simplecert
|
|
||||||
//
|
|
||||||
// Created by Philipp Mieden
|
|
||||||
// Contact: dreadl0ck@protonmail.ch
|
|
||||||
// Copyright © 2018 bestbytes. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/foomo/simplecert"
|
|
||||||
"github.com/foomo/tlsconfig"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Handler struct{}
|
|
||||||
|
|
||||||
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write([]byte("hello from simplecert"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
// do the cert magic
|
|
||||||
cfg := simplecert.Default
|
|
||||||
cfg.Domains = []string{"yourdomain.com", "www.yourdomain.com"}
|
|
||||||
cfg.CacheDir = "letsencrypt"
|
|
||||||
cfg.SSLEmail = "you@emailprovider.com"
|
|
||||||
cfg.Local = true
|
|
||||||
certReloader, err := simplecert.Init(cfg, func() {
|
|
||||||
// this function will be called upon receiving the syscall.SIGINT or syscall.SIGABRT signal
|
|
||||||
// and can be used to stop your backend gracefully
|
|
||||||
fmt.Println("cleaning up...")
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("simplecert init failed: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// redirect HTTP to HTTPS
|
|
||||||
log.Println("starting HTTP Listener on Port 80")
|
|
||||||
go http.ListenAndServe(":80", http.HandlerFunc(simplecert.Redirect))
|
|
||||||
|
|
||||||
// init strict tlsConfig with certReloader
|
|
||||||
tlsconf := tlsconfig.NewServerTLSConfig(tlsconfig.TLSModeServerStrict)
|
|
||||||
|
|
||||||
// now set GetCertificate to the reloaders GetCertificateFunc to enable hot reload
|
|
||||||
tlsconf.GetCertificate = certReloader.GetCertificateFunc()
|
|
||||||
|
|
||||||
// init server
|
|
||||||
s := &http.Server{
|
|
||||||
Addr: ":443",
|
|
||||||
TLSConfig: tlsconf,
|
|
||||||
Handler: Handler{},
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println("now visit: https://" + cfg.Domains[0])
|
|
||||||
|
|
||||||
// lets go
|
|
||||||
log.Fatal(s.ListenAndServeTLS("", ""))
|
|
||||||
}
|
|
||||||
143
examples/production/main.go
Normal file
143
examples/production/main.go
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
//
|
||||||
|
// simplecert
|
||||||
|
//
|
||||||
|
// Created by Philipp Mieden
|
||||||
|
// Contact: dreadl0ck@protonmail.ch
|
||||||
|
// Copyright © 2018 bestbytes. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/foomo/simplecert"
|
||||||
|
"github.com/foomo/tlsconfig"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handler struct{}
|
||||||
|
|
||||||
|
func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte("hello from simplecert!"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// This example demonstrates how spin up a custom HTTPS webserver for production deployment.
|
||||||
|
// It shows how to configure and start your service in a way that the certificate can be automatically renewed via the TLS challenge, before it expires.
|
||||||
|
// For this to succeed, we need to temporarily free port 443 (on which your service is running) and complete the challenge.
|
||||||
|
// Once the challenge has been completed the service will be restarted via the DidRenewCertificate hook.
|
||||||
|
// Requests to port 80 will always be redirected to the TLS secured version of your site.
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
var (
|
||||||
|
// the structure that handles reloading the certificate
|
||||||
|
certReloader *simplecert.CertReloader
|
||||||
|
err error
|
||||||
|
numRenews int
|
||||||
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
// init strict tlsConfig (this will enforce the use of modern TLS configurations)
|
||||||
|
// you could use a less strict configuration if you have a customer facing web application that has visitors with old browsers
|
||||||
|
tlsConf = tlsconfig.NewServerTLSConfig(tlsconfig.TLSModeServerStrict)
|
||||||
|
|
||||||
|
// a simple constructor for a http.Server with our Handler
|
||||||
|
makeServer = func() *http.Server {
|
||||||
|
return &http.Server{
|
||||||
|
Addr: ":443",
|
||||||
|
Handler: Handler{},
|
||||||
|
TLSConfig: tlsConf,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// init server
|
||||||
|
srv = makeServer()
|
||||||
|
|
||||||
|
// init simplecert configuration
|
||||||
|
cfg = simplecert.Default
|
||||||
|
)
|
||||||
|
|
||||||
|
// configure
|
||||||
|
cfg.Domains = []string{"yourdomain.com", "www.yourdomain.com"}
|
||||||
|
cfg.CacheDir = "letsencrypt"
|
||||||
|
cfg.SSLEmail = "you@emailprovider.com"
|
||||||
|
|
||||||
|
// disable HTTP challenges - we will only use the TLS challenge for this example.
|
||||||
|
cfg.HTTPAddress = ""
|
||||||
|
|
||||||
|
// this function will be called just before certificate renewal starts and is used to gracefully stop the service
|
||||||
|
// (we need to free port 443 in order to complete the TLS challenge)
|
||||||
|
cfg.WillRenewCertificate = func() {
|
||||||
|
// stop server
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function will be called after the certificate has been renewed, and is used to restart your service.
|
||||||
|
cfg.DidRenewCertificate = func() {
|
||||||
|
|
||||||
|
numRenews++
|
||||||
|
|
||||||
|
// restart server: both context and server instance need to be recreated!
|
||||||
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
srv = makeServer()
|
||||||
|
|
||||||
|
// force reload the updated cert from disk
|
||||||
|
certReloader.ReloadNow()
|
||||||
|
|
||||||
|
go serve(ctx, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("hello world")
|
||||||
|
|
||||||
|
// init config
|
||||||
|
certReloader, err = simplecert.Init(cfg, func() {
|
||||||
|
os.Exit(0)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("simplecert init failed: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// redirect HTTP to HTTPS
|
||||||
|
log.Println("starting HTTP Listener on Port 80")
|
||||||
|
go http.ListenAndServe(":80", http.HandlerFunc(simplecert.Redirect))
|
||||||
|
|
||||||
|
// enable hot reload
|
||||||
|
tlsConf.GetCertificate = certReloader.GetCertificateFunc()
|
||||||
|
|
||||||
|
// start serving
|
||||||
|
log.Println("will serve at: https://" + cfg.Domains[0])
|
||||||
|
serve(ctx, srv)
|
||||||
|
|
||||||
|
fmt.Println("waiting forever")
|
||||||
|
<-make(chan bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func serve(ctx context.Context, srv *http.Server) {
|
||||||
|
|
||||||
|
// lets go
|
||||||
|
go func() {
|
||||||
|
if err := srv.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed {
|
||||||
|
log.Fatalf("listen: %+s\n", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
log.Printf("server started")
|
||||||
|
<-ctx.Done()
|
||||||
|
log.Printf("server stopped")
|
||||||
|
|
||||||
|
ctxShutDown, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer func() {
|
||||||
|
cancel()
|
||||||
|
}()
|
||||||
|
|
||||||
|
err := srv.Shutdown(ctxShutDown)
|
||||||
|
if err == http.ErrServerClosed {
|
||||||
|
log.Printf("server exited properly")
|
||||||
|
} else if err != nil {
|
||||||
|
log.Printf("server encountered an error on exit: %+s\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user