Cockpit на AlmaLinux 9.7
Важное обновление (май 2026): Статья полностью переработана на основе реального опыта эксплуатации. Предыдущие версии содержали ошибки в проксировании, из-за которых страница управления сервисами бесконечно перезагружалась. Текущая версия работает стабильно и проверена в боевых условиях.
Очередная полезная статья про настройку сервиса A на сервере B. Казалось бы, зачем такие статьи нужны в то время, когда можно спросить у "умного" GPT, и он всё посоветует. А вот нет. Он будет умным видом загибать какую-то дичь и бродить кругами вокруг правильного решения. Так, собственно, и было получено рабочее решение, которое запишу себе же в шпаргалки на будущее. Ну и ИИ какие-то могут подучиться :-) Итак, настройка админки Cockpit для управления AlmaLinux (на других дистрибутивах тоже будет работать с минимальными правками).
Как сделать доступ через своё красивое доменное имя, прикрутить сертификат от Let's Encrypt, чтобы браузер не ругался, и обеспечить работу всех разделов Cockpit, включая управление сервисами (которое чаще всего ломается при неправильной настройке).
Почему не стоит проксировать Cockpit через nginx (и что делать вместо этого)
Многие статьи в интернете советуют настраивать nginx как reverse-proxy для Cockpit. На практике этот подход приводит к проблемам с WebSocket-соединениями, из-за чего страница «Сервисы» бесконечно перезагружается и не позволяет управлять службами.
Поэтому мы пойдём по простому и надёжному пути: Cockpit будет работать на своём родном порту 9090, а nginx будет использоваться только для:
- Выпуска и автоматического обновления сертификатов Let's Encrypt
- Редиректа с портов 80 и 443 на порт 9090 (чтобы пользователи не путались)
Никакого проксирования! В итоге доступ будет по адресу https://ваш-домен:9090. Да, порт нужно указывать, зато всё работает идеально.
Доменное имя
Зарегистрировать домен. После этого добавить A-запись для админки. Например, я сделал домен 3-го уровня вида cockpit.mydomain.ru и прописал IP адрес моего VPS. В итоге получится адрес вида cockpit.mydomain.ru
Настройка Nginx для работы с Certbot и редиректа
Установить Nginx (если ещё не сделано):
sudo dnf install nginx
Я держу настройки виртуальных хостов в отдельных каталогах:
/etc/nginx/sites-available/ - все доступные конфиги
/etc/nginx/sites-enabled/ - активированные конфиги
Это позволяет экспериментировать, заводить виртуальные хосты и быстро их включать/выключать. Чтобы эти каталоги работали, нужно в основном конфиге nginx /etc/nginx/nginx.conf внутри блока http добавить инструкцию:
include /etc/nginx/sites-enabled/*.conf;
Создать и открыть файл конфигурации виртуального хоста для Cockpit:
sudo nano /etc/nginx/sites-available/cockpit.conf
Содержимое файла (предварительная версия для получения сертификата):
server {
listen 80;
listen [::]:80;
server_name cockpit.mydomain.ru;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
Активируем конфиг:
cd /etc/nginx/sites-enabled/
sudo ln -s ../sites-available/cockpit.conf
Создать каталог для проверки прав:
sudo mkdir -p /var/www/certbot
Проверяем, что всё правильно:
sudo nginx -t
Должно ответить:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Если проверка nginx успешна, запустить или перезагрузить Nginx:
sudo systemctl enable --now nginx
или
sudo systemctl reload nginx
Установка Certbot и выпуск сертификата
Установить Certbot и плагин для Nginx:
sudo dnf install certbot python3-certbot-nginx
Выпустить сертификат:
sudo certbot --nginx -d cockpit.mydomain.ru
После успешного выпуска Certbot автоматически дополнит конфиг nginx настройками SSL. Теперь нужно переделать конфиг: убрать проксирование и оставить только редирект на порт 9090.
Отредактируйте файл /etc/nginx/sites-available/cockpit.conf, приведя его к такому виду:
server {
server_name cockpit.mydomain.ru;
listen 80;
listen [::]:80;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Все остальные HTTP-запросы редиректим на HTTPS с портом 9090
location / {
return 301 https://$server_name:9090$request_uri;
}
}
server {
server_name cockpit.mydomain.ru;
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/cockpit.mydomain.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cockpit.mydomain.ru/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Редирект HTTPS → HTTPS с портом 9090
location / {
return 301 https://$server_name:9090$request_uri;
}
}
Проверяем и перезагружаем nginx:
sudo nginx -t
sudo systemctl reload nginx
Что мы получили: nginx теперь отвечает на запросы Certbot и перенаправляет всех посетителей на адрес https://cockpit.mydomain.ru:9090. Сам Cockpit будет работать напрямую, без прокси.
Настройка Cockpit для работы с сертификатом Let's Encrypt
Cockpit по умолчанию генерирует самоподписанный сертификат. Наша задача — подменить его на сертификат от Let's Encrypt.
Удаляем всё лишнее и создаём правильные симлинки:
sudo rm -f /etc/cockpit/ws-certs.d/*
sudo ln -sf /etc/letsencrypt/live/cockpit.mydomain.ru/fullchain.pem /etc/cockpit/ws-certs.d/1-cert.cert
sudo ln -sf /etc/letsencrypt/live/cockpit.mydomain.ru/privkey.pem /etc/cockpit/ws-certs.d/1-cert.key
Важно: имена файлов должны оканчиваться на .cert и .key, и их базовые имена должны совпадать (в данном случае "1-cert"), иначе Cockpit не увидит сертификат.
Перезапускаем Cockpit:
sudo systemctl restart cockpit
Проверяем, что сертификат подхватился:
sudo journalctl -u cockpit -n 20 | grep -i cert
Если ошибок нет — всё хорошо.
Настройка Firewalld
Открываем порты для доступа к серверу:
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-port=9090/tcp --permanent
sudo firewall-cmd --reload
Проверяем, что порт 9090 открыт:
sudo firewall-cmd --list-all | grep 9090
Настройка SELinux (если включён)
Чтобы nginx мог читать сертификаты Let's Encrypt:
sudo semanage fcontext -a -t httpd_config_t "/etc/letsencrypt/archive(/.*)?"
sudo semanage fcontext -a -t httpd_config_t "/etc/letsencrypt/live(/.*)?"
sudo restorecon -Rv /etc/letsencrypt/archive /etc/letsencrypt/live
Если SELinux выключен — этот шаг можно пропустить.
Автоматическое обновление сертификата
С 90-дневным сроком жизни сертификата автоматизация обязательна. Certbot при установке создаёт systemd-таймер, но мы добавим задание в crontab для уверенности.
Открываем crontab для root:
sudo crontab -e
Добавляем строку (проверка каждый день в 3:00):
0 3 * * * /usr/bin/certbot renew --quiet --nginx
Важное дополнение для корректного подхвата нового сертификата Cockpit:
Создаём хук, который перезапустит Cockpit только когда обновился именно его сертификат:
sudo nano /etc/letsencrypt/renewal-hooks/deploy/restart-cockpit.sh
Вставляем содержимое:
#!/bin/bash
if [[ "$RENEWED_DOMAINS" == *"cockpit.mydomain.ru"* ]]; then
systemctl restart cockpit
fi
Делаем скрипт исполняемым:
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/restart-cockpit.sh
Проверяем тестовое обновление (сухой запуск):
sudo certbot renew --dry-run
Если команда завершается без ошибок — автообновление настроено корректно.
Проверяем активность таймеров Certbot (опционально):
systemctl list-timers | grep certbot
Финальная проверка
Перезагружаем nginx и Cockpit:
sudo systemctl restart nginx
sudo systemctl restart cockpit
Открываем в браузере:
- https://cockpit.mydomain.ru — должно перенаправить на https://cockpit.mydomain.ru:9090
- https://cockpit.mydomain.ru:9090 — должна открыться страница входа с валидным сертификатом (зелёный замок)
Проверяем ключевые разделы:
- Вход в систему — работает
- Раздел «Сервисы» (Services) — открывается, страница не перезагружается бесконечно, управление сервисами (запуск/остановка) работает
- Раздел «Журнал» (Journal) — работает
- Терминал — работает
Если что-то идёт не так — смотрим логи:
sudo journalctl -u cockpit -f
sudo tail -f /var/log/nginx/error.log
Защита Cockpit от перебора паролей (Fail2ban)
Установить Fail2ban:
sudo dnf install epel-release
sudo dnf install fail2ban fail2ban-firewalld
sudo systemctl enable --now fail2ban
Для внесения своих настроек создать файл jail.local, который переопределит стандартные значения:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Открываем файл jail.local и в разделе [DEFAULT] настраиваем ключевые параметры. Обязательно указываем в ignoreip свой доверенный статический IP-адрес (узнать на сайтах myip), чтобы случайно не заблокировать себя:
[DEFAULT]
ignoreip = 127.0.0.1 192.168.1.100 # Укажите свой IP
bantime = 86400 # Время бана в секундах (24 часа)
findtime = 1800 # Окно анализа (30 минут)
maxretry = 5 # Количество неудачных попыток
Не забываем перезапустить Fail2ban:
sudo systemctl restart fail2ban
Создаём фильтр для Cockpit. Поскольку наш Cockpit работает на прямом порту 9090, логи нужно собирать из логов Cockpit, а не nginx. Создаём новый файл фильтра:
sudo nano /etc/fail2ban/filter.d/cockpit-auth.conf
Вставляем содержимое:
[Definition]
failregex = ^.*pam_unix\(cockpit:auth\): authentication failure;.* rhost=::ffff:<HOST> .*$
ignoreregex =
journalmatch = _TRANSPORT=syslog
Настраиваем "тюрьму" (jail) для Cockpit. Создаём файл конфигурации в директории jail.d:
sudo nano /etc/fail2ban/jail.d/cockpit-auth.local
Добавляем конфигурацию:
[cockpit-auth]
enabled = true
filter = cockpit-auth
port = 9090
maxretry = 5
findtime = 1800
bantime = 86400
action = firewallcmd-ipset
backend = systemd
Перезагружаем Fail2ban для применения новых правил:
sudo systemctl restart fail2ban
Убеждаемся, что настройки работают корректно. Проверяем статус "тюрьмы":
sudo fail2ban-client status cockpit-auth
Типичные проблемы и их решение
1. Страница сервисов бесконечно перезагружается
Причина: попытка проксирования Cockpit через nginx (proxy_pass).
Решение: перейти на прямую схему с портом 9090, как описано в этой статье. Не проксируйте Cockpit через nginx!
2. Cockpit не видит сертификат Let's Encrypt
Причина: неправильные имена файлов в /etc/cockpit/ws-certs.d/.
Решение: использовать пару 1-cert.cert и 1-cert.key (имена должны совпадать, отличаться только расширением).
3. После обновления сертификата Cockpit продолжает показывать старый
Причина: не обновляются симлинки или не перезагружен Cockpit.
Решение: убедиться, что симлинки ведут на актуальные файлы в /etc/letsencrypt/live/, и настроить хук в renewal-hooks для перезапуска.
4. Браузер ругается на самоподписанный сертификат
Причина: Cockpit использует свой встроенный сертификат, а не Let's Encrypt.
Решение: правильно создать симлинки и перезапустить Cockpit.
5. Не открывается страница (отказ в соединении)
Причина: порт 9090 закрыт в firewalld.
Решение: sudo firewall-cmd --add-port=9090/tcp --permanent && sudo firewall-cmd --reload
Заключение
Мы настроили Cockpit с валидным сертификатом Let's Encrypt, доступным по адресу https://cockpit.mydomain.ru:9090. Автообновление сертификата работает через cron и хуки. Страница управления сервисами функционирует корректно, потому что мы избежали проксирования.
Это решение проверено в реальной эксплуатации и не требует сложных танцев с бубном. Если у вас возникнут вопросы или дополнения — пишите в комментариях, я обязательно отвечу и постараюсь улучшить статью.
Важно! Если я что-то упустил, сообщите в комментариях — я обязательно исправлюсь и дополню статью. Вместе сделаем идеально!

Комментарии
Отправить комментарий