# DirectAdmin ACME TLS Migration (1.706+): Safe Step-by-Step Plan

Source: https://srvscripts.com/guides/directadmin-acme-tls-migration-1-706/
Updated: 2026-10-03
Publisher: srvScripts (https://srvscripts.com/)

DirectAdmin 1.706, released in July 2026, replaced the long-serving `letsencrypt.sh` certificate flow with a native ACME client built into the panel. Domains that opt in are issued and renewed automatically by a task that runs every 24 hours, with a client based on lego v5 from 1.707 onwards. The old flow still works for domains that have not been migrated, but every release since has added features only to the new system, and 1.711 fixed a local privilege-escalation issue in it, so any server still on the old flow should be on 1.711 or later and moving.

In short: Update to 1.711 or later, then run the TLS migration task from Admin Level → Server TLS Certificate (or queue it through task.queue) so every domain with a letsencrypt.sh certificate is adopted by the native ACME system and renewed at 65…

**Short answer:** Update to 1.711 or later, then run the TLS migration task from Admin Level → Server TLS Certificate (or queue it through `task.queue`) so every domain with a `letsencrypt.sh` certificate is adopted by the native ACME system and renewed at 65 percent of its lifetime. Afterwards review the `acme_*` keys with `da config-get`, confirm manually installed certificates landed on the allowlist, and replace any old `letsencrypt.sh` hooks with the post-renew hooks in `scripts/custom/`.

## What actually changed

Under the old system a cron job called `letsencrypt.sh` for each domain, wrote certificates into the user’s `domains/<domain>/ssl` directory and rewrote the web-server configuration. Renewals were driven by a fixed 60-day schedule and failures produced an email to the user with a shell-script error.

The new system tracks each domain’s certificate as a first-class object. It issues, renews at 65 percent of the certificate’s lifetime (a 1.711 change that aligns with the shorter certificate lifetimes the CA/Browser Forum has scheduled), records every attempt in the **Provisioning history** page added in 1.710, and applies the certificate to Apache or LiteSpeed, Exim, Dovecot and the panel itself. Manually uploaded certificates are kept on an allowlist so the automation never overwrites them. From 1.707 a ZeroSSL account is created automatically as a second provider, and `default_acme_profile` selects the certificate profile.

The configuration keys changed too. 1.703 removed the `letsencrypt_*` keys from `directadmin.conf` in favour of `acme_*`. The ones that matter operationally:

```
da config-get acme_disable_after_failures
da config-get acme_dns_names_per_cert
da config-get acme_use_only_system_resolver
da config-get default_acme_profile
```

`acme_disable_after_failures` stops retrying a domain after repeated failures so that a dead domain does not consume rate-limit budget forever. `acme_dns_names_per_cert` (default 25, added in 1.708) caps the SANs per certificate. `acme_use_only_system_resolver` (1.709) forces DNS checks through the server’s resolver rather than authoritative lookups, which helps behind split-horizon DNS.

Only the Evolution skin exposes the new interface. The Enhanced skin is maintenance-only and shows the legacy pages.

## Running the migration

1.708 added a migration task that walks every domain with a certificate issued by the old flow, registers it with the new system and marks it for renewal on the new schedule. It is triggered from **Admin Level → Server TLS Certificate** in Evolution, or queued directly:

```
echo "action=tls&value=migrate" >> /usr/local/directadmin/data/task.queue
```

Check the changelog for your build if the task name differs, because the exact queue syntax was documented with the 1.708 release and may have been refined since. Watch the log while it runs:

```
tail -f /var/log/directadmin/system.log
tail -f /var/log/directadmin/errortaskq.log
```

The migration does not reissue certificates immediately; it adopts the existing ones and schedules renewal by the new rule. That means a domain whose old certificate has ten days left is renewed on the next daily pass, and a domain with fifty days left waits. No customer-visible change happens on the day of migration unless a certificate was already expired.

Domains with a manually installed certificate are detected and placed on the manual allowlist. Verify this for any domain where a customer paid for an EV or OV certificate, because if the detection misses one the automation will replace the paid certificate with an ACME one at the next renewal.

## Per-domain opt-in and existing customisations

New domains are opted into automatic TLS by default from 1.706. Existing domains that never had a certificate are not, and users enable it from **User Level → SSL Certificates**. Administrators can enable it in bulk by setting `ssl=ON` in each domain’s `domains/<domain>.conf` and issuing a rewrite, or by scripting the `/api/` endpoints.

If you had a custom `letsencrypt.sh` hook, a `custom/ssl/` script or a post-issue hook that pushed certificates to another server, none of it runs under the new system. The equivalent is the post-renew hooks in `/usr/local/directadmin/scripts/custom/`; check which hook names the current build calls before relying on them, since this area changed between 1.706 and 1.710.

## Common pitfall: the hostname certificate

The server hostname’s certificate is handled separately and is the one most likely to stall. From 1.710 the panel syncs manually set server certificates to Exim, Dovecot and the web server, but only if the hostname resolves to the server and port 80 reaches it. A hostname behind a proxy or with an old A record fails the HTTP challenge and the Provisioning history shows it. Fix DNS, then request the certificate again from **Admin Level → Server TLS Certificate**.

## Verify

After migration, list the domains and check the state of a few:

```
grep -l 'ssl=ON' /usr/local/directadmin/data/users/*/domains/*.conf | wc -l
openssl s_client -connect example.com:443 -servername example.com /dev/null | openssl x509 -noout -dates -issuer
```

Open **Admin Level → Provisioning history** and confirm that the most recent entries are successes. Then run our [SSL expiry check](/scripts/ssl-expiry-check/) across all hosted domains weekly for the first month; it catches the domains that were silently disabled by `acme_disable_after_failures` before their certificates run out. If a domain keeps failing, the troubleshooting steps in [Certificate not renewing on DirectAdmin](/guides/directadmin-certificate-not-renewing/) start from the history page.

## DirectAdmin ACME TLS migration at a glance

**Official documentation:** [Let’s Encrypt documentation](https://letsencrypt.org/docs/), [DirectAdmin documentation](https://docs.directadmin.com/), [Linux man pages](https://man7.org/linux/man-pages/).

**Related guides:** [KernelCare on cPanel and DirectAdmin servers: setup, verification and rollback](https://srvscripts.com/guides/kernelcare-setup-cpanel-directadmin/) · [Enabling ModSecurity with OWASP CRS or Comodo rules on DirectAdmin and managing per-domain exclusions](https://srvscripts.com/guides/directadmin-modsecurity-owasp-crs/) · [Installing and tuning CSF/LFD on DirectAdmin (the DirectAdmin fork, post-1.689 defaults)](https://srvscripts.com/guides/csf-directadmin-install-tune/).

## Frequently asked questions

### Does the ACME migration also apply to wildcard certificates issued with a DNS challenge?

Yes, provided the DNS challenge is configured in the new system; the migration adopts the existing wildcard certificate, but renewal only succeeds once the DNS provider credentials or the DirectAdmin-hosted zone update path are set up for the native client.

### How long does the TLS migration task take?

A few minutes for a few hundred domains, because it registers existing certificates rather than reissuing them; the actual renewals then happen over the following weeks on the normal daily pass as each certificate reaches its renewal point.

### Can I undo this?

Not cleanly. The old `letsencrypt.sh` flow is no longer maintained and its `letsencrypt_*` keys were removed in 1.703, so the practical fallback for a problem domain is to install a certificate manually, which places it on the allowlist and stops the automation touching it.
