• Stars
    star
    202
  • Rank 193,691 (Top 4 %)
  • Language
    Go
  • License
    MIT License
  • Created over 6 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

golang autocert library for letsencrypt
     _                 _                    _
 ___(_)_ __ ___  _ __ | | ___  ___ ___ _ __| |_
/ __| | '_ ` _ \| '_ \| |/ _ \/ __/ _ \ '__| __|
\__ \ | | | | | | |_) | |  __/ (_|  __/ |  | |_
|___/_|_| |_| |_| .__/|_|\___|\___\___|_|   \__|
                |_|

Golang Library for automatic LetsEncrypt SSL Certificates

Go Report Card License Golang Linux macOS windows GoDoc

Obtains certificates automatically, and manages renewal and hot reload for your Golang application. It uses the LEGO Library to perform ACME challenges, and the mkcert utility to generate self-signed trusted certificates for local development.

Main goals:

  • ease of use: simplicity and integration with go standard library
  • transparency: products of intermediate steps are preserved, dedicated logfile for simplecert
  • flexibility: configurable design and cross platform support

UPDATE: The vendored lego version has been updated to v2.2.0 and now supports issuing wildcard certificates by using ACMEv2 challenges.

You need to supply the following data to simplecert: Domains, Contact Email and a Directory to store the certs in (CacheDir). On startup, call the simplecert.Init() function and pass your config. You will receive a certReloader instance, that has a GetCertificateFunc to allow hot reloading the cert upon renewal. See Usage for a detailed example.

A new certificate will be obtained automatically if the domains have changed, both in local and in production mode.

For more advanced usage, see the config section for all configuration options.

Index

Install

go get -u -v github.com/foomo/simplecert

API

Simplecert provides a few wrappers similar to http.ListenAndServe from the go standard library:

For running on a production server:

func ListenAndServeTLS(addr string, handler http.Handler, mail string, cleanup func(), domains ...string) error

For local development:

func ListenAndServeTLSLocal(addr string, handler http.Handler, cleanup func(), domains ...string) error

The custom wrapper allows to pass a simplecert.Config and a tls.Config:

func ListenAndServeTLSCustom(addr string, handler http.Handler, cfg *Config, tlsconf *tls.Config, cleanup func(), domains ...string) error

There is a util for redirecting HTTP requests to HTTPS:

func Redirect(w http.ResponseWriter, req *http.Request)

And a function to initialize simplecert after applying the desired configuration:

func Init(cfg *Config, cleanup func()) (*CertReloader, error)

The cleanup function will be called upon receiving the syscall.SIGINT or syscall.SIGABRT signal and can be used to stop your backend gracefully. If you don't need it, simpy pass nil.

Local Development

To make local development less of a pain, simplecert integrates mkcert, to obtain self signed certificates for your desired domains, trusted by your computer.

Follow the installation instructions to install the mkcert commandline tool.

In order to use simplecert for local development, set the Local field in the config to true.

Certificates generated for local development are not checked for expiry, the certificates generated by mkcert are valid for 10 years!

Important:

Using wildcard certificates in local mode does not work out of the box, since /etc/hosts doesn't support resolving wild card entries.

You'll have to use other services like dnsmasq. Just edit dnsmasq.conf and add the following line:

address=/yourdomain.com/127.0.0.1

This will resolve all requests to domains that end on yourdomain.com with 127.0.0.1.

Host Entries

To resolve the domain name for your certificate to your localhost, simplecert adds an entry for each domain name to your /etc/hosts file.

This can be disabled by setting the UpdateHosts field in the config to false.

Usage

Simplecert has a default configuration available: simplecert.Default

You will need to update the Domains, CacheDir and SSLEmail and you are ready to go.

// do the cert magic
cfg := simplecert.Default
cfg.Domains = []string{"yourdomain.com", "www.yourdomain.com"}
cfg.CacheDir = "/etc/letsencrypt/live/yourdomain.com"
cfg.SSLEmail = "[email protected]"
cfg.DNSProvider = "cloudflare"
certReloader, err := simplecert.Init(cfg, nil)
if err != nil {
    log.Fatal("simplecert init failed: ", err)
}

// redirect HTTP to HTTPS
// CAUTION: This has to be done AFTER simplecert setup
// Otherwise Port 80 will be blocked and cert registration fails!
log.Println("starting HTTP Listener on Port 80")
go http.ListenAndServe(":80", http.HandlerFunc(redirect))

// init strict tlsConfig with certReloader
// you could also use a default &tls.Config{}, but be warned this is highly insecure
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,
}

// lets go
log.Fatal(s.ListenAndServeTLS("", ""))

Challenges

Simplecert uses the letsencrypt ACMEv2 API and supports HTTP, TLS and DNS Challenges.

For the DNS challenge, an API token of an provider must be exported as environment variable.

Graceful service shutdown and restart

In case of using the HTTP or TLS challenges, port 80 or 443 must temporarily be freed.

The simplecert.Config contains two functions that can be set to accomplish this:

  • WillRenewCertificate, called just before the certificate will be renewed.
  • DidRenewCertificate, called after the certificate was renewed.

These functions can be used to gracefully stop the running service, and bring it back up once the certificate renewal is complete.

If you want to exchange the certificates manually on disk and force the running service to reload them, simply send a SIGHUP signal to your running instance:

kill -HUP <pid>

Backup mechanism

Simplecert creates a backup of your old certificate when it is being renewed.

All data is stored in the configured CacheDir.

In case something goes wrong while renewing, simplecert will rollback to the original cert.

Configuration

You can pass a custom simplecert.Config to suit your needs.

Parameters are explained below.

// Config allows configuration of simplecert
type Config struct {

    // renew the certificate X hours before it expires
    // LetsEncrypt Certs are valid for 90 Days
    RenewBefore int

    // Interval for checking if cert is closer to expiration than RenewBefore
    CheckInterval time.Duration

    // SSLEmail for contact
    SSLEmail string

    // ACME Directory URL. 
    // Can be set to https://acme-staging.api.letsencrypt.org/directory for testing
    DirectoryURL string

    // Endpoints for webroot challenge
    // CAUTION: challenge must be received on port 80 and 443
    // if you choose different ports here you must redirect the traffic
    HTTPAddress string
    TLSAddress  string

    // UNIX Permission for the CacheDir and all files inside
    CacheDirPerm os.FileMode

    // Domains for which to obtain the certificate
    Domains []string

    // Path of the CacheDir
    CacheDir string

    // DNSProvider name for DNS challenges (optional)
    // see: https://godoc.org/github.com/go-acme/lego/providers/dns
    DNSProvider string

    // Local runmode
    Local bool

    // UpdateHosts adds the domains to /etc/hosts if running in local mode
    UpdateHosts bool

    // Handler funcs for graceful service shutdown and restoring
    WillRenewCertificate func()
    DidRenewCertificate  func()
    FailedToRenewCertificate func(error)
}

Examples

The examples directory contains two simple use cases.

A custom initialization:

go run examples/custom/main.go

And a simple example for local development with a locally trusted certificate (requires mkcert to be installed):

go run examples/simple/main.go

Debug

Simplecert writes all its logs to the simplecert.log file inside the configured cache directory.

It will contain information about certificate status and renewal, as well as errors that occured.

Troubleshooting

  • If you get an error that looks like the following during obtaining a certificate, please check your firewall configuration, and ensure the ports for performing the challenge (HTTP: 80, TLS: 443, DNS: 53) are reachable from the outside world.
urn:ietf:params:acme:error:connection :: Timeout during connect (likely firewall problem), url: ...
  • Dependency errors

The LEGO package imports various api clients for providing the DNS challenges - unfortunately this leads to frequent incompatibilities, in code that is not under our control. 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.

  • 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

MIT

More Repositories

1

pagespeed_exporter

Prometheus pagespeed exporter
Go
224
star
2

htpasswd

golang htpasswd utilities
Go
39
star
3

tlssocks

secure socks5 over tls / tcp
Go
26
star
4

gotsrpc

Go TypeScript RPC - expose Go code over http JSON RPC to TypeScript clients, oh and gorpc is much easier with this too
Go
25
star
5

soap

SOAP is dead, long live SOAP
Go
23
star
6

shop

generic ecommerce core framework
Go
19
star
7

gocontentful

An Contentful Entry-Reference Mapper for Go
Go
9
star
8

keel

Opinionated k8s service framework.
Go
8
star
9

contentserver

Serves content tree structures very quickly through a json socket api
Go
8
star
10

petze

monitor web services and report, if they are not working
Go
5
star
11

logfrog

cli program, that likes json logs and it helps you to like them too
Go
4
star
12

squadron

K8s Deployment Manager App
Go
4
star
13

config-bob

build configs. mixin secrets.
Go
3
star
14

crontinuous

Crontinuous is a time-based job scheduler for docker.
Go
2
star
15

Foomo.TestRunner

Foomo phpUnit module
PHP
2
star
16

Foomo.Services

Foomo services module
PHP
2
star
17

Sandbox

Foomo sandbox project to get your hands dirty fast
PHP
2
star
18

Foomo.Docs

Foomo docs module
PHP
2
star
19

Foomo.Theme

Foomo theme module
PHP
2
star
20

Foomo.Zugspitze

Foomo Zugspitze flash / flex client framework integration module
PHP
2
star
21

Foomo.Doctrine2

Foomo doctrine2 module
PHP
2
star
22

Foomo

Foomo core module
PHP
2
star
23

Foomo.Flash

Foomo flash module
PHP
2
star
24

walker

walks websites
Go
2
star
25

neosproxy

A NEOS proxy with support for the Foomo.Neos.Contentserver package
Go
2
star
26

fender

Opinionated validation library.
Go
2
star
27

ownbrew

Your local project package manager
Go
1
star
28

Foomo.ContentServer

php client for the go content server
PHP
1
star
29

go

Go standard library extension, adding the missing parts used in the foomo ecosystem to keep dry.
Go
1
star
30

Foomo.ElasticSearch

PHP
1
star
31

ASLibrary-foomo_mx

ActionScript
1
star
32

nodeflock

run node processes and talk to them
Go
1
star
33

FlexProject-zugspitze_as3Examples

ActionScript
1
star
34

ASLibrary-zugspitze_core

ActionScript
1
star
35

ASLibrary-zugspitze_as3

ActionScript
1
star
36

tlsconfig

tls configuration utilities
Go
1
star
37

FlexProject-foomo_examples_todo

Client application for Foomo.Todo
ActionScript
1
star
38

contentfulcommander

A toolbox of non-trivial Contentful interactions
Go
1
star
39

gograpple

go grapple that go program ...
Go
1
star
40

ASLibrary-foomo_spark

Common spark library
ActionScript
1
star
41

FlexProject-zugspitze_mxExamples

ActionScript
1
star
42

Foomo.Wordpress

Wordpress integration module
PHP
1
star
43

ASLibrary-foomo_air

Common air library
ActionScript
1
star
44

dumpster

dump project data and restore them
Go
1
star
45

foomo-releaser

Go
1
star
46

FlexProject-zugspitze_services_uploadExamples

ActionScript
1
star
47

ASLibrary-zugspitze_services_logger

Service and utility classes for client logging
ActionScript
1
star
48

ASLibrary-zugspitze_mx

ActionScript
1
star
49

ASLibrary-zugspitze_mobile

ActionScript
1
star
50

ASLibrary-foomo_as3

Common as3 library
ActionScript
1
star
51

ssiege

http benchmarking and load testing utility with session support
Go
1
star
52

ASLibrary-foomo_rpc

ActionScript
1
star
53

ASLibrary-foomo_core

ActionScript
1
star
54

FlexProject-zugspitze_mobileExamples

ActionScript
1
star
55

terradays

Terraform utility, cause even the good ones need a couple of days to create a planet
Go
1
star
56

ASLibrary-zugspitze_spark

ActionScript
1
star
57

ASLibrary-zugspitze_rpc

ActionScript
1
star
58

FlexProject-zugspitze_sparkExamples

ActionScript
1
star
59

sesamy-cli

Server Side Tag Management System CLI
Go
1
star
60

ASLibrary-zugspitze_air_spark

ActionScript
1
star
61

FlexProject-zugspitze_air_sparkExamples

ActionScript
1
star
62

Foomo.Examples

Example module
PHP
1
star
63

variant-balancer

web load balancer with support for variants
Go
1
star
64

webgrapple

a proxy to take over routes of a remote server with local web servers
Go
1
star
65

FlexProject-zugspitze_services_loggerExamples

Logger serivce examples
ActionScript
1
star
66

ASLibrary-zugspitze_services_upload

ActionScript
1
star
67

posh

Project Oriented SHELL
Go
1
star
68

foomo-docs

docs for the bestbytes foomo stack
MDX
1
star
69

posh-providers

Project Oriented SHELL (posh) Providers
Go
1
star
70

ASLibrary-zugspitze_air_mx

ActionScript
1
star