# Golang example using DNS verification

**URL:** <https://community.letsencrypt.org/t/golang-example-using-dns-verification/81696>\
**Category:** Client dev\
**Created:** [January 5, 2019, 10:29pm UTC](https://community.letsencrypt.org/t/golang-example-using-dns-verification/81696 "2019-01-05T22:29:26Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![digininja](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/digininja/32/28643_2.png) [@digininja](https://community.letsencrypt.org/u/digininja)\
**Post date:** [January 5, 2019, 10:29pm UTC](https://community.letsencrypt.org/t/golang-example-using-dns-verification/81696/1 "2019-01-05T22:29:26Z")

</div>

I’m trying to find a working example of using the ACME protocol with DNS validation in Go. I’ve found loads of examples using HTTP but none with DNS. Does anyone have any working code or any good examples of it in action?

I’ve read the GoDoc for the package but it doesn’t really help.

---

<div class="post-metadata">

**Author:** ![\_az](https://avatars.discourse-cdn.com/v4/letter/_/22d042/32.png) [@\_az](https://community.letsencrypt.org/u/_az)\
**Post date:** [January 5, 2019, 10:55pm UTC](https://community.letsencrypt.org/t/golang-example-using-dns-verification/81696/2 "2019-01-05T22:55:50Z")

</div>

> [@digininja](#):
>
> I’ve read the GoDoc for the package

Which package? The /x/crypto/acme one only supports ACME v1, which doesn't have wildcard support. Try `github.com/eggsampler/acme` or `github.com/xenolf/lego` for ACME v2 libraries.

But even with the v1 package, it's a very minor change to use the DNS challenge.

```go
package main

import (
	"context"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"log"

	"golang.org/x/crypto/acme"
)

func main() {

	// All the usual account registration prelude
	accountKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)

	client := &acme.Client{
		Key: accountKey,
		DirectoryURL: "https://acme-v01.api.letsencrypt.org/directory",
	}

	if _, err := client.Register(context.Background(), &acme.Account{},
		func(tos string) bool {
			log.Printf("Agreeing to ToS: %s", tos)
			return true
		}); err != nil {
		log.Fatal("Can't register an ACME account: ", err)
	}

	// Authorize a DNS name
	authz, err := client.Authorize(context.Background(), "example.org")
	if err != nil {
		log.Fatal("Can't authorize: ", err)
	}

	// Find the DNS challenge for this authorization
	var chal *acme.Challenge
	for _, c := range authz.Challenges {
		if c.Type == "dns-01" {
			chal = c
			break
		}
	}
	if chal == nil {
		log.Fatal("No DNS challenge was present")
	}

	// Determine the TXT record values for the DNS challenge
	txtLabel := "_acme-challenge." + authz.Identifier.Value
	txtValue, _ := client.DNS01ChallengeRecord(chal.Token)
	log.Printf("Creating record %s with value %s", txtLabel, txtValue)

	// Then the usual: accept the challenge, wait for the authorization ...
	if _, err := client.Accept(context.Background(), chal); err != nil {
		log.Fatal("Can't accept challenge: ", err)
	}

	if _, err := client.WaitAuthorization(context.Background(), authz.URI); err != nil {
		log.Fatal("Failed authorization: ", err)
	}

	// Submit certificate request if it suceeded ...
}

```

---

<div class="post-metadata">

**Author:** ![digininja](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/digininja/32/28643_2.png) [@digininja](https://community.letsencrypt.org/u/digininja)\
**Post date:** [January 6, 2019, 10:02am UTC](https://community.letsencrypt.org/t/golang-example-using-dns-verification/81696/3 "2019-01-06T10:02:29Z")

</div>

This is brilliant, thanks, it was the x/crypto library I was looking at.

I don’t need wildcards so is there any need to go to version 2? I’m only working on a fairly simple proof of concept that doesn’t need a long lifespan so I think I’ll probably be OK.

---

<div class="post-metadata">

**Author:** ![\_az](https://avatars.discourse-cdn.com/v4/letter/_/22d042/32.png) [@\_az](https://community.letsencrypt.org/u/_az)\
**Post date:** [January 6, 2019, 10:08am UTC](https://community.letsencrypt.org/t/golang-example-using-dns-verification/81696/4 "2019-01-06T10:08:28Z")

</div>

> [@digininja](#):
>
> any need to go to version 2

Not sure. There's no public plan to deprecate the v1 API, but using it for new integrations is "discouraged". I'd guess that it's going to be around for a few more years yet.

---

<div class="post-metadata">

**Author:** ![digininja](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/digininja/32/28643_2.png) [@digininja](https://community.letsencrypt.org/u/digininja)\
**Post date:** [January 6, 2019, 10:49am UTC](https://community.letsencrypt.org/t/golang-example-using-dns-verification/81696/5 "2019-01-06T10:49:37Z")

</div>

If the project lasts beyond six months then it has taken off and will need a rewrite to make it more production ready anyway so I don’t need to worry about deprecation at the moment.

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/letsencrypt/original/3X/c/a/ca6c06ea1ea201324bba7048c6841ce60236468d.png) [@system](https://community.letsencrypt.org/u/system)\
**Post date:** [February 5, 2019, 10:52am UTC](https://community.letsencrypt.org/t/golang-example-using-dns-verification/81696/6 "2019-02-05T10:52:06Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
