package module
v0.1.1 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2021 License: MIT Imports: 11 Imported by: 97



A Go library to handle acme-dns client communication and persistent account storage.

CI Status Lint Status Coverage Status Go Report Card

You may also be interested in a Python equivalent, pyacmedns.


Once you have installed Go 1.15+ you can install goacmedns with go get:

 go get github.com/cpu/goacmedns/...


The following is a short example of using the library to update a TXT record served by an acme-dns instance.

package main

import (


const (
	domain = "your.example.org"

var (
	whitelistedNetworks = []string{"", "[::1]/128"}

func main() {
	// Initialize the client. Point it towards your acme-dns instance.
	client := goacmedns.NewClient("https://auth.acme-dns.io")
	// Initialize the storage. If the file does not exist, it will be
	// automatically created.
	storage := goacmedns.NewFileStorage("/tmp/storage.json", 0600)

	// Check if credentials were previously saved for your domain
	account, err := storage.Fetch(domain)
	if err != nil && err != goacmedns.ErrDomainNotFound {
	} else if err == goacmedns.ErrDomainNotFound {
		// The account did not exist. Let's create a new one
		// The whitelisted networks parameter is optional and can be nil
		newAcct, err := client.RegisterAccount(whitelistedNetworks)
		if err != nil {
		// Save it
		err = storage.Put(domain, newAcct)
		if err != nil {
			log.Fatalf("Failed to put account in storage: %v", err)
		err = storage.Save()
		if err != nil {
			log.Fatalf("Failed to save storage: %v", err)
		account = newAcct

	// Update the acme-dns TXT record
	err = client.UpdateTXTRecord(account, "___validation_token_recieved_from_the_ca___")
	if err != nil {


When using goacmedns with an ACME client hook it may be desirable to do the initial ACME-DNS account creation and CNAME delegation ahead of time The goacmedns-register command line utility provides an easy way to do this:

 go install github.com/cpu/goacmedns/...
 goacmedns-register -api -domain example.com -allowFrom,,2002:c0a8:2a00::0/40 -storage /tmp/example.storage.json

This will register an account for example.com that is only usable from the specified CIDR -allowFrom networks with the ACME-DNS server at, saving the account details in /tmp/example.storage.json and printing the required CNAME record for the example.com DNS zone to stdout.




This section is empty.


View Source
var ErrDomainNotFound = errors.New("requested domain is not present in storage")

ErrDomainNotFound is returned from `Fetch` when the provided domain is not present in the storage.


This section is empty.


type Account

type Account struct {
	FullDomain string `json:"fulldomain"`
	SubDomain  string `json:"subdomain"`
	Username   string `json:"username"`
	Password   string `json:"password"`
	// ServerURL contains the URL of the acme-dns server the Account was registered with
	// (may be empty for Account instances registered before this field was added).
	ServerURL string `json:"server_url"`

Account is a struct that holds the registration response from an ACME-DNS server. It represents an API username/key that can be used to update TXT records for the account's subdomain.

type Client

type Client struct {
	// contains filtered or unexported fields

Client is a struct that can be used to interact with an ACME DNS server to register accounts and update TXT records.

func NewClient

func NewClient(url string) Client

NewClient returns a Client configured to interact with the ACME DNS server at the given URL.

func (Client) RegisterAccount

func (c Client) RegisterAccount(allowFrom []string) (Account, error)

RegisterAccount creates an Account with the ACME DNS server. The optional `allowFrom` argument is used to constrain which CIDR ranges can use the created Account.

func (Client) UpdateTXTRecord

func (c Client) UpdateTXTRecord(account Account, value string) error

UpdateTXTRecord updates a TXT record with the ACME DNS server to the `value` provided using the `account` specified.

type ClientError

type ClientError struct {
	// Message is a string describing the client operation that failed
	Message string
	// HTTPStatus is the HTTP status code the ACME DNS server returned
	HTTPStatus int
	// Body is the response body the ACME DNS server returned
	Body []byte

ClientError represents an error from the ACME-DNS server. It holds a `Message` describing the operation the client was doing, a `HTTPStatus` code returned by the server, and the `Body` of the HTTP Response from the server.

func (ClientError) Error

func (e ClientError) Error() string

Error collects all of the ClientError fields into a single string.

type Storage

type Storage interface {
	// Save will persist the `Account` data that has been `Put` so far
	Save() error
	// Put will add an `Account` for the given domain to the storage. It may not
	// be persisted until `Save` is called.
	Put(string, Account) error
	// Fetch will retrieve an `Account` for the given domain from the storage. If
	// the provided domain does not have an `Account` saved in the storage
	// `ErrDomainNotFound` will be returned
	Fetch(string) (Account, error)
	// FetchAll retrieves all the `Account` objects from the storage and
	// returns a map that has domain names as its keys and `Account` objects
	// as values.
	FetchAll() map[string]Account

Storage is an interface describing the required functions for an ACME DNS Account storage mechanism.

func NewFileStorage

func NewFileStorage(path string, mode os.FileMode) Storage

NewFileStorage returns a `Storage` implementation backed by JSON content saved into the provided `path` on disk. The file at `path` will be created if required. When creating a new file the provided `mode` is used to set the permissions.


Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL