Repository: certbot/certbot (language: python)

Issue:
Log files in /tmp do not have "certbot" or similar in filename
## My operating system is (include version):

Debian 4.19.181-1 (2021-03-19) x86_64 GNU/Linux

## I installed Certbot with (snap, OS package manager, pip, certbot-auto, etc):

OS package manager (apt)

## I ran this command and it produced this output:

N/A

## Certbot's behavior differed from what I expected because:

Certbot created approximately 264,744 log files in `/tmp/` from failing to get a lock (I think this is due to the specific way I run certbot in a cronjob). I asked in #9173 and was told this was expected behaviour, and I should delete them if I don't want them. However, since the files are simply named `/tmp/tmpXXXXXXXX` (where the Xs are random characters), it's impossible to delete just the certbot crash logs just by name — I need to either blow up every file starting with `/tmp/tmp*`, or write a script to grep for some specific string.

Instead, they should be named something like `/tmp/certbot_error_XXXXXXXX`.

## Here is a Certbot log showing the issue (if available):

N/A

## Here is the relevant nginx server block or Apache virtualhost for the domain I am configuring:

N/A


Discussion / hints:

Fix patch:
diff --git a/.azure-pipelines/templates/jobs/packaging-jobs.yml b/.azure-pipelines/templates/jobs/packaging-jobs.yml
index c5dcf16ddc6..cd2a088860b 100644
--- a/.azure-pipelines/templates/jobs/packaging-jobs.yml
+++ b/.azure-pipelines/templates/jobs/packaging-jobs.yml
@@ -6,12 +6,10 @@ jobs:
       matrix:
         amd64:
           DOCKER_ARCH: amd64
-        # Do not run the heavy non-amd64 builds for test branches
-        ${{ if not(startsWith(variables['Build.SourceBranchName'], 'test-')) }}:
-          arm32v6:
-            DOCKER_ARCH: arm32v6
-          arm64v8:
-            DOCKER_ARCH: arm64v8
+        arm32v6:
+          DOCKER_ARCH: arm32v6
+        arm64v8:
+          DOCKER_ARCH: arm64v8
     # The default timeout of 60 minutes is a little low for compiling
     # cryptography on ARM architectures.
     timeoutInMinutes: 180
@@ -121,12 +119,10 @@ jobs:
       matrix:
         amd64:
           SNAP_ARCH: amd64
-        # Do not run the heavy non-amd64 builds for test branches
-        ${{ if not(startsWith(variables['Build.SourceBranchName'], 'test-')) }}:
-          armhf:
-            SNAP_ARCH: armhf
-          arm64:
-            SNAP_ARCH: arm64
+        armhf:
+          SNAP_ARCH: armhf
+        arm64:
+          SNAP_ARCH: arm64
     timeoutInMinutes: 0
     steps:
       - script: |
diff --git a/acme/docs/jws-help.txt b/acme/docs/jws-help.txt
index 34cf5ce2356..bfd16dff4d7 100644
--- a/acme/docs/jws-help.txt
+++ b/acme/docs/jws-help.txt
@@ -3,6 +3,6 @@ usage: jws [-h] [--compact] {sign,verify} ...
 positional arguments:
   {sign,verify}
 
-optional arguments:
+options:
   -h, --help     show this help message and exit
   --compact
diff --git a/acme/setup.py b/acme/setup.py
index d71580153f7..5c1e42e03fd 100644
--- a/acme/setup.py
+++ b/acme/setup.py
@@ -3,7 +3,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'cryptography>=2.5.0',
diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py
index 425f85db7ac..eab74f5e3db 100644
--- a/certbot-apache/setup.py
+++ b/certbot-apache/setup.py
@@ -1,7 +1,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     # We specify the minimum acme and certbot version as the current plugin
diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py
index 81c053c04fa..b72f19f0816 100644
--- a/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py
+++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py
@@ -39,7 +39,7 @@
 zones you need certificates for.
 
 Using Cloudflare Tokens also requires at least version 2.3.1 of the ``cloudflare``
-python module. If the version that automatically installed with this plugin is
+Python module. If the version that automatically installed with this plugin is
 older than that, and you can't upgrade it on your system, you'll have to stick to
 the Global key.
 
@@ -77,6 +77,18 @@
 including for renewal, and cannot be silenced except by addressing the issue
 (e.g., by using a command like ``chmod 600`` to restrict access to the file).
 
+.. note::
+    Please note that the ``cloudflare`` Python module used by the plugin has
+    additional methods of providing credentials to the module, e.g. environment
+    variables or the ``cloudflare.cfg`` configuration file. These methods are not
+    supported by Certbot. If any of those additional methods of providing
+    credentials is being used, they must provide the same credentials (i.e.,
+    email and API key *or* an API token) as the credentials file provided to
+    Certbot. If there is a discrepancy, the ``cloudflare`` Python module will
+    raise an error. Also note that the credentials provided to Certbot will take
+    precedence over any other method of providing credentials to the ``cloudflare``
+    Python module.
+
 
 Examples
 --------
diff --git a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py
index eac29a85b9d..e8bf560c682 100644
--- a/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py
+++ b/certbot-dns-cloudflare/certbot_dns_cloudflare/_internal/dns_cloudflare.py
@@ -82,8 +82,9 @@ def _get_cloudflare_client(self) -> "_CloudflareClient":
         if not self.credentials:  # pragma: no cover
             raise errors.Error("Plugin has not been prepared.")
         if self.credentials.conf('api-token'):
-            return _CloudflareClient(None, self.credentials.conf('api-token'))
-        return _CloudflareClient(self.credentials.conf('email'), self.credentials.conf('api-key'))
+            return _CloudflareClient(api_token = self.credentials.conf('api-token'))
+        return _CloudflareClient(email = self.credentials.conf('email'),
+                                 api_key = self.credentials.conf('api-key'))
 
 
 class _CloudflareClient:
@@ -91,8 +92,19 @@ class _CloudflareClient:
     Encapsulates all communication with the Cloudflare API.
     """
 
-    def __init__(self, email: Optional[str], api_key: str) -> None:
-        self.cf = CloudFlare.CloudFlare(email, api_key)
+    def __init__(self, email: Optional[str] = None, api_key: Optional[str] = None,
+                 api_token: Optional[str] = None) -> None:
+        if email:
+            # If an email was specified, we're using an email/key combination and not a token.
+            # We can't use named arguments in this case, as it would break compatibility with
+            # the Cloudflare library since version 2.10.1, as the `token` argument was used for
+            # tokens and keys alike and the `key` argument did not exist in earlier versions.
+            self.cf = CloudFlare.CloudFlare(email, api_key)
+        else:
+            # If no email was specified, we're using just a token. Let's use the named argument
+            # for simplicity, which is compatible with all (current) versions of the Cloudflare
+            # library.
+            self.cf = CloudFlare.CloudFlare(token=api_token)
 
     def add_txt_record(self, domain: str, record_name: str, record_content: str,
                        record_ttl: int) -> None:
diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py
index 3efbb1494df..65eb1139995 100644
--- a/certbot-dns-cloudflare/setup.py
+++ b/certbot-dns-cloudflare/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'cloudflare>=1.5.1',
diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py
index 9b419613313..a51077afeb7 100644
--- a/certbot-dns-digitalocean/setup.py
+++ b/certbot-dns-digitalocean/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support
diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py
index dfc3e529fa0..6ad86155482 100644
--- a/certbot-dns-dnsimple/setup.py
+++ b/certbot-dns-dnsimple/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     # This version of lexicon is required to address the problem described in
diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py
index 276a94ca998..e1b4989c33f 100644
--- a/certbot-dns-dnsmadeeasy/setup.py
+++ b/certbot-dns-dnsmadeeasy/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'dns-lexicon>=3.2.1',
diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py
index c9247f34131..0acad3dba8e 100644
--- a/certbot-dns-gehirn/setup.py
+++ b/certbot-dns-gehirn/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'dns-lexicon>=3.2.1',
diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py
index d5a6acc94cc..86b11fe23a6 100644
--- a/certbot-dns-google/setup.py
+++ b/certbot-dns-google/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'google-api-python-client>=1.5.5',
diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py
index 03f3f3bc2d8..51cae0ab6bc 100644
--- a/certbot-dns-linode/setup.py
+++ b/certbot-dns-linode/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'dns-lexicon>=3.2.1',
diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py
index 2241815662d..cc3cce7ae43 100644
--- a/certbot-dns-luadns/setup.py
+++ b/certbot-dns-luadns/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'dns-lexicon>=3.2.1',
diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py
index b89b64e0104..aef59062999 100644
--- a/certbot-dns-nsone/setup.py
+++ b/certbot-dns-nsone/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'dns-lexicon>=3.2.1',
diff --git a/certbot-dns-ovh/certbot_dns_ovh/__init__.py b/certbot-dns-ovh/certbot_dns_ovh/__init__.py
index 6a079e59fd8..42eaed9a0b5 100644
--- a/certbot-dns-ovh/certbot_dns_ovh/__init__.py
+++ b/certbot-dns-ovh/certbot_dns_ovh/__init__.py
@@ -25,14 +25,22 @@
 -----------
 
 Use of this plugin requires a configuration file containing OVH API
-credentials for an account with the following access rules:
+credentials for an account with the following access rules (allowing all domains):
 
 * ``GET /domain/zone/*``
 * ``PUT /domain/zone/*``
 * ``POST /domain/zone/*``
 * ``DELETE /domain/zone/*``
 
-These credentials can be obtained there:
+Alternatively, to allow a single domain only, the following access rules apply:
+
+* ``GET /domain/zone/``
+* ``GET /domain/zone/<REQUIRED_DOMAIN>/*``
+* ``PUT /domain/zone/<REQUIRED_DOMAIN>/*``
+* ``POST /domain/zone/<REQUIRED_DOMAIN>/*``
+* ``DELETE /domain/zone/<REQUIRED_DOMAIN>/*``
+
+These credentials can be obtained at the following links:
 
 * `OVH Europe <https://eu.api.ovh.com/createToken/>`_ (endpoint: ``ovh-eu``)
 * `OVH North America <https://ca.api.ovh.com/createToken/>`_ (endpoint:
diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py
index 70c3d6fbed2..1d19ceed48e 100644
--- a/certbot-dns-ovh/setup.py
+++ b/certbot-dns-ovh/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'dns-lexicon>=3.2.1',
diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py
index 01a026d61d4..0c3283ed450 100644
--- a/certbot-dns-rfc2136/setup.py
+++ b/certbot-dns-rfc2136/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'dnspython>=1.15.0',
diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py
index ed4cc0a1172..51b1a5824c8 100644
--- a/certbot-dns-route53/setup.py
+++ b/certbot-dns-route53/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'boto3>=1.15.15',
diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py
index 10a606b4c6d..d7dda2406ce 100644
--- a/certbot-dns-sakuracloud/setup.py
+++ b/certbot-dns-sakuracloud/setup.py
@@ -4,7 +4,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'dns-lexicon>=3.2.1',
diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py
index 4a4d5750946..d3d2943670b 100644
--- a/certbot-nginx/setup.py
+++ b/certbot-nginx/setup.py
@@ -1,7 +1,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     # We specify the minimum acme and certbot version as the current plugin
diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md
index 8c5f65e50e8..231f5c45353 100644
--- a/certbot/CHANGELOG.md
+++ b/certbot/CHANGELOG.md
@@ -2,7 +2,7 @@
 
 Certbot adheres to [Semantic Versioning](https://semver.org/).
 
-## 1.31.0 - master
+## 1.32.0 - master
 
 ### Added
 
@@ -18,6 +18,25 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
 
 More details about these changes can be found on our GitHub repo.
 
+## 1.31.0 - 2022-10-04
+
+### Added
+
+*
+
+### Changed
+
+* If Certbot exits before setting up its usual log files, the temporary directory created to save logging information will begin with the name `certbot-log-` rather than a generic name. This should not be considered a [stable aspect of Certbot](https://certbot.eff.org/docs/compatibility.html) and may change again in the future.
+
+### Fixed
+
+* Fixed an incompatibility in the certbot-dns-cloudflare plugin and the Cloudflare library
+  which was introduced in the Cloudflare library version 2.10.1. The library would raise
+  an error if a token was specified in the Certbot `--dns-cloudflare-credentials` file as
+  well as the `cloudflare.cfg` configuration file of the Cloudflare library.
+
+More details about these changes can be found on our GitHub repo.
+
 ## 1.30.0 - 2022-09-07
 
 ### Added
diff --git a/certbot/certbot/__init__.py b/certbot/certbot/__init__.py
index 27b94a930cf..8e3878654c0 100644
--- a/certbot/certbot/__init__.py
+++ b/certbot/certbot/__init__.py
@@ -1,3 +1,3 @@
 """Certbot client."""
 # version number like 1.2.3a0, must have at least 2 parts, like 1.2
-__version__ = '1.31.0.dev0'
+__version__ = '2.0.0.dev0'
diff --git a/certbot/certbot/_internal/log.py b/certbot/certbot/_internal/log.py
index 6d089afd489..b6b7d4601a3 100644
--- a/certbot/certbot/_internal/log.py
+++ b/certbot/certbot/_internal/log.py
@@ -264,7 +264,7 @@ class TempHandler(logging.StreamHandler):
 
     """
     def __init__(self) -> None:
-        self._workdir = tempfile.mkdtemp()
+        self._workdir = tempfile.mkdtemp(prefix="certbot-log-")
         self.path = os.path.join(self._workdir, 'log')
         stream = util.safe_open(self.path, mode='w', chmod=0o600)
         super().__init__(stream)
diff --git a/certbot/docs/cli-help.txt b/certbot/docs/cli-help.txt
index 8592825f209..aadfb67cb5e 100644
--- a/certbot/docs/cli-help.txt
+++ b/certbot/docs/cli-help.txt
@@ -35,7 +35,7 @@ manage your account:
   --agree-tos       Agree to the ACME server's Subscriber Agreement
    -m EMAIL         Email address for important account notifications
 
-optional arguments:
+options:
   -h, --help            show this help message and exit
   -c CONFIG_FILE, --config CONFIG_FILE
                         path to config file (default: /etc/letsencrypt/cli.ini
@@ -126,7 +126,7 @@ optional arguments:
                         case, and to know when to deprecate support for past
                         Python versions and flags. If you wish to hide this
                         information from the Let's Encrypt server, set this to
-                        "". (default: CertbotACMEClient/1.30.0 (certbot;
+                        "". (default: CertbotACMEClient/1.31.0 (certbot;
                         OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY
                         (SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel).
                         The flags encoded in the user agent are: --duplicate,
diff --git a/certbot/docs/install.rst b/certbot/docs/install.rst
index d19b0caf30f..71f56b28503 100644
--- a/certbot/docs/install.rst
+++ b/certbot/docs/install.rst
@@ -6,80 +6,45 @@ Get Certbot
    :local:
 
 
-About Certbot
-=============
-
-*Certbot is meant to be run directly on a web server*, normally by a system administrator. In most cases, running Certbot on your personal computer is not a useful option. The instructions below relate to installing and running Certbot on a server.
-
-System administrators can use Certbot directly to request certificates; they should *not* allow unprivileged users to run arbitrary Certbot commands as ``root``, because Certbot allows its user to specify arbitrary file locations and run arbitrary scripts.
-
-Certbot is packaged for many common operating systems and web servers. Check whether
-``certbot`` (or ``letsencrypt``) is packaged for your web server's OS by visiting
-certbot.eff.org_, where you will also find the correct installation instructions for
-your system.
-
-.. Note:: Unless you have very specific requirements, we kindly suggest that you use the installation instructions for your system found at certbot.eff.org_.
+.. _system_requirements:
 
-.. _certbot.eff.org: https://certbot.eff.org
+System Requirements
+-------------------
+- Linux, macOS, BSD and Windows
+- Recommended root access on Linux/BSD/Required Administrator access on Windows
+- Port 80 Open
 
+.. Note:: Certbot is most useful when run with root privileges, because it is then able to automatically configure TLS/SSL for Apache and nginx. \
+   
+   *Certbot is meant to be run directly on a web server*, normally by a system administrator. In most cases, running Certbot on your personal computer is not a useful option. The instructions below relate to installing and running Certbot on a server.
 
-.. _system_requirements:
+Installation
+------------
 
-System Requirements
-===================
-
-Certbot currently requires Python 3.7+ running on a UNIX-like operating
-system. By default, it requires root access in order to write to
-``/etc/letsencrypt``, ``/var/log/letsencrypt``, ``/var/lib/letsencrypt``; to
-bind to port 80 (if you use the ``standalone`` plugin) and to read and
-modify webserver configurations (if you use the ``apache`` or ``nginx``
-plugins).  If none of these apply to you, it is theoretically possible to run
-without root privileges, but for most users who want to avoid running an ACME
-client as root, either `letsencrypt-nosudo
-<https://github.com/diafygi/letsencrypt-nosudo>`_ or `simp_le
-<https://github.com/zenhack/simp_le>`_ are more appropriate choices.
-
-The Apache plugin currently requires an OS with augeas version 1.0; currently `it
-supports
-<https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/constants.py>`_
-modern OSes based on Debian, Ubuntu, Fedora, SUSE, Gentoo and Darwin.
-
-Alternate installation methods
-================================
-
-If you are offline or your operating system doesn't provide a package, you can use
-an alternate method for installing ``certbot``.
+Unless you have very specific requirements, we kindly suggest that you use the installation instructions for your system found at https://certbot.eff.org/instructions.
 
 .. _snap-install:
 
-Snap
-----
+Snap (Recommended)
+------------------
+Our instructions are the same across all systems that use Snap. You can find instructions for installing Certbot through Snap can be found at https://certbot.eff.org/instructions by selecting your server software and then choosing "snapd" in the "System" dropdown menu.
 
-Most modern Linux distributions (basically any that use systemd) can install
-Certbot packaged as a snap. Snaps are available for x86_64, ARMv7 and ARMv8
-architectures. The Certbot snap provides an easy way to ensure you have the
-latest version of Certbot with features like automated certificate renewal
-preconfigured.
+Most modern Linux distributions (basically any that use systemd) can install Certbot packaged as a snap. Snaps are available for x86_64, ARMv7 and ARMv8 architectures. The Certbot snap provides an easy way to ensure you have the latest version of Certbot with features like automated certificate renewal preconfigured.
+
+If you unable to use snaps, you can use an alternate method for installing ``certbot``.
 
-You can find instructions for installing the Certbot snap at
-https://certbot.eff.org/instructions by selecting your server software and then
-choosing "snapd" in the "System" dropdown menu. (You should select "snapd"
-regardless of your operating system, as our instructions are the same across
-all systems.)
 
 .. _docker-user:
 
-Running with Docker
--------------------
+Alternative 1: Docker
+---------------------
 
 Docker_ is an amazingly simple and quick way to obtain a
 certificate. However, this mode of operation is unable to install
 certificates or configure your webserver, because our installer
 plugins cannot reach your webserver from inside the Docker container.
 
-Most users should use the instructions at certbot.eff.org_. You should only use
-Docker if you are sure you know what you are doing and have a good reason to do
-so.
+Most users should use the instructions at certbot.eff.org_. You should only use Docker if you are sure you know what you are doing and have a good reason to do so.
 
 You should definitely read the :ref:`where-certs` section, in order to
 know how to manage the certificates
@@ -124,11 +89,41 @@ of the ``/etc/letsencrypt`` directory, see :ref:`where-certs`.
 
 .. _Docker: https://docker.com
 .. _`install Docker`: https://docs.docker.com/engine/installation/
+.. _certbot.eff.org: https://certbot.eff.org/instructions
+
 
-Pip
----
+.. _pip:
+
+Alternative 2: Pip
+------------------
 
 Installing Certbot through pip is only supported on a best effort basis and
 when using a virtual environment. Instructions for installing Certbot through
 pip can be found at https://certbot.eff.org/instructions by selecting your
 server software and then choosing "pip" in the "System" dropdown menu.
+
+
+.. _third-party:
+
+Alternative 3: Third Party Distributions
+----------------------------------------
+
+Third party distributions exist for other specific needs. They often are maintained
+by these parties outside of Certbot and tend to rapidly fall out of date on LTS-style distributions.
+
+
+.. _certbot-auto:
+
+Certbot-Auto [Deprecated]
+-------------------------
+.. toctree::
+   :hidden:
+
+We used to have a shell script named ``certbot-auto`` to help people install
+Certbot on UNIX operating systems, however, this script is no longer supported.
+
+Please remove ``certbot-auto``. To do so, you need to do three things:
+
+1. If you added a cron job or systemd timer to automatically run certbot-auto to renew your certificates, you should delete it. If you did this by following our instructions, you can delete the entry added to `/etc/crontab` by running a command like `sudo sed -i '/certbot-auto/d' /etc/crontab`.
+2. Delete the certbot-auto script. If you placed it in `/usr/local/bin`` like we recommended, you can delete it by running `sudo rm /usr/local/bin/certbot-auto`.
+3. Delete the Certbot installation created by certbot-auto by running `sudo rm -rf /opt/eff.org`.
diff --git a/tools/docker/core/Dockerfile b/tools/docker/core/Dockerfile
index fc0912752b0..911e7796a59 100644
--- a/tools/docker/core/Dockerfile
+++ b/tools/docker/core/Dockerfile
@@ -1,6 +1,6 @@
 # Docker Arch (amd64, arm32v6, ...)
 ARG TARGET_ARCH
-FROM ${TARGET_ARCH}/python:3.8-alpine3.12
+FROM ${TARGET_ARCH}/python:3.10-alpine3.16
 
 # Qemu Arch (x86_64, arm, ...)
 ARG QEMU_ARCH
diff --git a/tools/requirements.txt b/tools/requirements.txt
index 36b0f512893..f79c3adc22f 100644
--- a/tools/requirements.txt
+++ b/tools/requirements.txt
@@ -10,58 +10,57 @@ apacheconfig==0.3.2; python_version >= "3.7"
 appdirs==1.4.4; python_version >= "3.7" and python_version < "4.0"
 appnope==0.1.3; python_version >= "3.7" and sys_platform == "darwin"
 astroid==2.11.7; python_version >= "3.7"
-atomicwrites==1.4.1; sys_platform == "win32" and python_version >= "3.7"
 attrs==22.1.0; python_version >= "3.7"
-awscli==1.25.40
-awscli==1.25.40; python_version >= "3.7"
+awscli==1.25.76
+awscli==1.25.76; python_version >= "3.7"
 azure-devops==6.0.0b4; python_version >= "3.7"
 babel==2.10.3; python_version >= "3.7"
 backcall==0.2.0; python_version >= "3.7"
-bcrypt==3.2.2; python_version >= "3.7"
+bcrypt==4.0.0; python_version >= "3.7"
 beautifulsoup4==4.11.1; python_version >= "3.7"
 bleach==5.0.1; python_version >= "3.7"
-boto3==1.24.40; python_version >= "3.7"
-botocore==1.27.40; python_version >= "3.7"
-cachecontrol==0.12.11; python_version >= "3.7" and python_version < "4.0"
-cached-property==1.5.2; python_version >= "3.7"
+boto3==1.24.75; python_version >= "3.7"
+botocore==1.27.75; python_version >= "3.7"
+cachecontrol==0.12.12; python_version >= "3.7" and python_version < "4.0"
+cached-property==1.5.2; python_version < "3.8" and python_version >= "3.7"
 cachetools==5.2.0; python_version >= "3.7" and python_version < "4.0"
 cachy==0.3.0; python_version >= "3.7" and python_version < "4.0"
-certifi==2022.6.15; python_version >= "3.7" and python_version < "4" or python_version >= "3.7"
+certifi==2022.9.14; python_version >= "3.7" and python_version < "4" or python_version >= "3.7"
 cffi==1.15.1; python_version >= "3.7"
-charset-normalizer==2.1.0; python_version >= "3.7" and python_version < "4"
+charset-normalizer==2.1.1; python_version >= "3.7" and python_version < "4"
 cleo==1.0.0a5; python_version >= "3.7" and python_version < "4.0"
-cloudflare==2.9.11; python_version >= "3.7"
+cloudflare==2.10.1; python_version >= "3.7"
 colorama==0.4.4; python_version >= "3.7"
 configargparse==1.5.3; python_version >= "3.7"
 configobj==5.0.6; python_version >= "3.7"
-coverage==6.4.2; python_version >= "3.7"
+coverage==6.4.4; python_version >= "3.7"
 crashtest==0.3.1; python_version >= "3.7" and python_version < "4.0"
-cryptography==37.0.4
-cryptography==37.0.4; python_version >= "3.7"
-cython==0.29.31
+cryptography==38.0.1
+cryptography==38.0.1; python_version >= "3.7"
+cython==0.29.32
 decorator==5.1.1; python_version >= "3.7"
 dill==0.3.5.1; python_version >= "3.7"
-distlib==0.3.5; python_version >= "3.7"
+distlib==0.3.6; python_version >= "3.7"
 distro==1.7.0; python_version >= "3.7"
 dns-lexicon==3.11.1; python_version >= "3.7" and python_version < "4.0"
 dnspython==2.2.1; python_version >= "3.7" and python_version < "4.0"
-docker-compose==1.26.2; python_version >= "3.7"
-docker==4.2.2; python_version >= "3.7"
+docker-compose==1.29.2; python_version >= "3.7"
+docker==6.0.0; python_version >= "3.7"
 dockerpty==0.4.1; python_version >= "3.7"
 docopt==0.6.2; python_version >= "3.7"
 docutils==0.16; python_version >= "3.7"
 entrypoints==0.3; python_version >= "3.7" and python_version < "4.0"
 execnet==1.9.0; python_version >= "3.7"
 fabric==2.7.1; python_version >= "3.7"
-filelock==3.7.1; python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0"
-google-api-core==2.8.2; python_version >= "3.7"
-google-api-python-client==2.55.0; python_version >= "3.7"
+filelock==3.8.0; python_version >= "3.7" or python_version >= "3.7" and python_version < "4.0"
+google-api-core==2.10.1; python_version >= "3.7"
+google-api-python-client==2.61.0; python_version >= "3.7"
 google-auth-httplib2==0.1.0; python_version >= "3.7"
-google-auth==2.9.1; python_version >= "3.7"
+google-auth==2.11.0; python_version >= "3.7"
 googleapis-common-protos==1.56.4; python_version >= "3.7"
 html5lib==1.1; python_version >= "3.7" and python_version < "4.0"
 httplib2==0.20.4; python_version >= "3.7"
-idna==3.3; python_version >= "3.7" and python_version < "4" or python_version >= "3.7" and python_version < "4.0"
+idna==3.4; python_version >= "3.7" and python_version < "4" or python_version >= "3.7" and python_version < "4.0"
 imagesize==1.4.1; python_version >= "3.7"
 importlib-metadata==1.7.0; python_version >= "3.7" and python_version < "3.8"
 iniconfig==1.1.1; python_version >= "3.7"
@@ -80,16 +79,15 @@ jsonpickle==2.2.0; python_version >= "3.7"
 jsonschema==3.2.0; python_version >= "3.7"
 keyring==22.3.0; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7"
 lazy-object-proxy==1.7.1; python_version >= "3.7"
-lockfile==0.12.2
 markupsafe==2.1.1; python_version >= "3.7"
-matplotlib-inline==0.1.3; python_version >= "3.7"
+matplotlib-inline==0.1.6; python_version >= "3.7"
 mccabe==0.7.0; python_version >= "3.7"
 msgpack==1.0.4; python_version >= "3.7" and python_version < "4.0"
 msrest==0.6.21; python_version >= "3.7"
 mypy-extensions==0.4.3; python_version >= "3.7"
 mypy==0.971; python_version >= "3.7"
 oauth2client==4.1.3; python_version >= "3.7"
-oauthlib==3.2.0; python_version >= "3.7"
+oauthlib==3.2.1; python_version >= "3.7"
 packaging==20.9; python_version >= "3.7"
 paramiko==2.11.0; python_version >= "3.7"
 parsedatetime==2.6; python_version >= "3.7"
@@ -97,43 +95,42 @@ parso==0.8.3; python_version >= "3.7"
 pathlib2==2.3.7.post1; python_version >= "3.7"
 pexpect==4.8.0; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7" and sys_platform != "win32"
 pickleshare==0.7.5; python_version >= "3.7"
-pip==22.2.1; python_version >= "3.7"
+pip==22.2.2; python_version >= "3.7"
 pkginfo==1.8.3; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7"
 platformdirs==2.5.2; python_version >= "3.7"
 pluggy==1.0.0; python_version >= "3.7"
 ply==3.11; python_version >= "3.7"
 poetry-core==1.1.0a7
 poetry==1.2.0a2
-prompt-toolkit==3.0.30; python_version >= "3.7"
-protobuf==4.21.4; python_version >= "3.7"
+prompt-toolkit==3.0.31; python_version >= "3.7"
+protobuf==4.21.6; python_version >= "3.7"
 ptyprocess==0.7.0; python_version >= "3.7" and python_version < "4.0"
 py==1.11.0; python_version >= "3.7"
 pyasn1-modules==0.2.8; python_version >= "3.7"
 pyasn1==0.4.8; python_version >= "3.7"
 pycparser==2.21; python_version >= "3.7"
-pygments==2.12.0; python_version >= "3.7"
+pygments==2.13.0; python_version >= "3.7"
 pylev==1.4.0; python_version >= "3.7" and python_version < "4.0"
 pylint==2.13.9
 pynacl==1.5.0; python_version >= "3.7"
 pynsist==2.7; python_version >= "3.7"
 pyopenssl==22.0.0; python_version >= "3.7"
 pyparsing==3.0.9; python_version >= "3.7"
-pypiwin32==223; sys_platform == "win32" and python_version >= "3.7"
 pyrfc3339==1.1; python_version >= "3.7"
 pyrsistent==0.18.1; python_version >= "3.7"
 pytest-cov==3.0.0; python_version >= "3.7"
 pytest-forked==1.4.0; python_version >= "3.7"
 pytest-xdist==2.5.0; python_version >= "3.7"
-pytest==7.1.2; python_version >= "3.7"
+pytest==7.1.3; python_version >= "3.7"
 python-augeas==1.1.0; python_version >= "3.7"
 python-dateutil==2.8.2; python_version >= "3.7"
 python-digitalocean==1.17.0; python_version >= "3.7"
-python-dotenv==0.20.0; python_version >= "3.7"
-pytz==2022.1; python_version >= "3.7"
+python-dotenv==0.21.0; python_version >= "3.7"
+pytz==2022.2.1; python_version >= "3.7"
 pywin32-ctypes==0.2.0; python_version >= "3.7" and python_version < "4.0" and sys_platform == "win32"
 pywin32==304; sys_platform == "win32" and python_version >= "3.7"
 pyyaml==5.4.1; python_version >= "3.7"
-readme-renderer==35.0; python_version >= "3.7"
+readme-renderer==37.1; python_version >= "3.7"
 requests-download==0.1.2; python_version >= "3.7"
 requests-file==1.5.1; python_version >= "3.7" and python_version < "4.0"
 requests-oauthlib==1.3.1; python_version >= "3.7"
@@ -142,11 +139,11 @@ requests==2.28.1; python_version >= "3.7" and python_version < "4"
 rfc3986==2.0.0; python_version >= "3.7"
 rsa==4.7.2; python_version >= "3.7" and python_version < "4"
 s3transfer==0.6.0; python_version >= "3.7"
-secretstorage==3.3.2; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
+secretstorage==3.3.3; python_version >= "3.7" and python_version < "4.0" and sys_platform == "linux"
 semantic-version==2.10.0; python_version >= "3.7"
-setuptools-rust==1.4.1
-setuptools==63.2.0; python_version >= "3.7"
-shellingham==1.4.0; python_version >= "3.7" and python_version < "4.0"
+setuptools-rust==1.5.1
+setuptools==65.3.0; python_version >= "3.7"
+shellingham==1.5.0; python_version >= "3.7" and python_version < "4.0"
 six==1.16.0; python_version >= "3.7"
 snowballstemmer==2.2.0; python_version >= "3.7"
 soupsieve==2.3.2.post1; python_version >= "3.7"
@@ -162,24 +159,24 @@ texttable==1.6.4; python_version >= "3.7"
 tldextract==3.3.1; python_version >= "3.7" and python_version < "4.0"
 toml==0.10.2; python_version >= "3.7"
 tomli==2.0.1; python_version < "3.11" and python_version >= "3.7" or python_full_version <= "3.11.0a6" and python_version >= "3.7" or python_version >= "3.7"
-tomlkit==0.11.1; python_version >= "3.7" and python_version < "4.0"
-tox==3.25.1; python_version >= "3.7"
-tqdm==4.64.0; python_version >= "3.7"
-traitlets==5.3.0; python_version >= "3.7"
+tomlkit==0.11.4; python_version >= "3.7" and python_version < "4.0"
+tox==3.26.0; python_version >= "3.7"
+tqdm==4.64.1; python_version >= "3.7"
+traitlets==5.4.0; python_version >= "3.7"
 twine==3.3.0; python_version >= "3.7"
 typed-ast==1.5.4; python_version >= "3.7" and python_version < "3.8" or implementation_name == "cpython" and python_version < "3.8" and python_version >= "3.7"
-types-cryptography==3.3.21; python_version >= "3.7"
-types-pyopenssl==22.0.9; python_version >= "3.7"
+types-cryptography==3.3.23; python_version >= "3.7"
+types-pyopenssl==22.0.10; python_version >= "3.7"
 types-pyrfc3339==1.1.1; python_version >= "3.7"
 types-python-dateutil==2.8.19; python_version >= "3.7"
-types-pytz==2022.1.2; python_version >= "3.7"
-types-requests==2.28.5; python_version >= "3.7"
-types-setuptools==63.2.2; python_version >= "3.7"
-types-six==1.16.18; python_version >= "3.7"
-types-urllib3==1.26.17; python_version >= "3.7"
+types-pytz==2022.2.1.0; python_version >= "3.7"
+types-requests==2.28.10; python_version >= "3.7"
+types-setuptools==65.3.0; python_version >= "3.7"
+types-six==1.16.19; python_version >= "3.7"
+types-urllib3==1.26.24; python_version >= "3.7"
 typing-extensions==4.3.0; python_version >= "3.7" or python_version < "3.10" and python_version >= "3.7" or python_version < "3.8" and python_version >= "3.7"
 uritemplate==4.1.1; python_version >= "3.7"
-urllib3==1.26.11; python_version >= "3.7" and python_version < "4"
+urllib3==1.26.12; python_version >= "3.7" and python_version < "4"
 virtualenv==20.4.4; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7"
 wcwidth==0.2.5; python_version >= "3.7"
 webencodings==0.5.1; python_version >= "3.7" and python_version < "4.0" or python_version >= "3.7"
@@ -188,3 +185,7 @@ wheel==0.37.1; python_version >= "3.7"
 wrapt==1.14.1; python_version >= "3.7"
 yarg==0.1.9; python_version >= "3.7"
 zipp==3.8.1; python_version >= "3.7" and python_version < "3.8"
+zope.component==5.0.1; python_version >= "3.7"
+zope.event==4.5.0; python_version >= "3.7"
+zope.hookable==5.2; python_version >= "3.7"
+zope.interface==5.4.0; python_version >= "3.7"
diff --git a/tools/snap/generate_dnsplugins_snapcraft.sh b/tools/snap/generate_dnsplugins_snapcraft.sh
index efa6473660a..43f1b20774f 100755
--- a/tools/snap/generate_dnsplugins_snapcraft.sh
+++ b/tools/snap/generate_dnsplugins_snapcraft.sh
@@ -7,7 +7,7 @@ set -e
 
 PLUGIN_PATH=$1
 PLUGIN=$(basename "${PLUGIN_PATH}")
-DESCRIPTION=$(grep description "${PLUGIN_PATH}/setup.py" | sed -E 's|\s+description="(.*)",|\1|g')
+DESCRIPTION=$(sed -E -n "/[[:space:]]+description=/ s/[[:space:]]+description=['\"](.*)['\"],/\1/ p" "${PLUGIN_PATH}/setup.py")
 mkdir -p "${PLUGIN_PATH}/snap"
 cat <<EOF > "${PLUGIN_PATH}/snap/snapcraft.yaml"
 # This file is generated automatically and should not be edited manually.


Test patch:
diff --git a/certbot-ci/certbot_integration_tests/nginx_tests/context.py b/certbot-ci/certbot_integration_tests/nginx_tests/context.py
index 2a8881aa923..d52501596ab 100644
--- a/certbot-ci/certbot_integration_tests/nginx_tests/context.py
+++ b/certbot-ci/certbot_integration_tests/nginx_tests/context.py
@@ -28,7 +28,7 @@ def __init__(self, request: pytest.FixtureRequest) -> None:
         self.nginx_config_path = os.path.join(self.nginx_root, 'nginx.conf')
         self.nginx_config: str
 
-        default_server = request.param['default_server']  # type: ignore[attr-defined]
+        default_server = request.param['default_server']
         self.process = self._start_nginx(default_server)
 
     def cleanup(self) -> None:
diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py
index f5c1291ea06..238906efb80 100644
--- a/certbot-compatibility-test/setup.py
+++ b/certbot-compatibility-test/setup.py
@@ -1,7 +1,7 @@
 from setuptools import find_packages
 from setuptools import setup
 
-version = '1.31.0.dev0'
+version = '2.0.0.dev0'
 
 install_requires = [
     'certbot',