How to check the details of an SSL certificate

With the release of DirectAdmin 1.62.0, support for Automatic SSL Certificatesopen in new window was added.  This will be a quick overview of the feature and a quick guide for debugging when needed.

Enable

For the Automatic SSL system to work, several flags must be enabled.
Run the following. All values should throw a value of 1:

cd /usr/local/directadmin  
./directadmin config | grep letsencrypt=  
./directadmin config | grep admin_ssl_cert_per_vh=  
./directadmin config | grep admin_ssl_check_retries=  
./directadmin config | grep mail_sni=

Should any not show 1, set them, eg:

./directadmin set admin_ssl_cert_per_vh 1

Disable

The simplest way to disable the Automatic SSL certificate generation is to shut off the admin_ssl_check_retries setting:

/usr/local/directadmin/directadmin set admin_ssl_check_retries 0  
service directadmin restart

Conditions

The domain in question (and all of it’s sub-hosts) must be using the Shared Server Certificate option on the SSL Certificates page, which is the default for new domains.

Wildcards

  1. By default, Domains and Pointers will try and use wildcards.  This saves the need for subdomains to get their own certificates.
  2. Wildcard use dns so the zone must be local (or the local DA has control of a remote dns server).
  3. Triggering a retry on a subdomain will always be http-only (never wildcard/dns).
  4. Should a wildcard request fail (eg: DNS does not yet resolve to this box), it will auto-fallback to an http-based request.  It will not change the domain.com.ssl request file, which would remain wildcard=yes when requested.  If the fallback also fails, the next_retry is set to a future time (admin_ssl_poll_frequency), and the original request-type is made at that time (eg: it would try the wildcard again).

Certificate Triggers

The system will attempt a certificate request based on the possible scenarios:

  • User host creation/restoration (Domain, subdomain, pointer): These will create the .ssl request and .ssl.next_retry files for that specific host.
  • Manual Triggers: Used if a host already exists and the User wishes to switch to the new system.
  • Pro-Pack options:
admin_ssl_replace_all_expired_invalid=1  
admin_ssl_install_to_missing=1

These are disabled by default and we’d typically encourage you to keep them disabled as they poll every minute and can create many requests (might be fine for smaller hosts, if needed).

Certificates Index

The /etc/virtual/snidomains file is central to this system.

  1. All User httpd.conf writes do a lookup for their host here (assuming “Shared Server Certificate” is selected).  Subdomains look for their exact match, and fallback to looking for a *.domain.com match. A pasted cert/key will always use that cert/key.
  2. Cross-User certificates are allowed with the pro-pack: cross_user_ssl_cert=1 where A sub-domain User would be allowed to reference some other User’s certificate.  Disabled by default.
  3. Dovecot sni domains files are created for domains and pointers (never subdomains), and fill the host values based on the host values within the certificate
  4. Exim already uses the snidomains file, and should already support wildcards.

Debug

You can manually see what the Ssl::admin_poll is up to by running it manually wish the SSL debug level:

echo "action=ssl&value=admin_ssl" >> /usr/local/directadmin/data/task.queue.cb
/usr/local/directadmin/dataskq d1245 --custombuild

It will hunt for any relevant next_retry files (or the pro-pack triggers), and attempt those requests.

Admin SSL

The Admin SSL section in Admin Level allows for overview and management of all user/domain certificates, as well as hostname certificates.

Enhanced Skin: CMD_ADMIN_SSL Evolution skin: /admin/ssl

In addition it allows back-end automatic ssl certificate generation based on poll frequency (to allow for domain to eventually resolve).

Requirements

  1. mail_sni=1 enabled
  2. admin_ssl_cert_per_vh=1
  3. admin_ssl_check_retries=1
  4. Domain will only be given an auto cert if it’s set to use the “Shared Server Cert”, in which case a per-VH will be created for each host (sorted out at httpd.conf write time based on snidomains)

Fix old/existing/expired/invalid certificates.

Internal default: admin_ssl_replace_all_expired_invalid=0

If set to 1, any fully expired/invalid LetsEncrypt certificates will automatically be brought back to life, following the polling schedule.

If set to 2, any fully expired/invalid certificates will automatically be brought back to life, following the polling schedule. This includes non-LetsEncrypt (Eg: EV) certificates, so be careful if you use this option. It does not poll for empty certs.

Install certs to hosts which do not have any.

Internal default: admin_ssl_install_to_missing=0

Set to: admin_ssl_install_to_missing=1

and DirectAdmin will check using the polling schedule to add or retry adding them. This setting is useful for newly added domains to automatically be given a certificate.

Retry enabled

admin_ssl_check_retries=1

You’d usually just keep this set to 1. Setting it to 0 will disable DA’s check for the .ssl.next_retry file, which is what the GUI would create during its requests.

Basically it is the main on/off switch, BUT the other missing/invalid/expired checks are not dependent on it.

If they fail, then they’d create the .ssl.next_retry file, then you’d need this on. This also need to be enabled for retries on other polling, like expired/invalid or missing.

The admin_ssl_check_retries=1 does not require the Pro-Pack, as the User Level Automatic SSL currently uses it.

Retry/Poll Frequency

Default value: admin_ssl_poll_frequency=5m:15m:30m:1h:12h:1d:1w

In more detail this option specifies that retry attempts should be run in these intervals:

<30minutes: every 5 minutes
30m-1h: every 15 minutes
1h-4hrs: every 30 minutes
4h-1day: hourly
2nd,3rd days: every 12 hours
4th day onward: once per day
Stop trying after 1 week (7th entry)

time units will all be case specific s,m,h,d,w,M,y

m is minute, M is Month.

No units will be treated as seconds, since that’s how they’re intended to end up anyway.

No spaces after the numbers before the units. (1 d will end up being one second).

When a trigger is done, it must save that NEXT window to the next_trigger file. The first_trigger must still remain so we know which window to check.

Disable all

If this feature is not behaving nicely, to quickly disable it:

cd /usr/local/directadmin
./directadmin set admin_ssl_replace_all_expired_invalid 0
./directadmin set admin_ssl_install_to_missing 0
./directadmin set admin_ssl_check_retries 0
service directadmin restart

View all certificates:

CMD_ADMIN_SSL?json=yes

REQUEST new certificates for selected domains

CMD_ADMIN_SSL
method: POST
action=multiple
request=yourdomain
select0=domain1.com
(select1=domain2.com)
(wildcard=yes)

Where you can select 1 or more domains with select0 and up.

wildcard=yes can be passed to request a *.domain.com cert.

Save the request to the data/users/USER/domains/DOMAIN.COM.ssl file, which will store the related request info and retry schedule.

Completion of a valid request (after however many retries it succeeds), if that requested host has a valid domain.com.conf file (it’s a full domain), then that domain will be switched over to use cert=server mode (Best Match mode), which means it’s now in full auto ssl.

Save settings to directadmin.conf

Admin accounts will be be able to call:

method: POST
action=settings

followed by any one of, or multiple of, the following settings:

letsencrypt_renewal_notice_to_admins
letsencrypt_renewal_error_to_users
renew_letsencrypt_on_suspended_domain
letsencrypt_renewal_success_notice
letsencrypt_disable_renew_after_renew_failure
letsencrypt_renewal_failure_notice_after_attempt

Caching

As the number of domain certificates on the box can be slow if we try to read all of them, a new cache file will be found here:

data/admin/certificate_cache.json

it will be rebuild every night after the tally is done (and after the LE retries are done)

Any “save” to a certificate by a User (or restore, etc) will trigger a rewrite of all domain/pointer certs for that User in that file. Deleting a domain does not clear entries from the cache, but the nightly rewrite will handle it. When being displayed, entries are retrieved based on the domainowners, so it will be fine as long as that’s updated as it currently does.

Task queue

you can force a retry with the task.queue using:

cd /usr/local/directadmin
echo "action=ssl&value=admin_ssl&domain=domain.com" >> data/task.queue; ./dataskq d1245

even if this domain’s cert does not qualify for a request/renewal, the above will try anyway.

You can force a full rebuild of the cache vwith:

echo "action=cache&value=certificates" >> data/task.queue; ./dataskq d1245

or only for one User with:

echo "action=cache&value=certificates&user=fred" >> data/task.queue; ./dataskq d1245

where the user method will first read the cache, and overwrite/add entries from fred to the cache file. The non-user mode will be a 100% rebuild without a read first.

Scripts

The ssl_save_pre.sh and ssl_save_post.sh should now accept:

action=single_cert
username=fred
domain=domain.com

where domain can be any of:

  • a full User domain.com
  • a sub-domain “sub.domain.com” below a domain.
  • a pointer “pointer.com” below a domain.
  • a pointer sub.pointer.com below a domain.

For action=single_cert, the domain value is only relevant to the host being requested, and to the value set in /etc/virtual/snidomains

Let’s Encrypt For Services

Using the free “Let’s Encrypt” tool to secure Port 2222 via the Hostname

As of DA 1.50.0, we’ve added a new featureopen in new window that allows you to make use of Let’s Encryptopen in new window, a tool offering free basic SSL certificates.

We’ve written the script in such a manner that you can also set up SSL for your hostname and all services in one simple command for your hostname e.g.,:

cd /usr/local/directadmin/scripts
./letsencrypt.sh request_single `hostname -f` 4096

which will also install the new cert/key/ca files in all respective global places for Apache, Dovecot, Exim, FTP, and DirectAdmin.

NOTE The hostname value, e.g., your.hostname.com must match the “servername” value set in the directadmin.confor it will not be in hostname mode, but User domain mode instead.

DirectAdmin should be protected with SSL in 1min when the command finished.

Notes:

If user connect to https on a different host, they’ll first get the ssl warning (since ssl is established before the host is passed), then they’ll be redirected to the correct host, where the error would not appear (assuming you’ve got a valid cert set up).

But we recommend you to set force_hostname to a non-apache-used host, like dabox.domain.com, and not www.domain.com, as HSTS doesn’t respect only port 2222 and would bleed over to Apache, changing http://www.domain.com (80) connections to use https://www.domain.com (443), even though the header was only set on port 2222.

I want a multi-domain certificate for my hostname/mailserver using Let’s Encrypt

Exim and Dovecot do support multi-IP ssl certificates, but their setup can be a little bit tricky to try and maintain.

With Let’s Encrypt, we can set up multi-domain certificates for the hostname, and mail domains, all in one value, to make managing SSL for mail a little simpler.

To do this, we use the letsencrypt.sh script normally, but we would manually create the ca.san_config file loaded with the values we want to use.

However, with Let’s Encrypt 1.0.4+, we can specify all values on the command line instead, like this:

cd /usr/local/directadmin/scripts
./letsencrypt.sh request `hostname`,mail.domain.com,smtp.domain.com,www.domain.com,domain.com 4096

Setting up DA (port 2222) with a commercial SSL certificate

This guide will detail the configuration of SSL certificates for the server’s services, such that the SSL is installed on the hostname and used for DirectAdmin, Exim, Dovecot, and FTP.

If you already have your own certificate and key, then paste them into the following files:

  • certificate: /usr/local/directadmin/conf/cacert.pem
  • key: /usr/local/directadmin/conf/cakey.pem

Ensure that ssl and certs are enabled in directadmin.conf file with:

/usr/local/directadmin/directadmin config | egrep "^ssl=|^cacert=|^cakey="

Sample output:

ssl=1
cacert=/usr/local/directadmin/conf/cacert.pem
cakey=/usr/local/directadmin/conf/cakey.pem

But these can be changed as needed.

DirectAdmin needs to be restarted after any changes to the directadmin.conf, please follow this guide for changes.

If you also have a CA Root Certificate, this can be specified by adding:

carootcert=/usr/local/directadmin/conf/carootcert.pem

into the directadmin.conf (won’t exist by default), and then by pasting the contents of the caroot cert into that file.

SSL Certificates with Exim

By default, the /etc/exim.conf will use the cert/key files as controlled by the exim.conf’s options:

tls_certificate = /etc/exim.cert
tls_privatekey = /etc/exim.key

Intermediate Certificates

If you have a CA Root certificate (ca bundle, chain, etcetera), you’ll add the contents of your CA into the exim.cert, after your actual certificate. Make sure to keep backups of all files in case errors are made.

Dovecot and ProFTPD should also read it correctly, so Dovecot no longer needs the ssl_ca option.

So for both cases, there is no need to make any changes to either the exim.conf or dovecot.conf (/etc/dovecot/conf/ssl.conf).

I want a 2nd shared certificate on a 2nd shared IP installed for Apache

There might be some cases where you’d want 2 IPs, both with their own shared certificates (e.g., each has its own wildcard certificate, or you might have 2 different hosting companies). This can be done for Apache, but requires a few manual changes.

These instructions reference the 2nd IP, which will be the IP we’re manually going to share among many Resellers (contrary to the default behavior DA allows).

We’ll call it 1.2.3.4.

  1. The 2nd IP must be “shared” so that multiple Users can use it. Set this at the Reseller Level -> IP manager for whichever account controls the IP (e.g., “admin”).
  2. For any Reseller (or just admin) that needs to have access to it in order to assign to Users, it needs to be in:
    /usr/local/directadmin/data/users/resellername/ip.list

For example, replace resellername with admin or the name of the Reseller, etc.

It’s only really an issue if you have multiple Resellers/Admins.

  1. The template (important part) is where we manually set it to use the other certificate.
cd /usr/local/directadmin/data/templates/custom
cp ../ips_virtual_host.conf .

Edit the custom/ips_virtual_host.conf file.

Find this line (the SSL VH on 443):

<VirtualHost |IP|:|PORT_443|>

And immediately above it, add the code:

|*if IP="1.2.3.4"|
|?CERT=/etc/httpd/conf/ssl.crt/subdomain.cert|
|?KEY=/etc/httpd/conf/ssl.key/subdomain.key|
|?CAROOT=/etc/httpd/conf/ssl.crt/subdomain.cacert|
|*endif|

Which controls the automatic adding of VirtualHosts to the following file (don’t edit this file directly) /etc/httpd/conf/ips.conf.

These within this file are the first VHs for the IP, and thus control which certificate is used.

  1. You might need to do the same thing for the virtual_host2_secure.conf and virtual_host2_secure_sub.conf, but in theory, this shouldn’t be needed (though this might be a good idea, as the VH’s cert wouldn’t match the 2nd IP cert).

SSL Certificate Locations

General information for default certificate locations for various services. The order will be cert,key, ca/chain, combined (cert+ca) and their related directadmin.conf settings, where applicable.

Apache/LiteSpeed

apachecert=/etc/httpd/conf/ssl.crt/server.crt

apachekey=/etc/httpd/conf/ssl.key/server.key

apacheca=/etc/httpd/conf/ssl.crt/server.ca

OpenLiteSpeed

openlitespeed_cert=/usr/local/lsws/ssl.crt/server.crt

openlitespeed_key=/usr/local/lsws/ssl.key/server.key

openlitespeed_ca=/usr/local/lsws/ssl.crt/server.ca

Nginx

nginx_cert=/etc/nginx/ssl.crt/server.crt

nginx_key=/etc/nginx/ssl.key/server.key

nginx_ca=/etc/nginx/ssl.crt/server.ca

/etc/nginx/ssl.crt/server.crt.combined

Exim + Dovecot

/etc/exim.cert

/etc/exim.key

Note that the exim.cert contains BOTH the cert and the ca, in that order.

User Domain

/usr/local/directadmin/data/users/USER/domains/DOMAIN.COM.cert

/usr/local/directadmin/data/users/USER/domains/DOMAIN.COM.key

/usr/local/directadmin/data/users/USER/domains/DOMAIN.COM.ca

/usr/local/directadmin/data/users/USER/domains/DOMAIN.COM.combined

DirectAdmin may automatically create the .combined version of the cert, when needed by various servers.

If you see one on disk beside the cert, put the cert + ca into the combined file, e.g.,

cat /etc/nginx/ssl.crt/server.crt /etc/nginx/ssl.crt/server.ca > /etc/nginx/ssl.crt/server.crt.combined

SSL warning about older SHA1 certificates

Some older certificates may have this info:

Signature Algorithm: sha1WithRSAEncryption

Newer versions of openssl 1.1 no longer support them, so if they’re loaded into apache, it will fail to start.

Internal default option has been added: ssl_allow_signed_sha1=0

This will force DirectAdmin to do a check at update time to look for these certificates and report back if any are found.

These certificates will not be allowed to be pasted in, nor imported via backup when ssl_allow_signed_sha1=0 is set. You can override the setting and allow them by typing:

/usr/local/directadmin/directadmin set ssl_allow_signed_sha1 1
service directadmin restart

DirectAdmin won’t be removing SHA1 certificates. It’s up to you to clear them out

Ensuring you’ve rid yourself of SHA1 certificates

Run:

echo "action=syscheck" >> /usr/local/directadmindata/task.queue.cb 
/usr/local/directadmin/dataskq d14 --custombuild

If you get output:

Ssl::found_sha1_certificates: JSON

with JSON below it, those will be your sha1 certifiates. You’ll also get another Message System notice:

Subject: A system issue requires your attention

If there’s no JSON and Message System notices, that means you’ve cleared all SHA1 certificates.

Let’s Encrypt For Domains

How to Enable Let’s Encrypt and Install an SSL for a Domain

Let’s Encrypt is a free SSL tool that lets you install a very basic free SSL Certificate with 1 click. It supports multiple domains, sub-domains, and wildcards, and will auto-renew automatically before it expires after it’s ~90 day lifespan.

To enable this feature in DirectAdmin, ensure you have DirectAdmin 1.50.1 or newer.

  • Enable the letsencrypt=1 option in the directadmin.conf
  • If you want wildcard domain SSL certificate support via Let’s Encryptopen in new window, ensure dns_ttl=1 is set in the directadmin.conf.
  • Remote DNS providers are now supported via LEGO.
  • Restart DirectAdmin:
echo "action=directadmin&value=restart" >> /usr/local/directadmin/data/task.queue; /usr/local/directadmin/dataskq d2000
  • Add the /.well-known Alias:
cd /usr/local/directadmin/custombuild
./build rewrite_confs
  • Install the most recent version of the script:
cd /usr/local/directadmin/custombuild
./build update
./build letsencrypt

Users should then be able to see the Let’s Encrypt option in their panel via User Level -> SSL Certificates and be able to use this option to enable SSLs for their domains.

Select the Let’s Encrypt option, review the subdomain/wildcard selections, adjust as desired, then proceed to request the SSL to be installed.

To install a Let’s Encrypt SSL for a domain via SSH, you can use the letsencrypt.sh scriptopen in new window located at /usr/local/directadmin/scripts/letsencrypt.sh:

usage:

./letsencrypt.sh request|renew|revoke domain.com 4096 (/path/to/csr-request-config-file) (document_root)

but you shouldn’t need to run it manually, as DA will call it automatically when the User triggers it through DA.

Note, when you run it through DA, the domain.com.san_config will have more details than if you run it from ssh (.san_config will be created, but with less info).

LEGO: Remote DNS Providers with Let’s Encrypt

LEGO is a LetsEncrypt client and ACME library written in Go, hence the name LEGO. This useful library facilitates the use of 3rd-party, remote DNS providers with Let’s Encrypt by utilizing those providers’ APIs to complete domain validation checks via DNS, thus permitting the issuance of LE SSLs for domains using remote DNS.

Wildcard certificates for LetsEncrypt require DNS confirmation. If you’re running at some remote DNS provider that is not currently supported by the Multi-Server Setup, then this tool lets you use wildcard certs with those DNS providers.

This document will use Cloudflare as the example remote DNS provider.

INSTALL

Ensure that wildcard domain SSL certificate support via Let’s Encryptopen in new window is enabled via dns_ttl=1 in the directadmin.conf.

GUI USAGE

This feature is only available in the Evolution Skin as of November 2020. You may access it via the User level Dashboard > Account Manager > SSL Certificates.

Click the option Free & automatic certificate from Let’s Encrypt, where, when creating the cert, once the Wildcard option is selected, a new field (below) will appear, defaulting to Dns Provider = Local.

You can then pick a new DNS provider, say “CloudFlare”, and enter your user/key + extra bits, as specified by that provider.

Once these details are entered and you trigger the request, the ENVs are passed to the new letsencrypt.sh script and your request will run in the background.

Once completed, you’ll be notified in the Message System.

We’ll be adding fixes/improvements as we go, so ensure you have the updated script if you encounter any issues!

JSON

To get the list of supported DNS providers, include &dnsproviders=yes in the request, e.g., CMD_SSL?domain=domain.com&dnsproviders=yes&json=yes

As the file is somewhat large, only load it if the given skin knows how to use it.

It will be loaded in a top-level array called:
dnsproviders["data"] = { "version" : "3.7.0", "acme-dns": ...}

Any info about the current domain settings will be in: dnsproviders["dnsprovider"] where the dnsprovider (singular) is a dump of the domain.com.dnsprovider file, used to auto-fill the pre-selected choice. If this file contains inherit=creator or inherit=global, it will use the respective dnsprovider.conf file.

INHERIT DNS PROVIDER

An Admin/Creator can set up 2 possible inherit files:

  • Global: /usr/local/directadmin/data/admin/dnsprovider.conf
  • Creator: /usr/local/directadmin/data/users/resellerbob/dnsprovider.conf

Should either of these exist, where creator=resellerbob is in the given User’s user.conf, they’ll be included in the list of dnsproviders["data"] output as:

dnsproviders["data"]["inherit-creator"]
dnsproviders["data"]["inherit-global"]

where each would still have the correct “Name”, but the type is prefixed, e.g., dnsproviders["data"]["inherit-creator"]["name"] = "Inherit Creator : Cloudflare"

“Inherit Creator : ” or “Inherit Global” would be prefixed beside the name from the used provider, Cloudflare in this example, for that inherited dnsprovider.conf type.

The inherit-creator or inherit-global arrays will have an empty credentials array, and zero credentials are allowed to be passed if the master (including inherited configs) have zero creds.

If the “dnsprovider” is empty (nothing picked yet), check for:
dnsproviders["settings"]["default"]
to know which selection should be used by default. It should be either localinherit-creator, or inherit-global.

The Global/Creator dnsprovider.conf files may contain one of the following:

default=inherit-creator
default=inherit-global
default=local

which is what specifies the default value for a User to have pre-selected.

RESELLERS/ADMINS: SETTING THE INHERITED VALUES

Resellers/Admins can set an inherit-creator dnsprovider.conf file. Admins can also set the inherit-global dnsprovider.conf file.

VIEW

Either can view that config (if it exists) via: CMD_SSL?action=dnsprovider&json=yes

or: CMD_SSL?action=dnsprovider&json=yes&type=global

which provides a similar array, e.g.,

dnsproviders["data"]
dnsproviders["dnsprovider"]
dnsproviders["type"] = "creator" | "global"

SAVE

CMD_SSL
method: POST
action=dnsprovider
default=local|inherit-global|inherit-creator   (optional)
dnsprovider=cloudflare
(type=global|creator)
CLOUDFLARE_EMAIL=foo@bar.com
CLOUDFLARE_API_KEY=sdgsd7681afn

where the last 3 depend on which “dnsprovider” was selected, similar to below for Users. The default is optional and is used to tell the User which default selection to use. Saved in the creator/reseller dnsprovider.conf.

If no type is passed, creator is used. A Reseller is not allowed to set type=global.

RESET

CMD_SSL
method: POST
action=dnsprovider
dnsprovider_reset=yes
(type=global|creator)

which simply deletes the given Admin/Reselelr dnsprovider.conf file.

USERS: POST PARAMETERS FOR SPECIFYING A DNSPROVIDER VS INHERITING

When saving data for a LetsEncrypt request for Users, include dnsprovider=NAME to activate the rest of the checks, e.g.,

CMD_SSL
method: POST
domain=domain.com
action=save
background=auto
type=create
request=letsencrypt
name=domain.com
wildcard=yes
keysize=secp384r1
encryption=sha256
le_wc_select0=domain.com
le_wc_select1=*.domain.com
submit=Save

dnsprovider=cloudflare
CLOUDFLARE_EMAIL=foo@bar.com
CLOUDFLARE_API_KEY=sdgsd7681afn

for example, assuming cloudflare is the desired remote dnsprovider.

Note, for an inherited dnsprovider, do not pass in a dnsprovider= parameter, else it will override the inherited value with the passed value.

ONLY SAVE DNSPROVIDER INFO

If you wish to only save the dnsprovider info, use:

CMD_SSL
method: POST
domain=domain.com
action=save
type=dnsprovider
dnsprovider=cloudflare
CLOUDFLARE_EMAIL=foo@bar.com
CLOUDFLARE_API_KEY=sdgsd7681afn
RESET

To remove the domain.com.dnsprovider file (thus resetting the dnsprovider to Local), include: dnsprovider_reset=yes to either of the above requests. Neither dnsprovider= nor its related fields are needed when dnsprovider_reset=yes is passed.

For example,

CMD_SSL
method: POST
domain=domain.com
action=save
type=dnsprovider
dnsprovider_reset=yes

USER / DOMAIN DATA FILES AND CONTENT

When a selection is made by a User (or via a creator’s default choice), the domain’s DNS settings will be stored in: /usr/local/directadmin/data/users/USERNAME/domains/DOMAIN.COM.dnsprovider

Sample data:

dnsprovider=cloudflare
CLOUDFLARE_EMAIL=foo@bar.com
CLOUDFLARE_API_KEY=sdgsd7681afn

OR:

inherit=yes

(or something similar),

This is loaded into the ENV and passed onto the letsencrypt.sh script.

Automatically redirect domain/pointer to SSL

Since a lot of domains use .htaccess for SSL redirection this feature is disabled by default to prevent loops. However, DirectAdmin SSL redirection comes directly from webserver so it will be faster than using .htaccess. Each user may individually enable redirection under:

User Level -> Domain Setup -> domain.com -> Force Redirect

Available redirection options:

  • www
  • non-www
  • none

Automatically set up Let’s Encrypt SSL for all domains that do not currently have a certificate

The new Let’s Encrypt feature is a great way to easily secure your website connections at no cost. If you already have many websites that you want to secure all at once, you can use the autoletsencrypt.sh script to do this.

After you’ve enabled Let’s Encrypt on the system, you can install certificates for all domains using the following script:

cd /root
wget -O autoletsencrypt.sh http://files.directadmin.com/services/all/letsencrypt/autoletsencrypt.sh
chmod 755 autoletsencrypt.sh
./autoletsencrypt.sh

Note that if you have too many domains, you might hit the Let’s Encrypt Rate-Limitopen in new window so if that happens, you should be able to wait until the time window has passed, run it again, which should continue where it left off.

Swapping cPanel SSLs on Domains Transferred from cPanel for Let’s Encrypt SSLs Managed by DirectAdmin

If you’ve recently migrated from cPanel to DirectAdmin, you will need to convert your cPanel/Sectigo SSLs to Let’s Encrypt SSLs.

A script from a DirectAdmin forum postopen in new window will create all necessary files so that DirectAdmin can manage automatic Let’s Encrypt SSL renewals for your migrated domains.

Running the script in the post will create all necessary files needed for DirectAdmin to manage the SSLs. You may also want to go ahead and proceed with ensuring all domains have valid SSLs by using the aforementioned autoletsencrypt.sh script from the above guide. You may also want to check that the hostname SSL is valid and will be autorenewed as well.

Combine every check into one single script that you can run following a migration from cPanel to DirectAdmin like so:

#!/bin/bash
#Convert cPanel SSLs to Let's Encrypt SSLs Managed by DirectAdmin
for i in `cat /etc/virtual/domainowners | cut -d: -f1`; do { 
    USER=`grep "^${i}:" /etc/virtual/domainowners | awk '{print $2}'`;
    CERT_PATH=/usr/local/directadmin/data/users/${USER}/domains/${i}.cert
    if [ -s ${CERT_PATH} ]; then
        if openssl x509 -issuer -in ${CERT_PATH} -noout | grep -m1 -q "cPanel"; then
            CERT_DATE="`openssl x509 -startdate -in ${CERT_PATH} -noout | cut -d= -f 2`"
            TIMESTAMP="`date --date=\"${CERT_DATE}\" +%s`"
            TIMESTAMP_LENGTH="`echo \"${TIMESTAMP}\" | wc -c`"
            if [ ! -s /usr/local/directadmin/data/users/${USER}/domains/${i}.cert.creation_time ]; then
                echo "Setting up ${i} (owned by ${USER}/) for autorenewal..."
                if [ ${TIMESTAMP_LENGTH} -gt 10 ]; then
                    echo "${TIMESTAMP}" > /usr/local/directadmin/data/users/${USER}/domains/${i}.cert.creation_time
                else
                    echo "0" > /usr/local/directadmin/data/users/${USER}/domains/${i}.cert.creation_time
                fi
            fi
            if [ ! -s /usr/local/directadmin/data/users/${USER}/domains/${i}.san_config ]; then
                SAN_CN="`openssl x509 -noout -subject -in ${CERT_PATH} | cut -d= -f3`"
                SAN_NAMES="`openssl x509 -noout -text -in ${CERT_PATH} | grep -m1 -A1 'Subject Alternative Name' | grep -o 'DNS:.*'`"
                cat <<< "
[ req ]
default_bits        = 4096
default_keyfile        = keyfile.pem
distinguished_name    = req_distinguished_name
attributes        = req_attributes
output_password        = bogus


[ req_distinguished_name ]
CN            = ${SAN_CN}
[ req_attributes ]
[ SAN ]
subjectAltName=${SAN_NAMES}" > /usr/local/directadmin/data/users/${USER}/domains/${i}.san_config
            fi
        fi
    fi
}; 
done


#run autoletsencrypt.sh for all domains to ensure any needed SSLs are installed as should be.
printf "Ensuring all migrated domains have valid SSLs installed...\n"
wget -O /root/autoletsencrypt.sh http://files.directadmin.com/services/all/letsencrypt/autoletsencrypt.sh
chmod 755 /root/autoletsencrypt.sh
sh /root/autoletsencrypt.sh


#enable hostname SSL if not present or expired
printf "Ensuring the hostname SSL is valid and will be autorenewed...\n"
HOSTCACERT=`/usr/local/directadmin/directadmin config | grep 'cacert.pem' | cut -d= -f2`

#request hostname SSL (note: doesn't affect self-signed SSLs, so another check would be needed for this)
if [[ `openssl x509 -checkend 0 -in $HOSTCACERT` != "Certificate will not expire" ]];then
  /usr/local/directadmin/scripts/letsencrypt.sh request `hostname` 4096
fi

#ensure creation_time file exists for hostname autorenewal...
if [ ! -s $HOSTCACERT.creation_time ]; then
  echo "Setting up the hostname SSL for autorenewal..."
  echo "0" > $HOSTCACERT.creation_time
fi

exit 0

Save the script as ssl.sh, make executable and run it:

chmod 755 ssl.sh
./ssl.sh

Create new User with ssl on, but with ssl off for the new domain

In some cases, you might want to create a new User and allow that User the ability to use SSL and SSL certificates, but don’t want it turned on by default for the domain, to keep the VirtualHost count down.

So create /usr/local/directadmin/scripts/custom/user_create_post_confirmed.sh with code:

#!/bin/sh
CONF=/usr/local/directadmin/data/users/$username/domains/$domain.conf
if [ -s $CONF ]; then
   perl -pi -e 's/ssl=ON/ssl=OFF/' $CONF
   echo "action=rewrite&value=httpd&user=$username" >> /usr/local/directadmin/data/task.queue
fi
exit 0;

and make it executable:

chmod 755 /usr/local/directadmin/scripts/custom/user_create_post_confirmed.sh

This will shut off SSL for the new domain after the User is created, and rewrite their httpd.conf file up to 1 minute later via task.queue (in case you’re wondering why the 443 VH might still be added immediately after User creation).

Enforcing ssl=ON for all Users, Resellers and their packages

For the modern age, websites should be using SSL for their websites. This guide provides a means to enforce enabling it for all Users/Resellers, their domains, and the packages used to create them.

First, we’ll setup the enforcement for actions in the GUI.

Saving a package

Create the directory and script:

/usr/local/directadmin/scripts/custom/package_write_pre/enforce_ssl.sh

with code:

#!/bin/sh
if [ "${ssl}" = "OFF" ]; then
   echo "SSL must be enabled";
   exit 1;
fi
exit 0;

Account creation/modification

Create both:

/usr/local/directadmin/scripts/custom/user_create_pre/enforce_ssl.sh

and

/usr/local/directadmin/scripts/custom/user_modify_pre/enforce_ssl.sh

with the same code as above.
Chmod all scripts to 755:

chmod 755 /usr/local/directadmin/scripts/custom/*/enforce_ssl.sh

Change all Users, domains, and packages to use ssl=ON:

cd /usr/local/directadmin/data
perl -pi -e 's/^ssl=OFF/ssl=ON/' users/*/user.conf
perl -pi -e 's/^ssl=OFF/ssl=ON/' users/*/domains/*.conf
perl -pi -e 's/^ssl=OFF/ssl=ON/' users/*/reseller.conf
perl -pi -e 's/^ssl=OFF/ssl=ON/' admin/packages/*.pkg
perl -pi -e 's/^ssl=OFF/ssl=ON/' users/*/packages/*.pkg

Follow up with a rewrite of the webserver configs to use the values:

cd /usr/local/directadmin/custombuild
./build rewrite_confs

Let’s Encrypt weekly domain rate limit

LetsEncrypt has a rate limit of 50 requests per week, per main domain.

DirectAdmin has this directadmin.conf option:

letsencrypt_max_requests_per_week=200

The 50 LE limit is only requests that make it that far. The letsencrypt.sh script has some prechecks which could fail before the LE limit, so the 200 limit is used to err on the side of caution to reach the actual LE 50 limits.

In effect, the letsencrypt_max_requests_per_week=200 value is mainly for a last-resort limit on “far too many requests”, vs trying to predict the true LE 50 limit.

DISABLE

You can fully disable the DA limit enforcement by setting:

/usr/local/directadmin/directadmin set letsencrypt_max_requests_per_week 0
service directadmin restart

FILES

/usr/local/directadmin/data/admin/letsencrypt_rate_limits/DOMAIN.COM/weekly_domain_count

which will be a JSON file, storing each request attempt.

Future requests will read, reduce old entries, and add new ones as needed. If there are 200 or more entries after reduction, the request will not happen and the new request will not be added to the file.

NIGHTLY TALLY

Each tally will see if the age of the weekly_domain_count for each main domain is older than 1 week and will fully remove the domain.com directory if it is.

USERS

These are cross-User files, meaning, if

  • User bob has domain.com
  • User fred has sub.domain.com

both Users will have their counts stored in the same domain.com/weekly_domain_count file.

If you run many subdomains on the system, it would be highly advisable to request a wildcard for domain.com, so that sub.domain.com does not need to create any requests, as the limit would be reached quite quickly.

Troubleshooting Let’s Encrypt Errors

Manually debugging /.well-known/acme-challenge/letsencrypt_12345

When trying to install a Let’s Encrypt certificate, if you’re hitting this error for :

Getting challenge for domain.com from acme-server...
Error:
http://domain.com/.well-known/acme-challenge/letsencrypt_1472046285
is not reachable. Aborting the script.
Please make sure /.well-known alias is setup in WWW server.

we can manually test this to see what’s going on.

  1. First, ensure that you have letsencrypt=1 in your directadmin.conf. You can use this guide to help you do this.
  2. Next, we’ll want to confirm the Alias /.well-known has been added to the file
/etc/httpd/conf/extra/httpd-alias.conf

If this is not set, add it using

cd /usr/local/directadmin/custombuild
./build update
./build rewrite_confs

and the build script should add it into the httpd-alias.conf file for you.

  1. To manually test things, create a file like this:
echo "test" >> /var/www/html/.well-known/acme-challenge/test.txt

and then test it via:

http://domain.com/.well-known/acme-challenge/test.txt

which should show you “test” in the output if all is working.

  1. If that works, but you still get the error, then try out exactly what curl is running. Login to ssh as root, and type:
curl -I -L -k -X GET http://domain.com/.well-known/acme-challenge/test.txt

where we’d be testing with the test.txt, while the letsencrypt.sh is testing on the letsencrypt_12345678, which is just a unix timestamp used to keep the file name moderately unique for the test.

  1. Another testing tool is to run bash in -x mode and enabling staging so rate limit will not be hit, e.g.,
staging=yes bash -x ./letsencrypt.sh request domain.com

which will dump all calls and helps in the debug process.

Let’s Encrypt: Manually forcing the automated renewal to test for errors

Sometimes you might want to force DirectAdmin to think a Let’s Encrypt certificate needs to be renewed. We can do this by manually changing the certificate’s creation time file to an older time (e.g., 61 days prior):

Assume:

Directadmin User: 

Domain: 

and that the Let’s Encrypt SSL is currently valid with a renewal time somewhere in the future.

Once that info is filled out, type:

cd /usr/local/directadmin
echo `date +%s --date='61 days ago'` > "data/users/user/domains/domain.com.cert.creation_time"
/usr/local/directadmin/directadmin taskq --run 'action=rewrite&value=letsencrypt&domain=domain.com' --debug 3100

Let’s Encrypt certificate creation works, but takes 15 minutes

Report that if your system **has IPv6 **present, but is not on a valid IPv6 network, Let’s Encrypt calls may try and used IPv6, and timeout after 15 minutes, then using the IPv4.

Solution for the DirectAdmin setup is to edit:

/usr/local/directadmin/scripts/letsencrypt.sh

and add the -4 option to all curl calls.

The simplest way to do this is to add -4 into the ${CURL} variable, after it’s been checked for existence. Find this code:

CURL=/usr/local/bin/curl
if [ ! -x ${CURL} ]; then
       CURL=/usr/bin/curl
fi

and right below it, add a line, so that it looks like this:

CURL=/usr/local/bin/curl
if [ ! -x ${CURL} ]; then
       CURL=/usr/bin/curl
fi
CURL="${CURL} -4"

so that all calls using ${CURL} will have the -4 option added.

Note, the file will be rewritten with the next letsencrypt update. Better to fix IPv6 or disable it completely.

Nonce is empty. Exiting. dig output of acme-v01.api.letsencrypt.org

When creating a certificate, if you get the following error:

Getting challenge for server.yourhost.com from acme-server...
Nonce is empty. Exiting. dig output of acme-v01.api.letsencrypt.org:
api.letsencrypt.org.edgekey.net.
e981.dscb.akamaiedge.net.
1.2.3.4
Full nonce request output:

Reports shows that it can be due to the following command

"FULL_NONCE="`${CURL} ${CURL_OPTIONS} --silent -I ${API}/directory`": curl --connect-timeout 15 -k -I https://acme-v01.api.letsencrypt.org/directory

throwing the error

curl: (43) CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!

which likely means your version of curl is old and should be updated. You can do this with CustomBuild like so:

cd /usr/local/directadmin/custombuild
./build update
./build curl

A similar report is related to the CustomBuild curl linking against an RPM-based curl library, e.g.,

[root@server scripts]# curl --connect-timeout 15 -k -I https://acme-v01.api.letsencrypt.org/directory
curl: (48) An unknown option was passed in to libcurl
[root@server scripts]# ldd /usr/local/bin/curl | grep curl
       libcurl.so.4 => /lib64/libcurl.so.4 (0x00007fdd1411a000)

where it should be /usr/local/lib/libcurl.so.4. To resolve that, remove the libcurl-devel RPM, re-compile curl and run ldconfig:

rpm -e libcurl-devel
cd /usr/local/directadmin/custombuild
./build curl
ldconfig

Now, confirm this worked:

[root@server custombuild]# ldd /usr/local/bin/curl | grep curl
       libcurl.so.4 => /usr/local/lib/libcurl.so.4 (0x00007f17c3cd5000)

Reported error:

Requesting new certificate order...
Nonce is empty. Exiting. dig output of acme-v02.api.letsencrypt.org:
prod.api.letsencrypt.org.
ca80a1adb12a4fbdac5ffcbc944e9a61.pacloudflare.com.
172.65.32.248
Full nonce request output:
HTTP/2 200
server: nginx
date: Thu, 10 Oct 2019 05:10:04 GMT
cache-control: public, max-age=0, no-cache
link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
replay-nonce: 00013TyemkZQGnX2K1N4l76MLUN-WybdRuqsJjKWrYpsHWA
x-frame-options: DENY
strict-transport-security: max-age=604800

The solution to this one is simply to grab an updated letsencrypt.sh script:

cd /usr/local/directadmin/custombuild
./build update
./build letsencrypt

Reported solution for Debian/Ubuntu Edit

/etc/ld.so.conf

and change the order of the paths, so that /usr/local/lib is higher up (so the file looks like this):

/usr/local/lib/
include /etc/ld.so.conf.d/*.conf

Save, then run

ldconfig

We’ve not tested this, as it could affect the libraries that system binaries use. Be sure to fully test things, especially SSHd (restart the SSHd server and test a login), before logging out of the current SSH session.

Let’s Encrypt request successful” but contains an error message for non-success

We had a few reports where Debian systems were returning a success message for Let’s Encrypt calls, while the message itself contained errors, e.g.,

Subject: Let's Encrypt request successful

Requesting new certificate order...
Processing authorization for fakedomain.com...
Error: http://fakedomain.com/.well-known/acme-challenge/letsencrypt_1560468322 is not reachable. Aborting the script.
dig output for fakedomain.com:
Please make sure /.well-known alias is setup in WWW server.

The message itself isn’t relevant, as the domain(s) in question does not exist.

The issue was that the subject was reporting success, when the letsencrypt.sh script was returning an error code.

Debugging the issue found /bin/dash (the Debian shell) to be the cause, in that it was returning code 0, when the script it was calling was returning code 1.

Simple solution: Use bash.

  1. Install bash on your system, if it’s not present:
apt-get install bash

and confirm the binary exists at:

ls -la /bin/bash
  1. /bin/bash is present, change /bin/sh to use it:
ln -sf bash /bin/sh

which changes the old “/bin/sh -> dash” link to point to the properly behaving bash binary.

“type”: “urn:acme:error:unauthorized”, “detail”: “Must agree to subscriber agreement before any further actions”

When creating a certificate, if you run into this error:

{
"type": "urn:acme:error:unauthorized",
"detail": "Must agree to subscriber agreement before any further actions",
"status": 403
}. Exiting...
/usr/local/directadmin/data/users/username/letsencrypt.key

and try again. The issue relates to a change in policy that must be approved, and the old letsencrypt.key file has to be wiped and re-generated as a sign of approval.

How to revoke a Let’s Encrypt hostname certificate

To revoke the certificate, please run the following (if the cert is still in-place):

cd /usr/local/directadmin/scripts
./letsencrypt.sh revoke `hostname -f`

To stop the auto-renewal:

rm -f /usr/local/directadmin/conf/cacert.pem.creation_time

CAA record prevents issuing the certificate

This error indicates either a DNS error or a CAA record exists for one of the domains included in the request and prevents the Certificate Authority “letsencrypt.org” from being authorized to issue an SSL.

Check the following for each domain/subdomain included in the SSL request to troubleshoot this error:

  1. Check for an existing CAA record that would prohibit the SSL to be issued by “letsencrypt.org” by running the following command in a terminal (change ‘DOMAIN.TLD’ to your actual domain):
dig caa +short DOMAIN.TLD

Keep in mind that a subdomain can have its own CAA record that overrides the parent domain. Check any other domains included in the request for the existence of this record, too.

  1. If no CAA records exist for the domains included in the SSL request, you should move on to check the DNS for the domains. Run the same CAA dig this time without the “+short” and look for “SERVFAIL” in the output. If this exists in the output, it signifies a DNS problem for the domain checked. At this point, you should check for the following:

A vast compilation of tools for checking your configuration exists here:

https://community.letsencrypt.org/t/third-party-tools-to-check-your-configuration/76272open in new window

  1. Make sure that you are running the latest letsencrypt.sh that uses POST-as-GET requests and that you have LEGO installed:
cd /usr/local/directadmin/custombuild
./build update
./build letsencrypt
  1. Run the command via the command line via debug and staging modes. If you had previously requested the SSL via the DirectAdmin SSL interface, you should use the DirectAdmin-generated san_config file containing all of your selections made via the DirectAdmin SSL GUI (make sure to replace “DOMAIN.TLD” & “USERNAME” below with your actual domain and username):
staging=yes bash -x /usr/local/directadmin/scripts/letsencrypt.sh request 'DOMAIN.TLD' 4096 /usr/local/directadmin/data/users/USERNAME/domains/DOMAIN.TLD.san_config /var/www/html

Now, review the output and check for errors. Pay close attention to the domains that are being tested. For example, a domain request may fail with a SERVFAIL because of an expired domain pointer included in the request. The actual domain may exhibit no DNS issues itself when checked, but if the domain pointer does, it will prevent the issuance of the SSL.

  1. If you still can’t figure it out, feel free to submit a ticket to DirectAdmin for examination. Please include all tests and output from said tests in your request.

Troubleshooting SSL Errors

How to check the details of an SSL certificate

If you’re not sure if the certificate you’re using is new, old, or what info is in it, you can use the “openssl” command with the 509 option to get you more info on a certificate, e.g.,

openssl x509 -in  -text -noout
Certificate:
   Data:
       Version: 3 (0x2)
       Serial Number: 0 (0x0)
       Signature Algorithm: md5WithRSAEncryption
       Issuer: C=US, ST=Someprovince, L=Sometown, O=none, OU=none, CN=/emailAddress=webaster@localhost
       Validity
           Not Before: Jul  7 05:58:09 2009 GMT
           Not After : Nov 21 05:58:09 2036 GMT
       Subject: C=US, ST=Someprovince, L=Sometown, O=none, OU=none, CN=/emailAddress=webaster@localhost
       Subject Public Key Info:
           Public Key Algorithm: rsaEncryption
           RSA Public Key: (1024 bit)
               Modulus (1024 bit):
                   00:98:32:24:b9:13:30:7b:97:6f:dc:35:c2:a0:e8:
                   58:de:9f:88:d2:b0:86:1c:b9:67:1f:7d:b1:28:6c:
                   b8:52:47:f0:14:32:4c:36:62:14:a7:bf:d1:d1:47:
                   ed:bc:63:60:c7:ee:3c:22:58:69:4f:b4:93:8c:3e:
                   f5:02:54:85:70:24:c6:3e:b1:67:90:50:ab:18:64:
                   60:b2:46:e1:19:d3:b7:34:7b:48:c6:6b:bb:da:56:
                   54:92:c0:2e:39:81:f7:94:af:3d:51:2c:cf:4a:86:
                   9e:0c:30:60:82:6b:34:f6:9b:e4:01:9c:39:1b:4f:
                   68:61:fa:5f:7e:cc:f6:e0:ed
               Exponent: 65537 (0x10001)
   Signature Algorithm: md5WithRSAEncryption
       20:86:28:65:d5:fe:d2:a9:0c:f9:c3:24:51:ff:de:ff:11:6e:
       ec:b4:dc:b1:11:70:cb:37:52:45:e7:cb:f3:e9:e1:b3:3a:5d:
       20:8b:49:07:43:a4:da:b8:17:bf:4b:84:89:d7:0e:18:34:b3:
       0c:c2:0c:cd:56:2b:9e:e1:e0:6a:c4:7d:fc:3f:3e:89:8a:a5:
       c9:a5:1a:1c:2c:7d:74:1c:34:54:b1:8b:36:2d:91:b6:38:79:
       ad:e5:14:53:d2:32:ce:ee:89:ef:60:f3:98:0f:38:79:e3:07:
       f5:e5:a5:ff:8f:6b:74:46:4c:89:7e:33:0e:66:cf:34:3b:c1:
       e3:79

Similarly, you can manually connect to a remote host

to check if a certificate is self-signed or not:

openssl s_client -servername  -host  -port 443 | grep 'Verify return code'

where the output might look like:

depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = 
verify return:1
   Verify return code: 0 (ok)
QUIT
DONE

We’d take note of the Verify return code: 0 (ok) status. The “code: 0” is good, as it means the certificate is correctly signed by a certificate authority.

I usually type “QUIT” to exit the current connection (this is a client connection to Apache, so you could create a request here). Else some systems might need Ctrl-D to send an “end-of-file” character to close it.

If you see:

Verify return code: 18 (self signed certificate)

then it means the certificate could be self-signed (you created the cert/key yourself), or the ca root bundle or chain have not been correctly installed.

How to check the details of a certificate request

If you have a certificate request, and want to see what information is set inside, you can use the “openssl” command with the “req” option to get you more info on the CSR.

openssl req -in /path/to/your/certificate.request -text -noout
Certificate Request:
   Data:
       Version: 0 (0x0)
       Subject: C=CA, ST=Alberta, L=St. Albert, O=JBMC-Software, CN=www.testdomain.com/emailAddress=my@email.com
       Subject Public Key Info:
           Public Key Algorithm: rsaEncryption
           RSA Public Key: (2048 bit)
               Modulus (2048 bit):
                   00:c5:bb:20:60:a2:bd:c1:aa:10:76:f4:d5:46:73:
                   e5:c5:b1:f8:a5:ae:f8:f0:70:02:1e:52:fb:ef:e3:
                   d5:8b:75:d0:b8:d5:72:ad:63:11:10:4a:99:b4:41:
                   ab:06:91:6a:5e:68:3b:5e:e2:c3:cb:d6:51:19:cb:
                   25:5a:40:05:fe:13:1b:f0:87:49:0e:95:04:d5:81:
                   bb:7c:07:1b:3c:69:08:9e:ad:ef:9e:1e:97:a0:5e:
                   f5:66:c2:e0:f5:65:2d:6f:cb:eb:45:4d:f6:3b:e0:
                   33:43:78:48:30:14:5b:40:99:e0:e3:14:7e:46:5b:
                   11:d0:d4:d9:6d:bf:61:ec:02:a0:96:d5:f8:0c:30:
                   ae:ce:88:64:88:01:a1:83:03:90:68:67:16:2d:77:
                   6c:41:ca:c4:8a:42:1d:b6:1a:a2:c2:06:20:31:89:
                   36:ae:6a:03:9f:e6:4f:cc:97:a4:24:f4:a5:c6:c2:
                   c6:be:d7:73:2f:a6:56:89:28:83:e1:be:cf:b7:57:
                   70:66:e5:7f:28:ac:2b:e2:3e:1e:a8:79:4c:64:db:
                   d7:a2:9c:20:5c:b2:cb:92:e5:4d:07:45:b2:4c:9a:
                   a6:01:ea:49:88:f4:c6:fc:d0:45:52:92:39:32:3e:
                   93:54:6a:d8:3d:c4:42:d1:30:a3:45:89:86:9c:c8:
                   12:63
               Exponent: 65537 (0x10001)
       Attributes:
           challengePassword        :A challenge password
   Signature Algorithm: md5WithRSAEncryption
       a8:b2:06:3d:a0:56:86:72:53:9a:8b:9a:b3:1a:9f:4f:6f:27:
       a2:d7:25:28:63:3b:39:3c:6d:f6:e0:66:43:1d:a6:1f:fc:2c:
       af:af:11:04:80:5d:4a:29:03:1f:24:8e:c2:3e:65:36:75:82:
       1e:6e:12:aa:68:fd:d7:8d:d5:8d:9c:12:74:6c:5e:8a:d1:af:
       a4:da:12:6e:fa:df:fe:cf:9c:1d:22:cd:8c:91:2a:1e:67:1b:
       bf:2f:95:7c:b2:4e:7d:e0:9b:41:d3:c5:30:e7:5e:04:91:e6:
       95:0e:8d:da:4c:cd:86:ac:37:c7:95:d5:3a:0a:9f:5e:d8:1e:
       9b:ea:27:11:7e:03:ff:b3:1a:66:da:ab:82:d2:ad:ad:8d:cd:
       b4:cb:67:b0:99:63:ae:e1:b9:8d:13:26:b1:df:84:85:72:61:
       a4:4f:82:9b:86:10:37:57:bc:d4:d8:6b:8b:f7:12:27:a3:ef:
       b3:c0:4b:20:8d:bb:0d:18:64:f8:38:06:69:31:0c:2d:2d:86:
       39:a1:98:26:7c:a7:02:98:e1:35:d8:ee:ca:a8:fe:80:29:d5:
       5c:6f:55:d0:b5:12:9e:31:86:ed:8f:c2:1c:ff:ec:3a:9b:3b:
       2c:c6:80:c2:1e:c7:a5:de:a0:ea:11:ef:f3:c7:df:74:8e:5e:
       a4:b6:50:80
[root@server]#

DirectAdmin is not accepting my encrypted SSL key

If you have an RSA PRIVATE KEY with headers that look something like:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,D061ACF7F7A7D27F

then you would have a password encrypted key.

This will not work with DirectAdmin since it would require someone to type in a password each time Apache restarts.

You do not have to start over unless you’ve forgotten the password. You can actually convert this password protected key into a normal key by typing:

openssl rsa -in /path/to/your/key -out /the/new/key

where you’d replace the path values with appropriate values.

This will ask you for the password you specified when you created the original key.

It will then create a non-password-protected key that you can use for DA.

The LetsEncrypt DST Root CA X3 Expiration, Fixes, and ZeroSSL Support

Albeit a rare occurrence, CA root certificates do occasionally expire, and this can cause a multitude of SSL errors for clients using older OpenSSL versions and/or outdated ca-certificate installations.

The Public Key Infrastructure (PKI) facilitates SSL and public key encryption management, providing CIA (confidentiality, integrity, and authenticity) trust services. It includes a Truststore, which is a locally stored list of all ‘trusted’ root CA self-signed certificates stored directly on your OS. This establishes explicit trust for the root CAs listed.

Root CA certificates are necessary in validating a Chain of Trust in order to verify the authenticity of an organization claiming to own the domain for which the SSL is implemented. A trusted Registration Authority (RA) will create their own self-signed root CA certificate (which is trusted explicitly via your truststore), then, in order to guard it as much as possible, will store it offline and create/sign intermediate SSLs (sub CA certificates) with it (these must be verified). These intermediate SSLs are then permitted to sign your domain’s SSLs on behalf of the root CA. If any of the SSLs in this Chain of Trust are broken, SSL errors may result.

So, what happens when a root CA certificate expires and how can we rectify the errors that result?

LetsEncrypt and ISRG

LetsEncrypt started out using a known and trusted CA, IdenTrust, to cross-sign their root certificate until their own ISRG root certificate became widely trusted. Now that it is, the existing root CA is expired. However, existing SSLs that were signed with this now expired root CA may show SSLs with different utilities if the computer you are connecting from has the expired root CA still listed in its truststore.

An example of this is recent connections via CustomBuild to DirectAdmin mirrors that have valid SSLs, but the chain includes the expired root certificate, so SSL errors like this excerpt from a CustomBuild run may result:

ERROR: cannot verify files-ca.directadmin.com's certificate, issued by '/C=US/O=Let\'s Encrypt/CN=R3':
  Issued certificate has expired.
To connect to files-ca.directadmin.com insecurely, use `--no-check-certificate'.

SSLLABS.com/ssltest against the mirror shows this:

In trust store 	DST Root CA X3   Self-signed	
Fingerprint SHA256: 0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739
Pin SHA256: Vjs8r4z+80wjNcr1YKepWQboSIRi63WsWXhIMN+eWys=
RSA 2048 bits (e 65537) / SHA1withRSA
Valid until: Thu, 30 Sep 2021 14:01:15 UTC
EXPIRED
Weak or insecure signature, but no impact on root certificate

The cross-signed SSL shouldn’t be a problem if the expired root SSL is removed from the TrustStore, or if OpenSSL v1.1.0 or later is in use rather than OpenSSL v1.0.2.

OpenSSL v1.1.0 has improved certificate chaining so that trusted store certificates are preferred over untrusted certificates, thus allowing a working certificate chain to be built.

So, if you’re using an older version of OpenSSL, you have the following options to rectify this issue for connecting to domains that use the expired root certificate in their chain:

  1. Upgrade OpenSSL to v1.1.0 or later
  2. Upgrade the package ca-certificates
  3. Blacklist the expired root certificate in your TrustStore

If these errors are occurring on your own site, you can:

  1. Use –preferred-chain in ACME LetsEncrypt libraries, such as is used with DA’s own letsencrypt.sh script now, to specify the preferred chain to be built using the valid ISRG root certificate.
  2. Use an alternate provider to issue your SSLs, but know that they, too, will have an expired root certificate one day, as this issue is not specific to LetsEncrypt only (recall the Comodo/Sectigo AddTrust External CA Expiration of May 2020?open in new window).

How to Upgrade OpenSSL

These upgrades would be handled by your OS. Reference your OS vendor’s documentation for how to proceed here.

For example, for CentOS, Cloudlinux and other RHEL servers, you can use yum or dnf to run updates: yum update or dnf update

Alternatively, you can update specific packages, via a package manager like dnf, or by compiling from source. Again, reference your OS vendor’s documentation for instructions.

How to Upgrade the ca-certificates package

This, too, is vendor specific.

Check if your truststore contains the expired LetsEncrypt DST CA Root X3 certificate:

trust list | grep -A2 -B2 'X3'

If yes and if you’re using CentOS or Cloudlinux, run this:

yum update ca-certificates

Then check that the expired certificate has been removed:

rpm -q -changelog ca-certificates | head -5

Output should be as follows:

[root@host4 ~]# rpm -q -changelog ca-certificates | head -5
* Tue Sep 14 2021 Bob Relyea <rrelyea@redhat.com> - 2021.2.50-72
- Fix expired certificate.
-    Removing:
-     # Certificate "DST Root CA X3"

[root@host4 ~]# 

And wget/curl commands used by CustomBuild should now succeed:

[root@host4 ~]#  wget https://files-ca.directadmin.com/services/custombuild/2.0/custombuild.tar.gz
--2021-11-11 09:17:11--  https://files-ca.directadmin.com/services/custombuild/2.0/custombuild.tar.gz
Resolving files-ca.directadmin.com (files-ca.directadmin.com)... 51.161.40.239, 2607:5300:60:1eb6::16
Connecting to files-ca.directadmin.com (files-ca.directadmin.com)|51.161.40.239|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 265985 (260K) [application/octet-stream]
Saving to: ‘custombuild.tar.gz.1’

100%[================================================================>] 265,985     --.-K/s   in 0.08s   

2021-11-11 09:17:11 (3.05 MB/s) - ‘custombuild.tar.gz.1’ saved [265985/265985]

[root@host4 ~]# 

If using Debian:
sudo apt-get --only-upgrade install ca-certificates or
sudo apt-get install --reinstall ca-certificates

How to blacklist the expired certificate in your TrustStore

First, get the pkics11 id:

trust list | grep -A2 -B2 'X3'

Example:

[root@host4 ~]# trust list | grep -A2 -B2 'X3'
pkcs11:id=%c4%a7%b1%a4%7b%2c%71%fa%db%e1%4b%90%75%ff%c4%15%60%85%89%10;type=cert
    type: certificate
    label: DST Root CA X3
    trust: anchor
    category: authority
[root@host4 ~]# 

Since this is a read-only certificate, it cannot be removed with the trust anchor --remove command:

[root@host4 ~]# trust anchor --remove "pkcs11:id=%c4%a7%b1%a4%7b%2c%71%fa%db%e1%4b%90%75%ff%c4%15%60%85%89%10;type=cert"
p11-kit: couldn't remove read-only certificate
[root@host4 ~]# 

Instead, dump the certificate into a file so that it will be blacklisted in your TrustStore (be sure to confirm the appropriate path for your OS):

trust dump --filter "pkcs11:id=%c4%a7%b1%a4%7b%2c%71%fa%db%e1%4b%90%75%ff%c4%15%60%85%89%10;type=cert"  > /etc/pki/ca-trust/source/blacklist/DST-root-CA-X3.p11-kit

Then, update the ca trust store:

update-ca-trust

Output expected will be similar to the following:

[root@host3 ~]# update-ca-trust
p11-kit: overriding trust for anchor in blacklist: DST-root-CA-X3.p11-kit
p11-kit: overriding trust for anchor in blacklist: DST-root-CA-X3.p11-kit
p11-kit: overriding trust for anchor in blacklist: DST-root-CA-X3.p11-kit
p11-kit: overriding trust for anchor in blacklist: DST-root-CA-X3.p11-kit
p11-kit: overriding trust for anchor in blacklist: DST-root-CA-X3.p11-kit
[root@host3 ~]#

Now, upon checking your TrustStore, you’ll see that the certificate is blacklisted:

[root@host3 ~]#  trust list | grep -A2 -B2 'X3'
p11-kit: overriding trust for anchor in blacklist: DST-root-CA-X3.p11-kit
pkcs11:id=%c4%a7%b1%a4%7b%2c%71%fa%db%e1%4b%90%75%ff%c4%15%60%85%89%10;type=cert
    type: certificate
    label: DST Root CA X3
    trust: blacklisted
    category: authority
[root@host3 ~]# 

And the errors are gone:

[root@host3 ~]# wget https://files-ca.directadmin.com/services/custombuild/2.0/custombuild.tar.gz
--2021-11-11 03:24:49--  https://files-ca.directadmin.com/services/custombuild/2.0/custombuild.tar.gz
Resolving files-ca.directadmin.com (files-ca.directadmin.com)... 51.161.40.239, 2607:5300:60:1eb6::16
Connecting to files-ca.directadmin.com (files-ca.directadmin.com)|51.161.40.239|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 265985 (260K) [application/octet-stream]
Saving to: ‘custombuild.tar.gz’

100%[==================================>] 265,985     --.-K/s   in 0.08s   

2021-11-11 03:24:50 (2.99 MB/s) - ‘custombuild.tar.gz’ saved [265985/265985]

[root@host3 ~]# 

How to use --preferred-chain with letsencrypt.sh

This allows you to specify which chain will take precedence, so that OpenSSL v1.0.2 won’t end up using the untrusted, expired certificate for the chain. It will instead use the certificate you specify. This is done for you automatically via the letsencrypt.sh script, which sets the preferred-chain to “ISRG Root X1”.

How to use an alternate provider- ZeroSSL

We have prepared an early tech preview of a ZeroSSL support. For this to work we released a new lego version (capable of issuing ZeroSSL certificates) and new letsencrypt version v2.0.24. Participation in this early preview is controlled by the existence of /root/.zerossl file. If this file is present DA will try issuing cert from ZeroSSL, if this file is absent everything will work as before (certs issued from LetsEncrypt).

If you would like to try it out please do the following:

/usr/local/directadmin/custombuild/build update
/usr/local/directadmin/custombuild/build lego
/usr/local/directadmin/custombuild/build letsencrypt
touch /root/.zerossl
/usr/local/directadmin/scripts/letsencrypt.sh request server.name.example.net

The following command can be used to confirm that a ZeroSSL certificate is now in use:
openssl s_client -connect example.net:2222 -servername example.net

If /root/.zerossl file is present all certs issued will use ZeroSSL provider (existing LetsEncrypt certificates will be replaced by ZeroSSL certificates on renewal).

This solution is intended for those who really need to maintain websites for old clients. Please report if you tried it out and it helped. We expect this experimental ZeroSSL mode to be dropped or replaced by proper ZeroSSL switch in GUI in the future depending on how this experiment goes.

 

To Get Daily Health Newsletter

We don’t spam! Read our privacy policy for more info.

Download Mobile Apps
Follow us on Social Media
© 2012 - 2025; All rights reserved by authors. Powered by Mediarx International LTD, a subsidiary company of Rx Foundation.
RxHarun
Logo