# DirectAdmin hosting — the certificate renews itself

> A cron job fetches the fresh certificate daily and installs it in DirectAdmin through the API with a login key allowed only SSL. No password needed.

URL: https://zrazu.com/en/docs/ssl-auto-directadmin/

Use this for hosting with the DirectAdmin panel: NIC.UA, Tucha and many others. You can tell DirectAdmin by the login address ending in `:2222` and menu sections **Account Manager**, **Advanced Features**, **System Info & Files**.

How it works: once a day the script fetches the certificate from the link and, if it is new, hands it to the panel together with your key — exactly as you would paste it by hand in **SSL Certificates**. It signs in to the panel not with your password but with a separate Login Key that is allowed one action only: installing a certificate. We never ask for or see your panel or hosting password.

## What you need

- The certificate link from your account: `https://api.zrazu.com/ssl-pull/zsp_YOUR_TOKEN`.
- The private key the certificate was ordered with. If the ZRAZU account generated the CSR, this is the file you saved back then.
- The **Cron Jobs** section in the panel (most plans have it) or any Linux server with `curl` and `openssl`.
- 15 minutes.

## Step 1. First installation (if the certificate is not there yet)

In **Account Manager → SSL Certificates** choose **Paste a pre-generated certificate and key**, paste the key and then the certificate below it into the one field, and save. Then **Click Here to paste a CA Root Certificate**, paste the chain (`chain.pem` from the certificate card), tick **Use a CA Cert** and save. Details are in [replacing the certificate in a panel by hand](https://zrazu.com/en/docs/ssl-auto-panels-manual.md).

## Step 2. A login key for SSL only

**Account Manager → Login Keys → Create Key** (in older skins, **Login Keys** on the main page):

- **Key Name** — `zrazu-ssl`;
- **Key Value** — click **Random** and copy the value: it is shown only once;
- **Expires On** — **Never** (the key is needed every day);
- **Commands** — tick only `CMD_API_SSL`; without this the key opens the whole panel;
- **Allowed IPs** — the IP the script will run from. If it is the hosting's own cron, the server IP (**System Info & Files → System Information**). An empty field lets the key work from any address;
- **Current Password** — your panel password, to confirm the creation.

If there is no **Login Keys** item, the hosting has turned the feature off. Then [replacing by hand](https://zrazu.com/en/docs/ssl-auto-panels-manual.md) remains, and we remind you in advance.

## Step 3. Files in the home directory

In **System Info & Files → File Manager** create a `.zrazu` folder in the home directory (above `domains` and `public_html`) and three files in it:

- `key.pem` — the private key including the `-----BEGIN … PRIVATE KEY-----` and `-----END … PRIVATE KEY-----` lines;
- `login` — one line in quotes: the panel user name, a colon, the login key value:

```
user = "USER_NAME:KEY_VALUE"
```

- `zrazu-ssl.sh` — the script below. Change only the `PANEL` line in it: the address you sign in to the panel with, including `:2222`, without a path.

Set permissions `600` on all three files (**Permissions** in File Manager): only your account can read them.

```sh file=zrazu-directadmin.sh
#!/bin/sh
# ZRAZU: updates the SSL certificate in DirectAdmin using the personal link. Run by cron once a day.
# The key stays with you; the certificate goes to the panel only if it matches the key.
set -eu
PATH=/usr/local/bin:/usr/bin:/bin
PULL="https://api.zrazu.com/ssl-pull/zsp_YOUR_TOKEN"
DOMAIN="example.com"
PANEL="https://server.example.com:2222"
DIR="$HOME/.zrazu"
KEY="$DIR/key.pem"
# The user name and login key live in a file, not on the command line, so other users of the server cannot see them.
LOGIN="$DIR/login"

umask 077
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT
TAG=""
[ -f "$DIR/$DOMAIN.etag" ] && TAG=$(cat "$DIR/$DOMAIN.etag")
CODE=$(curl -fsS --retry 3 --max-time 60 -o "$WORK/full.pem" -D "$WORK/hdr" -w '%{http_code}' -H "If-None-Match: $TAG" "$PULL/fullchain.pem")
if [ "$CODE" = "304" ]; then echo "ZRAZU: certificate unchanged"; exit 0; fi
grep -q "BEGIN CERTIFICATE" "$WORK/full.pem" || { echo "ZRAZU: the link does not return a certificate" >&2; exit 1; }
# The first certificate in the file is the site's, the rest is the chain.
awk -v d="$WORK" '/BEGIN CERTIFICATE/{n++} n==1{print > (d "/cert.pem")} n>1{print > (d "/chain.pem")}' "$WORK/full.pem"
if [ "$(openssl x509 -in "$WORK/cert.pem" -noout -pubkey | openssl sha256)" != "$(openssl pkey -in "$KEY" -pubout | openssl sha256)" ]; then
  echo "ZRAZU: certificate was issued for a different key — changing nothing, put the new key in $KEY" >&2
  exit 1
fi
openssl x509 -in "$WORK/cert.pem" -noout -checkend 0 >/dev/null || { echo "ZRAZU: certificate has already expired" >&2; exit 1; }
# The panel takes the key and certificate in one field: the key first, the certificate below it.
cat "$KEY" "$WORK/cert.pem" > "$WORK/paste.pem"
api() {
  OUT=$(curl -sS --max-time 60 -K "$LOGIN" "$PANEL/CMD_API_SSL" -d "domain=$DOMAIN" -d action=save "$@") || true
  case "$OUT" in
    error=0*) ;;
    *) echo "ZRAZU: the panel refused: $(printf '%s' "$OUT" | head -c 300)" >&2; exit 1 ;;
  esac
}
api -d type=paste -d request=no --data-urlencode "certificate@$WORK/paste.pem"
if [ -s "$WORK/chain.pem" ]; then
  api -d type=cacert -d active=yes --data-urlencode "cacert@$WORK/chain.pem"
fi
# The tag is written only after the panel accepted: if it did not, the next run tries again.
sed -n 's/^[Ee][Tt][Aa][Gg]: *//p' "$WORK/hdr" | tr -d '\r' > "$DIR/$DOMAIN.etag"
echo "ZRAZU: new certificate installed, valid until $(openssl x509 -in "$WORK/cert.pem" -noout -enddate | cut -d= -f2)"
```

The script changes nothing if the certificate has not changed, if the link does not return a certificate, or if the certificate does not match your key or has expired. The panel answers `error=0` when it has accepted the certificate; any other answer is an error, and the script tries again the next day.

## Step 4. Schedule

**Advanced Features → Cron Jobs → Create Cron Job**: Minute `17`, Hour `4`, the other fields `*`, command:

```sh
/bin/sh $HOME/.zrazu/zrazu-ssl.sh >> $HOME/.zrazu/log.txt 2>&1
```

Any minute will do — preferably not exactly 00. To check right away, temporarily set the time two minutes ahead, and after the run open `.zrazu/log.txt`: it should say "new certificate installed".

Your own Linux server instead of the hosting's cron: the same script with `HOME` pointing to your directory, a `crontab -e` line `17 4 * * * /bin/sh $HOME/.zrazu/zrazu-ssl.sh >> $HOME/.zrazu/log.txt 2>&1`, and that server's IP in the key's **Allowed IPs**.

## Check

Open [https://zrazu.com/tools/ssl/example.com/](https://zrazu.com/tools/ssl/example.com/) — it should show the ZRAZU certificate with the new expiry date.

## So the hosting does not replace our certificate

If the domain has the free certificate on (**Free & automatic certificate from Let's Encrypt** in **SSL Certificates**), the panel renews it by itself and may replace ours. The script installs the certificate as a pasted one, and the panel stops renewing the free one; after the first run, check that the pasted certificate is selected in **SSL Certificates**.

## If it did not work

This is a new guide: we have not yet tested it on a live panel. If it did not work, write to us in your account (**Support**) or by email with the text from `.zrazu/log.txt`, and we fix the guide the same day.

- "the panel refused" with HTML saying `Cannot Execute Your Request` — the login key has no right to `CMD_API_SSL`, or the run comes from an IP outside **Allowed IPs**. Check step 2.
- `error=1` and `text=…` — the panel explains the reason in `text`: most often the domain is written differently from the panel (without `*.` and without `www`).
- `curl: (60)` or `SSL certificate problem` — `PANEL` holds an address the panel has a different certificate for. Copy the address exactly from the browser bar when you sign in to the panel.
- `openssl: not found` — this hosting has no `openssl`; run the script from your own Linux server.
- `curl: (22) … 404` — the link is disabled or replaced: create a new one in the certificate card and replace the `PULL` line.
