Technical Overview

The plugin is comprised of two components:

  • cPanel Frontend (CGI)
  • Backend daemon

cPanel Frontend

This is the page that is usable by the cPanel end-user. The page is implemented as a Linux amd64 binary implementing the CGI interface, written in Go.

From here, the user can issue & and install new certificates, or remove existing ones from their domains.

All plugin code executes as the user who is logged into the cPanel session.

Data Storage

All data relating to the plugin is persisted in the user’s NVData store, which is located in ~/.cpanel/nvdata/letsencrypt-cpanel. This includes their Let’s Encrypt account key, domain private keys, and certificates. Keys and certificates are also stored in the SSL/TLS manager, as this is required to actually install the certificate to a domain.

Note that cPanel already stores its SSL private data in $HOME/ssl for each user, so this is not a security issue we are in a place to address.

Issuing a certificate

Issuing the certificate is a “one-click” operation, which involves:

  • Generating an Account Key if necessary
  • Generating a Domain Private Key (RSA 4096-bit)
  • Generating a Certificate Signing Request (CSR) for a single domain
  • Requesting an HTTP challenge from the Let’s Encrypt service
  • Installing the challenge response file into the relevant domain’s webroot
  • Notifying the Let’s Encrypt service that the challenge is ready
  • Issuing the certificate
  • Installing the certificate

Backend Daemon

This is a service that runs in the background as the root user (although all API actions are done via specific user impersonation sessions, in order to minimise risk).

The daemon is installed by the installer as a SysVinit or systemd service, and additionally monitored by checksrvd.

The daemon performs three roles:

  • Renewal of user domain certificates
  • Asynchronous issuing of deferred certificates
  • Issuing certificate for WHM host

Renewal

The renewal process runs every 12 hours, and iterates through all of the users on the server, searching for certificates managed by the plugin, that are within 30 days of expiry.

The end-user is notified (via the address attached to the cPanel account) of successful or failed renewal attempts.

Private keys are re-used to issue a new certificate.

Renewal presently is the same procedure as issuing a new certificate, as that is the only method supported currently by the ACME implementation (Boulder). Therefore, rate limits apply.

Asynchronous issuing

The ACME specification states that certificates may be not immediately issued.

This is not currently implemented by Boulder, but the plugin supports it anyway.

If the frontend CGI encounters the condition where certificate issuance is delayed, it will signal that to the daemon. The daemon will then poll for potentially delayed certificates repeatedly until the CA issues them, and will then install the certificates as usual.