Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support autocert #267

Closed
wants to merge 1 commit into from
Closed

feat: support autocert #267

wants to merge 1 commit into from

Conversation

mthli
Copy link

@mthli mthli commented Apr 8, 2020

Golang has a package called autocert which provides automatic access to certificates from Let's Encrypt and any other ACME-based CA. Since Let鈥檚 Encrypt certificates are valid for 90 days , automatic renew certificates is very convenient.

I want to use autocert with fiber but this issue #200 didn't completely solve my problem. So I adapted autocert to fiber by myself, and it works really nice. I think it's time to create a PR to this project.

This sample code shows how this PR works:

package main

import (
	"log"

	"github.com/gofiber/fiber"
	"golang.org/x/crypto/acme/autocert"
)

...

func run(app *fiber.Fiber) {
	// Initialize the autocert.Manager m's Cache, HostPolicy, Prompt, 
	// and other desired options by yourself.
	m := &autocert.Manager{
		Prompt:     autocert.AcceptTOS,
		HostPolicy: autocert.HostWhitelist("yourDomain"),
		Cache:      autocert.DirCache("yourCertsDirPath"),
	}

	// Then just call ListenAutoTLS.
	err := app.ListenAutoTLS(443, m)
	if err != nil {
		log.Fatal(err)
	}
}

馃嵒

@welcome
Copy link

welcome bot commented Apr 8, 2020

Thanks for opening this pull request! 馃帀 Please check out our contributing guidelines. If you want to chat with us, join ons on Telegram https://t.me/gofiber

@renanbastos93
Copy link
Member

Golang has a package called autocert which provides automatic access to certificates from Let's Encrypt and any other ACME-based CA. Since Let鈥檚 Encrypt certificates are valid for 90 days , automatic renew certificates is very convenient.

I want to use autocert with fiber but this issue #200 didn't completely solve my problem. So I adapted autocert to fiber by myself, and it works really nice. I think it's time to create a PR to this project.

This sample code shows how this PR works:

package main

import (
	"log"

	"github.com/gofiber/fiber"
	"golang.org/x/crypto/acme/autocert"
)

...

func run(app *fiber.Fiber) {
	// Initialize the autocert.Manager m's Cache, HostPolicy, Prompt, 
	// and other desired options by yourself.
	m := &autocert.Manager{
		Prompt:     autocert.AcceptTOS,
		HostPolicy: autocert.HostWhitelist("yourDomain"),
		Cache:      autocert.DirCache("yourCertsDirPath"),
	}

	// Then just call ListenAutoTLS.
	err := app.ListenAutoTLS(443, m)
	if err != nil {
		log.Fatal(err)
	}
}

馃嵒

it seems good to me, but I have a question.

Do you want to say that to make renew certs using lib acme, right?

@mthli
Copy link
Author

mthli commented Apr 8, 2020

@renanbastos93 Yes, renew certs using lib instead of manual. Another Go web framework called echo also use autocert to automatic renew certs, see it's doc Auto TLS Recipe.

@renanbastos93
Copy link
Member

@renanbastos93 Yes, renew certs using lib instead of manual. Another Go web framework called echo also use autocert to automatic renew certs, see it's doc Auto TLS Recipe.

How nice, I will review your code

Copy link
Member

@renanbastos93 renanbastos93 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Fenny
Copy link
Member

Fenny commented Apr 9, 2020

@mthli, Listen accepts a *tls.Config argument. So the following example should do the job, if you could confirm it works I can add it to the recipes repo 馃憤

package main

import (
    "crypto/tls"

    "github.com/gofiber/fiber"
    "golang.org/x/crypto/acme/autocert"
)

func main() {
    app := fiber.New()

    app.Get("/", func(c *fiber.Ctx) {
        c.Send("Hi TLS")
    })

    m := &autocert.Manager{
        Prompt:     autocert.AcceptTOS,
        HostPolicy: autocert.HostWhitelist("example.com"),
        Cache:      autocert.DirCache("./certs"),
    }

    tls := &tls.Config{
        GetCertificate: m.GetCertificate,
    }

    app.Listen(443, tls)
}

@mthli
Copy link
Author

mthli commented Apr 9, 2020

@Fenny the following code will work:

package main

import (
	"crypto/tls"
	"log"

	"github.com/gofiber/fiber"
	"golang.org/x/crypto/acme"
	"golang.org/x/crypto/acme/autocert"
)

func main() {
	app := fiber.New()

	app.Get("/", func(c *fiber.Ctx) {
		c.Send("Hi TLS")
	})

	m := &autocert.Manager{
		Prompt:     autocert.AcceptTOS,
		HostPolicy: autocert.HostWhitelist("example.com"), // replaced with your domain.
		Cache:      autocert.DirCache("./certs"),
	}

	tls := &tls.Config{
		GetCertificate: m.GetCertificate,
		// Must add acme.ALPNProto to NextProtos for TLS-ALPN-01.
		// Or just use m.TLSConfig() and remove it's NextProtos "h2" string.
		NextProtos: []string{
			"http/1.1", acme.ALPNProto,
		},
	}

	err := app.Listen(443, tls)
	if err != nil {
		log.Fatal(err)
	}
}

Since Let鈥檚 Encrypt has rate limits, it's recommended to use it's staging environment to test the code, see the doc Staging Environment. Here are some brief test steps:

  1. Open the package source code autocert.go , change DefaultACMEDirectory value to https://acme-staging-v02.api.letsencrypt.org/directory and save.
  2. Exec go build -a to force rebuilding all packages in your VPS.
  3. Download the staging environment intermediate certificate from the doc to your computer, add it to your computer trust store.
  4. Open a browser to visit your domain, you will see Hi LTS string.

Also, move to the recipes repo should be a better choice 馃槃

@Fenny
Copy link
Member

Fenny commented Apr 9, 2020

@mthli Awesome, I added it to the recipes :-)
https://github.com/gofiber/recipes/blob/master/autocert/main.go

@Fenny Fenny closed this Apr 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants