mirror of
https://github.com/go-acme/lego
synced 2026-03-14 14:35:48 +01:00
Automatic generation of documentation (#818)
* generate a detailed CLI help * generate a documentation site * new readme
This commit is contained in:
parent
235ab6653f
commit
62fea05e21
152 changed files with 9535 additions and 579 deletions
8
docs/content/usage/_index.md
Normal file
8
docs/content/usage/_index.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
title: "Usage"
|
||||
date: 2019-03-03T16:39:46+01:00
|
||||
draft: false
|
||||
weight: 2
|
||||
---
|
||||
|
||||
{{%children style="h2" description="true" %}}
|
||||
94
docs/content/usage/cli/_index.md
Normal file
94
docs/content/usage/cli/_index.md
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
---
|
||||
title: "CLI"
|
||||
date: 2019-03-03T16:39:46+01:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
Lego can be use as a CLI.
|
||||
|
||||
<!--more-->
|
||||
|
||||
## Usage
|
||||
|
||||
{{%expand "CLI help" %}}
|
||||
```slim
|
||||
NAME:
|
||||
lego - Let's Encrypt client written in Go
|
||||
|
||||
USAGE:
|
||||
lego [global options] command [command options] [arguments...]
|
||||
|
||||
COMMANDS:
|
||||
run Register an account, then create and install a certificate
|
||||
revoke Revoke a certificate
|
||||
renew Renew a certificate
|
||||
dnshelp Shows additional help for the --dns global option
|
||||
list Display certificates and accounts information.
|
||||
help, h Shows a list of commands or help for one command
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--domains value, -d value Add a domain to the process. Can be specified multiple times.
|
||||
--server value, -s value CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "https://acme-v02.api.letsencrypt.org/directory")
|
||||
--accept-tos, -a By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.
|
||||
--email value, -m value Email used for registration and recovery contact.
|
||||
--csr value, -c value Certificate signing request filename, if an external CSR is to be used.
|
||||
--eab Use External Account Binding for account registration. Requires --kid and --hmac.
|
||||
--kid value Key identifier from External CA. Used for External Account Binding.
|
||||
--hmac value MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.
|
||||
--key-type value, -k value Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384. (default: "rsa2048")
|
||||
--filename value (deprecated) Filename of the generated certificate.
|
||||
--path value Directory to use for storing the data. (default: "./.lego")
|
||||
--http Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges.
|
||||
--http.port value Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port. (default: ":80")
|
||||
--http.webroot value Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge.
|
||||
--http.memcached-host value Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.
|
||||
--tls Use the TLS challenge to solve challenges. Can be mixed with other types of challenges.
|
||||
--tls.port value Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port. (default: ":443")
|
||||
--dns value Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.
|
||||
--dns.disable-cp By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers.
|
||||
--dns.resolvers value Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.
|
||||
--http-timeout value Set the HTTP timeout value to a specific value in seconds. (default: 0)
|
||||
--dns-timeout value Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries. (default: 10)
|
||||
--pem Generate a .pem file by concatenating the .key and .crt files together.
|
||||
--cert.timeout value Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates. (default: 30)
|
||||
--help, -h show help
|
||||
--version, -v print the version
|
||||
```
|
||||
{{% /expand%}}
|
||||
|
||||
|
||||
When using the standard `--path` option, all certificates and account configurations are saved to a folder `.lego` in the current working directory.
|
||||
|
||||
|
||||
## Let's Encrypt ACME server
|
||||
|
||||
lego defaults to communicating with the production Let's Encrypt ACME server.
|
||||
If you'd like to test something without issuing real certificates, consider using the staging endpoint instead:
|
||||
|
||||
```bash
|
||||
lego --server=https://acme-staging-v02.api.letsencrypt.org/directory …
|
||||
```
|
||||
|
||||
## Sudo
|
||||
|
||||
The CLI does not require root permissions but needs to bind to port 80 and 443 for certain challenges.
|
||||
To run the CLI without sudo, you have four options:
|
||||
|
||||
- Use setcap 'cap_net_bind_service=+ep' /path/to/program
|
||||
- Pass the `--http.port` or/and the `--tls.port` option and specify a custom port to bind to. In this case you have to forward port 80/443 to these custom ports (see [Port Usage](usage/cli#port-usage)).
|
||||
- Pass the `--http.webroot` option and specify the path to your webroot folder. In this case the challenge will be written in a file in `.well-known/acme-challenge/` inside your webroot.
|
||||
- Pass the `--dns` option and specify a DNS provider.
|
||||
|
||||
## Port Usage
|
||||
|
||||
By default lego assumes it is able to bind to ports 80 and 443 to solve challenges.
|
||||
If this is not possible in your environment, you can use the `--http.port` and `--tls.port` options to instruct
|
||||
lego to listen on that interface:port for any incoming challenges.
|
||||
|
||||
If you are using this option, make sure you proxy all of the following traffic to these ports.
|
||||
|
||||
**HTTP Port:** All plaintext HTTP requests to port **80** which begin with a request path of `/.well-known/acme-challenge/` for the HTTP challenge.
|
||||
|
||||
**TLS Port:** All TLS handshakes on port **443** for the TLS-ALPN challenge.
|
||||
|
||||
This traffic redirection is only needed as long as lego solves challenges. As soon as you have received your certificates you can deactivate the forwarding.
|
||||
48
docs/content/usage/cli/examples.md
Normal file
48
docs/content/usage/cli/examples.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
title: "Examples"
|
||||
date: 2019-03-03T16:39:46+01:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
## CLI Examples
|
||||
|
||||
Assumes the `lego` binary has permission to bind to ports 80 and 443.
|
||||
You can get a pre-built binary from the [releases](https://github.com/xenolf/lego/releases) page.
|
||||
If your environment does not allow you to bind to these ports, please read [Port Usage](usage/cli#port-usage).
|
||||
|
||||
### Obtain a certificate
|
||||
|
||||
```bash
|
||||
lego --email="foo@bar.com" --domains="example.com" --http run
|
||||
```
|
||||
|
||||
(Find your certificate in the `.lego` folder of current working directory.)
|
||||
|
||||
### To renew the certificate
|
||||
|
||||
```bash
|
||||
lego --email="foo@bar.com" --domains="example.com" --http renew
|
||||
```
|
||||
|
||||
### To renew the certificate only if it expires within 45 days
|
||||
|
||||
```bash
|
||||
lego --email="foo@bar.com" --domains="example.com" --http renew --days 45
|
||||
```
|
||||
|
||||
### Obtain a certificate using the DNS challenge
|
||||
|
||||
```bash
|
||||
AWS_REGION=us-east-1 \
|
||||
AWS_ACCESS_KEY_ID=my_id \
|
||||
AWS_SECRET_ACCESS_KEY=my_key \
|
||||
lego --email="foo@bar.com" --domains="example.com" --dns="route53" run
|
||||
```
|
||||
|
||||
### Obtain a certificate given a certificate signing request (CSR) generated by something else
|
||||
|
||||
```bash
|
||||
lego --email="foo@bar.com" --http --csr=/path/to/csr.pem run
|
||||
```
|
||||
|
||||
(lego will infer the domains to be validated based on the contents of the CSR, so make sure the CSR's Common Name and optional SubjectAltNames are set correctly.)
|
||||
103
docs/content/usage/library/Writing-a-Challenge-Solver.md
Normal file
103
docs/content/usage/library/Writing-a-Challenge-Solver.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
---
|
||||
title: "Writing a Challenge Solver"
|
||||
date: 2019-03-03T16:39:46+01:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
Lego can solve multiple ACME challenge types out of the box, but sometimes you have custom requirements.
|
||||
|
||||
<!--more-->
|
||||
|
||||
For example, you may want to write a solver for the DNS-01 challenge that works with a different DNS provider (lego already supports CloudFlare, AWS, DigitalOcean, and others).
|
||||
|
||||
The DNS-01 challenge is advantageous when other challenge types are impossible.
|
||||
For example, the HTTP-01 challenge doesn't work well behind a load balancer or CDN and the TLS-ALPN-01 challenge breaks behind TLS termination.
|
||||
|
||||
But even if using HTTP-01 or TLS-ALPN-01 challenges, you may have specific needs that lego does not consider by default.
|
||||
|
||||
You can write something called a `challenge.Provider` that implements [this interface](https://godoc.org/github.com/xenolf/lego/challenge#Provider):
|
||||
|
||||
```go
|
||||
type Provider interface {
|
||||
Present(domain, token, keyAuth string) error
|
||||
CleanUp(domain, token, keyAuth string) error
|
||||
}
|
||||
```
|
||||
|
||||
This provides the means to solve a challenge.
|
||||
First you present a token to the ACME server in a way defined by the challenge type you're solving for, then you "clean up" after the challenge finishes.
|
||||
|
||||
## Writing a challenge.Provider
|
||||
|
||||
Pretend we want to write our own DNS-01 challenge provider (other challenge types have different requirements but the same principles apply).
|
||||
|
||||
This will let us prove ownership of domain names parked at a new, imaginary DNS service called BestDNS without having to start our own HTTP server.
|
||||
BestDNS has an API that, given an authentication token, allows us to manipulate DNS records.
|
||||
|
||||
This simplistic example has only one field to store the auth token, but in reality you may need to keep more state.
|
||||
|
||||
```go
|
||||
type DNSProviderBestDNS struct {
|
||||
apiAuthToken string
|
||||
}
|
||||
```
|
||||
|
||||
We should provide a constructor that returns a *pointer* to the `struct`.
|
||||
This is important in case we need to maintain state in the `struct`.
|
||||
|
||||
```go
|
||||
func NewDNSProviderBestDNS(apiAuthToken string) (*DNSProviderBestDNS, error) {
|
||||
return &DNSProviderBestDNS{apiAuthToken: apiAuthToken}, nil
|
||||
}
|
||||
```
|
||||
|
||||
Now we need to implement the interface.
|
||||
We'll start with the `Present` method.
|
||||
You'll be passed the `domain` name for which you're proving ownership, a `token`, and a `keyAuth` string.
|
||||
How your provider uses `token` and `keyAuth`, or if you even use them at all, depends on the challenge type.
|
||||
For DNS-01, we'll just use `domain` and `keyAuth`.
|
||||
|
||||
```go
|
||||
func (d *DNSProviderBestDNS) Present(domain, token, keyAuth string) error {
|
||||
fqdn, value := dns01.GetRecord(domain, keyAuth)
|
||||
// make API request to set a TXT record on fqdn with value and ttl
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
After calling `dns01.GetRecord(domain, keyAuth)`, we now have the information we need to make our API request and set the TXT record:
|
||||
- `fqdn` is the fully qualified domain name on which to set the TXT record.
|
||||
- `value` is the record's value to set on the record.
|
||||
|
||||
So then you make an API request to the DNS service according to their docs.
|
||||
Once the TXT record is set on the domain, you may return and the challenge will proceed.
|
||||
|
||||
The ACME server will then verify that you did what it required you to do, and once it is finished, lego will call your `CleanUp` method.
|
||||
In our case, we want to remove the TXT record we just created.
|
||||
|
||||
```go
|
||||
func (d *DNSProviderBestDNS) CleanUp(domain, token, keyAuth string) error {
|
||||
// clean up any state you created in Present, like removing the TXT record
|
||||
}
|
||||
```
|
||||
|
||||
In our case, we'd just make another API request to have the DNS record deleted; no need to keep it and clutter the zone file.
|
||||
|
||||
## Using your new challenge.Provider
|
||||
|
||||
To use your new challenge provider, call [`client.Challenge.SetDNS01Provider`](https://godoc.org/github.com/xenolf/lego/challenge/resolver#SolverManager.SetDNS01Provider) to tell lego, "For this challenge, use this provider".
|
||||
In our case:
|
||||
|
||||
```go
|
||||
bestDNS, err := NewDNSProviderBestDNS("my-auth-token")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client.Challenge.SetDNS01Provider(bestDNS)
|
||||
```
|
||||
|
||||
Then, when this client tries to solve the DNS-01 challenge, it will use our new provider, which sets TXT records on a domain name hosted by BestDNS.
|
||||
|
||||
That's really all there is to it.
|
||||
Go make awesome things!
|
||||
115
docs/content/usage/library/_index.md
Normal file
115
docs/content/usage/library/_index.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
---
|
||||
title: "Library"
|
||||
date: 2019-03-03T16:39:46+01:00
|
||||
draft: false
|
||||
---
|
||||
|
||||
Lego can be use as a Go Library.
|
||||
|
||||
<!--more-->
|
||||
|
||||
## GoDoc
|
||||
|
||||
The GoDoc can be found here: [GoDoc](https://godoc.org/github.com/xenolf/lego/acme)
|
||||
|
||||
## Usage
|
||||
|
||||
A valid, but bare-bones example use of the acme package:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/xenolf/lego/certcrypto"
|
||||
"github.com/xenolf/lego/certificate"
|
||||
"github.com/xenolf/lego/challenge/http01"
|
||||
"github.com/xenolf/lego/challenge/tlsalpn01"
|
||||
"github.com/xenolf/lego/lego"
|
||||
"github.com/xenolf/lego/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
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
myUser := MyUser{
|
||||
Email: "you@yours.com",
|
||||
key: privateKey,
|
||||
}
|
||||
|
||||
config := lego.NewConfig(&myUser)
|
||||
|
||||
// This CA URL is configured for a local dev instance of Boulder running in Docker in a VM.
|
||||
config.CADirURL = "http://192.168.99.100:4000/directory"
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
|
||||
// A client facilitates communication with the CA server.
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// We specify an http port of 5002 and an tls port of 5001 on all interfaces
|
||||
// because we aren't running as root and can't bind a listener to port 80 and 443
|
||||
// (used later when we attempt to pass challenges). Keep in mind that you still
|
||||
// need to proxy challenge traffic to port 5002 and 5001.
|
||||
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "5002"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "5001"))
|
||||
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{"mydomain.com"},
|
||||
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.
|
||||
fmt.Printf("%#v\n", certificates)
|
||||
|
||||
// ... all done.
|
||||
}
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue