With the release of DirectAdmin 1.62.0, support for Automatic SSL Certificates 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
- By default, Domains and Pointers will try and use wildcards. This saves the need for subdomains to get their own certificates.
- Wildcard use dns so the zone must be local (or the local DA has control of a remote dns server).
- Triggering a retry on a subdomain will always be http-only (never wildcard/dns).
- 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=yeswhen 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
.sslrequest and.ssl.next_retryfiles 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.
- All User
httpd.confwrites 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. - Cross-User certificates are allowed with the pro-pack:
cross_user_ssl_cert=1where A sub-domain User would be allowed to reference some other User’s certificate. Disabled by default. - 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
- 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
mail_sni=1enabledadmin_ssl_cert_per_vh=1admin_ssl_check_retries=1- 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.confwrite 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 feature that allows you to make use of Let’s Encrypt, 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.conf, or 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.
- 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”).
- 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.
- 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.
- You might need to do the same thing for the
virtual_host2_secure.confandvirtual_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 Encrypt, 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 script 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 Encrypt 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 local, inherit-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-Limit 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 post 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.
- First, ensure that you have letsencrypt=1 in your directadmin.conf. You can use this guide to help you do this.
- 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.
- 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.
- 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.
- 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.
- Install bash on your system, if it’s not present:
apt-get install bash
and confirm the binary exists at:
ls -la /bin/bash
- /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:
- 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.
- 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:
- invalid DNSSEC
- general DNS errors, such as mismatched nameservers, for example.
- check your domain’s overall DNS health using IntoDNS.com
A vast compilation of tools for checking your configuration exists here:
https://community.letsencrypt.org/t/third-party-tools-to-check-your-configuration/76272
- 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
- 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.
- 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:
- Upgrade OpenSSL to v1.1.0 or later
- Upgrade the package ca-certificates
- Blacklist the expired root certificate in your TrustStore
If these errors are occurring on your own site, you can:
- Use –preferred-chain in ACME LetsEncrypt libraries, such as is used with DA’s own
letsencrypt.shscript now, to specify the preferred chain to be built using the valid ISRG root certificate. - 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?).
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.



