Для корректной работы почтового сервера Zimbra необходим SSL-сертификат, который можно получить с помощью Certbot от Let’s Encrypt. В сети существует множество статей и скриптов автоматизации обновления сертификатов и установки на сервер Zimbra. Однако важно учесть один нюанс: Certbot требует, чтобы сервер на котором выполняется запрос на получение и обновление сертификата, в данном случае сервер Zimbra, был напрямую доступен из интернета по 80 порту. Если в инфраструктуре перед сервером Zimbra располагается проксирующий сервер, попытка обновления сертификата через Certbot завершится ошибкой.
Проблему можно решить двумя способами. Первый вариант — временно перенаправить 80 порт на маршрутизаторе с проксирующего сервера на сервер Zimbra во время обновления сертификата. Второй вариант — обновлять сертификат непосредственно на проксирующем сервере и затем передавать его на сервер Zimbra. Именно второй способ и будет использоваться.
Конфигурация
- Прокси сервер — Nginx;
- Почтовый сервер — Zimbra 8.8.15_GA в односерверной конфигурации;
- CI/CD — GitLab Community Edition v17.3.0.
Создание проекта
- Авторизуемся в GitLab и создаём новый проект;
- Добавляем GitLab Runners
Settings -> CI/CD -> Runners
;- Прокси сервер — GitLab Runner в режиме
shell
с тегомproxy
; - Почтовый сервер — GitLab Runner в режиме
shell
с тегомzimbra
; - GitLab сервер — GitLab Runner в режиме docker с тегом build ;
- Прокси сервер — GitLab Runner в режиме
- Создаём в проекте новый файл с именем:
.gitlab-ci.yml
и вставляем следующий код:
variables:
CERT_PROXY_PATH: "/etc/letsencrypt/live/DOMAIN"
stages:
- delivery
- build
- deploy
delivery-cert-job:
stage: delivery
tags:
- proxy
script:
- mkdir build
- sudo cp ${CERT_PROXY_PATH}/cert.pem build/cert.pem
- sudo cp ${CERT_PROXY_PATH}/privkey.pem build/privkey.pem
- sudo cp ${CERT_PROXY_PATH}/fullchain.pem build/fullchain.pem
- sudo chmod -R 777 build
artifacts:
paths:
- build/
expire_in: 1h
build-cert-job:
stage: build
image: curlimages/curl:latest
tags:
- build
script:
- curl -o AUTH-X3.pem https://letsencrypt.org/certs/letsencryptauthorityx3.pem.txt
- curl -o ISRG-X1.pem https://letsencrypt.org/certs/isrgrootx1.pem.txt
- cat AUTH-X3.pem >> build/fullchain.pem
- cat ISRG-X1.pem >> build/fullchain.pem
artifacts:
paths:
- build/fullchain.pem
expire_in: 1h
deploy-zimbra-job:
stage: deploy
tags:
- zimbra
before_script:
- sudo su - zimbra -c "zmproxyctl stop"
- sudo su - zimbra -c "zmmailboxdctl stop"
script:
- sudo rm -rf /opt/zimbra/ssl/zimbra/commercial
- sudo mkdir /opt/zimbra/ssl/zimbra/commercial
- sudo cp build/* /opt/zimbra/ssl/zimbra/commercial/
- sudo chmod -R 744 /opt/zimbra/ssl/zimbra/commercial
- sudo chown -R zimbra:zimbra /opt/zimbra/ssl/zimbra/commercial
- sudo su - zimbra -c "cd /opt/zimbra/ssl/zimbra/commercial && zmcertmgr verifycrt comm privkey.pem cert.pem fullchain.pem"
- sudo mv /opt/zimbra/ssl/zimbra/commercial/privkey.pem /opt/zimbra/ssl/zimbra/commercial/commercial.key
- sudo su - zimbra -c "cd /opt/zimbra/ssl/zimbra/commercial && zmcertmgr deploycrt comm cert.pem fullchain.pem"
after_script:
- sudo su - zimbra -c "zmcontrol restart"
Давайте подробнее рассмотрим, что происходит в этом шаге. Мы задаём значение переменной CERT_PROXY_PATH
, которое указывает путь к каталогу с сертификатами:
variables:
CERT_PROXY_PATH: "/etc/letsencrypt/live/DOMAIN"
Здесь вместо DOMAIN необходимо указать имя каталога, содержащего сертификаты Let’s Encrypt.
Затем определяем этапы в пайплайне CI/CD:
- delivery — на этом этапе сертификаты забираются с прокси сервера и через артефакты передаются на следующие этапы;
- build — этап сборки, на котором в цепочку сертификатов добавляются корневые сертификаты Let’s Encrypt;
- deploy — этап развёртывания, на котором сертификаты устанавливаются на сервер Zimbra.
stages:
- delivery
- build
- deploy
Build -> Pipelines
и ожидаем завершения выполнения всех задач: Теперь необходимо настроить запуск пайплайна по расписанию.
- В проекте
Build -> Pipeline schedules -> New schedule
; - Настраиваем расписание:
-
- Description — Run update cert;
- Interval Pattern —
00 00 14 * *
, означает запускать задание 14 числа каждого месяца в 00 часов 00 минут; - Cron timezone — [UTC+3] Moscow;
- Select target branch or tag — main;
- Variables — по-умолчанию;
- Activated – включено.