# Хостинг с DirectAdmin — сертификат обновляется сам

> Задача cron раз в сутки забирает свежий сертификат и ставит его в DirectAdmin через API по ключу входа, которому разрешён только SSL. Пароль не нужен.

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

Подходит для хостинга с панелью DirectAdmin: NIC.UA, Tucha и многие другие. Признак DirectAdmin — адрес входа заканчивается на `:2222`, в меню есть **Account Manager**, **Advanced Features**, **System Info & Files**.

Как это работает: скрипт раз в сутки забирает сертификат по ссылке и, если он новый, передаёт его панели вместе с вашим ключом — так же, как вы вставили бы его руками в **SSL Certificates**. В панель он входит не паролем, а отдельным ключом входа (Login Key), которому разрешено одно действие — установить сертификат. Ваш пароль от панели и от хостинга мы не просим и не видим.

## Что понадобится

- Ссылка на сертификат из кабинета: `https://api.zrazu.com/ssl-pull/zsp_ВАШ_ТОКЕН`.
- Закрытый ключ, с которым заказывали сертификат. Если CSR создавал кабинет ZRAZU — это файл, который вы тогда сохранили.
- Раздел **Cron Jobs** в панели (есть на большинстве тарифов) или любой сервер Linux с `curl` и `openssl`.
- 15 минут.

## Шаг 1. Первая установка (если сертификат ещё не стоит)

В **Account Manager → SSL Certificates** выберите **Paste a pre-generated certificate and key**, вставьте в одно поле сначала ключ, под ним — сертификат, сохраните. Затем **Click Here to paste a CA Root Certificate**, вставьте цепочку (`chain.pem` из карточки сертификата), отметьте **Use a CA Cert** и сохраните. Подробности — в [замене сертификата в панели вручную](https://zrazu.com/ru/docs/ssl-auto-panels-manual.md).

## Шаг 2. Ключ входа только для SSL

**Account Manager → Login Keys → Create Key** (в старых темах — **Login Keys** на главной):

- **Key Name** — `zrazu-ssl`;
- **Key Value** — нажмите **Random** и скопируйте значение: его покажут только раз;
- **Expires On** — **Never** (ключ нужен каждый день);
- **Commands** — отметьте только `CMD_API_SSL`; без этого ключ открывает всю панель;
- **Allowed IPs** — IP, с которого будет запускаться скрипт. Если это cron самого хостинга — IP сервера (**System Info & Files → System Information**). Поле пустое — ключ действует с любого адреса;
- **Current Password** — ваш пароль от панели, чтобы подтвердить создание.

Если пункта **Login Keys** нет — хостинг отключил эту возможность. Тогда остаётся [ручная замена](https://zrazu.com/ru/docs/ssl-auto-panels-manual.md), мы напомним о ней заранее.

## Шаг 3. Файлы в домашнем каталоге

В **System Info & Files → File Manager** создайте в домашнем каталоге (над `domains` и `public_html`) папку `.zrazu` и в ней три файла:

- `key.pem` — закрытый ключ вместе со строками `-----BEGIN … PRIVATE KEY-----` и `-----END … PRIVATE KEY-----`;
- `login` — одна строка в кавычках: имя пользователя панели, двоеточие, значение ключа входа:

```
user = "ИМЯ_ПОЛЬЗОВАТЕЛЯ:ЗНАЧЕНИЕ_КЛЮЧА"
```

- `zrazu-ssl.sh` — скрипт ниже. Измените в нём только строку `PANEL` — адрес, по которому вы заходите в панель, с `:2222`, без пути.

Всем трём файлам поставьте права `600` (**Permissions** в File Manager): читать их может только ваша учётная запись.

```sh file=zrazu-directadmin.sh
#!/bin/sh
# ZRAZU: обновление SSL-сертификата в DirectAdmin по личной ссылке. Запускается cron раз в сутки.
# Ключ остаётся у вас; в панель сертификат идёт, только если он подходит к ключу.
set -eu
PATH=/usr/local/bin:/usr/bin:/bin
PULL="https://api.zrazu.com/ssl-pull/zsp_ВАШ_ТОКЕН"
DOMAIN="example.com"
PANEL="https://server.example.com:2222"
DIR="$HOME/.zrazu"
KEY="$DIR/key.pem"
# Имя и ключ входа — в файле, а не в строке запуска: так их не видно другим пользователям сервера.
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: сертификат не изменился"; exit 0; fi
grep -q "BEGIN CERTIFICATE" "$WORK/full.pem" || { echo "ZRAZU: по ссылке не сертификат" >&2; exit 1; }
# Первый сертификат в файле — сайта, остальное — цепочка.
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: сертификат выпущен на другой ключ — ничего не меняю, положите новый ключ в $KEY" >&2
  exit 1
fi
openssl x509 -in "$WORK/cert.pem" -noout -checkend 0 >/dev/null || { echo "ZRAZU: сертификат уже не действует" >&2; exit 1; }
# Панель принимает ключ и сертификат одним полем: сначала ключ, под ним сертификат.
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: панель не приняла: $(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
# Метка — только после того, как панель приняла: не получилось — следующий запуск попробует снова.
sed -n 's/^[Ee][Tt][Aa][Gg]: *//p' "$WORK/hdr" | tr -d '\r' > "$DIR/$DOMAIN.etag"
echo "ZRAZU: новый сертификат установлен, действует до $(openssl x509 -in "$WORK/cert.pem" -noout -enddate | cut -d= -f2)"
```

Скрипт ничего не меняет, если сертификат не изменился, если по ссылке не сертификат, если сертификат не подходит к вашему ключу или уже не действует. Панель отвечает `error=0`, когда приняла сертификат; любой другой ответ — ошибка, и на следующий день скрипт попробует снова.

## Шаг 4. Расписание

**Advanced Features → Cron Jobs → Create Cron Job**: Minute `17`, Hour `4`, остальные поля — `*`, команда:

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

Минуту можно взять любую — лучше не ровно 00. Чтобы проверить сразу, временно поставьте время на две минуты вперёд, а после запуска откройте `.zrazu/log.txt`: должно быть «новый сертификат установлен».

Свой сервер Linux вместо cron хостинга — тот же скрипт с `HOME` на свой каталог, строка `crontab -e`: `17 4 * * * /bin/sh $HOME/.zrazu/zrazu-ssl.sh >> $HOME/.zrazu/log.txt 2>&1`, а в **Allowed IPs** ключа — IP этого сервера.

## Проверка

Откройте [https://zrazu.com/tools/ssl/example.com/](https://zrazu.com/tools/ssl/example.com/) — должен быть сертификат ZRAZU с новой датой окончания.

## Чтобы хостинг не заменил наш сертификат

Если для домена включён бесплатный сертификат (**Free & automatic certificate from Let's Encrypt** в **SSL Certificates**), панель сама продлевает его и может заменить наш. Скрипт ставит сертификат как вставленный вручную, и панель перестаёт продлевать бесплатный; проверьте после первого запуска, что в **SSL Certificates** выбран вставленный сертификат.

## Если не получилось

Это новая инструкция: на живой панели мы её ещё не проверили. Не сработало — напишите нам в кабинете (**Обращения**) или на почту с текстом из `.zrazu/log.txt`, исправим инструкцию в тот же день.

- «панель не приняла» и в ответе HTML со словами `Cannot Execute Your Request` — ключ входа не имеет права на `CMD_API_SSL` или запуск идёт с IP вне **Allowed IPs**. Проверьте шаг 2.
- `error=1` и `text=…` — панель объяснила причину в `text`: чаще всего домен записан не так, как в панели (без `*.` и без `www`).
- `curl: (60)` или `SSL certificate problem` — в `PANEL` адрес, на который у панели другой сертификат. Возьмите адрес точно из строки браузера, когда заходите в панель.
- `openssl: not found` — на этом хостинге нет `openssl`; запускайте скрипт со своего сервера Linux.
- `curl: (22) … 404` — ссылка отключена или заменена: создайте новую в карточке сертификата и замените строку `PULL`.
