Skip to content

[Bug]: Can't renew multiple domains (certonly, webroot, nginx) #10506

Closed

Description

@0tanay

OS

Arch Linux on Docker

Installation method

pacman

Certbot Version

5.2.1

What happened?

Hey there!

Certbot cannot renew or create a certificate when multiple domain names are requested. Although it works as expected if only a single domain name is requested.

Error

An unexpected error occurred:
TypeError: DNSName SAN compared to non-SAN: <class 'str'>

Setup

#! /bin/bash
set -euo pipefail
IFS=$'\n\t'

HOSTS=(
	"tanayg.com"
	"tanayg.network"
)

PARAMETERS=()

for host in "${HOSTS[@]}"; do
	path="/opt/certbot/webroot/$host"
	mkdir -p "$path"
	PARAMETERS+=("--webroot-path")
	PARAMETERS+=("$path")
	PARAMETERS+=("-d")
	PARAMETERS+=("$host")
done

certbot --config-dir /opt/certbot --cert-name tanayg --non-interactive --agree-tos \
certonly --force-renewal -a webroot -i nginx -m [email protected] \
"${PARAMETERS[@]}"

/opt/certbot is mounted on a docker volume shared with my nginx container. Also note that each domain has its own webroot path that my nginx container serves correctly.

This setup has worked for me for the past year.

Diagnosis

From the attached log, it looks like the commits for #10468 and #10478 are involved.

Fix?

This is just a hack. I don't know the code very well so I'm hoping this helps someone fix this properly.

Allow DNSName comparison with str

certbot/_internal/san.py

class DNSName(SAN):

    def __eq__(self, other: Any) -> bool:
        match other:
            case DNSName():
                return self.dns_name == other.dns_name
            case IPAddress():
                return False
            case str():
                return self.dns_name == other
            case _:
                raise TypeError(f"DNSName SAN compared to non-SAN: {type(other)}")

configobj can't store non-strings

  File "/usr/lib/python3.13/site-packages/configobj/__init__.py", line 579, in __setitem__
    raise ValueError('The key "%s" is not a string.' % key)
ValueError: The key "tanayg.com" is not a string.

certbot/_internal/storage.py

def relevant_values(config: configuration.NamespaceConfig) -> dict[str, Any]:

    ...

    rv = {
        str(option): str(value)
        for option, value in all_values.items()
        if _relevant(namespaces, option) and config.set_by_user(option)
    }

    ...

With these changes, the certificate renewal works!


I appreciate your help! Thanks!

Expected behavior

Certbot should renew all requested domain names.

Relevant log output

2025-12-07 11:47:18,023:DEBUG:certbot._internal.log:Exiting abnormally:
Traceback (most recent call last):
  File "/usr/sbin/certbot", line 8, in <module>
    sys.exit(main())
             ~~~~^^
  File "/usr/lib/python3.13/site-packages/certbot/main.py", line 18, in main
    return internal_main.main(cli_args)
           ~~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/certbot/_internal/main.py", line 1876, in main
    return config.func(config, plugins)
           ~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/certbot/_internal/main.py", line 1588, in certonly
    lineage = _get_and_save_cert(le_client, config, sans, certname, lineage)
  File "/usr/lib/python3.13/site-packages/certbot/_internal/main.py", line 131, in _get_and_save_cert
    renewal.renew_cert(config, sans, le_client, lineage)
    ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/certbot/_internal/renewal.py", line 564, in renew_cert
    new_cert, new_chain, new_key, _ = le_client.obtain_certificate(sans, new_key)
                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/certbot/_internal/client.py", line 432, in obtain_certificate
    orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
  File "/usr/lib/python3.13/site-packages/certbot/_internal/client.py", line 510, in _get_order_and_authorizations
    authzr = self.auth_handler.handle_authorizations(orderr, self.config, best_effort)
  File "/usr/lib/python3.13/site-packages/certbot/_internal/auth_handler.py", line 84, in handle_authorizations
    resps = self.auth.perform(achalls)
  File "/usr/lib/python3.13/site-packages/certbot/_internal/plugins/webroot.py", line 109, in perform
    self._set_webroots(achalls)
    ~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/certbot/_internal/plugins/webroot.py", line 121, in _set_webroots
    self.conf("map").setdefault(achall.domain, webroot_path)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.13/site-packages/certbot/_internal/san.py", line 90, in __eq__
    raise TypeError(f"DNSName SAN compared to non-SAN: {type(other)}")
TypeError: DNSName SAN compared to non-SAN: <class 'str'>
2025-12-07 11:47:18,025:ERROR:certbot._internal.log:An unexpected error occurred:

Activity

  1. added theissue type on Dec 7, 2025
  2. bmw commented on Dec 8, 2025

    @bmw
    Member

    hey @0tanay

    thanks so much for the detailed bug report. we'll get this fixed soon

    just to be sure, when you say certificate renewal is also broken, you're renewing your certificates with the certbot certonly subcommand instead of certbot renew right? i've been able to reproduce the problem with certbot certonly but not certbot renew and i want to make sure i'm not missing part of the problem here

  3. 0tanay commented on Dec 8, 2025

    @0tanay
    Author

    you're renewing your certificates with the certbot certonly subcommand instead of certbot renew right?

    That's right. I've only tried certbot certonly.

  4. jsha commented on Dec 9, 2025

    @jsha
    Contributor

    I've made a PR with a fix here: #10509

  5. 0tanay commented on Dec 10, 2025

    @0tanay
    Author

    Just saw this was fixed. Thanks a lot, everyone!

  6. fmonts commented on Dec 10, 2025

    @fmonts

    Can you please tag and publish a release?

    The issue is still present in certbot installed via snap on Ubuntu latest LTS, which basically broke a lot of production setups worldwide 🥲

  7. added 2 commits that reference this issue on Dec 10, 2025
    8bcf7f6
    305ebe1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions