Compare commits

...

95 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
Fernandez Ludovic
27075d562a Prepare release v4.30.1 2025-12-16 21:35:22 +01:00
Ludovic Fernandez
5574de68cd
fix: downgrade aliyun credentials to v1.4.7 (#2756) 2025-12-16 19:33:30 +01:00
Ludovic Fernandez
43dc1aa835
chore: fix attest-build-provenance subject-checksums path (#2755) 2025-12-16 19:04:42 +01:00
Fernandez Ludovic
222cd85cbc Detach v4.30.0 2025-12-16 18:07:20 +01:00
Fernandez Ludovic
4e6426cb2e Prepare release v4.30.0 2025-12-16 18:07:20 +01:00
Ludovic Fernandez
5b30df22b5
chore: update dependencies (#2753) 2025-12-16 17:20:51 +01:00
Karl Fritsche
e21ba75da8
Add DNS provider for Ionos Cloud (#2752)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2025-12-15 23:45:24 +01:00
Fernandez Ludovic
bb5e70a4e5 docs: improve contributing guide 2025-12-15 23:34:25 +01:00
Fernandez Ludovic
a6e6b92d35 chore: clean maps 2025-12-15 23:22:16 +01:00
Ludovic Fernandez
465d7918a8
Add DNS provider for hosting.nl (#1967) 2025-12-15 20:16:31 +01:00
Fernandez Ludovic
c59d163e79
chore: improves github templates 2025-12-11 14:16:34 +01:00
Ludovic Fernandez
e54598536b
Add DNS provider for Virtualname (#2748) 2025-12-11 12:58:21 +01:00
Adrian
9e2dffe8d2
Add DNS Provider for Neodigit (#2747)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2025-12-10 21:52:23 +01:00
Fernandez Ludovic
1e57e29a9d
chore: skip jekyll 2025-12-09 16:32:14 +01:00
Fernandez Ludovic
961fd586d9
docs: add notes 2025-12-09 16:25:30 +01:00
Ludovic Fernandez
02dd7152f0
Add DNS provider for Syse.no (#2742) 2025-12-08 20:25:08 +01:00
Ludovic Fernandez
36552da309
chore: update workflows (#2741) 2025-12-05 16:45:51 +01:00
Ludovic Fernandez
dea97e4dfa
Add DNS provider for Gravity (#2738) 2025-12-01 21:37:20 +01:00
Ludovic Fernandez
bc163db9ed
feat: remove email requirement (#2736) 2025-12-01 20:55:41 +01:00
Ludovic Fernandez
ea97ce2f62
chore: move provider "manual" into a dedicated package (#2739) 2025-12-01 20:51:43 +01:00
Ludovic Fernandez
cc83c025b5
autodns: use the right response structure (#2737) 2025-12-01 20:50:46 +01:00
Fernandez Ludovic
742741fe05 Detach v4.29.0 2025-11-29 14:49:25 +01:00
Fernandez Ludovic
5488fdf856 Prepare release v4.29.0 2025-11-29 14:49:25 +01:00
Fernandez Ludovic
fc5e0174b8
docs: update the number of supported DNS 2025-11-29 14:28:34 +01:00
Fernandez Ludovic
3f2ebf7ef1
chore: improve issue templates 2025-11-29 14:28:08 +01:00
Ludovic Fernandez
1757cdeaee
chore: use common implementations of the providers instead of the API clients (#2734) 2025-11-29 14:20:42 +01:00
Ludovic Fernandez
dc0a595a9f
Add DNS provider for United-Domains (#2731) 2025-11-27 20:40:55 +01:00
Ludovic Fernandez
42fb4346e2
chore: update dependencies (#2733) 2025-11-27 20:40:23 +01:00
Ludovic Fernandez
ad6adbffd4
tests: fix flaky test (#2729) 2025-11-25 19:30:22 +01:00
Ludovic Fernandez
56cb356ef2
edgeone: add zones mapping (#2728) 2025-11-25 19:29:47 +01:00
Ludovic Fernandez
aea6afe2d6
Add DNS provider for Gigahost.no (#2723) 2025-11-24 18:44:43 +01:00
Ludovic Fernandez
93b8bb71ca
hetzner: use int64 for IDs (#2720) 2025-11-22 01:11:55 +01:00
Fernandez Ludovic
0abf391bd1
docs: remove author names 2025-11-19 01:27:40 +01:00
Fernandez Ludovic
57c14f8d2a
chore: add pull request template 2025-11-14 18:35:15 +01:00
Ludovic Fernandez
ea8aca4366
Add DNS provider for AlibabaCloud ESA (#2703) 2025-11-14 14:33:54 +01:00
Ludovic Fernandez
a8226a6713
namecheap: add experimental proxy support (#2715) 2025-11-14 14:12:57 +01:00
RHQYZ
b338263c96
baiducloud: pagination and TTL (#2712)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2025-11-11 13:36:35 +01:00
Evgeniy Medvedev
877738cef3
Add DNS provider for EdgeCenter (#2710)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2025-11-09 20:56:16 +01:00
Ludovic Fernandez
1c33fba180
chore: add major version tag for Docker images (#2709) 2025-11-08 13:38:05 +01:00
oliverbr
d5dc3866e6
gandiv5: update base API URL (#2708) 2025-11-08 02:29:10 +00:00
Fernandez Ludovic
22955739a1 Detach v4.28.1 2025-11-06 17:53:18 +01:00
Fernandez Ludovic
b704b26e6c Prepare release v4.28.1 2025-11-06 17:53:18 +01:00
Ludovic Fernandez
14778cc1f1
fix: skip nil response (#2705) 2025-11-06 13:19:09 +01:00
Fernandez Ludovic
e12c9fc637 Detach v4.28.0 2025-10-31 11:44:04 +01:00
842 changed files with 27215 additions and 2539 deletions

View file

@ -45,6 +45,7 @@ body:
- Through Bitnami
- Through 1Panel
- Through Zoraxy
- Through Certimate
- go install
- Other
validations:

View file

@ -24,6 +24,7 @@ body:
- Through Bitnami
- Through 1Panel
- Through Zoraxy
- Through Certimate
- go install
- Other
validations:

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
@ -34,11 +40,23 @@ body:
- Through Bitnami
- Through 1Panel
- Through Zoraxy
- Through Certimate
- go install
- Other
validations:
required: true
- type: dropdown
id: profile
attributes:
label: Who are you?
options:
- A customer of this DNS provider
- An employee of this DNS provider
- Other (please explain)
validations:
required: true
- type: input
id: provider-link
attributes:

12
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,12 @@
<!--
IMPORTANT:
1. Create an issue and wait for a maintainer to approve it BEFORE opening a pull request.
2. Don't open a work-in-progress pull request. If you open a PR, the PR must be ready to be reviewed.
3. If a pull request doesn't follow one of the previous elements, it will be closed.
Also, pull requests from a fork inside a GitHub organization are not allowed because of access limitation on them.
Only pull requests from personal forks are allowed.
-->

View file

@ -17,15 +17,11 @@ jobs:
steps:
# https://github.com/marketplace/actions/checkout
- name: Check out code
uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}

View file

@ -20,13 +20,8 @@ jobs:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
# https://github.com/marketplace/actions/checkout
- name: Checkout code
uses: actions/checkout@v4
# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go-version }}

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
env:
GO_VERSION: stable
GOLANGCI_LINT_VERSION: v2.6.0
GOLANGCI_LINT_VERSION: v2.10
HUGO_VERSION: 0.148.2
CGO_ENABLED: 0
LEGO_E2E_TESTS: CI
@ -21,43 +21,36 @@ jobs:
steps:
# https://github.com/marketplace/actions/checkout
- name: Check out code
uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
- name: Check and get dependencies
run: |
go mod tidy
git diff --exit-code go.mod
git diff --exit-code go.sum
go mod tidy --diff
- name: Generate and Check generated elements
run: |
make generate-dns
git diff --exit-code
# https://golangci-lint.run/usage/install#other-ci
- name: Install golangci-lint ${{ env.GOLANGCI_LINT_VERSION }}
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION}
golangci-lint --version
- uses: golangci/golangci-lint-action@v9
with:
version: ${{ env.GOLANGCI_LINT_VERSION }}
install-only: true
- name: Install Pebble
run: go install github.com/letsencrypt/pebble/v2/cmd/pebble@v2.7.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.7.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

@ -42,13 +42,11 @@ jobs:
docker-images: true
swap-storage: false
- name: Check out code
uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
- uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
@ -69,9 +67,10 @@ jobs:
# https://goreleaser.com/ci/actions/
- name: Run GoReleaser
id: goreleaser
uses: goreleaser/goreleaser-action@v6
with:
version: v2.12.3
version: v2.13.0
args: release -p 1 --clean --timeout=90m
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_REPO }}
@ -80,7 +79,9 @@ jobs:
- uses: actions/attest-build-provenance@v3
with:
subject-checksums: ./dist/lego_*_checksums.txt
subject-checksums: ./dist/lego_${{ fromJSON(steps.goreleaser.outputs.metadata).version }}_checksums.txt
github-token: ${{ secrets.GH_TOKEN_REPO }}
- uses: actions/attest-build-provenance@v3
with:
subject-checksums: ./dist/digests.txt
github-token: ${{ secrets.GH_TOKEN_REPO }}

View file

@ -180,6 +180,12 @@ linters:
text: Error return value of `fmt.Fprintln` is not checked
linters:
- errcheck
- 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:
@ -216,11 +222,7 @@ linters:
text: load is a global variable
linters:
- gochecknoglobals
- path: providers/dns/([\d\w]+/)*[\d\w]+_test.go
text: envTest is a global variable
linters:
- gochecknoglobals
- path: providers/http/([\d\w]+/)*[\d\w]+_test.go
- path: providers/(dns|http)/([\d\w]+/)*[\d\w]+_test.go
text: envTest is a global variable
linters:
- gochecknoglobals
@ -228,6 +230,10 @@ linters:
text: testCases is a global variable
linters:
- gochecknoglobals
- path: providers/dns/namecheap/transport.go
text: (envProxyOnce|envProxyFuncValue) is a global variable
linters:
- gochecknoglobals
- path: providers/dns/acmedns/mock_test.go
text: egTestAccount is a global variable
linters:
@ -263,6 +269,10 @@ linters:
text: cyclomatic complexity 13 of func `\(\*DNSProvider\)\.CleanUp` is high
linters:
- gocyclo
- path: providers/dns/manual/manual.go
text: 'SA1019: dns01.DNSProviderManual is deprecated'
linters:
- staticcheck
# Those elements have been replaced by non-exposed structures.
- path: providers/dns/linode/linode_test.go
text: 'SA1019: linodego\.(DomainsPagedResponse|DomainRecordsPagedResponse) is deprecated'

View file

@ -90,8 +90,9 @@ dockers_v2:
- linux/arm/v7
tags:
- 'latest'
- '{{ .Tag }}'
- 'v{{ .Major }}'
- 'v{{ .Major }}.{{ .Minor }}'
- '{{ .Tag }}'
labels:
# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
'org.opencontainers.image.title': '{{.ProjectName}}'

View file

@ -1,11 +1,129 @@
# Changelog
lego is an independent, free, and open-source project, if you value it, consider [supporting it](https://donate.ldez.dev)! ❤️
lego is an independent, free, open-source project, if you value it, consider [supporting it](https://donate.ldez.dev)! ❤️
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
- Tag: [v4.30.1](https://github.com/go-acme/lego/releases/tag/v4.30.1)
Due to an error related to `aliyun/credentials-go`, some artifacts of the v4.30.0 release have not been published.
This release contains the same things as v4.30.0.
## v4.30.0
- Release date: 2025-12-16
- Tag: [v4.30.0](https://github.com/go-acme/lego/releases/tag/v4.30.0)
### Added
- **[dnsprovider]** Add DNS provider for Ionos Cloud
- **[dnsprovider]** Add DNS provider for Virtualname
- **[dnsprovider]** Add DNS Provider for Neodigit
- **[dnsprovider]** Add DNS provider for Syse.no
- **[dnsprovider]** Add DNS provider for Gravity
- **[dnsprovider]** Add DNS provider for hosting.nl
### Changed
- **[cli]** feat: remove email requirement
### Fixed
- **[dnsprovider]** autodns: use the right response structure
## v4.29.0
- Release date: 2025-11-29
- Tag: [v4.29.0](https://github.com/go-acme/lego/releases/tag/v4.29.0)
### Added
- **[dnsprovider]** Add DNS provider for United-Domains
- **[dnsprovider]** Add DNS provider for Gigahost.no
- **[dnsprovider]** Add DNS provider for EdgeCenter
- **[dnsprovider]** Add DNS provider for AlibabaCloud ESA
- **[dnsprovider]** edgeone: add zones mapping
- **[dnsprovider]** namecheap: add experimental proxy support
### Changed
- **[dnsprovider]** gandiv5: update base API URL
### Fixed
- **[dnsprovider]** hetzner: use int64 for IDs
- **[dnsprovider]** baiducloud: pagination and TTL
- **[dnsprovider]** inwx: fix API breaking changes with record IDs
## v4.28.1
- Release date: 2025-11-06
- Tag: [v4.28.1](https://github.com/go-acme/lego/releases/tag/v4.28.1)
### Fixed
- **[cli]** fix: skip nil response
## v4.28.0
- Release date: 2025-10-31

View file

@ -10,7 +10,7 @@ To ensure a great and easy experience for everyone, please review the few guidel
- If both of the above do not apply, create a new issue and include as much information as possible.
Bug reports should include all information a person could need to reproduce your problem without the need to
follow up for more information. If possible, provide detailed steps for us to reproduce it, the expected behaviour and the actual behaviour.
follow up for more information. If possible, provide detailed steps for us to reproduce it, the expected behavior and the actual behavior.
## Feature proposals and requests
@ -20,31 +20,26 @@ It is up to you to make a strong point about your proposal and convince us of th
## Pull requests
Create an issue and wait for a maintainer to approve it BEFORE opening a pull request.
Patches, new features and improvements are a great way to help the project.
Please keep them focused on one thing and do not include unrelated commits.
All pull requests which alter the behaviour of the program, add new behaviour or somehow alter code in a non-trivial way should **always** include tests.
All pull requests that alter the behavior of the program,
add new behavior or somehow alter code in a non-trivial way should **always** include tests.
If you want to contribute a significant pull request (with a non-trivial workload for you) please **ask first**. We do not want you to spend
a lot of time on something the project's developers might not want to merge into the project.
**IMPORTANT**: By submitting a patch, you agree to allow the project
owners to license your work under the terms of the [MIT License](LICENSE).
**IMPORTANT**: By submitting a patch, you agree to allow the project owners to license your work under the terms of the [MIT License](LICENSE).
### How to create a pull request
Requirements:
- `go` v1.15+
- `go` v1.24+
- environment variable: `GO111MODULE=on`
First, you have to install [GoLang](https://golang.org/doc/install) and [golangci-lint](https://github.com/golangci/golangci-lint#install).
```bash
# Create the root folder
mkdir -p $GOPATH/src/github.com/go-acme
cd $GOPATH/src/github.com/go-acme
# clone your fork
git clone git@github.com:YOUR_USERNAME/lego.git
cd lego
@ -56,14 +51,12 @@ git fetch upstream
```bash
# Create your branch
git checkout -b my-feature
git switch -c my-feature
## Create your code ##
```
```bash
# Format
make fmt
# Linters
make checks
# Tests

104
README.md
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,51 +56,63 @@ 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/allinkl/">all-inkl</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/arvancloud/">ArvanCloud</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>
<td><a href="https://go-acme.github.io/lego/dns/autodns/">Autodns</a></td>
<td><a href="https://go-acme.github.io/lego/dns/axelname/">Axelname</a></td>
<td><a href="https://go-acme.github.io/lego/dns/azion/">Azion</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/azion/">Azion</a></td>
<td><a href="https://go-acme.github.io/lego/dns/azure/">Azure (deprecated)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/azuredns/">Azure DNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/baiducloud/">Baidu Cloud</a></td>
<td><a href="https://go-acme.github.io/lego/dns/beget/">Beget.com</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/beget/">Beget.com</a></td>
<td><a href="https://go-acme.github.io/lego/dns/binarylane/">Binary Lane</a></td>
<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>
<td><a href="https://go-acme.github.io/lego/dns/bookmyname/">BookMyName</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>
</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>
</tr><tr>
<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>
</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>
</tr><tr>
<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>
</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>
</tr><tr>
<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>
</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>
@ -109,38 +121,48 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
<td><a href="https://go-acme.github.io/lego/dns/directadmin/">DirectAdmin</a></td>
<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>
<td><a href="https://go-acme.github.io/lego/dns/dode/">Domain Offensive (do.de)</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/dode/">Domain Offensive (do.de)</a></td>
<td><a href="https://go-acme.github.io/lego/dns/domeneshop/">Domeneshop</a></td>
<td><a href="https://go-acme.github.io/lego/dns/dreamhost/">DreamHost</a></td>
<td><a href="https://go-acme.github.io/lego/dns/duckdns/">Duck DNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/dyn/">Dyn</a></td>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/dyn/">Dyn</a></td>
<td><a href="https://go-acme.github.io/lego/dns/dyndnsfree/">DynDnsFree.de</a></td>
<td><a href="https://go-acme.github.io/lego/dns/dynu/">Dynu</a></td>
<td><a href="https://go-acme.github.io/lego/dns/easydns/">EasyDNS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/efficientip/">Efficient IP</a></td>
</tr><tr>
<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/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>
</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>
<td><a href="https://go-acme.github.io/lego/dns/gandiv5/">Gandi Live DNS (v5)</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>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/gravity/">Gravity</a></td>
<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>
<td><a href="https://go-acme.github.io/lego/dns/hosttech/">Hosttech</a></td>
</tr><tr>
@ -160,114 +182,124 @@ Detailed documentation is available [here](https://go-acme.github.io/lego/dns).
<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>
<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>
<td><a href="https://go-acme.github.io/lego/dns/limacity/">Lima-City</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>
<td><a href="https://go-acme.github.io/lego/dns/loopia/">Loopia</a></td>
<td><a href="https://go-acme.github.io/lego/dns/luadns/">LuaDNS</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>
<td><a href="https://go-acme.github.io/lego/dns/manual/">Manual</a></td>
<td><a href="https://go-acme.github.io/lego/dns/metaname/">Metaname</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>
<td><a href="https://go-acme.github.io/lego/dns/mittwald/">Mittwald</a></td>
<td><a href="https://go-acme.github.io/lego/dns/myaddr/">myaddr.{tools,dev,io}</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>
<td><a href="https://go-acme.github.io/lego/dns/namedotcom/">Name.com</a></td>
<td><a href="https://go-acme.github.io/lego/dns/namecheap/">Namecheap</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>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/nicmanager/">Nicmanager</a></td>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/ns1/">NS1</a></td>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/ovh/">OVH</a></td>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/rackspace/">Rackspace</a></td>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/regfish/">Regfish</a></td>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/sakuracloud/">Sakura Cloud</a></td>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/selfhostde/">SelfHost.(de|eu)</a></td>
<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>
</tr><tr>
<td><a href="https://go-acme.github.io/lego/dns/sonic/">Sonic</a></td>
<td><a href="https://go-acme.github.io/lego/dns/spaceship/">Spaceship</a></td>
<td><a href="https://go-acme.github.io/lego/dns/stackpath/">Stackpath</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/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>
<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>
<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>
<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/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>
<td><a href="https://go-acme.github.io/lego/dns/vultr/">Vultr</a></td>
<td><a href="https://go-acme.github.io/lego/dns/webnamesca/">webnames.ca</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>
<td><a href="https://go-acme.github.io/lego/dns/wedos/">WEDOS</a></td>
<td><a href="https://go-acme.github.io/lego/dns/westcn/">West.cn/西部数码</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>
<td><a href="https://go-acme.github.io/lego/dns/yandex/">Yandex PDD</a></td>
<td><a href="https://go-acme.github.io/lego/dns/zoneee/">Zone.ee</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>
<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.28.0"
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

@ -12,9 +12,14 @@ const (
)
// DNSProviderManual is an implementation of the ChallengeProvider interface.
// TODO(ldez): move this to providers/dns/manual
//
// Deprecated: Use the manual.DNSProvider instead.
type DNSProviderManual struct{}
// NewDNSProviderManual returns a DNSProviderManual instance.
//
// Deprecated: Use the manual.NewDNSProvider instead.
func NewDNSProviderManual() (*DNSProviderManual, error) {
return &DNSProviderManual{}, nil
}

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

@ -16,6 +16,8 @@ import (
"github.com/urfave/cli/v2"
)
const userIDPlaceholder = "noemail@example.com"
const (
baseAccountsRootFolderName = "accounts"
baseKeysFolderName = "keys"
@ -32,7 +34,7 @@ const (
//
// rootUserPath:
//
// ./.lego/accounts/localhost_14000/hubert@hubert.com/
// ./.lego/accounts/localhost_14000/foo@example.com/
// │ │ │ └── userID ("email" option)
// │ │ └── CA server ("server" option)
// │ └── root accounts directory
@ -40,7 +42,7 @@ const (
//
// keysPath:
//
// ./.lego/accounts/localhost_14000/hubert@hubert.com/keys/
// ./.lego/accounts/localhost_14000/foo@example.com/keys/
// │ │ │ │ └── root keys directory
// │ │ │ └── userID ("email" option)
// │ │ └── CA server ("server" option)
@ -49,7 +51,7 @@ const (
//
// accountFilePath:
//
// ./.lego/accounts/localhost_14000/hubert@hubert.com/account.json
// ./.lego/accounts/localhost_14000/foo@example.com/account.json
// │ │ │ │ └── account file
// │ │ │ └── userID ("email" option)
// │ │ └── CA server ("server" option)
@ -57,6 +59,7 @@ const (
// └── "path" option
type AccountsStorage struct {
userID string
email string
rootPath string
rootUserPath string
keysPath string
@ -66,8 +69,13 @@ type AccountsStorage struct {
// NewAccountsStorage Creates a new AccountsStorage.
func NewAccountsStorage(ctx *cli.Context) *AccountsStorage {
// TODO: move to account struct? Currently MUST pass email.
email := getEmail(ctx)
// TODO: move to account struct?
email := ctx.String(flgEmail)
userID := email
if userID == "" {
userID = userIDPlaceholder
}
serverURL, err := url.Parse(ctx.String(flgServer))
if err != nil {
@ -77,10 +85,11 @@ func NewAccountsStorage(ctx *cli.Context) *AccountsStorage {
rootPath := filepath.Join(ctx.String(flgPath), baseAccountsRootFolderName)
serverPath := strings.NewReplacer(":", "_", "/", string(os.PathSeparator)).Replace(serverURL.Host)
accountsPath := filepath.Join(rootPath, serverPath)
rootUserPath := filepath.Join(accountsPath, email)
rootUserPath := filepath.Join(accountsPath, userID)
return &AccountsStorage{
userID: email,
userID: userID,
email: email,
rootPath: rootPath,
rootUserPath: rootUserPath,
keysPath: filepath.Join(rootUserPath, baseKeysFolderName),
@ -112,6 +121,10 @@ func (s *AccountsStorage) GetUserID() string {
return s.userID
}
func (s *AccountsStorage) GetEmail() string {
return s.email
}
func (s *AccountsStorage) Save(account *Account) error {
jsonBytes, err := json.MarshalIndent(account, "", "\t")
if err != nil {
@ -124,14 +137,14 @@ func (s *AccountsStorage) Save(account *Account) error {
func (s *AccountsStorage) LoadAccount(privateKey crypto.PrivateKey) *Account {
fileBytes, err := os.ReadFile(s.accountFilePath)
if err != nil {
log.Fatalf("Could not load file for account %s: %v", s.userID, err)
log.Fatalf("Could not load file for account %s: %v", s.GetUserID(), err)
}
var account Account
err = json.Unmarshal(fileBytes, &account)
if err != nil {
log.Fatalf("Could not parse file for account %s: %v", s.userID, err)
log.Fatalf("Could not parse file for account %s: %v", s.GetUserID(), err)
}
account.key = privateKey
@ -139,14 +152,14 @@ func (s *AccountsStorage) LoadAccount(privateKey crypto.PrivateKey) *Account {
if account.Registration == nil || account.Registration.Body.Status == "" {
reg, err := tryRecoverRegistration(s.ctx, privateKey)
if err != nil {
log.Fatalf("Could not load account for %s. Registration is nil: %#v", s.userID, err)
log.Fatalf("Could not load account for %s. Registration is nil: %#v", s.GetUserID(), err)
}
account.Registration = reg
err = s.Save(&account)
if err != nil {
log.Fatalf("Could not save account for %s. Registration is nil: %#v", s.userID, err)
log.Fatalf("Could not save account for %s. Registration is nil: %#v", s.GetUserID(), err)
}
}
@ -154,15 +167,15 @@ func (s *AccountsStorage) LoadAccount(privateKey crypto.PrivateKey) *Account {
}
func (s *AccountsStorage) GetPrivateKey(keyType certcrypto.KeyType) crypto.PrivateKey {
accKeyPath := filepath.Join(s.keysPath, s.userID+".key")
accKeyPath := filepath.Join(s.keysPath, s.GetUserID()+".key")
if _, err := os.Stat(accKeyPath); os.IsNotExist(err) {
log.Printf("No key found for account %s. Generating a %s key.", s.userID, keyType)
log.Printf("No key found for account %s. Generating a %s key.", s.GetUserID(), keyType)
s.createKeysFolder()
privateKey, err := generatePrivateKey(accKeyPath, keyType)
if err != nil {
log.Fatalf("Could not generate RSA private account key for account %s: %v", s.userID, err)
log.Fatalf("Could not generate RSA private account key for account %s: %v", s.GetUserID(), err)
}
log.Printf("Saved key to %s", accKeyPath)
@ -180,7 +193,7 @@ func (s *AccountsStorage) GetPrivateKey(keyType certcrypto.KeyType) crypto.Priva
func (s *AccountsStorage) createKeysFolder() {
if err := createNonExistingFolder(s.keysPath); err != nil {
log.Fatalf("Could not check/create directory for account %s: %v", s.userID, err)
log.Fatalf("Could not check/create directory for account %s: %v", s.GetUserID(), err)
}
}

View file

@ -3,6 +3,7 @@ package cmd
import (
"encoding/json"
"fmt"
"net"
"net/url"
"os"
"path/filepath"
@ -36,7 +37,7 @@ func createList() *cli.Command {
// fake email, needed by NewAccountsStorage
&cli.StringFlag{
Name: flgEmail,
Value: "unknown",
Value: "",
Hidden: true,
},
},
@ -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

@ -144,7 +144,9 @@ func renew(ctx *cli.Context) error {
bundle := !ctx.Bool(flgNoBundle)
meta := map[string]string{hookEnvAccountEmail: account.Email}
meta := map[string]string{
hookEnvAccountEmail: account.Email,
}
// CSR
if ctx.IsSet(flgCSR) {

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.28.0+dev-release"
const defaultVersion = "v4.32.0+dev-detach"
var version = ""

View file

@ -40,7 +40,7 @@ func setupAccount(ctx *cli.Context, accountsStorage *AccountsStorage) (*Account,
if accountsStorage.ExistsAccountFilePath() {
account = accountsStorage.LoadAccount(privateKey)
} else {
account = &Account{Email: accountsStorage.GetUserID(), key: privateKey}
account = &Account{Email: accountsStorage.GetEmail(), key: privateKey}
}
return account, keyType
@ -118,15 +118,6 @@ func getKeyType(ctx *cli.Context) certcrypto.KeyType {
return ""
}
func getEmail(ctx *cli.Context) string {
email := ctx.String(flgEmail)
if email == "" {
log.Fatalf("You have to pass an account (email address) to the program using --%s or -m", flgEmail)
}
return email
}
func getUserAgent(ctx *cli.Context) string {
return strings.TrimSpace(fmt.Sprintf("%s lego-cli/%s", ctx.String(flgUserAgent), ctx.App.Version))
}
@ -180,6 +171,10 @@ func checkRetry(ctx context.Context, resp *http.Response, err error) (bool, erro
return rt, err
}
if resp == nil {
return rt, nil
}
if resp.StatusCode/100 == 2 {
return rt, nil
}

View file

@ -12,12 +12,14 @@ import (
func allDNSCodes() string {
providers := []string{
"manual",
"acme-dns",
"active24",
"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",
@ -62,10 +69,13 @@ func allDNSCodes() string {
"dyndnsfree",
"dynu",
"easydns",
"edgecenter",
"edgedns",
"edgeone",
"efficientip",
"epik",
"eurodns",
"excedo",
"exec",
"exoscale",
"f5xc",
@ -74,12 +84,15 @@ func allDNSCodes() string {
"gandiv5",
"gcloud",
"gcore",
"gigahostno",
"glesys",
"godaddy",
"googledomains",
"gravity",
"hetzner",
"hostingde",
"hostinger",
"hostingnl",
"hosttech",
"httpnet",
"httpreq",
@ -94,10 +107,15 @@ func allDNSCodes() string {
"internetbs",
"inwx",
"ionos",
"ionoscloud",
"ipv64",
"ispconfig",
"ispconfigddns",
"iwantmyname",
"jdcloud",
"joker",
"keyhelp",
"leaseweb",
"liara",
"lightsail",
"limacity",
@ -107,6 +125,7 @@ func allDNSCodes() string {
"luadns",
"mailinabox",
"manageengine",
"manual",
"metaname",
"metaregistrar",
"mijnhost",
@ -117,7 +136,9 @@ func allDNSCodes() string {
"namecheap",
"namedotcom",
"namesilo",
"namesurfer",
"nearlyfreespeech",
"neodigit",
"netcup",
"netlify",
"nicmanager",
@ -153,16 +174,20 @@ func allDNSCodes() string {
"sonic",
"spaceship",
"stackpath",
"syse",
"technitium",
"tencentcloud",
"timewebcloud",
"todaynic",
"transip",
"ultradns",
"uniteddomains",
"variomedia",
"vegadns",
"vercel",
"versio",
"vinyldns",
"virtualname",
"vkcloud",
"volcengine",
"vscale",
@ -244,13 +269,38 @@ 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()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/alidns`)
case "aliesa":
// generated from: providers/dns/aliesa/aliesa.toml
ew.writeln(`Configuration for AlibabaCloud ESA.`)
ew.writeln(`Code: 'aliesa'`)
ew.writeln(`Since: 'v4.29.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "ALIESA_ACCESS_KEY": Access key ID`)
ew.writeln(` - "ALIESA_RAM_ROLE": Your instance RAM role (https://www.alibabacloud.com/help/en/ecs/user-guide/attach-an-instance-ram-role-to-an-ecs-instance)`)
ew.writeln(` - "ALIESA_SECRET_KEY": Access Key secret`)
ew.writeln(` - "ALIESA_SECURITY_TOKEN": STS Security Token (optional)`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "ALIESA_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "ALIESA_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "ALIESA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "ALIESA_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/aliesa`)
case "allinkl":
// generated from: providers/dns/allinkl/allinkl.toml
ew.writeln(`Configuration for all-inkl.`)
@ -271,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.`)
@ -292,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.`)
@ -471,7 +563,7 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "BAIDUCLOUD_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "BAIDUCLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "BAIDUCLOUD_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)`)
ew.writeln(` - "BAIDUCLOUD_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/baiducloud`)
@ -561,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.`)
@ -779,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.`)
@ -891,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.`)
@ -1006,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.`)
@ -1252,6 +1451,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/easydns`)
case "edgecenter":
// generated from: providers/dns/edgecenter/edgecenter.toml
ew.writeln(`Configuration for EdgeCenter.`)
ew.writeln(`Code: 'edgecenter'`)
ew.writeln(`Since: 'v4.29.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "EDGECENTER_PERMANENT_API_TOKEN": Permanent API token (https://edgecenter.ru/blog/permanent-api-token-explained/)`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "EDGECENTER_HTTP_TIMEOUT": API request timeout in seconds (Default: 10)`)
ew.writeln(` - "EDGECENTER_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 20)`)
ew.writeln(` - "EDGECENTER_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 360)`)
ew.writeln(` - "EDGECENTER_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/edgecenter`)
case "edgedns":
// generated from: providers/dns/edgedns/edgedns.toml
ew.writeln(`Configuration for Akamai EdgeDNS.`)
@ -1296,6 +1515,7 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln(` - "EDGEONE_REGION": Region`)
ew.writeln(` - "EDGEONE_SESSION_TOKEN": Access Key token`)
ew.writeln(` - "EDGEONE_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)`)
ew.writeln(` - "EDGEONE_ZONES_MAPPING": Mapping between DNS zones and site IDs. (ex: 'example.org:id1,example.com:id2')`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/edgeone`)
@ -1344,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.`)
@ -1393,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()
@ -1505,6 +1768,28 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/gcore`)
case "gigahostno":
// generated from: providers/dns/gigahostno/gigahostno.toml
ew.writeln(`Configuration for Gigahost.no.`)
ew.writeln(`Code: 'gigahostno'`)
ew.writeln(`Since: 'v4.29.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "GIGAHOSTNO_PASSWORD": Password`)
ew.writeln(` - "GIGAHOSTNO_USERNAME": Username`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "GIGAHOSTNO_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "GIGAHOSTNO_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "GIGAHOSTNO_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "GIGAHOSTNO_SECRET": TOTP secret`)
ew.writeln(` - "GIGAHOSTNO_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/gigahostno`)
case "glesys":
// generated from: providers/dns/glesys/glesys.toml
ew.writeln(`Configuration for Glesys.`)
@ -1566,6 +1851,28 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/googledomains`)
case "gravity":
// generated from: providers/dns/gravity/gravity.toml
ew.writeln(`Configuration for Gravity.`)
ew.writeln(`Code: 'gravity'`)
ew.writeln(`Since: 'v4.30.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "GRAVITY_PASSWORD": Password`)
ew.writeln(` - "GRAVITY_SERVER_URL": URL of the server`)
ew.writeln(` - "GRAVITY_USERNAME": Username`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "GRAVITY_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "GRAVITY_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "GRAVITY_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 60)`)
ew.writeln(` - "GRAVITY_SEQUENCE_INTERVAL": Time between sequential requests in seconds (Default: 1)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/gravity`)
case "hetzner":
// generated from: providers/dns/hetzner/hetzner.toml
ew.writeln(`Configuration for Hetzner.`)
@ -1627,6 +1934,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/hostinger`)
case "hostingnl":
// generated from: providers/dns/hostingnl/hostingnl.toml
ew.writeln(`Configuration for Hosting.nl.`)
ew.writeln(`Code: 'hostingnl'`)
ew.writeln(`Since: 'v4.30.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "HOSTINGNL_API_KEY": The API key`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "HOSTINGNL_HTTP_TIMEOUT": API request timeout in seconds (Default: 10)`)
ew.writeln(` - "HOSTINGNL_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "HOSTINGNL_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 120)`)
ew.writeln(` - "HOSTINGNL_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/hostingnl`)
case "hosttech":
// generated from: providers/dns/hosttech/hosttech.toml
ew.writeln(`Configuration for Hosttech.`)
@ -1926,6 +2253,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/ionos`)
case "ionoscloud":
// generated from: providers/dns/ionoscloud/ionoscloud.toml
ew.writeln(`Configuration for Ionos Cloud.`)
ew.writeln(`Code: 'ionoscloud'`)
ew.writeln(`Since: 'v4.30.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "IONOSCLOUD_API_TOKEN": API token`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "IONOSCLOUD_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "IONOSCLOUD_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "IONOSCLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 120)`)
ew.writeln(` - "IONOSCLOUD_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/ionoscloud`)
case "ipv64":
// generated from: providers/dns/ipv64/ipv64.toml
ew.writeln(`Configuration for IPv64.`)
@ -1945,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).`)
@ -1966,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.`)
@ -2011,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.`)
@ -2026,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()
@ -2200,6 +2634,16 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/manageengine`)
case "manual":
// generated from: providers/dns/manual/manual.toml
ew.writeln(`Configuration for Manual.`)
ew.writeln(`Code: 'manual'`)
ew.writeln(`Since: 'v0.3.0'`)
ew.writeln()
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/manual`)
case "metaname":
// generated from: providers/dns/metaname/metaname.toml
ew.writeln(`Configuration for Metaname.`)
@ -2408,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.`)
@ -2430,6 +2898,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/nearlyfreespeech`)
case "neodigit":
// generated from: providers/dns/neodigit/neodigit.toml
ew.writeln(`Configuration for Neodigit.`)
ew.writeln(`Code: 'neodigit'`)
ew.writeln(`Since: 'v4.30.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "NEODIGIT_TOKEN": API token`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "NEODIGIT_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "NEODIGIT_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 10)`)
ew.writeln(` - "NEODIGIT_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 300)`)
ew.writeln(` - "NEODIGIT_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/neodigit`)
case "netcup":
// generated from: providers/dns/netcup/netcup.toml
ew.writeln(`Configuration for Netcup.`)
@ -2951,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()
@ -3209,6 +3697,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/stackpath`)
case "syse":
// generated from: providers/dns/syse/syse.toml
ew.writeln(`Configuration for Syse.`)
ew.writeln(`Code: 'syse'`)
ew.writeln(`Since: 'v4.30.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "SYSE_CREDENTIALS": Comma-separated list of 'zone:password' credential pairs`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "SYSE_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "SYSE_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 10)`)
ew.writeln(` - "SYSE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 1200)`)
ew.writeln(` - "SYSE_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/syse`)
case "technitium":
// generated from: providers/dns/technitium/technitium.toml
ew.writeln(`Configuration for Technitium.`)
@ -3272,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.`)
@ -3314,6 +3843,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/ultradns`)
case "uniteddomains":
// generated from: providers/dns/uniteddomains/uniteddomains.toml
ew.writeln(`Configuration for United-Domains.`)
ew.writeln(`Code: 'uniteddomains'`)
ew.writeln(`Since: 'v4.29.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "UNITEDDOMAINS_API_KEY": API key '<prefix>.<secret>' https://www.united-domains.de/help/faq-article/getting-started-with-the-united-domains-dns-api/`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "UNITEDDOMAINS_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "UNITEDDOMAINS_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 2)`)
ew.writeln(` - "UNITEDDOMAINS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 900)`)
ew.writeln(` - "UNITEDDOMAINS_TTL": The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)`)
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/uniteddomains`)
case "variomedia":
// generated from: providers/dns/variomedia/variomedia.toml
ew.writeln(`Configuration for Variomedia.`)
@ -3423,6 +3972,26 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/vinyldns`)
case "virtualname":
// generated from: providers/dns/virtualname/virtualname.toml
ew.writeln(`Configuration for Virtualname.`)
ew.writeln(`Code: 'virtualname'`)
ew.writeln(`Since: 'v4.30.0'`)
ew.writeln()
ew.writeln(`Credentials:`)
ew.writeln(` - "VIRTUALNAME_TOKEN": API token`)
ew.writeln()
ew.writeln(`Additional Configuration:`)
ew.writeln(` - "VIRTUALNAME_HTTP_TIMEOUT": API request timeout in seconds (Default: 30)`)
ew.writeln(` - "VIRTUALNAME_POLLING_INTERVAL": Time between DNS propagation check in seconds (Default: 10)`)
ew.writeln(` - "VIRTUALNAME_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation in seconds (Default: 300)`)
ew.writeln(` - "VIRTUALNAME_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/virtualname`)
case "vkcloud":
// generated from: providers/dns/vkcloud/vkcloud.toml
ew.writeln(`Configuration for VK Cloud.`)
@ -3738,8 +4307,6 @@ func displayDNSHelp(w io.Writer, name string) error {
ew.writeln()
ew.writeln(`More information: https://go-acme.github.io/lego/dns/zonomi`)
case "manual":
ew.writeln(`Solving the DNS-01 challenge using CLI prompt.`)
default:
return fmt.Errorf("%q is not yet supported", name)
}

View file

@ -7,6 +7,16 @@ chapter: false
Let's Encrypt client and ACME library written in Go.
{{% notice important %}}
lego is an independent, free, and open-source project, if you value it, consider [supporting it](https://donate.ldez.dev)! ❤️
This project is not owned by a company. I'm not an employee of a company.
I don't have gifted domains/accounts from DNS companies.
I've been maintaining it for about 10 years.
{{% /notice %}}
## Features
- ACME v2 [RFC 8555](https://www.rfc-editor.org/rfc/rfc8555.html)
@ -14,7 +24,7 @@ Let's Encrypt client and ACME library written in Go.
- 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 [150 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

@ -5,6 +5,16 @@ draft: false
weight: 3
---
{{% notice important %}}
lego is an independent, free, and open-source project, if you value it, consider [supporting it](https://donate.ldez.dev)! ❤️
This project is not owned by a company. I'm not an employee of a company.
I don't have gifted domains/accounts from DNS companies.
I've been maintaining it for about 10 years.
{{% /notice %}}
## Configuration and Credentials
Credentials and DNS configuration for DNS providers must be passed through environment variables.

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.

78
docs/content/dns/zz_gen_aliesa.md generated Normal file
View file

@ -0,0 +1,78 @@
---
title: "AlibabaCloud ESA"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: aliesa
dnsprovider:
since: "v4.29.0"
code: "aliesa"
url: "https://www.alibabacloud.com/en/product/esa"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/aliesa/aliesa.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [AlibabaCloud ESA](https://www.alibabacloud.com/en/product/esa).
<!--more-->
- Code: `aliesa`
- Since: v4.29.0
Here is an example bash command using the AlibabaCloud ESA provider:
```bash
# Setup using instance RAM role
ALIESA_RAM_ROLE=lego \
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 --dns aliesa - -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `ALIESA_ACCESS_KEY` | Access key ID |
| `ALIESA_RAM_ROLE` | Your instance RAM role (https://www.alibabacloud.com/help/en/ecs/user-guide/attach-an-instance-ram-role-to-an-ecs-instance) |
| `ALIESA_SECRET_KEY` | Access Key secret |
| `ALIESA_SECURITY_TOKEN` | STS Security Token (optional) |
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 |
|--------------------------------|-------------|
| `ALIESA_HTTP_TIMEOUT` | API request timeout in seconds (Default: 30) |
| `ALIESA_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `ALIESA_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `ALIESA_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://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-overview?spm=a2c63.p38356.help-menu-2673927.d_6_0_0.20b224c28PSZDc#:~:text=DNS-,DNS%20records,-DNS%20records)
- [Go client](https://github.com/alibabacloud-go/esa-20240910)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/aliesa/aliesa.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

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
```
@ -51,7 +51,7 @@ More information [here]({{% ref "dns#configuration-and-credentials" %}}).
|--------------------------------|-------------|
| `BAIDUCLOUD_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 2) |
| `BAIDUCLOUD_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 60) |
| `BAIDUCLOUD_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 120) |
| `BAIDUCLOUD_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 300) |
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" %}}).

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
```

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

@ -0,0 +1,67 @@
---
title: "EdgeCenter"
date: 2019-03-03T16:39:46+01:00
draft: false
slug: edgecenter
dnsprovider:
since: "v4.29.0"
code: "edgecenter"
url: "https://edgecenter.ru/dns"
---
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/edgecenter/edgecenter.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
Configuration for [EdgeCenter](https://edgecenter.ru/dns).
<!--more-->
- Code: `edgecenter`
- Since: v4.29.0
Here is an example bash command using the EdgeCenter provider:
```bash
EDGECENTER_PERMANENT_API_TOKEN=xxxxx \
lego --dns edgecenter -d '*.example.com' -d example.com run
```
## Credentials
| Environment Variable Name | Description |
|-----------------------|-------------|
| `EDGECENTER_PERMANENT_API_TOKEN` | Permanent API token (https://edgecenter.ru/blog/permanent-api-token-explained/) |
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 |
|--------------------------------|-------------|
| `EDGECENTER_HTTP_TIMEOUT` | API request timeout in seconds (Default: 10) |
| `EDGECENTER_POLLING_INTERVAL` | Time between DNS propagation check in seconds (Default: 20) |
| `EDGECENTER_PROPAGATION_TIMEOUT` | Maximum waiting time for DNS propagation in seconds (Default: 360) |
| `EDGECENTER_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://apidocs.edgecenter.ru/dns)
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->
<!-- providers/dns/edgecenter/edgecenter.toml -->
<!-- THIS DOCUMENTATION IS AUTO-GENERATED. PLEASE DO NOT EDIT. -->

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
```
@ -55,6 +55,7 @@ More information [here]({{% ref "dns#configuration-and-credentials" %}}).
| `EDGEONE_REGION` | Region |
| `EDGEONE_SESSION_TOKEN` | Access Key token |
| `EDGEONE_TTL` | The TTL of the TXT record used for the DNS challenge in seconds (Default: 60) |
| `EDGEONE_ZONES_MAPPING` | Mapping between DNS zones and site IDs. (ex: 'example.org:id1,example.com:id2') |
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" %}}).

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
```

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