package main import ( "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "fmt" "log" "os" "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/certificate" "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/registration" ) // You'll need a user or account type that implements acme.User type MyUser struct { Email string Registration *registration.Resource key crypto.PrivateKey } func (u *MyUser) GetEmail() string { return u.Email } func (u MyUser) GetRegistration() *registration.Resource { return u.Registration } func (u *MyUser) GetPrivateKey() crypto.PrivateKey { return u.key } type DNSProviderBestDNS struct { apiAuthToken string } func NewDNSProviderBestDNS(apiAuthToken string) (*DNSProviderBestDNS, error) { return &DNSProviderBestDNS{apiAuthToken: apiAuthToken}, nil } func (d *DNSProviderBestDNS) Present(domain, token, keyAuth string) error { info := dns01.GetChallengeInfo(domain, keyAuth) fmt.Println() fmt.Println("------") fmt.Println() fmt.Println("Please create DNS TXT record, for domain", info.FQDN, "with these content:") fmt.Println() fmt.Println(info.Value) fmt.Println() fmt.Println("------") fmt.Scanln() // make API request to set a TXT record on fqdn with value and TTL return nil } func (d *DNSProviderBestDNS) CleanUp(domain, token, keyAuth string) error { // clean up any state you created in Present, like removing the TXT record fmt.Println("------") fmt.Println() fmt.Println("you can delete the TXT record, and press enter to continue") fmt.Println() fmt.Println("------") fmt.Scanln() return nil } func main() { if len(os.Args) != 2 { fmt.Println("usage: ./cert root.domain") os.Exit(1) } fmt.Println("root domain is", os.Args[1]) // Create a user. New accounts need an email and private key to start. privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { log.Fatal(err) } var email string fmt.Print("enter you email > ") fmt.Scanln(&email) myUser := MyUser{ Email: email, key: privateKey, } config := lego.NewConfig(&myUser) //config.CADirURL = lego.LEDirectoryStaging config.Certificate.KeyType = certcrypto.RSA2048 // A client facilitates communication with the CA server. client, err := lego.NewClient(config) if err != nil { log.Fatal(err) } bestDNS, err := NewDNSProviderBestDNS("my-auth-token") if err != nil { log.Fatal(err) } err = client.Challenge.SetDNS01Provider(bestDNS) if err != nil { log.Fatal(err) } // New users will need to register reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) if err != nil { log.Fatal(err) } myUser.Registration = reg request := certificate.ObtainRequest{ Domains: []string{os.Args[1], "*." + os.Args[1]}, Bundle: true, } certificates, err := client.Certificate.Obtain(request) if err != nil { log.Fatal(err) } // Each certificate comes back with the cert bytes, the bytes of the client's // private key, and a certificate URL. SAVE THESE TO DISK. os.Mkdir("/etc/ssl", 0777) os.WriteFile("/etc/ssl/cert.crt", certificates.Certificate, 0777) os.WriteFile("/etc/ssl/priv.key", certificates.PrivateKey, 0777) // ... all done. }