Compare commits

..

51 commits

Author SHA1 Message Date
Ludovic Fernandez
87b172f103
gigahostno: remove unused Zone fields (#2913) 2026-03-12 21:27:46 +01:00
exsesa
9be8cd43ae
Add DNS provider for Excedo (#2910)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2026-03-10 22:58:13 +01:00
Dane
7b1aa50081
safedns: rename UKFast SafeDNS to ANS SafeDNS (#2877)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2026-03-08 23:02:14 +00:00
Ludovic Fernandez
a56697ed1c
Add DNS provider for EuroDNS (#2898) 2026-03-08 23:32:56 +01:00
Ludovic Fernandez
847c763504
feat: Add DNS provider for Czechia (#2885) 2026-03-04 18:04:04 +01:00
Fernandez Ludovic
da51631cd3
chore: improve issue template 2026-03-04 17:59:58 +01:00
Ludovic Fernandez
491dcaad1d
feat: allow to Unwrap obtainError (#2874) 2026-02-25 23:12:43 +01:00
Ludovic Fernandez
7d459b59c5
liara: add support for team ID (#2867) 2026-02-22 14:14:18 +01:00
Fernandez Ludovic
4547c4317e
Detach v4.32.0 2026-02-19 13:14:28 +01:00
Fernandez Ludovic
c50918c54e
Prepare release v4.32.0 2026-02-19 13:14:13 +01:00
Ludovic Fernandez
dd1ea80c08
Add DNS provider for Leaseweb (#2856) 2026-02-19 12:52:04 +01:00
Ludovic Fernandez
078a1889c8
Add DNS provider for ArtFiles (#2859) 2026-02-19 12:26:53 +01:00
Ludovic Fernandez
d896c1f036
fix: preserve domain order (#2862) 2026-02-19 12:25:10 +01:00
Ludovic Fernandez
84f3be40f0
chore: update dependencies (#2860) 2026-02-18 23:26:31 +01:00
Ludovic Fernandez
94e3bfb96a
chore: update linter (#2857) 2026-02-17 23:34:27 +01:00
Ludovic Fernandez
c06f378f0e
namesurfer: fix updateDNSHost (#2854) 2026-02-15 10:42:48 +01:00
Grigas Šukys
2e095b95a5
Add DNS provider for FusionLayer NameSurfer (#2852)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2026-02-15 02:22:35 +00:00
Ludovic Fernandez
4a61728ff0
fix: deduplicate authz for DNS01 challenge (#2828) 2026-02-12 19:13:49 +01:00
Ludovic Fernandez
1991339cc1
timewebcloud: fix subdomain support (#2845) 2026-02-12 18:20:05 +01:00
Ludovic Fernandez
dc51d5ee65
chore: use memcache Docker image directly (#2846) 2026-02-12 18:01:57 +01:00
Fernandez Ludovic
4c6d29882e
chore: update linter, and workflows 2026-02-12 17:32:23 +01:00
Andy Warner
c1aaf19aac
docs: make it more clear that any ACME CA may be used (#2841) 2026-02-10 02:51:54 +01:00
Mortie Torabi
fac5c39f5f
fix: implement parsing for Retry-After header according to RFC 7231 (#2830)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2026-01-30 20:36:46 +01:00
Ludovic Fernandez
a7145a29ac
fix: use IPs to define the main domain (#2817) 2026-01-28 18:41:23 +01:00
Ludovic Fernandez
2ce04a6586
alidns: add line record option (#2814) 2026-01-25 14:51:12 +01:00
Fernandez Ludovic
44b89b7e92
allinkl: factorize findZone 2026-01-22 05:10:35 +01:00
Ludovic Fernandez
16894fb99e
allinkl: detect zone through API (#2721) 2026-01-20 17:59:42 +01:00
Ludovic Fernandez
de869c8a7e
Add DNS provider for Bluecat v2 (#2791) 2026-01-19 17:31:56 +01:00
Ameer Ghani
05333f3c84
chore: improve warning message about backups (#2797) 2026-01-16 20:13:42 +00:00
Ludovic Fernandez
4d41c52db8
Add DNS provider for DDNSS (#2795) 2026-01-15 23:16:02 +01:00
Ludovic Fernandez
d063b15c02
azure: reinforces deprecation (#2792) 2026-01-15 01:04:30 +01:00
Ludovic Fernandez
527d51d485
Add DNS provider for DNSExit (#2787) 2026-01-12 17:04:28 +00:00
Ludovic Fernandez
7f10c131f4
Add DNS provider for TodayNIC/时代互联 (#2788) 2026-01-12 17:50:21 +01:00
Fernandez Ludovic
ac1092710d Detach v4.31.0 2026-01-08 17:58:41 +01:00
Fernandez Ludovic
9f3dde3f6d Prepare release v4.31.0 2026-01-08 17:58:41 +01:00
Ludovic Fernandez
b77b8709b6
namedotcom: follow CNAME (#2390) 2026-01-08 17:34:37 +01:00
Ludovic Fernandez
eed3f0dcc8
chore: update linter (#2785) 2026-01-08 17:33:57 +01:00
Ludovic Fernandez
b7a9b7dad0
chore: update dependencies (#2783) 2026-01-08 17:33:11 +01:00
Ludovic Fernandez
dd6ab7ca95
Add DNS provider for JDCloud (#2782) 2026-01-07 18:03:32 +01:00
Ludovic Fernandez
c5a259564f
Add DNS provider for 35.com/三五互联 (#2779) 2026-01-06 19:06:05 +01:00
Ludovic Fernandez
4783c128fa
chore: minor changes (#2776) 2026-01-05 00:05:16 +01:00
Ludovic Fernandez
2eede6d620
hetzner: fix compatibility with _FILE suffix (#2775) 2026-01-01 22:11:38 +01:00
Ludovic Fernandez
1b634097c1
docs: remove email from examples (#2773) 2025-12-29 18:33:53 +01:00
Ludovic Fernandez
a6a73754af
Add DNS provider for Alwaysdata (#2770) 2025-12-29 14:09:06 +01:00
Ludovic Fernandez
ff885d99c2
gandiv5: fix API Key header (#2769) 2025-12-23 16:39:06 +01:00
Ludovic Fernandez
ee616417a1
f5xc: add an option to configure the domain of the server (#2767) 2025-12-23 13:52:22 +01:00
Simon Merschjohann
8b327005b3
Add DNS Provider for ISPConfig (DDNS Module) (#2760)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2025-12-22 03:50:29 +01:00
Ludovic Fernandez
96168f78de
Add DNS provider for ISPConfig (#2762) 2025-12-21 22:55:28 +01:00
Ludovic Fernandez
bb98b9a899
chore: update pebble to v2.9.0 (#2763) 2025-12-19 02:27:38 +01:00
Ludovic Fernandez
a5cc0e1555
feat: improve ACME error types (#2761) 2025-12-18 14:29:52 +01:00
Fernandez Ludovic
7af0efdf72 Detach v4.30.1 2025-12-16 21:35:22 +01:00
624 changed files with 17117 additions and 1143 deletions

View file

@ -14,9 +14,15 @@ body:
required: true
- label: Yes, I know that the lego maintainers don't have an account in all DNS providers in the world.
required: true
- type: checkboxes
id: pr
attributes:
label: Implementation
options:
- label: Yes, I'm able to create a pull request and be able to maintain the implementation.
required: false
- label: Yes, I'm able to test an implementation if someone creates a pull request to add the support of this DNS provider.
- label: Yes, I can test an implementation with the help of the maintainers if someone creates a pull request.
required: false
- type: dropdown

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
env:
GO_VERSION: stable
GOLANGCI_LINT_VERSION: v2.7.1
GOLANGCI_LINT_VERSION: v2.10
HUGO_VERSION: 0.148.2
CGO_ENABLED: 0
LEGO_E2E_TESTS: CI
@ -44,13 +44,13 @@ jobs:
install-only: true
- name: Install Pebble
run: go install github.com/letsencrypt/pebble/v2/cmd/pebble@v2.8.0
run: go install github.com/letsencrypt/pebble/v2/cmd/pebble@v2.9.0
- name: Install challtestsrv
run: go install github.com/letsencrypt/pebble/v2/cmd/pebble-challtestsrv@v2.8.0
run: go install github.com/letsencrypt/pebble/v2/cmd/pebble-challtestsrv@v2.9.0
- name: Set up a Memcached server
uses: niden/actions-memcached@v7
run: docker run -d --rm -p 11211:11211 memcached:1.6-alpine
- name: Make
run: |

View file

@ -183,6 +183,9 @@ linters:
- text: "var-naming: avoid meaningless package names"
linters:
- revive
- text: "var-naming: avoid package names that conflict with Go standard library package names"
linters:
- revive
- path: certcrypto/crypto.go
text: (tlsFeatureExtensionOID|ocspMustStapleFeature) is a global variable
linters:

View file

@ -6,6 +6,60 @@ Everybody thinks that the others will donate, but in the end, nobody does.
So if you think that lego is worth it, please consider [donating](https://donate.ldez.dev).
## v4.32.0
- Release date: 2026-02-19
- Tag: [v4.32.0](https://github.com/go-acme/lego/releases/tag/v4.32.0)
### Added
- **[dnsprovider]** Add DNS provider for ArtFiles
- **[dnsprovider]** Add DNS provider for Leaseweb
- **[dnsprovider]** Add DNS provider for FusionLayer NameSurfer
- **[dnsprovider]** Add DNS provider for DDNSS
- **[dnsprovider]** Add DNS provider for Bluecat v2
- **[dnsprovider]** Add DNS provider for TodayNIC/时代互联
- **[dnsprovider]** Add DNS provider for DNSExit
- **[dnsprovider]** alidns: add line record option
### Changed
- **[dnsprovider]** azure: reinforces deprecation
- **[dnsprovider]** allinkl: detect zone through API
### Fixed
- **[ari]** fix: implement parsing for Retry-After header according to RFC 7231
- **[dnsprovider]** namesurfer: fix updateDNSHost
- **[dnsprovider]** timewebcloud: fix subdomain support
- **[dnsprovider]** fix: deduplicate authz for DNS01 challenge
- **[lib,cli]** fix: use IPs to define the main domain
- **[lib]** fix: preserve domain order
## v4.31.0
- Release date: 2026-01-08
- Tag: [v4.31.0](https://github.com/go-acme/lego/releases/tag/v4.31.0)
### Added
- **[dnsprovider]** Add DNS provider for ISPConfig
- **[dnsprovider]** Add DNS Provider for ISPConfig (DDNS Module)
- **[dnsprovider]** Add DNS provider for Alwaysdata
- **[dnsprovider]** Add DNS provider for JDCloud
- **[dnsprovider]** Add DNS provider for 35.com/三五互联
- **[dnsprovider]** f5xc: add an option to configure the domain of the server
### Changed
- **[lib]** feat: improve ACME error types
- **[dnsprovider,cname]** namedotcom: follow CNAME
### Fixed
- **[dnsprovider]** hetzner: fix compatibility with _FILE suffix
- **[dnsprovider]** gandiv5: fix API Key header
## v4.30.1
- Release date: 2025-12-16

View file

@ -5,7 +5,7 @@
# Lego
Let's Encrypt client and ACME library written in Go.
[ACME](https://www.rfc-editor.org/rfc/rfc8555.html) client and library for Let's Encrypt and other ACME CAs written in Go.
[![Go Reference](https://pkg.go.dev/badge/github.com/go-acme/lego/v4.svg)](https://pkg.go.dev/github.com/go-acme/lego/v4)
[![Build Status](https://github.com//go-acme/lego/workflows/Main/badge.svg?branch=master)](https://github.com//go-acme/lego/actions)
@ -24,7 +24,7 @@ So if you think that lego is worth it, please consider [donating](https://donate
- Support [RFC 8738](https://www.rfc-editor.org/rfc/rfc8738.html): certificates for IP addresses
- Support [RFC 9773](https://www.rfc-editor.org/rfc/rfc9773.html): Renewal Information (ARI) Extension
- Support [draft-ietf-acme-profiles-00](https://datatracker.ietf.org/doc/draft-ietf-acme-profiles/): Profiles Extension
- Comes with about [170 DNS providers](https://go-acme.github.io/lego/dns)
- Comes with about [180 DNS providers](https://go-acme.github.io/lego/dns)
- Register with CA
- Obtain certificates, both from scratch or with an existing CSR
- Renew certificates
@ -56,18 +56,25 @@ Documentation is hosted live at https://go-acme.github.io/lego/.
Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
If your DNS provider is not supported, please open an [issue](https://github.com/go-acme/lego/issues/new?assignees=&labels=enhancement%2C+new-provider&template=new_dns_provider.yml).
<!-- START DNS PROVIDERS LIST -->
<table><tr>
<td><a href="https://go-acme.github.io/lego/dns/com35/">35.com/三五互联</a></td>
<td><a href="https://go-acme.github.io/lego/dns/active24/">Active24</a></td>
<td><a href="https://go-acme.github.io/lego/dns/edgedns/">Akamai EdgeDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/alidns/">Alibaba Cloud DNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/aliesa/">AlibabaCloud ESA</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/aliesa/">AlibabaCloud ESA</a></td>
<td><a href="https://go-acme.github.io/lego/dns/allinkl/">all-inkl</a></td>
<td><a href="https://go-acme.github.io/lego/dns/alwaysdata/">Alwaysdata</a></td>
<td><a href="https://go-acme.github.io/lego/dns/lightsail/">Amazon Lightsail</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/route53/">Amazon Route 53</a></td>
<td><a href="https://go-acme.github.io/lego/dns/anexia/">Anexia CloudDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/safedns/">ANS SafeDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/artfiles/">ArtFiles</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/arvancloud/">ArvanCloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/auroradns/">Aurora DNS</a></td>
@ -84,32 +91,37 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
<td><a href="https://go-acme.github.io/lego/dns/bindman/">Bindman</a></td>
<td><a href="https://go-acme.github.io/lego/dns/bluecat/">Bluecat</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/bluecatv2/">Bluecat v2</a></td>
<td><a href="https://go-acme.github.io/lego/dns/bookmyname/">BookMyName</a></td>
<td><a href="https://go-acme.github.io/lego/dns/brandit/">Brandit (deprecated)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/bunny/">Bunny</a></td>
<td><a href="https://go-acme.github.io/lego/dns/checkdomain/">Checkdomain</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/checkdomain/">Checkdomain</a></td>
<td><a href="https://go-acme.github.io/lego/dns/civo/">Civo</a></td>
<td><a href="https://go-acme.github.io/lego/dns/cloudru/">Cloud.ru</a></td>
<td><a href="https://go-acme.github.io/lego/dns/clouddns/">CloudDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/cloudflare/">Cloudflare</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/cloudflare/">Cloudflare</a></td>
<td><a href="https://go-acme.github.io/lego/dns/cloudns/">ClouDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/cloudxns/">CloudXNS (Deprecated)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/conoha/">ConoHa v2</a></td>
<td><a href="https://go-acme.github.io/lego/dns/conohav3/">ConoHa v3</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/conohav3/">ConoHa v3</a></td>
<td><a href="https://go-acme.github.io/lego/dns/constellix/">Constellix</a></td>
<td><a href="https://go-acme.github.io/lego/dns/corenetworks/">Core-Networks</a></td>
<td><a href="https://go-acme.github.io/lego/dns/cpanel/">CPanel/WHM</a></td>
<td><a href="https://go-acme.github.io/lego/dns/derak/">Derak Cloud</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/czechia/">Czechia</a></td>
<td><a href="https://go-acme.github.io/lego/dns/ddnss/">DDnss (DynDNS Service)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/derak/">Derak Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/desec/">deSEC.io</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/designate/">Designate DNSaaS for Openstack</a></td>
<td><a href="https://go-acme.github.io/lego/dns/digitalocean/">Digital Ocean</a></td>
<td><a href="https://go-acme.github.io/lego/dns/directadmin/">DirectAdmin</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/dnsmadeeasy/">DNS Made Easy</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/dnsexit/">DNSExit</a></td>
<td><a href="https://go-acme.github.io/lego/dns/dnshomede/">dnsHome.de</a></td>
<td><a href="https://go-acme.github.io/lego/dns/dnsimple/">DNSimple</a></td>
<td><a href="https://go-acme.github.io/lego/dns/dnspod/">DNSPod (deprecated)</a></td>
@ -127,157 +139,167 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
<td><a href="https://go-acme.github.io/lego/dns/edgecenter/">EdgeCenter</a></td>
<td><a href="https://go-acme.github.io/lego/dns/efficientip/">Efficient IP</a></td>
<td><a href="https://go-acme.github.io/lego/dns/epik/">Epik</a></td>
<td><a href="https://go-acme.github.io/lego/dns/exoscale/">Exoscale</a></td>
<td><a href="https://go-acme.github.io/lego/dns/eurodns/">EuroDNS</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/excedo/">Excedo</a></td>
<td><a href="https://go-acme.github.io/lego/dns/exoscale/">Exoscale</a></td>
<td><a href="https://go-acme.github.io/lego/dns/exec/">External program</a></td>
<td><a href="https://go-acme.github.io/lego/dns/f5xc/">F5 XC</a></td>
<td><a href="https://go-acme.github.io/lego/dns/freemyip/">freemyip.com</a></td>
<td><a href="https://go-acme.github.io/lego/dns/gcore/">G-Core</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/freemyip/">freemyip.com</a></td>
<td><a href="https://go-acme.github.io/lego/dns/namesurfer/">FusionLayer NameSurfer</a></td>
<td><a href="https://go-acme.github.io/lego/dns/gcore/">G-Core</a></td>
<td><a href="https://go-acme.github.io/lego/dns/gandi/">Gandi</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/gandiv5/">Gandi Live DNS (v5)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/gigahostno/">Gigahost.no</a></td>
<td><a href="https://go-acme.github.io/lego/dns/glesys/">Glesys</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/godaddy/">Go Daddy</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/gcloud/">Google Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/googledomains/">Google Domains</a></td>
<td><a href="https://go-acme.github.io/lego/dns/gravity/">Gravity</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/hetzner/">Hetzner</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/hostingde/">Hosting.de</a></td>
<td><a href="https://go-acme.github.io/lego/dns/hostingnl/">Hosting.nl</a></td>
<td><a href="https://go-acme.github.io/lego/dns/hostinger/">Hostinger</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/hosttech/">Hosttech</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/httpreq/">HTTP request</a></td>
<td><a href="https://go-acme.github.io/lego/dns/httpnet/">http.net</a></td>
<td><a href="https://go-acme.github.io/lego/dns/huaweicloud/">Huawei Cloud</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/hurricane/">Hurricane Electric DNS</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/hyperone/">HyperOne</a></td>
<td><a href="https://go-acme.github.io/lego/dns/ibmcloud/">IBM Cloud (SoftLayer)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/iijdpf/">IIJ DNS Platform Service</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/infoblox/">Infoblox</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/infomaniak/">Infomaniak</a></td>
<td><a href="https://go-acme.github.io/lego/dns/iij/">Internet Initiative Japan</a></td>
<td><a href="https://go-acme.github.io/lego/dns/internetbs/">Internet.bs</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/inwx/">INWX</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/ionos/">Ionos</a></td>
<td><a href="https://go-acme.github.io/lego/dns/ionoscloud/">Ionos Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/ipv64/">IPv64</a></td>
<td><a href="https://go-acme.github.io/lego/dns/ispconfig/">ISPConfig 3</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/ispconfigddns/">ISPConfig 3 - Dynamic DNS (DDNS) Module</a></td>
<td><a href="https://go-acme.github.io/lego/dns/iwantmyname/">iwantmyname (Deprecated)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/jdcloud/">JD Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/joker/">Joker</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/acme-dns/">Joohoi&#39;s ACME-DNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/keyhelp/">KeyHelp</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/leaseweb/">Leaseweb</a></td>
<td><a href="https://go-acme.github.io/lego/dns/liara/">Liara</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/limacity/">Lima-City</a></td>
<td><a href="https://go-acme.github.io/lego/dns/linode/">Linode (v4)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/liquidweb/">Liquid Web</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/loopia/">Loopia</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/luadns/">LuaDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/mailinabox/">Mail-in-a-Box</a></td>
<td><a href="https://go-acme.github.io/lego/dns/manageengine/">ManageEngine CloudDNS</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/manual/">Manual</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/metaname/">Metaname</a></td>
<td><a href="https://go-acme.github.io/lego/dns/metaregistrar/">Metaregistrar</a></td>
<td><a href="https://go-acme.github.io/lego/dns/mijnhost/">mijn.host</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/mittwald/">Mittwald</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/myaddr/">myaddr.{tools,dev,io}</a></td>
<td><a href="https://go-acme.github.io/lego/dns/mydnsjp/">MyDNS.jp</a></td>
<td><a href="https://go-acme.github.io/lego/dns/mythicbeasts/">MythicBeasts</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/namedotcom/">Name.com</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/namecheap/">Namecheap</a></td>
<td><a href="https://go-acme.github.io/lego/dns/namesilo/">Namesilo</a></td>
<td><a href="https://go-acme.github.io/lego/dns/nearlyfreespeech/">NearlyFreeSpeech.NET</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/neodigit/">Neodigit</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/netcup/">Netcup</a></td>
<td><a href="https://go-acme.github.io/lego/dns/netlify/">Netlify</a></td>
<td><a href="https://go-acme.github.io/lego/dns/nicmanager/">Nicmanager</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/nifcloud/">NIFCloud</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/njalla/">Njalla</a></td>
<td><a href="https://go-acme.github.io/lego/dns/nodion/">Nodion</a></td>
<td><a href="https://go-acme.github.io/lego/dns/ns1/">NS1</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/octenium/">Octenium</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/otc/">Open Telekom Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/oraclecloud/">Oracle Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/ovh/">OVH</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/plesk/">plesk.com</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/porkbun/">Porkbun</a></td>
<td><a href="https://go-acme.github.io/lego/dns/pdns/">PowerDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/rackspace/">Rackspace</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/rainyun/">Rain Yun/雨云</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/rcodezero/">RcodeZero</a></td>
<td><a href="https://go-acme.github.io/lego/dns/regru/">reg.ru</a></td>
<td><a href="https://go-acme.github.io/lego/dns/regfish/">Regfish</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/rfc2136/">RFC2136</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/rimuhosting/">RimuHosting</a></td>
<td><a href="https://go-acme.github.io/lego/dns/nicru/">RU CENTER</a></td>
<td><a href="https://go-acme.github.io/lego/dns/sakuracloud/">Sakura Cloud</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/scaleway/">Scaleway</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/selectel/">Selectel</a></td>
<td><a href="https://go-acme.github.io/lego/dns/selectelv2/">Selectel v2</a></td>
<td><a href="https://go-acme.github.io/lego/dns/selfhostde/">SelfHost.(de|eu)</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/servercow/">Servercow</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/shellrent/">Shellrent</a></td>
<td><a href="https://go-acme.github.io/lego/dns/simply/">Simply.com</a></td>
<td><a href="https://go-acme.github.io/lego/dns/sonic/">Sonic</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/spaceship/">Spaceship</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/stackpath/">Stackpath</a></td>
<td><a href="https://go-acme.github.io/lego/dns/syse/">Syse</a></td>
<td><a href="https://go-acme.github.io/lego/dns/technitium/">Technitium</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/tencentcloud/">Tencent Cloud DNS</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/edgeone/">Tencent EdgeOne</a></td>
<td><a href="https://go-acme.github.io/lego/dns/timewebcloud/">Timeweb Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/todaynic/">TodayNIC/时代互联</a></td>
<td><a href="https://go-acme.github.io/lego/dns/transip/">TransIP</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/safedns/">UKFast SafeDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/ultradns/">Ultradns</a></td>
<td><a href="https://go-acme.github.io/lego/dns/uniteddomains/">United-Domains</a></td>
<td><a href="https://go-acme.github.io/lego/dns/variomedia/">Variomedia</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/vegadns/">VegaDNS</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/vercel/">Vercel</a></td>
<td><a href="https://go-acme.github.io/lego/dns/versio/">Versio.[nl|eu|uk]</a></td>
<td><a href="https://go-acme.github.io/lego/dns/vinyldns/">VinylDNS</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/virtualname/">Virtualname</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/vkcloud/">VK Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/volcengine/">Volcano Engine/火山引擎</a></td>
<td><a href="https://go-acme.github.io/lego/dns/vscale/">Vscale</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/vultr/">Vultr</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/webnamesca/">webnames.ca</a></td>
<td><a href="https://go-acme.github.io/lego/dns/webnames/">webnames.ru</a></td>
<td><a href="https://go-acme.github.io/lego/dns/websupport/">Websupport</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/wedos/">WEDOS</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/westcn/">West.cn/西部数码</a></td>
<td><a href="https://go-acme.github.io/lego/dns/yandex360/">Yandex 360</a></td>
<td><a href="https://go-acme.github.io/lego/dns/yandexcloud/">Yandex Cloud</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/yandex/">Yandex PDD</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/zoneee/">Zone.ee</a></td>
<td><a href="https://go-acme.github.io/lego/dns/zoneedit/">ZoneEdit</a></td>
<td><a href="https://go-acme.github.io/lego/dns/zonomi/">Zonomi</a></td>
<td></td>
</tr></table>
<!-- END DNS PROVIDERS LIST -->

View file

@ -2,7 +2,6 @@ package api
import (
"cmp"
"maps"
"net"
"slices"
@ -10,7 +9,9 @@ import (
)
func createIdentifiers(domains []string) []acme.Identifier {
uniqIdentifiers := make(map[string]acme.Identifier)
uniqIdentifiers := make(map[string]struct{})
var identifiers []acme.Identifier
for _, domain := range domains {
if _, ok := uniqIdentifiers[domain]; ok {
@ -23,10 +24,12 @@ func createIdentifiers(domains []string) []acme.Identifier {
ident.Type = "ip"
}
uniqIdentifiers[domain] = ident
identifiers = append(identifiers, ident)
uniqIdentifiers[domain] = struct{}{}
}
return slices.AppendSeq(make([]acme.Identifier, 0, len(uniqIdentifiers)), maps.Values(uniqIdentifiers))
return identifiers
}
// compareIdentifiers compares 2 slices of [acme.Identifier].

View file

@ -120,39 +120,46 @@ func (d *Doer) formatUserAgent() string {
}
func checkError(req *http.Request, resp *http.Response) error {
if resp.StatusCode >= http.StatusBadRequest {
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("%d :: %s :: %s :: %w", resp.StatusCode, req.Method, req.URL, err)
}
var errorDetails *acme.ProblemDetails
err = json.Unmarshal(body, &errorDetails)
if err != nil {
return fmt.Errorf("%d ::%s :: %s :: %w :: %s", resp.StatusCode, req.Method, req.URL, err, string(body))
}
errorDetails.Method = req.Method
errorDetails.URL = req.URL.String()
if errorDetails.HTTPStatus == 0 {
errorDetails.HTTPStatus = resp.StatusCode
}
// Check for errors we handle specifically
if errorDetails.HTTPStatus == http.StatusBadRequest && errorDetails.Type == acme.BadNonceErr {
return &acme.NonceError{ProblemDetails: errorDetails}
}
if errorDetails.HTTPStatus == http.StatusConflict && errorDetails.Type == acme.AlreadyReplacedErr {
return &acme.AlreadyReplacedError{ProblemDetails: errorDetails}
}
return errorDetails
if resp.StatusCode < http.StatusBadRequest {
return nil
}
return nil
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("%d :: %s :: %s :: %w", resp.StatusCode, req.Method, req.URL, err)
}
var errorDetails *acme.ProblemDetails
err = json.Unmarshal(body, &errorDetails)
if err != nil {
return fmt.Errorf("%d ::%s :: %s :: %w :: %s", resp.StatusCode, req.Method, req.URL, err, string(body))
}
errorDetails.Method = req.Method
errorDetails.URL = req.URL.String()
if errorDetails.HTTPStatus == 0 {
errorDetails.HTTPStatus = resp.StatusCode
}
// Check for errors we handle specifically
switch {
case errorDetails.HTTPStatus == http.StatusBadRequest && errorDetails.Type == acme.BadNonceErr:
return &acme.NonceError{ProblemDetails: errorDetails}
case errorDetails.HTTPStatus == http.StatusConflict && errorDetails.Type == acme.AlreadyReplacedErr:
return &acme.AlreadyReplacedError{ProblemDetails: errorDetails}
case errorDetails.HTTPStatus == http.StatusTooManyRequests && errorDetails.Type == acme.RateLimitedErr:
return &acme.RateLimitedError{
ProblemDetails: errorDetails,
RetryAfter: resp.Header.Get("Retry-After"),
}
default:
return errorDetails
}
}
type httpsOnly struct {

View file

@ -1,11 +1,14 @@
package sender
import (
"bytes"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/go-acme/lego/v4/acme"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -78,3 +81,70 @@ func TestDo_failWithHTTP(t *testing.T) {
_, err := sender.Post(server.URL, strings.NewReader("data"), "text/plain", nil)
require.ErrorContains(t, err, "HTTPS is required: http://")
}
func Test_checkError(t *testing.T) {
testCases := []struct {
desc string
resp *http.Response
assert func(t *testing.T, err error)
}{
{
desc: "default",
resp: &http.Response{
StatusCode: http.StatusNotFound,
Body: io.NopCloser(bytes.NewBufferString(`{"type":"urn:ietf:params:acme:error:example","detail":"message","status":404}`)),
},
assert: errorAs[*acme.ProblemDetails],
},
{
desc: "badNonce",
resp: &http.Response{
StatusCode: http.StatusBadRequest,
Body: io.NopCloser(bytes.NewBufferString(`{"type":"urn:ietf:params:acme:error:badNonce","detail":"message","status":400}`)),
},
assert: errorAs[*acme.NonceError],
},
{
desc: "alreadyReplaced",
resp: &http.Response{
StatusCode: http.StatusConflict,
Body: io.NopCloser(bytes.NewBufferString(`{"type":"urn:ietf:params:acme:error:alreadyReplaced","detail":"message","status":409}`)),
},
assert: errorAs[*acme.AlreadyReplacedError],
},
{
desc: "rateLimited",
resp: &http.Response{
StatusCode: http.StatusConflict,
Header: http.Header{
"Retry-After": []string{"1"},
},
Body: io.NopCloser(bytes.NewBufferString(`{"type":"urn:ietf:params:acme:error:rateLimited","detail":"message","status":429}`)),
},
assert: errorAs[*acme.RateLimitedError],
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
req := httptest.NewRequestWithContext(t.Context(), http.MethodPost, "https://example.com", nil)
err := checkError(req, test.resp)
require.Error(t, err)
pb := &acme.ProblemDetails{}
assert.ErrorAs(t, err, &pb)
test.assert(t, err)
})
}
}
func errorAs[T error](t *testing.T, err error) {
t.Helper()
var zero T
assert.ErrorAs(t, err, &zero)
}

View file

@ -4,10 +4,10 @@ package sender
const (
// ourUserAgent is the User-Agent of this underlying library package.
ourUserAgent = "xenolf-acme/4.30.1"
ourUserAgent = "xenolf-acme/4.32.0"
// ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package.
// values: detach|release
// NOTE: Update this with each tagged release.
ourUserAgentComment = "release"
ourUserAgentComment = "detach"
)

View file

@ -1,8 +1,11 @@
package api
import (
"fmt"
"net/http"
"regexp"
"strconv"
"time"
)
type service struct {
@ -56,3 +59,29 @@ func getRetryAfter(resp *http.Response) string {
return resp.Header.Get("Retry-After")
}
// ParseRetryAfter parses the Retry-After header value according to RFC 7231.
// The header can be either delay-seconds (numeric) or HTTP-date (RFC 1123 format).
// https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.3
// Returns the duration until the retry time.
// TODO(ldez): unexposed this function in v5.
func ParseRetryAfter(value string) (time.Duration, error) {
if value == "" {
return 0, nil
}
if seconds, err := strconv.ParseInt(value, 10, 64); err == nil {
return time.Duration(seconds) * time.Second, nil
}
if retryTime, err := time.Parse(time.RFC1123, value); err == nil {
duration := time.Until(retryTime)
if duration < 0 {
return 0, nil
}
return duration, nil
}
return 0, fmt.Errorf("invalid Retry-After value: %q", value)
}

View file

@ -3,8 +3,10 @@ package api
import (
"net/http"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_getLink(t *testing.T) {
@ -53,3 +55,38 @@ func Test_getLink(t *testing.T) {
})
}
}
func TestParseRetryAfter(t *testing.T) {
testCases := []struct {
desc string
value string
expected time.Duration
}{
{
desc: "empty header value",
value: "",
expected: time.Duration(0),
},
{
desc: "delay-seconds",
value: "123",
expected: 123 * time.Second,
},
{
desc: "HTTP-date",
value: time.Now().Add(3 * time.Second).Format(time.RFC1123),
expected: 3 * time.Second,
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
rt, err := ParseRetryAfter(test.value)
require.NoError(t, err)
assert.InDelta(t, test.expected.Seconds(), rt.Seconds(), 1)
})
}
}

View file

@ -10,6 +10,7 @@ const (
errNS = "urn:ietf:params:acme:error:"
BadNonceErr = errNS + "badNonce"
AlreadyReplacedErr = errNS + "alreadyReplaced"
RateLimitedErr = errNS + "rateLimited"
)
// ProblemDetails the problem details object.
@ -28,18 +29,18 @@ type ProblemDetails struct {
}
func (p *ProblemDetails) Error() string {
var msg strings.Builder
msg := new(strings.Builder)
msg.WriteString(fmt.Sprintf("acme: error: %d", p.HTTPStatus))
_, _ = fmt.Fprintf(msg, "acme: error: %d", p.HTTPStatus)
if p.Method != "" || p.URL != "" {
msg.WriteString(fmt.Sprintf(" :: %s :: %s", p.Method, p.URL))
_, _ = fmt.Fprintf(msg, " :: %s :: %s", p.Method, p.URL)
}
msg.WriteString(fmt.Sprintf(" :: %s :: %s", p.Type, p.Detail))
_, _ = fmt.Fprintf(msg, " :: %s :: %s", p.Type, p.Detail)
for _, sub := range p.SubProblems {
msg.WriteString(fmt.Sprintf(", problem: %q :: %s", sub.Type, sub.Detail))
_, _ = fmt.Fprintf(msg, ", problem: %q :: %s", sub.Type, sub.Detail)
}
if p.Instance != "" {
@ -63,9 +64,30 @@ type NonceError struct {
*ProblemDetails
}
func (e *NonceError) Unwrap() error {
return e.ProblemDetails
}
// AlreadyReplacedError represents the error which is returned
// If the Server rejects the request because the identified certificate has already been marked as replaced.
// if the Server rejects the request because the identified certificate has already been marked as replaced.
// - https://www.rfc-editor.org/rfc/rfc9773.html#section-5
type AlreadyReplacedError struct {
*ProblemDetails
}
func (e *AlreadyReplacedError) Unwrap() error {
return e.ProblemDetails
}
// RateLimitedError represents the error which is returned
// if the server rejects the request because the client has exceeded the rate limit.
// - https://www.rfc-editor.org/rfc/rfc8555.html#section-6.6
type RateLimitedError struct {
*ProblemDetails
RetryAfter string
}
func (e *RateLimitedError) Unwrap() error {
return e.ProblemDetails
}

View file

@ -242,15 +242,15 @@ func ParsePEMCertificate(cert []byte) (*x509.Certificate, error) {
}
func GetCertificateMainDomain(cert *x509.Certificate) (string, error) {
return getMainDomain(cert.Subject, cert.DNSNames)
return getMainDomain(cert.Subject, cert.DNSNames, cert.IPAddresses)
}
func GetCSRMainDomain(cert *x509.CertificateRequest) (string, error) {
return getMainDomain(cert.Subject, cert.DNSNames)
return getMainDomain(cert.Subject, cert.DNSNames, cert.IPAddresses)
}
func getMainDomain(subject pkix.Name, dnsNames []string) (string, error) {
if subject.CommonName == "" && len(dnsNames) == 0 {
func getMainDomain(subject pkix.Name, dnsNames []string, ips []net.IP) (string, error) {
if subject.CommonName == "" && len(dnsNames) == 0 && len(ips) == 0 {
return "", errors.New("missing domain")
}
@ -258,7 +258,11 @@ func getMainDomain(subject pkix.Name, dnsNames []string) (string, error) {
return subject.CommonName, nil
}
return dnsNames[0], nil
if len(dnsNames) > 0 {
return dnsNames[0], nil
}
return ips[0].String(), nil
}
func ExtractDomains(cert *x509.Certificate) []string {

View file

@ -11,6 +11,7 @@ import (
"time"
"github.com/go-acme/lego/v4/acme"
"github.com/go-acme/lego/v4/acme/api"
)
// RenewalInfoRequest contains the necessary renewal information.
@ -92,9 +93,9 @@ func (c *Certifier) GetRenewalInfo(req RenewalInfoRequest) (*RenewalInfoResponse
}
if retry := resp.Header.Get("Retry-After"); retry != "" {
info.RetryAfter, err = time.ParseDuration(retry + "s")
info.RetryAfter, err = api.ParseRetryAfter(retry)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to parse Retry-After header: %w", err)
}
}

View file

@ -74,6 +74,42 @@ func TestCertifier_GetRenewalInfo(t *testing.T) {
assert.Equal(t, time.Duration(21600000000000), ri.RetryAfter)
}
func TestCertifier_GetRenewalInfo_retryAfter(t *testing.T) {
leaf, err := certcrypto.ParsePEMCertificate([]byte(ariLeafPEM))
require.NoError(t, err)
server := tester.MockACMEServer().
Route("GET /renewalInfo/"+ariLeafCertID,
servermock.RawStringResponse(`{
"suggestedWindow": {
"start": "2020-03-17T17:51:09Z",
"end": "2020-03-17T18:21:09Z"
},
"explanationUrl": "https://aricapable.ca.example/docs/renewal-advice/"
}
}`).
WithHeader("Content-Type", "application/json").
WithHeader("Retry-After", time.Now().UTC().Add(6*time.Hour).Format(time.RFC1123))).
BuildHTTPS(t)
key, err := rsa.GenerateKey(rand.Reader, 2048)
require.NoError(t, err, "Could not generate test key")
core, err := api.New(server.Client(), "lego-test", server.URL+"/dir", "", key)
require.NoError(t, err)
certifier := NewCertifier(core, &resolverMock{}, CertifierOptions{KeyType: certcrypto.RSA2048})
ri, err := certifier.GetRenewalInfo(RenewalInfoRequest{leaf})
require.NoError(t, err)
require.NotNil(t, ri)
assert.Equal(t, "2020-03-17T17:51:09Z", ri.SuggestedWindow.Start.Format(time.RFC3339))
assert.Equal(t, "2020-03-17T18:21:09Z", ri.SuggestedWindow.End.Format(time.RFC3339))
assert.Equal(t, "https://aricapable.ca.example/docs/renewal-advice/", ri.ExplanationURL)
assert.InDelta(t, 6, ri.RetryAfter.Hours(), 0.001)
}
func TestCertifier_GetRenewalInfo_errors(t *testing.T) {
leaf, err := certcrypto.ParsePEMCertificate([]byte(ariLeafPEM))
require.NoError(t, err)

View file

@ -3,6 +3,8 @@ package resolver
import (
"bytes"
"fmt"
"maps"
"slices"
"sort"
)
@ -25,3 +27,7 @@ func (e obtainError) Error() string {
return buffer.String()
}
func (e obtainError) Unwrap() []error {
return slices.AppendSeq(make([]error, 0, len(e)), maps.Values(e))
}

View file

@ -0,0 +1,70 @@
package resolver
import (
"errors"
"testing"
"github.com/go-acme/lego/v4/acme"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_obtainError_Error(t *testing.T) {
err := obtainError{
"a": &acme.ProblemDetails{Type: "001"},
"b": errors.New("oops"),
"c": errors.New("I did it again"),
}
require.EqualError(t, err, `error: one or more domains had a problem:
[a] acme: error: 0 :: 001 ::
[b] oops
[c] I did it again
`)
}
func Test_obtainError_Unwrap(t *testing.T) {
testCases := []struct {
desc string
err obtainError
assert assert.BoolAssertionFunc
}{
{
desc: "one ok",
err: obtainError{
"a": &acme.ProblemDetails{},
"b": errors.New("oops"),
"c": errors.New("I did it again"),
},
assert: assert.True,
},
{
desc: "all ok",
err: obtainError{
"a": &acme.ProblemDetails{Type: "001"},
"b": &acme.ProblemDetails{Type: "002"},
"c": &acme.ProblemDetails{Type: "002"},
},
assert: assert.True,
},
{
desc: "nope",
err: obtainError{
"a": errors.New("hello"),
"b": errors.New("oops"),
"c": errors.New("I did it again"),
},
assert: assert.False,
},
}
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
var pd *acme.ProblemDetails
test.assert(t, errors.As(test.err, &pd))
})
}
}

View file

@ -98,11 +98,24 @@ func (p *Prober) Solve(authorizations []acme.Authorization) error {
}
func sequentialSolve(authSolvers []*selectedAuthSolver, failures obtainError) {
// Some CA are using the same token,
// this can be a problem with the DNS01 challenge when the DNS provider doesn't support duplicate TXT records.
// In the sequential mode, this is not a problem because we can solve the challenges in order.
// But it can reduce the number of call the DNS provider APIs.
uniq := make(map[string]struct{})
for i, authSolver := range authSolvers {
// Submit the challenge
domain := challenge.GetTargetedDomain(authSolver.authz)
chlg, _ := challenge.FindChallenge(challenge.DNS01, authSolver.authz)
if solvr, ok := authSolver.solver.(preSolver); ok {
if _, ok := uniq[authSolver.authz.Identifier.Value+chlg.Token]; ok && chlg.Token != "" {
log.Infof("acme: duplicate token for %q (DNS-01); skipping pre-solve.", authSolver.authz.Identifier.Value)
continue
}
err := solvr.PreSolve(authSolver.authz)
if err != nil {
failures[domain] = err
@ -111,6 +124,8 @@ func sequentialSolve(authSolvers []*selectedAuthSolver, failures obtainError) {
continue
}
uniq[authSolver.authz.Identifier.Value+chlg.Token] = struct{}{}
}
// Solve challenge
@ -123,22 +138,43 @@ func sequentialSolve(authSolvers []*selectedAuthSolver, failures obtainError) {
continue
}
// Clean challenge
cleanUp(authSolver.solver, authSolver.authz)
if _, ok := uniq[authSolver.authz.Identifier.Value+chlg.Token]; ok || chlg.Token == "" {
// Clean challenge
cleanUp(authSolver.solver, authSolver.authz)
if len(authSolvers)-1 > i {
solvr := authSolver.solver.(sequential)
_, interval := solvr.Sequential()
log.Infof("sequence: wait for %s", interval)
time.Sleep(interval)
if len(authSolvers)-1 > i {
solvr := authSolver.solver.(sequential)
_, interval := solvr.Sequential()
log.Infof("sequence: wait for %s", interval)
time.Sleep(interval)
}
delete(uniq, authSolver.authz.Identifier.Value+chlg.Token)
} else {
log.Infof("acme: duplicate token for %q (DNS-01); skipping cleanup.", authSolver.authz.Identifier.Value)
}
}
}
func parallelSolve(authSolvers []*selectedAuthSolver, failures obtainError) {
// Some CA are using the same token,
// this can be a problem with the DNS01 challenge when the DNS provider doesn't support duplicate TXT records.
uniq := make(map[string]struct{})
// For all valid preSolvers, first submit the challenges, so they have max time to propagate
for _, authSolver := range authSolvers {
authz := authSolver.authz
chlg, err := challenge.FindChallenge(challenge.DNS01, authz)
if err == nil {
if _, ok := uniq[authz.Identifier.Value+chlg.Token]; ok {
log.Infof("acme: duplicate token for %q (DNS-01); skipping pre-solve.", authSolver.authz.Identifier.Value)
continue
}
uniq[authz.Identifier.Value+chlg.Token] = struct{}{}
}
if solvr, ok := authSolver.solver.(preSolver); ok {
err := solvr.PreSolve(authz)
if err != nil {
@ -150,6 +186,16 @@ func parallelSolve(authSolvers []*selectedAuthSolver, failures obtainError) {
defer func() {
// Clean all created TXT records
for _, authSolver := range authSolvers {
chlg, err := challenge.FindChallenge(challenge.DNS01, authSolver.authz)
if err == nil {
if _, ok := uniq[authSolver.authz.Identifier.Value+chlg.Token]; ok {
delete(uniq, authSolver.authz.Identifier.Value+chlg.Token)
} else {
log.Infof("acme: duplicate token for %q (DNS-01); skipping cleanup.", authSolver.authz.Identifier.Value)
continue
}
}
cleanUp(authSolver.solver, authSolver.authz)
}
}()

View file

@ -1,6 +1,7 @@
package resolver
import (
"fmt"
"time"
"github.com/go-acme/lego/v4/acme"
@ -11,34 +12,68 @@ type preSolverMock struct {
preSolve map[string]error
solve map[string]error
cleanUp map[string]error
preSolveCounter int
solveCounter int
cleanUpCounter int
}
func (s *preSolverMock) PreSolve(authorization acme.Authorization) error {
s.preSolveCounter++
return s.preSolve[authorization.Identifier.Value]
}
func (s *preSolverMock) Solve(authorization acme.Authorization) error {
s.solveCounter++
return s.solve[authorization.Identifier.Value]
}
func (s *preSolverMock) CleanUp(authorization acme.Authorization) error {
s.cleanUpCounter++
return s.cleanUp[authorization.Identifier.Value]
}
func (s *preSolverMock) String() string {
return fmt.Sprintf("PreSolve: %d, Solve: %d, CleanUp: %d", s.preSolveCounter, s.solveCounter, s.cleanUpCounter)
}
func createStubAuthorizationHTTP01(domain, status string) acme.Authorization {
return createStubAuthorization(domain, status, false, acme.Challenge{
Type: challenge.HTTP01.String(),
Validated: time.Now(),
})
}
func createStubAuthorizationDNS01(domain string, wildcard bool) acme.Authorization {
var chlgs []acme.Challenge
if wildcard {
chlgs = append(chlgs, acme.Challenge{
Type: challenge.HTTP01.String(),
Validated: time.Now(),
})
}
chlgs = append(chlgs, acme.Challenge{
Type: challenge.DNS01.String(),
Validated: time.Now(),
})
return createStubAuthorization(domain, acme.StatusProcessing, wildcard, chlgs...)
}
func createStubAuthorization(domain, status string, wildcard bool, chlgs ...acme.Challenge) acme.Authorization {
return acme.Authorization{
Status: status,
Expires: time.Now(),
Wildcard: wildcard,
Status: status,
Expires: time.Now(),
Identifier: acme.Identifier{
Type: challenge.HTTP01.String(),
Type: "dns",
Value: domain,
},
Challenges: []acme.Challenge{
{
Type: challenge.HTTP01.String(),
Validated: time.Now(),
Error: nil,
},
},
Challenges: chlgs,
}
}

View file

@ -2,19 +2,22 @@ package resolver
import (
"errors"
"fmt"
"testing"
"github.com/go-acme/lego/v4/acme"
"github.com/go-acme/lego/v4/challenge"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestProber_Solve(t *testing.T) {
testCases := []struct {
desc string
solvers map[challenge.Type]solver
authz []acme.Authorization
expectedError string
desc string
solvers map[challenge.Type]solver
authz []acme.Authorization
expectedError string
expectedCounters map[challenge.Type]string
}{
{
desc: "success",
@ -30,6 +33,30 @@ func TestProber_Solve(t *testing.T) {
createStubAuthorizationHTTP01("example.org", acme.StatusProcessing),
createStubAuthorizationHTTP01("example.net", acme.StatusProcessing),
},
expectedCounters: map[challenge.Type]string{
challenge.HTTP01: "PreSolve: 3, Solve: 3, CleanUp: 3",
},
},
{
desc: "DNS-01 deduplicate",
solvers: map[challenge.Type]solver{
challenge.DNS01: &preSolverMock{
preSolve: map[string]error{},
solve: map[string]error{},
cleanUp: map[string]error{},
},
},
authz: []acme.Authorization{
createStubAuthorizationDNS01("a.example", false),
createStubAuthorizationDNS01("a.example", true),
createStubAuthorizationDNS01("b.example", false),
createStubAuthorizationDNS01("b.example", true),
createStubAuthorizationDNS01("c.example", true),
createStubAuthorizationDNS01("d.example", false),
},
expectedCounters: map[challenge.Type]string{
challenge.DNS01: "PreSolve: 4, Solve: 6, CleanUp: 4",
},
},
{
desc: "already valid",
@ -45,6 +72,9 @@ func TestProber_Solve(t *testing.T) {
createStubAuthorizationHTTP01("example.org", acme.StatusValid),
createStubAuthorizationHTTP01("example.net", acme.StatusValid),
},
expectedCounters: map[challenge.Type]string{
challenge.HTTP01: "PreSolve: 0, Solve: 0, CleanUp: 0",
},
},
{
desc: "when preSolve fail, auth is flagged as error and skipped",
@ -69,6 +99,9 @@ func TestProber_Solve(t *testing.T) {
expectedError: `error: one or more domains had a problem:
[example.com] preSolve error example.com
`,
expectedCounters: map[challenge.Type]string{
challenge.HTTP01: "PreSolve: 3, Solve: 2, CleanUp: 3",
},
},
{
desc: "errors at different stages",
@ -95,6 +128,9 @@ func TestProber_Solve(t *testing.T) {
[example.com] preSolve error example.com
[example.org] solve error example.org
`,
expectedCounters: map[challenge.Type]string{
challenge.HTTP01: "PreSolve: 3, Solve: 2, CleanUp: 3",
},
},
}
@ -112,6 +148,10 @@ func TestProber_Solve(t *testing.T) {
} else {
require.NoError(t, err)
}
for n, s := range test.solvers {
assert.Equal(t, test.expectedCounters[n], fmt.Sprintf("%s", s))
}
})
}
}

View file

@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"sort"
"strconv"
"time"
"github.com/cenkalti/backoff/v5"
@ -94,22 +93,20 @@ func validate(core *api.Core, domain string, chlg acme.Challenge) error {
return nil
}
ra, err := strconv.Atoi(chlng.RetryAfter)
if err != nil {
retryAfter, err := api.ParseRetryAfter(chlng.RetryAfter)
if err != nil || retryAfter == 0 {
// The ACME server MUST return a Retry-After.
// If it doesn't, we'll just poll hard.
// If it doesn't, or if it's invalid, we'll just poll hard.
// Boulder does not implement the ability to retry challenges or the Retry-After header.
// https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md#section-82
ra = 5
retryAfter = 5 * time.Second
}
initialInterval := time.Duration(ra) * time.Second
ctx := context.Background()
bo := backoff.NewExponentialBackOff()
bo.InitialInterval = initialInterval
bo.MaxInterval = 10 * initialInterval
bo.InitialInterval = retryAfter
bo.MaxInterval = 10 * retryAfter
// After the path is sent, the ACME server will access our server.
// Repeatedly check the server for an updated status on our request.
@ -134,7 +131,7 @@ func validate(core *api.Core, domain string, chlg acme.Challenge) error {
return wait.Retry(ctx, operation,
backoff.WithBackOff(bo),
backoff.WithMaxElapsedTime(100*initialInterval))
backoff.WithMaxElapsedTime(100*retryAfter))
}
func checkChallengeStatus(chlng acme.ExtendedChallenge) (bool, error) {

View file

@ -3,6 +3,7 @@ package cmd
import (
"encoding/json"
"fmt"
"net"
"net/url"
"os"
"path/filepath"
@ -100,6 +101,11 @@ func listCertificates(ctx *cli.Context) error {
} else {
fmt.Println(" Certificate Name:", name)
fmt.Println(" Domains:", strings.Join(pCert.DNSNames, ", "))
if len(pCert.IPAddresses) > 0 {
fmt.Println(" IPs:", formatIPAddresses(pCert.IPAddresses))
}
fmt.Println(" Expiry Date:", pCert.NotAfter)
fmt.Println(" Certificate Path:", filename)
fmt.Println()
@ -150,3 +156,12 @@ func listAccount(ctx *cli.Context) error {
return nil
}
func formatIPAddresses(ipAddresses []net.IP) string {
var ips []string
for _, ip := range ipAddresses {
ips = append(ips, ip.String())
}
return strings.Join(ips, ", ")
}

View file

@ -104,9 +104,9 @@ Your account credentials have been saved in your
configuration directory at "%s".
You should make a secure backup of this folder now. This
configuration directory will also contain certificates and
private keys obtained from the ACME server so making regular
backups of this folder is ideal.
configuration directory will also contain private keys
generated by lego and certificates obtained from the ACME
server. Making regular backups of this folder is ideal.
`
func run(ctx *cli.Context) error {

View file

@ -2,7 +2,7 @@
package main
const defaultVersion = "v4.30.1+dev-release"
const defaultVersion = "v4.32.0+dev-detach"
var version = ""

View file

@ -17,7 +17,9 @@ func allDNSCodes() string {
"alidns",
"aliesa",
"allinkl",
"alwaysdata",
"anexia",
"artfiles",
"arvancloud",
"auroradns",
"autodns",
@ -30,6 +32,7 @@ func allDNSCodes() string {
"binarylane",
"bindman",
"bluecat",
"bluecatv2",
"bookmyname",
"brandit",
"bunny",
@ -40,16 +43,20 @@ func allDNSCodes() string {
"cloudns",
"cloudru",
"cloudxns",
"com35",
"conoha",
"conohav3",
"constellix",
"corenetworks",
"cpanel",
"czechia",
"ddnss",
"derak",
"desec",
"designate",
"digitalocean",
"directadmin",
"dnsexit",
"dnshomede",
"dnsimple",
"dnsmadeeasy",
@ -67,6 +74,8 @@ func allDNSCodes() string {
"edgeone",
"efficientip",
"epik",
"eurodns",
"excedo",
"exec",
"exoscale",
"f5xc",
@ -100,9 +109,13 @@ func allDNSCodes() string {
"ionos",
"ionoscloud",
"ipv64",
"ispconfig",
"ispconfigddns",
"iwantmyname",
"jdcloud",
"joker",
"keyhelp",
"leaseweb",
"liara",
"lightsail",
"limacity",
@ -123,6 +136,7 @@ func allDNSCodes() string {
"namecheap",
"namedotcom",
"namesilo",
"namesurfer",
"nearlyfreespeech",
"neodigit",
"netcup",
@ -164,6 +178,7 @@ func allDNSCodes() string {
"technitium",
"tencentcloud",
"timewebcloud",
"todaynic",
"transip",
"ultradns",
"uniteddomains",
@ -254,8 +269,10 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "ALICLOUD_HTTP_TIMEOUT": API request timeout in seconds (Default: 10)`)
ew.writeln(` - "ALICLOUD_LINE": Line (Default: default)`)
ew.writeln(` - "ALICLOUD_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "ALICLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "ALICLOUD_REGION_ID": Region ID (Default: cn-hangzhou)`)
ew.writeln(` - "ALICLOUD_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 600)`)
ew.writeln()
@ -304,6 +321,27 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/allinkl`)
case "alwaysdata":
// generated from: providers/dns/alwaysdata/alwaysdata.toml
ew.writeln(`Configuration for Alwaysdata.`)
ew.writeln(`Code: 'alwaysdata'`)
ew.writeln(`Since: 'v4.31.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "ALWAYSDATA_API_KEY": API Key`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "ALWAYSDATA_ACCOUNT": Account name`)
ew.writeln(` - "ALWAYSDATA_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "ALWAYSDATA_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "ALWAYSDATA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "ALWAYSDATA_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/alwaysdata`)
case "anexia":
// generated from: providers/dns/anexia/anexia.toml
ew.writeln(`Configuration for Anexia CloudDNS.`)
@ -325,6 +363,27 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/anexia`)
case "artfiles":
// generated from: providers/dns/artfiles/artfiles.toml
ew.writeln(`Configuration for ArtFiles.`)
ew.writeln(`Code: 'artfiles'`)
ew.writeln(`Since: 'v4.32.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "ARTFILES_PASSWORD": API password`)
ew.writeln(` - "ARTFILES_USERNAME": API username`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "ARTFILES_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "ARTFILES_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "ARTFILES_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 360)`)
ew.writeln(` - "ARTFILES_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/artfiles`)
case "arvancloud":
// generated from: providers/dns/arvancloud/arvancloud.toml
ew.writeln(`Configuration for ArvanCloud.`)
@ -594,6 +653,31 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/bluecat`)
case "bluecatv2":
// generated from: providers/dns/bluecatv2/bluecatv2.toml
ew.writeln(`Configuration for Bluecat v2.`)
ew.writeln(`Code: 'bluecatv2'`)
ew.writeln(`Since: 'v4.32.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "BLUECATV2_CONFIG_NAME": Configuration name`)
ew.writeln(` - "BLUECATV2_PASSWORD": API password`)
ew.writeln(` - "BLUECATV2_USERNAME": API username`)
ew.writeln(` - "BLUECATV2_VIEW_NAME": DNS View Name`)
ew.writeln(` - "BLUECAT_SERVER_URL": The server URL: it should have a scheme, hostname, and port (if required) of the authoritative Bluecat BAM serve`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "BLUECATV2_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "BLUECATV2_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "BLUECATV2_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "BLUECATV2_SKIP_DEPLOY": Skip quick deployements`)
ew.writeln(` - "BLUECATV2_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/bluecatv2`)
case "bookmyname":
// generated from: providers/dns/bookmyname/bookmyname.toml
ew.writeln(`Configuration for BookMyName.`)
@ -812,6 +896,27 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/cloudxns`)
case "com35":
// generated from: providers/dns/com35/com35.toml
ew.writeln(`Configuration for 35.com/三五互联.`)
ew.writeln(`Code: 'com35'`)
ew.writeln(`Since: 'v4.31.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "COM35_PASSWORD": API password`)
ew.writeln(` - "COM35_USERNAME": Username`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "COM35_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "COM35_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 10)`)
ew.writeln(` - "COM35_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 120)`)
ew.writeln(` - "COM35_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/com35`)
case "conoha":
// generated from: providers/dns/conoha/conoha.toml
ew.writeln(`Configuration for ConoHa v2.`)
@ -924,6 +1029,47 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/cpanel`)
case "czechia":
// generated from: providers/dns/czechia/czechia.toml
ew.writeln(`Configuration for Czechia.`)
ew.writeln(`Code: 'czechia'`)
ew.writeln(`Since: 'v4.33.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "CZECHIA_TOKEN": Authorization token`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "CZECHIA_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "CZECHIA_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "CZECHIA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "CZECHIA_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/czechia`)
case "ddnss":
// generated from: providers/dns/ddnss/ddnss.toml
ew.writeln(`Configuration for DDnss (DynDNS Service).`)
ew.writeln(`Code: 'ddnss'`)
ew.writeln(`Since: 'v4.32.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "DDNSS_KEY": Update key`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "DDNSS_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "DDNSS_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "DDNSS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "DDNSS_SEQUENCE_INTERVAL": Time between sequential requests in seconds (Default: 60)`)
ew.writeln(` - "DDNSS_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/ddnss`)
case "derak":
// generated from: providers/dns/derak/derak.toml
ew.writeln(`Configuration for Derak Cloud.`)
@ -1039,6 +1185,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/directadmin`)
case "dnsexit":
// generated from: providers/dns/dnsexit/dnsexit.toml
ew.writeln(`Configuration for DNSExit.`)
ew.writeln(`Code: 'dnsexit'`)
ew.writeln(`Since: 'v4.32.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "DNSEXIT_API_KEY": API key`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "DNSEXIT_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "DNSEXIT_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 10)`)
ew.writeln(` - "DNSEXIT_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 300)`)
ew.writeln(` - "DNSEXIT_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/dnsexit`)
case "dnshomede":
// generated from: providers/dns/dnshomede/dnshomede.toml
ew.writeln(`Configuration for dnsHome.de.`)
@ -1398,6 +1564,48 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/epik`)
case "eurodns":
// generated from: providers/dns/eurodns/eurodns.toml
ew.writeln(`Configuration for EuroDNS.`)
ew.writeln(`Code: 'eurodns'`)
ew.writeln(`Since: 'v4.33.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "EURODNS_API_KEY": API key`)
ew.writeln(` - "EURODNS_APP_ID": Application ID`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "EURODNS_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "EURODNS_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "EURODNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "EURODNS_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 600)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/eurodns`)
case "excedo":
// generated from: providers/dns/excedo/excedo.toml
ew.writeln(`Configuration for Excedo.`)
ew.writeln(`Code: 'excedo'`)
ew.writeln(`Since: 'v4.33.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "EXCEDO_API_KEY": API key`)
ew.writeln(` - "EXCEDO_API_URL": API base URL`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "EXCEDO_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "EXCEDO_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 10)`)
ew.writeln(` - "EXCEDO_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 300)`)
ew.writeln(` - "EXCEDO_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/excedo`)
case "exec":
// generated from: providers/dns/exec/exec.toml
ew.writeln(`Configuration for External program.`)
@ -1447,6 +1655,7 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln(` - "F5XC_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "F5XC_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "F5XC_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "F5XC_SERVER": Server domain (Default: console.ves.volterra.io)`)
ew.writeln(` - "F5XC_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
@ -2083,6 +2292,50 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/ipv64`)
case "ispconfig":
// generated from: providers/dns/ispconfig/ispconfig.toml
ew.writeln(`Configuration for ISPConfig 3.`)
ew.writeln(`Code: 'ispconfig'`)
ew.writeln(`Since: 'v4.31.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "ISPCONFIG_PASSWORD": Password`)
ew.writeln(` - "ISPCONFIG_SERVER_URL": Server URL`)
ew.writeln(` - "ISPCONFIG_USERNAME": Username`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "ISPCONFIG_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "ISPCONFIG_INSECURE_SKIP_VERIFY": Whether to verify the API certificate`)
ew.writeln(` - "ISPCONFIG_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "ISPCONFIG_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "ISPCONFIG_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/ispconfig`)
case "ispconfigddns":
// generated from: providers/dns/ispconfigddns/ispconfigddns.toml
ew.writeln(`Configuration for ISPConfig 3 - Dynamic DNS (DDNS) Module.`)
ew.writeln(`Code: 'ispconfigddns'`)
ew.writeln(`Since: 'v4.31.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "ISPCONFIG_DDNS_SERVER_URL": API server URL (ex: https://panel.example.com:8080)`)
ew.writeln(` - "ISPCONFIG_DDNS_TOKEN": DDNS API token`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "ISPCONFIG_DDNS_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "ISPCONFIG_DDNS_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "ISPCONFIG_DDNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "ISPCONFIG_DDNS_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/ispconfigddns`)
case "iwantmyname":
// generated from: providers/dns/iwantmyname/iwantmyname.toml
ew.writeln(`Configuration for iwantmyname (Deprecated).`)
@ -2104,6 +2357,28 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/iwantmyname`)
case "jdcloud":
// generated from: providers/dns/jdcloud/jdcloud.toml
ew.writeln(`Configuration for JD Cloud.`)
ew.writeln(`Code: 'jdcloud'`)
ew.writeln(`Since: 'v4.31.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "JDCLOUD_ACCESS_KEY_ID": Access key ID`)
ew.writeln(` - "JDCLOUD_ACCESS_KEY_SECRET": Access key secret`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "JDCLOUD_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "JDCLOUD_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "JDCLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "JDCLOUD_REGION_ID": Region ID (Default: cn-north-1)`)
ew.writeln(` - "JDCLOUD_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/jdcloud`)
case "joker":
// generated from: providers/dns/joker/joker.toml
ew.writeln(`Configuration for Joker.`)
@ -2149,6 +2424,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/keyhelp`)
case "leaseweb":
// generated from: providers/dns/leaseweb/leaseweb.toml
ew.writeln(`Configuration for Leaseweb.`)
ew.writeln(`Code: 'leaseweb'`)
ew.writeln(`Since: 'v4.32.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "LEASEWEB_API_KEY": API key`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "LEASEWEB_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "LEASEWEB_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "LEASEWEB_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "LEASEWEB_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/leaseweb`)
case "liara":
// generated from: providers/dns/liara/liara.toml
ew.writeln(`Configuration for Liara.`)
@ -2164,6 +2459,7 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln(` - "LIARA_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "LIARA_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "LIARA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "LIARA_TEAM_ID": The team ID to access services in a team`)
ew.writeln(` - "LIARA_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)`)
ew.writeln()
@ -2556,6 +2852,30 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/namesilo`)
case "namesurfer":
// generated from: providers/dns/namesurfer/namesurfer.toml
ew.writeln(`Configuration for FusionLayer NameSurfer.`)
ew.writeln(`Code: 'namesurfer'`)
ew.writeln(`Since: 'v4.32.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "NAMESURFER_API_KEY": API key name`)
ew.writeln(` - "NAMESURFER_API_SECRET": API secret`)
ew.writeln(` - "NAMESURFER_BASE_URL": The base URL of NameSurfer API (jsonrpc10) endpoint URL (e.g., https://foo.example.com:8443/API/NSService_10)`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "NAMESURFER_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "NAMESURFER_INSECURE_SKIP_VERIFY": Whether to verify the API certificate`)
ew.writeln(` - "NAMESURFER_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "NAMESURFER_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 120)`)
ew.writeln(` - "NAMESURFER_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)`)
ew.writeln(` - "NAMESURFER_VIEW": DNS view name (optional, default: empty string)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/namesurfer`)
case "nearlyfreespeech":
// generated from: providers/dns/nearlyfreespeech/nearlyfreespeech.toml
ew.writeln(`Configuration for NearlyFreeSpeech.NET.`)
@ -3119,7 +3439,7 @@ func displayDNSHelp(w io.Writer, name string) error {
case "safedns":
// generated from: providers/dns/safedns/safedns.toml
ew.writeln(`Configuration for UKFast SafeDNS.`)
ew.writeln(`Configuration for ANS SafeDNS.`)
ew.writeln(`Code: 'safedns'`)
ew.writeln(`Since: 'v4.6.0'`)
ew.writeln()
@ -3460,6 +3780,27 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/timewebcloud`)
case "todaynic":
// generated from: providers/dns/todaynic/todaynic.toml
ew.writeln(`Configuration for TodayNIC/时代互联.`)
ew.writeln(`Code: 'todaynic'`)
ew.writeln(`Since: 'v4.32.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "TODAYNIC_API_KEY": API key`)
ew.writeln(` - "TODAYNIC_AUTH_USER_ID": account ID`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "TODAYNIC_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "TODAYNIC_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "TODAYNIC_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "TODAYNIC_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 600)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/todaynic`)
case "transip":
// generated from: providers/dns/transip/transip.toml
ew.writeln(`Configuration for TransIP.`)

View file

@ -24,7 +24,7 @@ I've been maintaining it for about 10 years.
- Support [RFC 8738](https://www.rfc-editor.org/rfc/rfc8738.html): issues certificates for IP addresses
- Support [RFC 9773](https://www.rfc-editor.org/rfc/rfc9773.html): Renewal Information (ARI) Extension
- Support [draft-ietf-acme-profiles-00](https://datatracker.ietf.org/doc/draft-ietf-acme-profiles/): Profiles Extension
- Comes with about [170 DNS providers]({{% ref "dns" %}})
- Comes with about [180 DNS providers]({{% ref "dns" %}})
- Register with CA
- Obtain certificates, both from scratch or with an existing CSR
- Renew certificates

View file

@ -28,13 +28,13 @@ Here is an example bash command using the Joohoi's ACME-DNS provider:
```bash
ACME_DNS_API_BASE=http://10.0.0.8:4443 \
ACME_DNS_STORAGE_PATH=/root/.lego-acme-dns-accounts.json \
lego --email you@example.com --dns "acme-dns" -d '*.example.com' -d example.com run
lego --dns "acme-dns" -d '*.example.com' -d example.com run
# or
ACME_DNS_API_BASE=http://10.0.0.8:4443 \
ACME_DNS_STORAGE_BASE_URL=http://10.10.10.10:80 \
lego --email you@example.com --dns "acme-dns" -d '*.example.com' -d example.com run
lego --dns "acme-dns" -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Active24 provider:
```bash
ACTIVE24_API_KEY="xxx" \
ACTIVE24_SECRET="yyy" \
lego --email you@example.com --dns active24 -d '*.example.com' -d example.com run
lego --dns active24 -d '*.example.com' -d example.com run
```

View file

@ -28,13 +28,13 @@ Here is an example bash command using the Alibaba Cloud DNS provider:
```bash
# Setup using instance RAM role
ALICLOUD_RAM_ROLE=lego \
lego --email you@example.com --dns alidns -d '*.example.com' -d example.com run
lego --dns alidns -d '*.example.com' -d example.com run
# Or, using credentials
ALICLOUD_ACCESS_KEY=abcdefghijklmnopqrstuvwx \
ALICLOUD_SECRET_KEY=your-secret-key \
ALICLOUD_SECURITY_TOKEN=your-sts-token \
lego --email you@example.com --dns alidns - -d '*.example.com' -d example.com run
lego --dns alidns - -d '*.example.com' -d example.com run
```
@ -58,8 +58,10 @@ More information [here]({{% ref "dns#configuration-and-credentials" %}}).
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `ALICLOUD_HTTP_TIMEOUT` | API request timeout in seconds (Default: 10) |
| `ALICLOUD_LINE` | Line (Default: default) |
| `ALICLOUD_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `ALICLOUD_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `ALICLOUD_REGION_ID` | Region ID (Default: cn-hangzhou) |
| `ALICLOUD_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 600) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.

View file

@ -28,13 +28,13 @@ Here is an example bash command using the AlibabaCloud ESA provider:
```bash
# Setup using instance RAM role
ALIESA_RAM_ROLE=lego \
lego --email you@example.com --dns aliesa -d '*.example.com' -d example.com run
lego --dns aliesa -d '*.example.com' -d example.com run
# Or, using credentials
ALIESA_ACCESS_KEY=abcdefghijklmnopqrstuvwx \
ALIESA_SECRET_KEY=your-secret-key \
ALIESA_SECURITY_TOKEN=your-sts-token \
lego --email you@example.com --dns aliesa - -d '*.example.com' -d example.com run
lego --dns aliesa - -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the all-inkl provider:
```bash
ALL_INKL_LOGIN=xxxxxxxxxxxxxxxxxxxxxxxxxx \
ALL_INKL_PASSWORD=yyyyyyyyyyyyyyyyyyyyyyyyyy \
lego --email you@example.com --dns allinkl -d '*.example.com' -d example.com run
lego --dns allinkl -d '*.example.com' -d example.com run
```

68
docs/content/dns/zz_gen_alwaysdata.md generated Normal file
View file

@ -0,0 +1,68 @@
---
title: "Alwaysdata"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: alwaysdata
dnsprovider:
since: "v4.31.0"
code: "alwaysdata"
url: "https://alwaysdata.com/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/alwaysdata/alwaysdata.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [Alwaysdata](https://alwaysdata.com/).
<!--more-->
- Code: `alwaysdata`
- Since: v4.31.0
Here is an example bash command using the Alwaysdata provider:
```bash
ALWAYSDATA_API_KEY="xxxxxxxxxxxxxxxxxxxxx" \
lego --dns alwaysdata -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `ALWAYSDATA_API_KEY` | API Key |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `ALWAYSDATA_ACCOUNT` | Account name |
| `ALWAYSDATA_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `ALWAYSDATA_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `ALWAYSDATA_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `ALWAYSDATA_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://help.alwaysdata.com/en/api/resources/)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/alwaysdata/alwaysdata.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Anexia CloudDNS provider:
```bash
ANEXIA_TOKEN=xxx \
lego --email you@example.com --dns anexia -d '*.example.com' -d example.com run
lego --dns anexia -d '*.example.com' -d example.com run
```

69
docs/content/dns/zz_gen_artfiles.md generated Normal file
View file

@ -0,0 +1,69 @@
---
title: "ArtFiles"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: artfiles
dnsprovider:
since: "v4.32.0"
code: "artfiles"
url: "https://www.artfiles.de/extras/domains/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/artfiles/artfiles.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [ArtFiles](https://www.artfiles.de/extras/domains/).
<!--more-->
- Code: `artfiles`
- Since: v4.32.0
Here is an example bash command using the ArtFiles provider:
```bash
ARTFILES_USERNAME="xxx" \
ARTFILES_PASSWORD="yyy" \
lego --dns artfiles -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `ARTFILES_PASSWORD` | API password |
| `ARTFILES_USERNAME` | API username |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `ARTFILES_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `ARTFILES_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `ARTFILES_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 360) |
| `ARTFILES_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://support.artfiles.de/DCP-API#dns)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/artfiles/artfiles.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -27,7 +27,7 @@ Here is an example bash command using the ArvanCloud provider:
```bash
ARVANCLOUD_API_KEY="Apikey xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \
lego --email you@example.com --dns arvancloud -d '*.example.com' -d example.com run
lego --dns arvancloud -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Aurora DNS provider:
```bash
AURORA_API_KEY=xxxxx \
AURORA_SECRET=yyyyyy \
lego --email you@example.com --dns auroradns -d '*.example.com' -d example.com run
lego --dns auroradns -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Autodns provider:
```bash
AUTODNS_API_USER=username \
AUTODNS_API_PASSWORD=supersecretpassword \
lego --email you@example.com --dns autodns -d '*.example.com' -d example.com run
lego --dns autodns -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Axelname provider:
```bash
AXELNAME_NICKNAME="yyy" \
AXELNAME_TOKEN="xxx" \
lego --email you@example.com --dns axelname -d '*.example.com' -d example.com run
lego --dns axelname -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Azion provider:
```bash
AZION_PERSONAL_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxx \
lego --email you@example.com --dns azion -d '*.example.com' -d example.com run
lego --dns azion -d '*.example.com' -d example.com run
```

View file

@ -31,32 +31,32 @@ Here is an example bash command using the Azure DNS provider:
AZURE_CLIENT_ID=<your service principal client ID> \
AZURE_TENANT_ID=<your service principal tenant ID> \
AZURE_CLIENT_SECRET=<your service principal client secret> \
lego --email you@example.com --dns azuredns -d '*.example.com' -d example.com run
lego --dns azuredns -d '*.example.com' -d example.com run
### Using client certificate
AZURE_CLIENT_ID=<your service principal client ID> \
AZURE_TENANT_ID=<your service principal tenant ID> \
AZURE_CLIENT_CERTIFICATE_PATH=<your service principal certificate path> \
lego --email you@example.com --dns azuredns -d '*.example.com' -d example.com run
lego --dns azuredns -d '*.example.com' -d example.com run
### Using Azure CLI
az login \
lego --email you@example.com --dns azuredns -d '*.example.com' -d example.com run
lego --dns azuredns -d '*.example.com' -d example.com run
### Using Managed Identity (Azure VM)
AZURE_TENANT_ID=<your service principal tenant ID> \
AZURE_RESOURCE_GROUP=<your target zone resource group name> \
lego --email you@example.com --dns azuredns -d '*.example.com' -d example.com run
lego --dns azuredns -d '*.example.com' -d example.com run
### Using Managed Identity (Azure Arc)
AZURE_TENANT_ID=<your service principal tenant ID> \
IMDS_ENDPOINT=http://localhost:40342 \
IDENTITY_ENDPOINT=http://localhost:40342/metadata/identity/oauth2/token \
lego --email you@example.com --dns azuredns -d '*.example.com' -d example.com run
lego --dns azuredns -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Baidu Cloud provider:
```bash
BAIDUCLOUD_ACCESS_KEY_ID="xxx" \
BAIDUCLOUD_SECRET_ACCESS_KEY="yyy" \
lego --email you@example.com --dns baiducloud -d '*.example.com' -d example.com run
lego --dns baiducloud -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Beget.com provider:
```bash
BEGET_USERNAME=xxxxxx \
BEGET_PASSWORD=yyyyyy \
lego --email you@example.com --dns beget -d '*.example.com' -d example.com run
lego --dns beget -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Binary Lane provider:
```bash
BINARYLANE_API_TOKEN="xxxxxxxxxxxxxxxxxxxxx" \
lego --email you@example.com --dns binarylane -d '*.example.com' -d example.com run
lego --dns binarylane -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Bindman provider:
```bash
BINDMAN_MANAGER_ADDRESS=<your bindman manager address> \
lego --email you@example.com --dns bindman -d '*.example.com' -d example.com run
lego --dns bindman -d '*.example.com' -d example.com run
```

View file

@ -32,7 +32,7 @@ BLUECAT_USER_NAME=myusername \
BLUECAT_CONFIG_NAME=myconfig \
BLUECAT_SERVER_URL=https://bam.example.com \
BLUECAT_TTL=30 \
lego --email you@example.com --dns bluecat -d '*.example.com' -d example.com run
lego --dns bluecat -d '*.example.com' -d example.com run
```

76
docs/content/dns/zz_gen_bluecatv2.md generated Normal file
View file

@ -0,0 +1,76 @@
---
title: "Bluecat v2"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: bluecatv2
dnsprovider:
since: "v4.32.0"
code: "bluecatv2"
url: "https://www.bluecatnetworks.com"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/bluecatv2/bluecatv2.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [Bluecat v2](https://www.bluecatnetworks.com).
<!--more-->
- Code: `bluecatv2`
- Since: v4.32.0
Here is an example bash command using the Bluecat v2 provider:
```bash
BLUECATV2_SERVER_URL="https://example.com" \
BLUECATV2_USERNAME="xxx" \
BLUECATV2_PASSWORD="yyy" \
BLUECATV2_CONFIG_NAME="myConfiguration" \
BLUECATV2_VIEW_NAME="myView" \
lego --dns bluecatv2 -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `BLUECATV2_CONFIG_NAME` | Configuration name |
| `BLUECATV2_PASSWORD` | API password |
| `BLUECATV2_USERNAME` | API username |
| `BLUECATV2_VIEW_NAME` | DNS View Name |
| `BLUECAT_SERVER_URL` | The server URL: it should have a scheme, hostname, and port (if required) of the authoritative Bluecat BAM serve |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `BLUECATV2_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `BLUECATV2_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `BLUECATV2_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `BLUECATV2_SKIP_DEPLOY` | Skip quick deployements |
| `BLUECATV2_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://docs.bluecatnetworks.com/r/Address-Manager-RESTful-v2-API-Guide/Introduction/9.6.0)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/bluecatv2/bluecatv2.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -28,7 +28,7 @@ Here is an example bash command using the BookMyName provider:
```bash
BOOKMYNAME_USERNAME="xxx" \
BOOKMYNAME_PASSWORD="yyy" \
lego --email you@example.com --dns bookmyname -d '*.example.com' -d example.com run
lego --dns bookmyname -d '*.example.com' -d example.com run
```

View file

@ -31,7 +31,7 @@ Here is an example bash command using the Brandit (deprecated) provider:
```bash
BRANDIT_API_KEY=xxxxxxxxxxxxxxxxxxxxx \
BRANDIT_API_USERNAME=yyyyyyyyyyyyyyyyyyyy \
lego --email you@example.com --dns brandit -d '*.example.com' -d example.com run
lego --dns brandit -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Bunny provider:
```bash
BUNNY_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
lego --email you@example.com --dns bunny -d '*.example.com' -d example.com run
lego --dns bunny -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Checkdomain provider:
```bash
CHECKDOMAIN_TOKEN=yoursecrettoken \
lego --email you@example.com --dns checkdomain -d '*.example.com' -d example.com run
lego --dns checkdomain -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Civo provider:
```bash
CIVO_TOKEN=xxxxxx \
lego --email you@example.com --dns civo -d '*.example.com' -d example.com run
lego --dns civo -d '*.example.com' -d example.com run
```

View file

@ -29,7 +29,7 @@ Here is an example bash command using the CloudDNS provider:
CLOUDDNS_CLIENT_ID=bLsdFAks23429841238feb177a572aX \
CLOUDDNS_EMAIL=you@example.com \
CLOUDDNS_PASSWORD=b9841238feb177a84330f \
lego --email you@example.com --dns clouddns -d '*.example.com' -d example.com run
lego --dns clouddns -d '*.example.com' -d example.com run
```

View file

@ -28,12 +28,12 @@ Here is an example bash command using the Cloudflare provider:
```bash
CLOUDFLARE_EMAIL=you@example.com \
CLOUDFLARE_API_KEY=b9841238feb177a84330febba8a83208921177bffe733 \
lego --email you@example.com --dns cloudflare -d '*.example.com' -d example.com run
lego --dns cloudflare -d '*.example.com' -d example.com run
# or
CLOUDFLARE_DNS_API_TOKEN=1234567890abcdefghijklmnopqrstuvwxyz \
lego --email you@example.com --dns cloudflare -d '*.example.com' -d example.com run
lego --dns cloudflare -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the ClouDNS provider:
```bash
CLOUDNS_AUTH_ID=xxxx \
CLOUDNS_AUTH_PASSWORD=yyyy \
lego --email you@example.com --dns cloudns -d '*.example.com' -d example.com run
lego --dns cloudns -d '*.example.com' -d example.com run
```

View file

@ -29,7 +29,7 @@ Here is an example bash command using the Cloud.ru provider:
CLOUDRU_SERVICE_INSTANCE_ID=ppp \
CLOUDRU_KEY_ID=xxx \
CLOUDRU_SECRET=yyy \
lego --email you@example.com --dns cloudru -d '*.example.com' -d example.com run
lego --dns cloudru -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the CloudXNS (Deprecated) provider:
```bash
CLOUDXNS_API_KEY=xxxx \
CLOUDXNS_SECRET_KEY=yyyy \
lego --email you@example.com --dns cloudxns -d '*.example.com' -d example.com run
lego --dns cloudxns -d '*.example.com' -d example.com run
```

69
docs/content/dns/zz_gen_com35.md generated Normal file
View file

@ -0,0 +1,69 @@
---
title: "35.com/三五互联"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: com35
dnsprovider:
since: "v4.31.0"
code: "com35"
url: "https://www.35.cn/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/com35/com35.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [35.com/三五互联](https://www.35.cn/).
<!--more-->
- Code: `com35`
- Since: v4.31.0
Here is an example bash command using the 35.com/三五互联 provider:
```bash
COM35_USERNAME="xxx" \
COM35_PASSWORD="yyy" \
lego --dns com35 -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `COM35_PASSWORD` | API password |
| `COM35_USERNAME` | Username |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `COM35_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `COM35_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 10) |
| `COM35_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 120) |
| `COM35_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 60) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://api.35.cn/CustomerCenter/doc/domain_v2.html)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/com35/com35.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -29,7 +29,7 @@ Here is an example bash command using the ConoHa v2 provider:
CONOHA_TENANT_ID=487727e3921d44e3bfe7ebb337bf085e \
CONOHA_API_USERNAME=xxxx \
CONOHA_API_PASSWORD=yyyy \
lego --email you@example.com --dns conoha -d '*.example.com' -d example.com run
lego --dns conoha -d '*.example.com' -d example.com run
```

View file

@ -29,7 +29,7 @@ Here is an example bash command using the ConoHa v3 provider:
CONOHAV3_TENANT_ID=487727e3921d44e3bfe7ebb337bf085e \
CONOHAV3_API_USER_ID=xxxx \
CONOHAV3_API_PASSWORD=yyyy \
lego --email you@example.com --dns conohav3 -d '*.example.com' -d example.com run
lego --dns conohav3 -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Constellix provider:
```bash
CONSTELLIX_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
CONSTELLIX_SECRET_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
lego --email you@example.com --dns constellix -d '*.example.com' -d example.com run
lego --dns constellix -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Core-Networks provider:
```bash
CORENETWORKS_LOGIN="xxxx" \
CORENETWORKS_PASSWORD="yyyy" \
lego --email you@example.com --dns corenetworks -d '*.example.com' -d example.com run
lego --dns corenetworks -d '*.example.com' -d example.com run
```

View file

@ -31,7 +31,7 @@ Here is an example bash command using the CPanel/WHM provider:
CPANEL_USERNAME="yyyy" \
CPANEL_TOKEN="xxxx" \
CPANEL_BASE_URL="https://example.com:2083" \
lego --email you@example.com --dns cpanel -d '*.example.com' -d example.com run
lego --dns cpanel -d '*.example.com' -d example.com run
## WHM
@ -39,7 +39,7 @@ CPANEL_MODE=whm \
CPANEL_USERNAME="yyyy" \
CPANEL_TOKEN="xxxx" \
CPANEL_BASE_URL="https://example.com:2087" \
lego --email you@example.com --dns cpanel -d '*.example.com' -d example.com run
lego --dns cpanel -d '*.example.com' -d example.com run
```

67
docs/content/dns/zz_gen_czechia.md generated Normal file
View file

@ -0,0 +1,67 @@
---
title: "Czechia"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: czechia
dnsprovider:
since: "v4.33.0"
code: "czechia"
url: "https://www.czechia.com/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/czechia/czechia.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [Czechia](https://www.czechia.com/).
<!--more-->
- Code: `czechia`
- Since: v4.33.0
Here is an example bash command using the Czechia provider:
```bash
CZECHIA_TOKEN="xxxxxxxxxxxxxxxxxxxxx" \
lego --dns czechia -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `CZECHIA_TOKEN` | Authorization token |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `CZECHIA_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `CZECHIA_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `CZECHIA_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `CZECHIA_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://api.czechia.com/swagger/index.html)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/czechia/czechia.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

68
docs/content/dns/zz_gen_ddnss.md generated Normal file
View file

@ -0,0 +1,68 @@
---
title: "DDnss (DynDNS Service)"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: ddnss
dnsprovider:
since: "v4.32.0"
code: "ddnss"
url: "https://ddnss.de/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/ddnss/ddnss.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [DDnss (DynDNS Service)](https://ddnss.de/).
<!--more-->
- Code: `ddnss`
- Since: v4.32.0
Here is an example bash command using the DDnss (DynDNS Service) provider:
```bash
DDNSS_KEY="xxxxxxxxxxxxxxxxxxxxx" \
lego --dns ddnss -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `DDNSS_KEY` | Update key |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `DDNSS_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `DDNSS_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `DDNSS_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `DDNSS_SEQUENCE_INTERVAL` | Time between sequential requests in seconds (Default: 60) |
| `DDNSS_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://ddnss.de/info.php)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/ddnss/ddnss.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Derak Cloud provider:
```bash
DERAK_API_KEY="xxxxxxxxxxxxxxxxxxxxx" \
lego --email you@example.com --dns derak -d '*.example.com' -d example.com run
lego --dns derak -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the deSEC.io provider:
```bash
DESEC_TOKEN=x-xxxxxxxxxxxxxxxxxxxxxxxxxx \
lego --email you@example.com --dns desec -d '*.example.com' -d example.com run
lego --dns desec -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Designate DNSaaS for Openstack provide
```bash
# With a `clouds.yaml`
OS_CLOUD=my_openstack \
lego --email you@example.com --dns designate -d '*.example.com' -d example.com run
lego --dns designate -d '*.example.com' -d example.com run
# or
@ -37,7 +37,7 @@ OS_REGION_NAME=RegionOne \
OS_PROJECT_ID=23d4522a987d4ab529f722a007c27846
OS_USERNAME=myuser \
OS_PASSWORD=passw0rd \
lego --email you@example.com --dns designate -d '*.example.com' -d example.com run
lego --dns designate -d '*.example.com' -d example.com run
# or
@ -46,7 +46,7 @@ OS_REGION_NAME=RegionOne \
OS_AUTH_TYPE=v3applicationcredential \
OS_APPLICATION_CREDENTIAL_ID=imn74uq0or7dyzz20dwo1ytls4me8dry \
OS_APPLICATION_CREDENTIAL_SECRET=68FuSPSdQqkFQYH5X1OoriEIJOwyLtQ8QSqXZOc9XxFK1A9tzZT6He2PfPw0OMja \
lego --email you@example.com --dns designate -d '*.example.com' -d example.com run
lego --dns designate -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Digital Ocean provider:
```bash
DO_AUTH_TOKEN=xxxxxx \
lego --email you@example.com --dns digitalocean -d '*.example.com' -d example.com run
lego --dns digitalocean -d '*.example.com' -d example.com run
```

View file

@ -29,7 +29,7 @@ Here is an example bash command using the DirectAdmin provider:
DIRECTADMIN_API_URL="http://example.com:2222" \
DIRECTADMIN_USERNAME=xxxx \
DIRECTADMIN_PASSWORD=yyy \
lego --email you@example.com --dns directadmin -d '*.example.com' -d example.com run
lego --dns directadmin -d '*.example.com' -d example.com run
```

67
docs/content/dns/zz_gen_dnsexit.md generated Normal file
View file

@ -0,0 +1,67 @@
---
title: "DNSExit"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: dnsexit
dnsprovider:
since: "v4.32.0"
code: "dnsexit"
url: "https://dnsexit.com"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/dnsexit/dnsexit.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [DNSExit](https://dnsexit.com).
<!--more-->
- Code: `dnsexit`
- Since: v4.32.0
Here is an example bash command using the DNSExit provider:
```bash
DNSEXIT_API_KEY="xxxxxxxxxxxxxxxxxxxxx" \
lego --dns dnsexit -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `DNSEXIT_API_KEY` | API key |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `DNSEXIT_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `DNSEXIT_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 10) |
| `DNSEXIT_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 300) |
| `DNSEXIT_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://dnsexit.com/dns/dns-api/)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/dnsexit/dnsexit.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -27,10 +27,10 @@ Here is an example bash command using the dnsHome.de provider:
```bash
DNSHOMEDE_CREDENTIALS=example.org:password \
lego --email you@example.com --dns dnshomede -d '*.example.com' -d example.com run
lego --dns dnshomede -d '*.example.com' -d example.com run
DNSHOMEDE_CREDENTIALS=my.example.org:password1,demo.example.org:password2 \
lego --email you@example.com --dns dnshomede -d my.example.org -d demo.example.org
lego --dns dnshomede -d my.example.org -d demo.example.org
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the DNSimple provider:
```bash
DNSIMPLE_OAUTH_TOKEN=1234567890abcdefghijklmnopqrstuvwxyz \
lego --email you@example.com --dns dnsimple -d '*.example.com' -d example.com run
lego --dns dnsimple -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the DNS Made Easy provider:
```bash
DNSMADEEASY_API_KEY=xxxxxx \
DNSMADEEASY_API_SECRET=yyyyy \
lego --email you@example.com --dns dnsmadeeasy -d '*.example.com' -d example.com run
lego --dns dnsmadeeasy -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the DNSPod (deprecated) provider:
```bash
DNSPOD_API_KEY=xxxxxx \
lego --email you@example.com --dns dnspod -d '*.example.com' -d example.com run
lego --dns dnspod -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Domain Offensive (do.de) provider:
```bash
DODE_TOKEN=xxxxxx \
lego --email you@example.com --dns dode -d '*.example.com' -d example.com run
lego --dns dode -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Domeneshop provider:
```bash
DOMENESHOP_API_TOKEN=<token> \
DOMENESHOP_API_SECRET=<secret> \
lego --email example@example.com --dns domeneshop -d '*.example.com' -d example.com run
lego --dns domeneshop -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the DreamHost provider:
```bash
DREAMHOST_API_KEY="YOURAPIKEY" \
lego --email you@example.com --dns dreamhost -d '*.example.com' -d example.com run
lego --dns dreamhost -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Duck DNS provider:
```bash
DUCKDNS_TOKEN=xxxxxx \
lego --email you@example.com --dns duckdns -d '*.example.com' -d example.com run
lego --dns duckdns -d '*.example.com' -d example.com run
```

View file

@ -29,7 +29,7 @@ Here is an example bash command using the Dyn provider:
DYN_CUSTOMER_NAME=xxxxxx \
DYN_USER_NAME=yyyyy \
DYN_PASSWORD=zzzz \
lego --email you@example.com --dns dyn -d '*.example.com' -d example.com run
lego --dns dyn -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the DynDnsFree.de provider:
```bash
DYNDNSFREE_USERNAME="xxx" \
DYNDNSFREE_PASSWORD="yyy" \
lego --email you@example.com --dns dyndnsfree -d '*.example.com' -d example.com run
lego --dns dyndnsfree -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Dynu provider:
```bash
DYNU_API_KEY=1234567890abcdefghijklmnopqrstuvwxyz \
lego --email you@example.com --dns dynu -d '*.example.com' -d example.com run
lego --dns dynu -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the EasyDNS provider:
```bash
EASYDNS_TOKEN=xxx \
EASYDNS_KEY=yyy \
lego --email you@example.com --dns easydns -d '*.example.com' -d example.com run
lego --dns easydns -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the EdgeCenter provider:
```bash
EDGECENTER_PERMANENT_API_TOKEN=xxxxx \
lego --email you@example.com --dns edgecenter -d '*.example.com' -d example.com run
lego --dns edgecenter -d '*.example.com' -d example.com run
```

View file

@ -30,7 +30,7 @@ AKAMAI_CLIENT_SECRET=abcdefghijklmnopqrstuvwxyz1234567890ABCDEFG= \
AKAMAI_CLIENT_TOKEN=akab-mnbvcxzlkjhgfdsapoiuytrewq1234567 \
AKAMAI_HOST=akab-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.luna.akamaiapis.net \
AKAMAI_ACCESS_TOKEN=akab-1234567890qwerty-asdfghjklzxcvtnu \
lego --email you@example.com --dns edgedns -d '*.example.com' -d example.com run
lego --dns edgedns -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Tencent EdgeOne provider:
```bash
EDGEONE_SECRET_ID=abcdefghijklmnopqrstuvwx \
EDGEONE_SECRET_KEY=your-secret-key \
lego --email you@example.com --dns edgeone -d '*.example.com' -d example.com run
lego --dns edgeone -d '*.example.com' -d example.com run
```

View file

@ -30,7 +30,7 @@ EFFICIENTIP_USERNAME="user" \
EFFICIENTIP_PASSWORD="secret" \
EFFICIENTIP_HOSTNAME="ipam.example.org" \
EFFICIENTIP_DNS_NAME="dns.smart" \
lego --email you@example.com --dns efficientip -d '*.example.com' -d example.com run
lego --dns efficientip -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Epik provider:
```bash
EPIK_SIGNATURE=xxxxxxxxxxxxxxxxxxxxxxxxxx \
lego --email you@example.com --dns epik -d '*.example.com' -d example.com run
lego --dns epik -d '*.example.com' -d example.com run
```

69
docs/content/dns/zz_gen_eurodns.md generated Normal file
View file

@ -0,0 +1,69 @@
---
title: "EuroDNS"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: eurodns
dnsprovider:
since: "v4.33.0"
code: "eurodns"
url: "https://www.eurodns.com/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/eurodns/eurodns.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [EuroDNS](https://www.eurodns.com/).
<!--more-->
- Code: `eurodns`
- Since: v4.33.0
Here is an example bash command using the EuroDNS provider:
```bash
EURODNS_APP_ID="xxx" \
EURODNS_API_KEY="yyy" \
lego --dns eurodns -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `EURODNS_API_KEY` | API key |
| `EURODNS_APP_ID` | Application ID |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `EURODNS_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `EURODNS_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `EURODNS_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `EURODNS_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 600) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](https://docapi.eurodns.com/)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/eurodns/eurodns.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

69
docs/content/dns/zz_gen_excedo.md generated Normal file
View file

@ -0,0 +1,69 @@
---
title: "Excedo"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: excedo
dnsprovider:
since: "v4.33.0"
code: "excedo"
url: "https://excedo.se/"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/excedo/excedo.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [Excedo](https://excedo.se/).
<!--more-->
- Code: `excedo`
- Since: v4.33.0
Here is an example bash command using the Excedo provider:
```bash
EXCEDO_API_KEY=your-api-key \
EXCEDO_API_URL=your-base-url \
lego --dns excedo -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `EXCEDO_API_KEY` | API key |
| `EXCEDO_API_URL` | API base URL |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## Additional Configuration
| Environment Variable Name | Description |
|--------------------------------|-------------|
| `EXCEDO_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `EXCEDO_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 10) |
| `EXCEDO_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 300) |
| `EXCEDO_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 60) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.
More information [here]({{% ref "dns#configuration-and-credentials" %}}).
## More information
- [API documentation](none)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/excedo/excedo.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

View file

@ -26,7 +26,7 @@ Here is an example bash command using the External program provider:
```bash
EXEC_PATH=/the/path/to/myscript.sh \
lego --email you@example.com --dns exec -d '*.example.com' -d example.com run
lego --dns exec -d '*.example.com' -d example.com run
```
@ -61,7 +61,7 @@ For example, requesting a certificate for the domain 'my.example.org' can be ach
```bash
EXEC_PATH=./update-dns.sh \
lego --email you@example.com --dns exec --d my.example.org run
lego --dns exec --d my.example.org run
```
It will then call the program './update-dns.sh' with like this:
@ -81,7 +81,7 @@ If you want to use the raw domain, token, and keyAuth values with your program,
```bash
EXEC_MODE=RAW \
EXEC_PATH=./update-dns.sh \
lego --email you@example.com --dns exec -d my.example.org run
lego --dns exec -d my.example.org run
```
It will then call the program `./update-dns.sh` like this:

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Exoscale provider:
```bash
EXOSCALE_API_KEY=abcdefghijklmnopqrstuvwx \
EXOSCALE_API_SECRET=xxxxxxx \
lego --email you@example.com --dns exoscale -d '*.example.com' -d example.com run
lego --dns exoscale -d '*.example.com' -d example.com run
```

View file

@ -29,7 +29,7 @@ Here is an example bash command using the F5 XC provider:
F5XC_API_TOKEN="xxx" \
F5XC_TENANT_NAME="yyy" \
F5XC_GROUP_NAME="zzz" \
lego --email you@example.com --dns f5xc -d '*.example.com' -d example.com run
lego --dns f5xc -d '*.example.com' -d example.com run
```
@ -54,6 +54,7 @@ More information [here]({{% ref "dns#configuration-and-credentials" %}}).
| `F5XC_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `F5XC_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `F5XC_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `F5XC_SERVER` | Server domain (Default: console.ves.volterra.io) |
| `F5XC_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
The environment variable names can be suffixed by `_FILE` to reference a file instead of a value.

View file

@ -27,7 +27,7 @@ Here is an example bash command using the freemyip.com provider:
```bash
FREEMYIP_TOKEN=xxxxxx \
lego --email you@example.com --dns freemyip -d '*.example.com' -d example.com run
lego --dns freemyip -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Gandi provider:
```bash
GANDI_API_KEY=abcdefghijklmnopqrstuvwx \
lego --email you@example.com --dns gandi -d '*.example.com' -d example.com run
lego --dns gandi -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the Gandi Live DNS (v5) provider:
```bash
GANDIV5_PERSONAL_ACCESS_TOKEN=abcdefghijklmnopqrstuvwx \
lego --email you@example.com --dns gandiv5 -d '*.example.com' -d example.com run
lego --dns gandiv5 -d '*.example.com' -d example.com run
```

View file

@ -29,18 +29,18 @@ Here is an example bash command using the Google Cloud provider:
# Using a service account file
GCE_PROJECT="gc-project-id" \
GCE_SERVICE_ACCOUNT_FILE="/path/to/svc/account/file.json" \
lego --email you@example.com --dns gcloud -d '*.example.com' -d example.com run
lego --dns gcloud -d '*.example.com' -d example.com run
# Using default credentials with impersonation
GCE_PROJECT="gc-project-id" \
GCE_IMPERSONATE_SERVICE_ACCOUNT="target-sa@gc-project-id.iam.gserviceaccount.com" \
lego --email you@example.com --dns gcloud -d '*.example.com' -d example.com run
lego --dns gcloud -d '*.example.com' -d example.com run
# Using service account key with impersonation
GCE_PROJECT="gc-project-id" \
GCE_SERVICE_ACCOUNT_FILE="/path/to/svc/account/file.json" \
GCE_IMPERSONATE_SERVICE_ACCOUNT="target-sa@gc-project-id.iam.gserviceaccount.com" \
lego --email you@example.com --dns gcloud -d '*.example.com' -d example.com run
lego --dns gcloud -d '*.example.com' -d example.com run
```

View file

@ -27,7 +27,7 @@ Here is an example bash command using the G-Core provider:
```bash
GCORE_PERMANENT_API_TOKEN=xxxxx \
lego --email you@example.com --dns gcore -d '*.example.com' -d example.com run
lego --dns gcore -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Gigahost.no provider:
```bash
GIGAHOSTNO_USERNAME="xxxxxxxxxxxxxxxxxxxxx" \
GIGAHOSTNO_PASSWORD="yyyyyyyyyyyyyyyyyyyyy" \
lego --email you@example.com --dns gigahostno -d '*.example.com' -d example.com run
lego --dns gigahostno -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Glesys provider:
```bash
GLESYS_API_USER=xxxxx \
GLESYS_API_KEY=yyyyy \
lego --email you@example.com --dns glesys -d '*.example.com' -d example.com run
lego --dns glesys -d '*.example.com' -d example.com run
```

View file

@ -28,7 +28,7 @@ Here is an example bash command using the Go Daddy provider:
```bash
GODADDY_API_KEY=xxxxxxxx \
GODADDY_API_SECRET=yyyyyyyy \
lego --email you@example.com --dns godaddy -d '*.example.com' -d example.com run
lego --dns godaddy -d '*.example.com' -d example.com run
```

Some files were not shown because too many files have changed in this diff Show more