Originally created by @strophy on GitHub (Nov 30, 2020).
Does/will dehydrated support RFC 8738 to issue certificates to IP addresses over ACME? ZeroSSL currently supports this over their REST API, but I am unable to test it with ACME because I am unable to find a client that supports both RFC 8738 and the EAB now requried by ZeroSSL. Looks dehydrated might be a possible choice, is this feature planned? Thanks!
Originally created by @strophy on GitHub (Nov 30, 2020).
Does/will dehydrated support [RFC 8738](https://tools.ietf.org/html/rfc8738) to issue certificates to IP addresses over ACME? ZeroSSL currently supports this over their REST API, but I am unable to test it with ACME because I am unable to find a client that supports both RFC 8738 and the EAB now requried by ZeroSSL. Looks dehydrated might be a possible choice, is this feature planned? Thanks!
adam
added the testing label 2025-12-29 01:26:28 +01:00
This will be integrated for the upcoming release 👍
But I'm not sure if ZeroSSL supports it on their ACME API.
@lukas2511 commented on GitHub (Dec 1, 2020):
This will be integrated for the upcoming release :+1:
But I'm not sure if ZeroSSL supports it on their ACME API.
Thanks! I have confirmed ZeroSSL only supports it over their REST API but not ACME yet. Either way, it's great to see more client support for this feature 👍
@strophy commented on GitHub (Dec 2, 2020):
Thanks! I have confirmed ZeroSSL only supports it over their REST API but not ACME yet. Either way, it's great to see more client support for this feature :+1:
I have an experimental implementation locally but since I want to release the new version today and didn't yet have an opportunity to test the code I'll postpone it for the next release (which will follow much quicker than the current one).
@lukas2511 commented on GitHub (Dec 10, 2020):
I have an experimental implementation locally but since I want to release the new version today and didn't yet have an opportunity to test the code I'll postpone it for the next release (which will follow much quicker than the current one).
So that I understand, that would mean this would work?
# echo 'CA="https://acme.zerossl.com/v2/DV90"' >> /etc/dehydrated/config
# dehydrated --register --accept-terms
# INFO: Using main config file /etc/dehydrated/config
# INFO: Using additional config file /etc/dehydrated/conf.d/hooks.sh
# INFO: Using additional config file /etc/dehydrated/conf.d/neuropoly.sh
+ Generating account key...
+ Registering account key with ACME server...
+ ERROR: An error occurred while sending post-request to https://acme.zerossl.com/v2/DV90/newAccount (Status 400)
Details:
HTTP/2 400
server: nginx
date: Tue, 20 Apr 2021 07:53:13 GMT
content-type: application/problem+json
content-length: 159
replay-nonce: zbqMLe3MhuyqQXP2ZUZ2MEZ5XZJAVw_EZOJxUr6cO_g
cache-control: max-age=0, no-cache, no-store
access-control-allow-origin: *
link: <https://acme.zerossl.com/v2/DV90>;rel="index"
cache-control: max-age=-1
{"type":"urn:ietf:params:acme:error:externalAccountRequired","status":400,"detail":"The request must include a value for the \"externalAccountBinding\" field"}
@kousu commented on GitHub (Apr 20, 2021):
So that I understand, that would mean this would work?
```
# echo 'CA="https://acme.zerossl.com/v2/DV90"' >> /etc/dehydrated/config
# dehydrated --register --accept-terms
# INFO: Using main config file /etc/dehydrated/config
# INFO: Using additional config file /etc/dehydrated/conf.d/hooks.sh
# INFO: Using additional config file /etc/dehydrated/conf.d/neuropoly.sh
+ Generating account key...
+ Registering account key with ACME server...
+ ERROR: An error occurred while sending post-request to https://acme.zerossl.com/v2/DV90/newAccount (Status 400)
Details:
HTTP/2 400
server: nginx
date: Tue, 20 Apr 2021 07:53:13 GMT
content-type: application/problem+json
content-length: 159
replay-nonce: zbqMLe3MhuyqQXP2ZUZ2MEZ5XZJAVw_EZOJxUr6cO_g
cache-control: max-age=0, no-cache, no-store
access-control-allow-origin: *
link: <https://acme.zerossl.com/v2/DV90>;rel="index"
cache-control: max-age=-1
{"type":"urn:ietf:params:acme:error:externalAccountRequired","status":400,"detail":"The request must include a value for the \"externalAccountBinding\" field"}
```
So that I understand, that would mean this would work?
# echo 'CA="https://acme.zerossl.com/v2/DV90"' >> /etc/dehydrated/config
# dehydrated --register --accept-terms
# INFO: Using main config file /etc/dehydrated/config
# INFO: Using additional config file /etc/dehydrated/conf.d/hooks.sh
# INFO: Using additional config file /etc/dehydrated/conf.d/neuropoly.sh
+ Generating account key...
+ Registering account key with ACME server...
+ ERROR: An error occurred while sending post-request to https://acme.zerossl.com/v2/DV90/newAccount (Status 400)
Details:
HTTP/2 400
server: nginx
date: Tue, 20 Apr 2021 07:53:13 GMT
content-type: application/problem+json
content-length: 159
replay-nonce: zbqMLe3MhuyqQXP2ZUZ2MEZ5XZJAVw_EZOJxUr6cO_g
cache-control: max-age=0, no-cache, no-store
access-control-allow-origin: *
link: <https://acme.zerossl.com/v2/DV90>;rel="index"
cache-control: max-age=-1
{"type":"urn:ietf:params:acme:error:externalAccountRequired","status":400,"detail":"The request must include a value for the \"externalAccountBinding\" field"}
Wrong thread. RFC 8738 is about getting certificates signed directly for IP addresses instead of domains. If you're having issues with zerossl please make sure to have the newest dehydrated version and open a new issue if the problem persists.
@lukas2511 commented on GitHub (Apr 21, 2021):
> So that I understand, that would mean this would work?
>
> ```
> # echo 'CA="https://acme.zerossl.com/v2/DV90"' >> /etc/dehydrated/config
> # dehydrated --register --accept-terms
> # INFO: Using main config file /etc/dehydrated/config
> # INFO: Using additional config file /etc/dehydrated/conf.d/hooks.sh
> # INFO: Using additional config file /etc/dehydrated/conf.d/neuropoly.sh
> + Generating account key...
> + Registering account key with ACME server...
> + ERROR: An error occurred while sending post-request to https://acme.zerossl.com/v2/DV90/newAccount (Status 400)
>
> Details:
> HTTP/2 400
> server: nginx
> date: Tue, 20 Apr 2021 07:53:13 GMT
> content-type: application/problem+json
> content-length: 159
> replay-nonce: zbqMLe3MhuyqQXP2ZUZ2MEZ5XZJAVw_EZOJxUr6cO_g
> cache-control: max-age=0, no-cache, no-store
> access-control-allow-origin: *
> link: <https://acme.zerossl.com/v2/DV90>;rel="index"
> cache-control: max-age=-1
>
> {"type":"urn:ietf:params:acme:error:externalAccountRequired","status":400,"detail":"The request must include a value for the \"externalAccountBinding\" field"}
> ```
Wrong thread. RFC 8738 is about getting certificates signed directly for IP addresses instead of domains. If you're having issues with zerossl please make sure to have the newest dehydrated version and open a new issue if the problem persists.
Thank you @lukas2511, installing 0.7.0 made ZeroSSL work. Debian stable has 0.6.5 packaged; testing has 0.7.0 so in like a year when the next Debian stable comes around this will work more easily.
For reference for anyone who stumbles across this thread, my install script is now:
ssh root@server apt-get install dehydrated
scp ./usr/bin/dehydrated root@server:/usr/bin/ # where ./usr/bin/dehydrated is from https://github.com/dehydrated-io/dehydrated/releases/tag/v0.7.0
ssh root@server "echo 'CA=\"https://acme.zerossl.com/v2/DV90\"' >> /etc/dehydrated/conf.d/site.sh"
And this seems to work fine for getting ZeroSSL working on Debian stable.
@kousu commented on GitHub (Apr 23, 2021):
Thank you @lukas2511, installing 0.7.0 made ZeroSSL work. Debian stable has 0.6.5 packaged; [testing has 0.7.0](https://packages.debian.org/sid/dehydrated) so in like a year when the next Debian stable comes around this will work more easily.
For reference for anyone who stumbles across this thread, my install script is now:
```
ssh root@server apt-get install dehydrated
scp ./usr/bin/dehydrated root@server:/usr/bin/ # where ./usr/bin/dehydrated is from https://github.com/dehydrated-io/dehydrated/releases/tag/v0.7.0
ssh root@server "echo 'CA=\"https://acme.zerossl.com/v2/DV90\"' >> /etc/dehydrated/conf.d/site.sh"
```
And this seems to work fine for getting ZeroSSL working on Debian stable.
RFC 8738 support is now implemented on the rfc8738 branch. There are still a few issues, e.g. comparison on already signed certificates is missing normalization for now so certificates especially for IPv6 addresses might be refreshed on every run. Also signing of external CSRs hasn't been tested yet.
I don't think any public CA supports this feature yet, but e.g. step-ca can be used for testing or whatever internal use-cases one might have (e.g. etcd or ssh).
@lukas2511 commented on GitHub (Apr 7, 2022):
RFC 8738 support is now implemented on the [rfc8738 branch](https://github.com/dehydrated-io/dehydrated/tree/rfc8738). There are still a few issues, e.g. comparison on already signed certificates is missing normalization for now so certificates especially for IPv6 addresses might be refreshed on every run. Also signing of external CSRs hasn't been tested yet.
I don't think any public CA supports this feature yet, but e.g. step-ca can be used for testing or whatever internal use-cases one might have (e.g. etcd or ssh).
RFC 8738 support is now implemented on the rfc8738 branch. There are still a few issues, e.g. comparison on already signed certificates is missing normalization for now so certificates especially for IPv6 addresses might be refreshed on every run. Also signing of external CSRs hasn't been tested yet.
I don't think any public CA supports this feature yet, but e.g. step-ca can be used for testing or whatever internal use-cases one might have (e.g. etcd or ssh).
zerossl allows to have ip based certificates, but probably only in rest api...
anyway, can you please share a command line example? Thanks in advance
@fragolinux commented on GitHub (Apr 14, 2022):
> RFC 8738 support is now implemented on the [rfc8738 branch](https://github.com/dehydrated-io/dehydrated/tree/rfc8738). There are still a few issues, e.g. comparison on already signed certificates is missing normalization for now so certificates especially for IPv6 addresses might be refreshed on every run. Also signing of external CSRs hasn't been tested yet.
>
> I don't think any public CA supports this feature yet, but e.g. step-ca can be used for testing or whatever internal use-cases one might have (e.g. etcd or ssh).
zerossl allows to have ip based certificates, but probably only in rest api...
anyway, can you please share a command line example? Thanks in advance
RFC 8738 support is now implemented on the rfc8738 branch. There are still a few issues, e.g. comparison on already signed certificates is missing normalization for now so certificates especially for IPv6 addresses might be refreshed on every run. Also signing of external CSRs hasn't been tested yet.
I don't think any public CA supports this feature yet, but e.g. step-ca can be used for testing or whatever internal use-cases one might have (e.g. etcd or ssh).
zerossl allows to have ip based certificates, but probably only in rest api... anyway, can you please share a command line example? Thanks in advance
Unfortunately they are not supporting ip certs via acme.
Example usage (for now) would be dehydrated -c -d IP:192.0.2.42 --ca zerossl (but it will fail). The IP: prefix may be dropped, not entirely sure about that yet.
@lukas2511 commented on GitHub (Apr 15, 2022):
> > RFC 8738 support is now implemented on the [rfc8738 branch](https://github.com/dehydrated-io/dehydrated/tree/rfc8738). There are still a few issues, e.g. comparison on already signed certificates is missing normalization for now so certificates especially for IPv6 addresses might be refreshed on every run. Also signing of external CSRs hasn't been tested yet.
> > I don't think any public CA supports this feature yet, but e.g. step-ca can be used for testing or whatever internal use-cases one might have (e.g. etcd or ssh).
>
> zerossl allows to have ip based certificates, but probably only in rest api... anyway, can you please share a command line example? Thanks in advance
Unfortunately they are not supporting ip certs via acme.
Example usage (for now) would be `dehydrated -c -d IP:192.0.2.42 --ca zerossl` (but it will fail). The `IP:` prefix may be dropped, not entirely sure about that yet.
@lukas2511 Is this done or its still in implementation stage? I have a similar requirement where both ip and fqdn are being added as SANS in a certificate.
@suhastm19 commented on GitHub (Feb 22, 2023):
@lukas2511 Is this done or its still in implementation stage? I have a similar requirement where both ip and fqdn are being added as SANS in a certificate.
@lukas2511 Is this done or its still in implementation stage? I have a similar requirement where both ip and fqdn are being added as SANS in a certificate.
It's implemented, but basically untested as afaik there are no public CAs supporting this (yet). It should probably work fine with private CAs like smallstep. Also the normalization issue with IPv6 addresses still exists but that can be worked around.
@lukas2511 commented on GitHub (Feb 22, 2023):
> @lukas2511 Is this done or its still in implementation stage? I have a similar requirement where both ip and fqdn are being added as SANS in a certificate.
It's implemented, but basically untested as afaik there are no public CAs supporting this (yet). It should probably work fine with private CAs like smallstep. Also the normalization issue with IPv6 addresses still exists but that can be worked around.
Should probably be ( Address)*. This showed up in shellcheck, which you really should be running.
@quite commented on GitHub (Jun 15, 2023):
@lukas2511 I think there is a typo here in the code:
https://github.com/dehydrated-io/dehydrated/blob/master/dehydrated#L1812
Should probably be `( Address)*`. This showed up in `shellcheck`, which you really should be running.
The solution is to request an empty subject (note that empty string or // are rejected by openssl req, but / is OK)
--- dehydrated.orig 2025-07-03 10:04:07.747841033 +0000
+++ dehydrated 2025-07-03 10:56:08.896896518 +0000
@@ -1554,7 +1554,7 @@
fi
done
if [[ "${domain}" =~ ^ip: ]]; then
- SUBJ="/CN=${domain:3}/"
+ SUBJ="/"
else
SUBJ="/CN=${domain}/"
fi
Any garbage subject like /DC=example/ also works; in either case the issued certificate has an empty subject.
The fact that LetsEncrypt accepts and ignores almost any subject except one which contains a commonName IP address seems weird. I have raised it with LetsEncrypt here.
@candlerb commented on GitHub (Jul 3, 2025):
This is *almost* working out-of-the-box with Letsencrypt Staging, which now offers IP SANs.
The challenge validation is successful, but the final stage fails:
```
HTTP/2 400
server: nginx
date: Thu, 03 Jul 2025 10:37:47 GMT
content-type: application/problem+json
content-length: 146
boulder-requester: 210222443
cache-control: public, max-age=0, no-cache
link: <https://acme-staging-v02.api.letsencrypt.org/directory>;rel="index"
replay-nonce: 8GeDqaBia2BthCHmE7GQHe5T-z1uLiHZ5QS5T4hwOxQXKoIukMo
{
"type": "urn:ietf:params:acme:error:badCSR",
"detail": "Error finalizing order :: CSR contains IP address in Common Name",
"status": 400
}
```
This is with dehydrated 0.7.2. Relevant config:
```
CA="letsencrypt-test"
ACME_PROFILE="shortlived"
WELLKNOWN=/var/www/dehydrated/.well-known/acme-challenge
```
domains.txt (with addresses masked):
```
ip:xxx.xxx.xxx.193 ip:xxx:xxx:xxx:xxx::62 >ipsan
```
The solution is to request an [empty subject](https://superuser.com/questions/512673/openssl-how-to-create-a-certificate-with-an-empty-subject-dn) (note that empty string or `//` are rejected by `openssl req`, but `/` is OK)
```
--- dehydrated.orig 2025-07-03 10:04:07.747841033 +0000
+++ dehydrated 2025-07-03 10:56:08.896896518 +0000
@@ -1554,7 +1554,7 @@
fi
done
if [[ "${domain}" =~ ^ip: ]]; then
- SUBJ="/CN=${domain:3}/"
+ SUBJ="/"
else
SUBJ="/CN=${domain}/"
fi
```
Any garbage subject like `/DC=example/` also works; in either case the issued certificate has an empty subject.
The fact that LetsEncrypt accepts and ignores almost any subject *except* one which contains a commonName IP address seems weird. I have raised it with LetsEncrypt [here](https://community.letsencrypt.org/t/ip-san-error-csr-contains-ip-address-in-common-name/239012).
I think that one-line fix I gave is correct: for LetsEncrypt, if you provide a subject commonName, it is only allowed to match a DNS SAN in the same CSR.
(Although Subject is obsolete anyway, and it would probably be fine to set an empty subject for all certificates)
@candlerb commented on GitHub (Jul 3, 2025):
I think that one-line fix I gave is correct: for LetsEncrypt, if you provide a subject commonName, it is only allowed to match a *DNS* SAN in the same CSR.
(Although Subject is obsolete anyway, and it would probably be fine to set an empty subject for *all* certificates)
Of additional note, the initial IP cert Let'sEncrypt issued uses an empty Subject too as can be seen at https://crt.sh/?id=19376952215
@jobe1986 commented on GitHub (Jul 3, 2025):
Of additional note, the initial IP cert Let'sEncrypt issued uses an empty Subject too as can be seen at https://crt.sh/?id=19376952215
I think that one-line fix I gave is correct: for LetsEncrypt, if you provide a subject commonName, it is only allowed to match a DNS SAN in the same CSR.
(Although Subject is obsolete anyway, and it would probably be fine to set an empty subject for all certificates)
Thanks for the suggestion, I've added the change to the script. And yes, normally subjects are obsolete and an empty subject should be fine, but since some CAs are really weird I think it's better for now to just keep the old behaviour for non-ip names.
@lukas2511 commented on GitHub (Jul 5, 2025):
> I think that one-line fix I gave is correct: for LetsEncrypt, if you provide a subject commonName, it is only allowed to match a _DNS_ SAN in the same CSR.
>
> (Although Subject is obsolete anyway, and it would probably be fine to set an empty subject for _all_ certificates)
Thanks for the suggestion, I've added the change to the script. And yes, normally subjects are obsolete and an empty subject should be fine, but since some CAs are really weird I think it's better for now to just keep the old behaviour for non-ip names.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @strophy on GitHub (Nov 30, 2020).
Does/will dehydrated support RFC 8738 to issue certificates to IP addresses over ACME? ZeroSSL currently supports this over their REST API, but I am unable to test it with ACME because I am unable to find a client that supports both RFC 8738 and the EAB now requried by ZeroSSL. Looks dehydrated might be a possible choice, is this feature planned? Thanks!
@lukas2511 commented on GitHub (Dec 1, 2020):
This will be integrated for the upcoming release 👍
But I'm not sure if ZeroSSL supports it on their ACME API.
@strophy commented on GitHub (Dec 2, 2020):
Thanks! I have confirmed ZeroSSL only supports it over their REST API but not ACME yet. Either way, it's great to see more client support for this feature 👍
@lukas2511 commented on GitHub (Dec 10, 2020):
I have an experimental implementation locally but since I want to release the new version today and didn't yet have an opportunity to test the code I'll postpone it for the next release (which will follow much quicker than the current one).
@kousu commented on GitHub (Apr 20, 2021):
So that I understand, that would mean this would work?
@lukas2511 commented on GitHub (Apr 21, 2021):
Wrong thread. RFC 8738 is about getting certificates signed directly for IP addresses instead of domains. If you're having issues with zerossl please make sure to have the newest dehydrated version and open a new issue if the problem persists.
@kousu commented on GitHub (Apr 23, 2021):
Thank you @lukas2511, installing 0.7.0 made ZeroSSL work. Debian stable has 0.6.5 packaged; testing has 0.7.0 so in like a year when the next Debian stable comes around this will work more easily.
For reference for anyone who stumbles across this thread, my install script is now:
And this seems to work fine for getting ZeroSSL working on Debian stable.
@lukas2511 commented on GitHub (Apr 7, 2022):
RFC 8738 support is now implemented on the rfc8738 branch. There are still a few issues, e.g. comparison on already signed certificates is missing normalization for now so certificates especially for IPv6 addresses might be refreshed on every run. Also signing of external CSRs hasn't been tested yet.
I don't think any public CA supports this feature yet, but e.g. step-ca can be used for testing or whatever internal use-cases one might have (e.g. etcd or ssh).
@fragolinux commented on GitHub (Apr 14, 2022):
zerossl allows to have ip based certificates, but probably only in rest api...
anyway, can you please share a command line example? Thanks in advance
@lukas2511 commented on GitHub (Apr 15, 2022):
Unfortunately they are not supporting ip certs via acme.
Example usage (for now) would be
dehydrated -c -d IP:192.0.2.42 --ca zerossl(but it will fail). TheIP:prefix may be dropped, not entirely sure about that yet.@suhastm19 commented on GitHub (Feb 22, 2023):
@lukas2511 Is this done or its still in implementation stage? I have a similar requirement where both ip and fqdn are being added as SANS in a certificate.
@lukas2511 commented on GitHub (Feb 22, 2023):
It's implemented, but basically untested as afaik there are no public CAs supporting this (yet). It should probably work fine with private CAs like smallstep. Also the normalization issue with IPv6 addresses still exists but that can be worked around.
@suhastm19 commented on GitHub (Mar 2, 2023):
Is this code available in v0.7.1 release?
@lukas2511 commented on GitHub (Mar 2, 2023):
Yes.
@quite commented on GitHub (Jun 15, 2023):
@lukas2511 I think there is a typo here in the code:
https://github.com/dehydrated-io/dehydrated/blob/master/dehydrated#L1812
Should probably be
( Address)*. This showed up inshellcheck, which you really should be running.@candlerb commented on GitHub (Jul 3, 2025):
This is almost working out-of-the-box with Letsencrypt Staging, which now offers IP SANs.
The challenge validation is successful, but the final stage fails:
This is with dehydrated 0.7.2. Relevant config:
domains.txt (with addresses masked):
The solution is to request an empty subject (note that empty string or
//are rejected byopenssl req, but/is OK)Any garbage subject like
/DC=example/also works; in either case the issued certificate has an empty subject.The fact that LetsEncrypt accepts and ignores almost any subject except one which contains a commonName IP address seems weird. I have raised it with LetsEncrypt here.
@candlerb commented on GitHub (Jul 3, 2025):
I think that one-line fix I gave is correct: for LetsEncrypt, if you provide a subject commonName, it is only allowed to match a DNS SAN in the same CSR.
(Although Subject is obsolete anyway, and it would probably be fine to set an empty subject for all certificates)
@jobe1986 commented on GitHub (Jul 3, 2025):
Of additional note, the initial IP cert Let'sEncrypt issued uses an empty Subject too as can be seen at https://crt.sh/?id=19376952215
@lukas2511 commented on GitHub (Jul 5, 2025):
Thanks for the suggestion, I've added the change to the script. And yes, normally subjects are obsolete and an empty subject should be fine, but since some CAs are really weird I think it's better for now to just keep the old behaviour for non-ip names.