Добавлены новые документы и скрипты для автоматизации создания и управления SSL сертификатами Let's Encrypt с использованием API reg.ru и Nginx Proxy Manager. Обновлены инструкции по тестированию, настройке и использованию сертификатов, включая создание тестовых сертификатов и интеграцию с NPM. Включены примеры использования и устранения неполадок, а также улучшена структура проекта.

This commit is contained in:
Dmitriy Fofanov
2025-10-27 21:47:55 +03:00
parent 07a65ffbba
commit 95dde0c073
14 changed files with 3117 additions and 18 deletions

153
CHANGELOG.md Normal file
View File

@@ -0,0 +1,153 @@
# 📋 Журнал изменений (Changelog)
## [2.1.0] - 2025-10-27
### 🆕 Добавлено
#### Генерация тестовых SSL сертификатов
-**Новый класс `TestCertificateGenerator`** - генерация самоподписанных сертификатов
-**Команда `--test-cert`** в Python скрипте для создания тестовых сертификатов
-**Скрипт `test_certificate.sh`** - автономное создание через OpenSSL
-**Команда `make test-cert`** в Makefile для быстрого тестирования
#### Документация
- 📘 **TESTING_GUIDE.md** (370+ строк) - полное руководство по тестированию
- Обход лимитов Let's Encrypt (5 сертификатов в неделю)
- Сравнение методов создания сертификатов
- Примеры для CI/CD и Docker
- Переход с тестовых на production
- Частые вопросы и решения
- 📘 **PROJECT_STRUCTURE.md** - структура проекта
- Описание всех файлов
- Список возможностей
- Технологии
- 📘 **CHEATSHEET.md** - быстрая шпаргалка
- Основные команды
- Сценарии использования
- Частые ошибки и решения
- Workflow разработки
#### Функциональность
- ✨ Поддержка **неограниченного количества** тестовых сертификатов
-**Мгновенное создание** (1-2 секунды) без DNS валидации
-**Автоматическая загрузка** тестовых сертификатов в NPM
-**Полная совместимость** структуры с Let's Encrypt
-**Wildcard поддержка** для тестовых сертификатов
### 🔧 Улучшено
#### Python скрипт
- Добавлен импорт библиотеки `cryptography` с проверкой установки
- Новые параметры командной строки:
- `--test-cert` - создание тестового сертификата
- `--auto` - явное указание автоматического режима
- Улучшенная обработка тестовых сертификатов в NPM
- Детальное логирование процесса генерации
#### Makefile
- Добавлена команда `make test-cert` с красивым выводом
- Информационные сообщения о преимуществах тестовых сертификатов
- Предупреждения о безопасности
#### README.md
- Раздел "Создание тестового самоподписанного сертификата"
- Обновленное содержание с ссылкой на тестовые сертификаты
- Примеры использования тестовых сертификатов
- Интеграция с NPM для тестовых сертификатов
- Ссылки на дополнительную документацию
### 🎯 Преимущества
#### Для разработчиков
-**Нет лимитов** - неограниченное количество сертификатов
-**Быстро** - создание за 1-2 секунды
-**Офлайн** - работает без интернета
-**Идентичная структура** - те же файлы что и Let's Encrypt
#### Для тестирования
-**CI/CD friendly** - быстрое создание в pipeline
-**Docker ready** - легко встраивается в контейнеры
-**Staging окружения** - идеально для тестовых серверов
-**Локальная разработка** - HTTPS на localhost
### 📊 Статистика
- **Строк кода**: 1,411 (Python скрипт)
- **Строк в Makefile**: 415
- **Строк документации**: 2,200+
- **Команд в Makefile**: 13
- **Режимов работы**: 4 (obtain, renew, auto, test-cert)
---
## [2.0.0] - 2025-10-27
### 🆕 Добавлено
- ✨ Интеграция с Nginx Proxy Manager (NPM)
- ✨ Класс `NginxProxyManagerAPI` для управления сертификатами через API
- ✨ Автоматическая загрузка сертификатов в NPM
- ✨ Автоматическое обновление сертификатов в NPM
- ✨ Автоматическая проверка срока действия
- ✨ Настраиваемый порог обновления (`renewal_days`)
- ✨ Makefile для автоматизации установки/удаления
- ✨ Systemd service + timer
- ✨ Cron автоматизация
### 🔧 Улучшено
- Консолидация документации в единый README.md
- Подробное логирование с статусами операций
- Валидация конфигурации
- Улучшенная обработка ошибок
### 📘 Документация
- Полное руководство по NPM интеграции
- Быстрый старт за 3 команды
- Примеры автоматизации
---
## [1.0.0] - 2025-10-26
### 🆕 Первый релиз
- Python скрипт для Let's Encrypt через reg.ru API
- Bash скрипт с certbot-dns-regru
- PowerShell версия для Windows
- DNS-01 валидация
- Wildcard сертификаты
- Базовая документация
---
## Roadmap (Планы)
### [2.2.0] - Планируется
- [ ] Веб-интерфейс для управления
- [ ] Поддержка множественных доменов
- [ ] Notifications (email, telegram)
- [ ] Grafana dashboard для мониторинга
- [ ] Backup сертификатов
### [3.0.0] - Будущее
- [ ] Поддержка других DNS провайдеров
- [ ] Cloudflare API
- [ ] Route53 (AWS)
- [ ] Google Cloud DNS
---
## Типы изменений
- `🆕 Добавлено` - новый функционал
- `🔧 Улучшено` - улучшения существующего функционала
- `🐛 Исправлено` - исправление багов
- `🗑️ Удалено` - удаленный функционал
- `🔒 Безопасность` - изменения безопасности
- `📘 Документация` - изменения в документации
---
**Версионирование**: Semantic Versioning (MAJOR.MINOR.PATCH)
- **MAJOR**: Несовместимые изменения API
- **MINOR**: Новый функционал с обратной совместимостью
- **PATCH**: Исправления багов

263
CHEATSHEET.md Normal file
View File

@@ -0,0 +1,263 @@
# ⚡ Шпаргалка по SSL сертификатам
## 🚀 Быстрый старт
### Установка за 3 команды
```bash
sudo make install
sudo nano /etc/letsencrypt/regru_config.json # Заполнить данные
sudo make test-cert # Тест
```
---
## 🧪 Тестирование (БЕЗ лимитов Let's Encrypt)
```bash
# Создать тестовый сертификат (неограниченно)
sudo make test-cert
# Проверить статус
sudo make status
# Просмотреть логи
sudo make logs
```
**Когда использовать:**
- ⚠️ Let's Encrypt: макс. 5 сертификатов/неделю
- ✅ Тестовые: НЕОГРАНИЧЕННО
- ⚡ Создание: 1-2 секунды vs 2-5 минут
---
## 🔒 Production (Let's Encrypt)
```bash
# Получить настоящий сертификат
sudo make obtain
# Автоматический режим (проверка + обновление)
sudo make run
# Принудительное обновление
sudo make renew
```
---
## 📋 Основные команды
| Команда | Описание | Лимиты |
|---------|----------|--------|
| `make test-cert` | Тестовый сертификат | ✅ Нет |
| `make obtain` | Let's Encrypt новый | ⚠️ 5/неделю |
| `make renew` | Обновить существующий | ⚠️ 5/неделю |
| `make run` | Авто-режим | ⚠️ 5/неделю |
| `make status` | Статус системы | - |
| `make logs` | Показать логи | - |
| `make check-config` | Проверить конфигурацию | - |
---
## 📝 Конфигурация
### Минимальная (тестирование)
```json
{
"domain": "test.example.com",
"wildcard": true,
"cert_dir": "/etc/letsencrypt/live"
}
```
### Полная (production + NPM)
```json
{
"regru_username": "myuser",
"regru_password": "mypassword",
"domain": "example.com",
"wildcard": true,
"email": "admin@example.com",
"renewal_days": 30,
"npm_enabled": true,
"npm_host": "https://npm.example.com",
"npm_email": "admin@example.com",
"npm_password": "npm_password"
}
```
---
## 🔄 Workflow
### Разработка → Production
```bash
# 1. Разработка (тестовые сертификаты)
sudo make test-cert # Создать тестовый
# Тестировать приложение...
# 2. Production (Let's Encrypt)
sudo rm -rf /etc/letsencrypt/live/example.com/ # Удалить тест
sudo make obtain # Создать production
```
---
## 📁 Важные пути
```bash
# Конфигурация
/etc/letsencrypt/regru_config.json
# Сертификаты
/etc/letsencrypt/live/example.com/
├── privkey.pem # Приватный ключ
├── cert.pem # Сертификат
├── fullchain.pem # Полная цепочка (для nginx)
└── chain.pem # CA цепочка
# Скрипты
/opt/letsencrypt-regru/letsencrypt_regru_api.py
# Логи
/var/log/letsencrypt_regru.log
```
---
## 🔍 Проверка
```bash
# Проверить конфигурацию
sudo make check-config
# Проверить сертификат
openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -text -noout
# Проверить срок действия
openssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -noout -dates
# Проверить systemd
sudo systemctl status letsencrypt-regru.timer
sudo systemctl list-timers letsencrypt-regru.timer
# Проверить cron
sudo crontab -l | grep letsencrypt
```
---
## 🐛 Отладка
```bash
# Подробные логи
sudo make logs
# Тестовый запуск с подробностями
sudo python3 /opt/letsencrypt-regru/letsencrypt_regru_api.py \
-c /etc/letsencrypt/regru_config.json --check -v
# Логи certbot
sudo tail -f /var/log/letsencrypt/letsencrypt.log
# Логи systemd
sudo journalctl -u letsencrypt-regru.service -f
```
---
## ⚠️ Частые ошибки
### Let's Encrypt: Rate limit exceeded
```bash
# РЕШЕНИЕ: Используйте тестовые сертификаты
sudo make test-cert
```
### NPM: Certificate not found
```bash
# РЕШЕНИЕ: Проверьте настройки NPM
sudo make check-config
# Проверьте подключение
curl -k https://npm.example.com
```
### Permission denied
```bash
# РЕШЕНИЕ: Запускайте с sudo
sudo make test-cert
```
---
## 🎯 Сценарии использования
### Локальная разработка
```bash
sudo make test-cert
# Открыть https://localhost (игнорировать предупреждение)
```
### CI/CD тестирование
```bash
# В pipeline
sudo make test-cert
# Запустить тесты...
sudo make status
```
### Staging окружение
```bash
sudo make test-cert # Или
sudo make obtain # Если есть домен
```
### Production окружение
```bash
sudo make install
sudo make obtain
# Автоматическое обновление через cron/systemd
```
---
## 📚 Документация
- **README.md** - Полное руководство (1420+ строк)
- **TESTING_GUIDE.md** - Тестирование (370+ строк)
- **PROJECT_STRUCTURE.md** - Структура проекта
- **CHEATSHEET.md** - Эта шпаргалка
---
## 🆘 Быстрая помощь
```bash
# Показать все команды
make help
# Проверить установку
sudo make status
# Полная переустановка
sudo make uninstall
sudo make install
```
---
## 💡 Советы
1. **Всегда начинайте с тестовых сертификатов** - избегайте лимитов
2. **Проверяйте конфигурацию** - `make check-config`
3. **Мониторьте логи** - `make logs`
4. **Автоматизируйте** - systemd/cron уже настроены
5. **Храните бэкапы** конфигурации
---
**Версия**: 2.1
**Обновлено**: 27.10.2025

410
Makefile Normal file
View File

@@ -0,0 +1,410 @@
# ==============================================================================
# Makefile для установки и удаления скрипта управления SSL сертификатами
# Let's Encrypt с DNS-валидацией через API reg.ru
# ==============================================================================
# Переменные
INSTALL_DIR = /opt/letsencrypt-regru
SCRIPT_NAME = letsencrypt_regru_api.py
CONFIG_EXAMPLE = config.json.example
SERVICE_NAME = letsencrypt-regru
SERVICE_FILE = $(SERVICE_NAME).service
TIMER_FILE = $(SERVICE_NAME).timer
CONFIG_DIR = /etc/letsencrypt
CONFIG_FILE = $(CONFIG_DIR)/regru_config.json
LOG_DIR = /var/log
LOG_FILE = $(LOG_DIR)/letsencrypt_regru.log
CRON_LOG = $(LOG_DIR)/letsencrypt_cron.log
SYSTEMD_DIR = /etc/systemd/system
PYTHON = python3
# Цвета для вывода
RED = \033[0;31m
GREEN = \033[0;32m
YELLOW = \033[1;33m
BLUE = \033[0;34m
NC = \033[0m # No Color
.PHONY: help install uninstall status check-root setup-dirs install-script install-service install-cron clean
# ==============================================================================
# Помощь
# ==============================================================================
help:
@echo "$(BLUE)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(BLUE)║ Makefile для управления Let's Encrypt SSL сертификатами ║$(NC)"
@echo "$(BLUE)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@echo "$(GREEN)Доступные команды:$(NC)"
@echo ""
@echo " $(YELLOW)make install$(NC) - Установить скрипт и настроить автоматизацию"
@echo " $(YELLOW)make uninstall$(NC) - Удалить скрипт и очистить систему"
@echo " $(YELLOW)make status$(NC) - Проверить статус установки"
@echo " $(YELLOW)make check-config$(NC) - Проверить конфигурацию"
@echo " $(YELLOW)make test-run$(NC) - Тестовый запуск скрипта"
@echo " $(YELLOW)make test-cert$(NC) - Создать тестовый самоподписанный сертификат"
@echo " $(YELLOW)make logs$(NC) - Показать логи"
@echo " $(YELLOW)make help$(NC) - Показать эту справку"
@echo ""
# ==============================================================================
# Проверка прав root
# ==============================================================================
check-root:
@if [ "$$(id -u)" != "0" ]; then \
echo "$(RED)✗ Ошибка: Требуются права root$(NC)"; \
echo "$(YELLOW)Запустите: sudo make install$(NC)"; \
exit 1; \
fi
# ==============================================================================
# Установка
# ==============================================================================
install: check-root
@echo "$(BLUE)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(BLUE)║ Установка Let's Encrypt SSL Manager ║$(NC)"
@echo "$(BLUE)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@$(MAKE) setup-dirs
@$(MAKE) install-dependencies
@$(MAKE) install-script
@$(MAKE) install-service
@$(MAKE) install-cron
@echo ""
@echo "$(GREEN)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(GREEN)║ ✓ Установка завершена успешно! ║$(NC)"
@echo "$(GREEN)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@echo "$(YELLOW)Следующие шаги:$(NC)"
@echo " 1. Отредактируйте конфигурацию:"
@echo " $(BLUE)sudo nano $(CONFIG_FILE)$(NC)"
@echo ""
@echo " 2. Проверьте конфигурацию:"
@echo " $(BLUE)make check-config$(NC)"
@echo ""
@echo " 3. Запустите тестовую проверку:"
@echo " $(BLUE)make test-run$(NC)"
@echo ""
@echo " 4. Проверьте статус службы:"
@echo " $(BLUE)make status$(NC)"
@echo ""
# Создание директорий
setup-dirs:
@echo "$(YELLOW)→ Создание директорий...$(NC)"
@mkdir -p $(INSTALL_DIR)
@mkdir -p $(CONFIG_DIR)
@mkdir -p $(LOG_DIR)
@echo "$(GREEN)✓ Директории созданы$(NC)"
# Установка зависимостей
install-dependencies:
@echo "$(YELLOW)→ Установка зависимостей Python...$(NC)"
@if ! command -v pip3 >/dev/null 2>&1; then \
echo "$(RED)✗ pip3 не найден. Установите python3-pip$(NC)"; \
exit 1; \
fi
@pip3 install -q requests cryptography 2>/dev/null || pip3 install requests cryptography
@echo "$(GREEN)✓ Зависимости установлены$(NC)"
# Копирование скрипта
install-script:
@echo "$(YELLOW)→ Установка скрипта...$(NC)"
@if [ ! -f "$(SCRIPT_NAME)" ]; then \
echo "$(RED)✗ Файл $(SCRIPT_NAME) не найден!$(NC)"; \
exit 1; \
fi
@cp $(SCRIPT_NAME) $(INSTALL_DIR)/
@chmod +x $(INSTALL_DIR)/$(SCRIPT_NAME)
@echo "$(GREEN)✓ Скрипт установлен в $(INSTALL_DIR)/$(NC)"
@echo ""
@echo "$(YELLOW)→ Создание конфигурации...$(NC)"
@if [ ! -f "$(CONFIG_FILE)" ]; then \
if [ -f "$(CONFIG_EXAMPLE)" ]; then \
cp $(CONFIG_EXAMPLE) $(CONFIG_FILE); \
chmod 600 $(CONFIG_FILE); \
echo "$(GREEN)✓ Создан файл конфигурации: $(CONFIG_FILE)$(NC)"; \
echo "$(YELLOW)⚠ ВНИМАНИЕ: Отредактируйте конфигурацию перед использованием!$(NC)"; \
else \
echo "$(YELLOW)⚠ Файл config.json.example не найден$(NC)"; \
$(PYTHON) $(INSTALL_DIR)/$(SCRIPT_NAME) --create-config $(CONFIG_FILE); \
chmod 600 $(CONFIG_FILE); \
echo "$(GREEN)✓ Создана конфигурация по умолчанию$(NC)"; \
fi \
else \
echo "$(GREEN)✓ Конфигурация уже существует: $(CONFIG_FILE)$(NC)"; \
fi
# Установка systemd service и timer
install-service:
@echo "$(YELLOW)→ Создание systemd service...$(NC)"
@echo "[Unit]" > $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "Description=Let's Encrypt Certificate Manager with reg.ru DNS" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "After=network.target" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "[Service]" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "Type=oneshot" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "ExecStart=$(PYTHON) $(INSTALL_DIR)/$(SCRIPT_NAME) -c $(CONFIG_FILE)" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "StandardOutput=journal" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "StandardError=journal" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "User=root" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "[Install]" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "WantedBy=multi-user.target" >> $(SYSTEMD_DIR)/$(SERVICE_FILE)
@echo "$(GREEN)✓ Service файл создан$(NC)"
@echo ""
@echo "$(YELLOW)→ Создание systemd timer...$(NC)"
@echo "[Unit]" > $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "Description=Daily Let's Encrypt Certificate Check and Renewal" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "Requires=$(SERVICE_FILE)" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "[Timer]" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "OnCalendar=daily" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "Persistent=true" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "RandomizedDelaySec=1h" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "[Install]" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "WantedBy=timers.target" >> $(SYSTEMD_DIR)/$(TIMER_FILE)
@echo "$(GREEN)✓ Timer файл создан$(NC)"
@echo ""
@echo "$(YELLOW)→ Активация systemd службы...$(NC)"
@systemctl daemon-reload
@systemctl enable $(SERVICE_FILE) 2>/dev/null || true
@systemctl enable $(TIMER_FILE) 2>/dev/null || true
@systemctl start $(TIMER_FILE) 2>/dev/null || true
@echo "$(GREEN)✓ Systemd служба активирована$(NC)"
# Установка cron задачи
install-cron:
@echo "$(YELLOW)→ Настройка cron задачи...$(NC)"
@CRON_CMD="0 3 * * * $(PYTHON) $(INSTALL_DIR)/$(SCRIPT_NAME) -c $(CONFIG_FILE) >> $(CRON_LOG) 2>&1"; \
(crontab -l 2>/dev/null | grep -v "$(SCRIPT_NAME)" ; echo "$$CRON_CMD") | crontab -
@echo "$(GREEN)✓ Cron задача добавлена (ежедневно в 3:00 AM)$(NC)"
# ==============================================================================
# Удаление
# ==============================================================================
uninstall: check-root
@echo "$(RED)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(RED)║ Удаление Let's Encrypt SSL Manager ║$(NC)"
@echo "$(RED)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@read -p "Вы уверены? Это удалит все файлы и настройки [y/N]: " -n 1 -r; \
echo ""; \
if [[ $$REPLY =~ ^[Yy]$$ ]]; then \
$(MAKE) remove-service; \
$(MAKE) remove-cron; \
$(MAKE) remove-files; \
echo ""; \
echo "$(GREEN)✓ Удаление завершено$(NC)"; \
else \
echo "$(YELLOW)Удаление отменено$(NC)"; \
fi
# Удаление systemd service
remove-service:
@echo "$(YELLOW)→ Остановка и удаление systemd служб...$(NC)"
@systemctl stop $(TIMER_FILE) 2>/dev/null || true
@systemctl stop $(SERVICE_FILE) 2>/dev/null || true
@systemctl disable $(TIMER_FILE) 2>/dev/null || true
@systemctl disable $(SERVICE_FILE) 2>/dev/null || true
@rm -f $(SYSTEMD_DIR)/$(SERVICE_FILE)
@rm -f $(SYSTEMD_DIR)/$(TIMER_FILE)
@systemctl daemon-reload
@echo "$(GREEN)✓ Systemd службы удалены$(NC)"
# Удаление cron задачи
remove-cron:
@echo "$(YELLOW)→ Удаление cron задачи...$(NC)"
@crontab -l 2>/dev/null | grep -v "$(SCRIPT_NAME)" | crontab - 2>/dev/null || true
@echo "$(GREEN)✓ Cron задача удалена$(NC)"
# Удаление файлов
remove-files:
@echo "$(YELLOW)→ Удаление файлов...$(NC)"
@rm -rf $(INSTALL_DIR)
@echo "$(GREEN)✓ Директория $(INSTALL_DIR) удалена$(NC)"
@echo ""
@read -p "Удалить конфигурацию $(CONFIG_FILE)? [y/N]: " -n 1 -r; \
echo ""; \
if [[ $$REPLY =~ ^[Yy]$$ ]]; then \
rm -f $(CONFIG_FILE); \
echo "$(GREEN)✓ Конфигурация удалена$(NC)"; \
else \
echo "$(YELLOW)Конфигурация сохранена$(NC)"; \
fi
@echo ""
@read -p "Удалить логи? [y/N]: " -n 1 -r; \
echo ""; \
if [[ $$REPLY =~ ^[Yy]$$ ]]; then \
rm -f $(LOG_FILE) $(CRON_LOG); \
echo "$(GREEN)✓ Логи удалены$(NC)"; \
else \
echo "$(YELLOW)Логи сохранены$(NC)"; \
fi
# ==============================================================================
# Утилиты
# ==============================================================================
# Проверка статуса
status:
@echo "$(BLUE)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(BLUE)║ Статус Let's Encrypt SSL Manager ║$(NC)"
@echo "$(BLUE)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@echo "$(YELLOW)→ Установка:$(NC)"
@if [ -d "$(INSTALL_DIR)" ]; then \
echo " $(GREEN)✓ Директория: $(INSTALL_DIR)$(NC)"; \
else \
echo " $(RED)✗ Директория не найдена$(NC)"; \
fi
@if [ -f "$(INSTALL_DIR)/$(SCRIPT_NAME)" ]; then \
echo " $(GREEN)✓ Скрипт установлен$(NC)"; \
else \
echo " $(RED)✗ Скрипт не найден$(NC)"; \
fi
@if [ -f "$(CONFIG_FILE)" ]; then \
echo " $(GREEN)✓ Конфигурация: $(CONFIG_FILE)$(NC)"; \
else \
echo " $(YELLOW)⚠ Конфигурация не найдена$(NC)"; \
fi
@echo ""
@echo "$(YELLOW)→ Systemd служба:$(NC)"
@systemctl is-enabled $(SERVICE_FILE) 2>/dev/null && echo " $(GREEN)✓ Service включен$(NC)" || echo " $(RED)✗ Service отключен$(NC)"
@systemctl is-active $(SERVICE_FILE) 2>/dev/null && echo " $(GREEN)✓ Service активен$(NC)" || echo " $(YELLOW)⚠ Service неактивен (oneshot)$(NC)"
@echo ""
@echo "$(YELLOW)→ Systemd timer:$(NC)"
@systemctl is-enabled $(TIMER_FILE) 2>/dev/null && echo " $(GREEN)✓ Timer включен$(NC)" || echo " $(RED)✗ Timer отключен$(NC)"
@systemctl is-active $(TIMER_FILE) 2>/dev/null && echo " $(GREEN)✓ Timer активен$(NC)" || echo " $(RED)✗ Timer неактивен$(NC)"
@echo ""
@echo "$(YELLOW)→ Следующий запуск:$(NC)"
@systemctl list-timers $(TIMER_FILE) --no-pager 2>/dev/null || echo " $(RED)✗ Timer не найден$(NC)"
@echo ""
@echo "$(YELLOW)→ Cron задача:$(NC)"
@if crontab -l 2>/dev/null | grep -q "$(SCRIPT_NAME)"; then \
echo " $(GREEN)✓ Cron задача настроена$(NC)"; \
crontab -l 2>/dev/null | grep "$(SCRIPT_NAME)"; \
else \
echo " $(RED)✗ Cron задача не найдена$(NC)"; \
fi
# Проверка конфигурации
check-config:
@echo "$(BLUE)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(BLUE)║ Проверка конфигурации ║$(NC)"
@echo "$(BLUE)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@if [ ! -f "$(CONFIG_FILE)" ]; then \
echo "$(RED)✗ Конфигурация не найдена: $(CONFIG_FILE)$(NC)"; \
exit 1; \
fi
@echo "$(GREEN)✓ Конфигурация найдена$(NC)"
@echo ""
@$(PYTHON) -c "import json; print(json.dumps(json.load(open('$(CONFIG_FILE)')), indent=2, ensure_ascii=False))" 2>/dev/null || \
(echo "$(RED)✗ Ошибка: Неверный формат JSON$(NC)"; exit 1)
@echo ""
@echo "$(YELLOW)→ Проверка обязательных параметров:$(NC)"
@$(PYTHON) -c "import json; c=json.load(open('$(CONFIG_FILE)')); assert c.get('regru_username'), 'regru_username не задан'" && echo " $(GREEN)✓ regru_username$(NC)" || echo " $(RED)✗ regru_username$(NC)"
@$(PYTHON) -c "import json; c=json.load(open('$(CONFIG_FILE)')); assert c.get('regru_password'), 'regru_password не задан'" && echo " $(GREEN)✓ regru_password$(NC)" || echo " $(RED)✗ regru_password$(NC)"
@$(PYTHON) -c "import json; c=json.load(open('$(CONFIG_FILE)')); assert c.get('domain'), 'domain не задан'" && echo " $(GREEN)✓ domain$(NC)" || echo " $(RED)✗ domain$(NC)"
@$(PYTHON) -c "import json; c=json.load(open('$(CONFIG_FILE)')); assert c.get('email'), 'email не задан'" && echo " $(GREEN)✓ email$(NC)" || echo " $(RED)✗ email$(NC)"
# Тестовый запуск
test-run: check-root
@echo "$(BLUE)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(BLUE)║ Тестовый запуск скрипта ║$(NC)"
@echo "$(BLUE)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@if [ ! -f "$(CONFIG_FILE)" ]; then \
echo "$(RED)✗ Конфигурация не найдена. Запустите: make install$(NC)"; \
exit 1; \
fi
@echo "$(YELLOW)→ Запуск проверки сертификата...$(NC)"
@echo ""
@$(PYTHON) $(INSTALL_DIR)/$(SCRIPT_NAME) -c $(CONFIG_FILE) --check -v
# Просмотр логов
logs:
@echo "$(BLUE)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(BLUE)║ Логи Let's Encrypt SSL Manager ║$(NC)"
@echo "$(BLUE)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@echo "$(YELLOW)→ Основной лог скрипта:$(NC)"
@if [ -f "$(LOG_FILE)" ]; then \
tail -n 50 $(LOG_FILE); \
else \
echo "$(YELLOW)Лог файл не найден$(NC)"; \
fi
@echo ""
@echo "$(YELLOW)→ Лог cron задачи:$(NC)"
@if [ -f "$(CRON_LOG)" ]; then \
tail -n 50 $(CRON_LOG); \
else \
echo "$(YELLOW)Лог cron не найден$(NC)"; \
fi
@echo ""
@echo "$(YELLOW)→ Логи systemd:$(NC)"
@journalctl -u $(SERVICE_FILE) -n 50 --no-pager 2>/dev/null || echo "$(YELLOW)Логи systemd не найдены$(NC)"
# Ручной запуск обновления
run: check-root
@echo "$(YELLOW)→ Запуск обновления сертификата...$(NC)"
@$(PYTHON) $(INSTALL_DIR)/$(SCRIPT_NAME) -c $(CONFIG_FILE) -v
# Принудительное получение сертификата
obtain: check-root
@echo "$(YELLOW)→ Принудительное получение нового сертификата...$(NC)"
@$(PYTHON) $(INSTALL_DIR)/$(SCRIPT_NAME) -c $(CONFIG_FILE) --obtain -v
# Принудительное обновление сертификата
renew: check-root
@echo "$(YELLOW)→ Принудительное обновление сертификата...$(NC)"
@$(PYTHON) $(INSTALL_DIR)/$(SCRIPT_NAME) -c $(CONFIG_FILE) --renew -v
# Создание тестового самоподписанного сертификата
test-cert: check-root
@echo "$(BLUE)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(BLUE)║ Создание тестового самоподписанного сертификата ║$(NC)"
@echo "$(BLUE)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@echo "$(YELLOW)⚠️ ВНИМАНИЕ: Это тестовый сертификат для разработки!$(NC)"
@echo "$(YELLOW) Браузеры будут показывать предупреждение безопасности.$(NC)"
@echo "$(YELLOW) Для production используйте Let's Encrypt сертификаты.$(NC)"
@echo ""
@if [ ! -f "$(CONFIG_FILE)" ]; then \
echo "$(RED)✗ Конфигурация не найдена. Запустите: make install$(NC)"; \
exit 1; \
fi
@echo "$(YELLOW)→ Генерация самоподписанного сертификата...$(NC)"
@echo ""
@$(PYTHON) $(INSTALL_DIR)/$(SCRIPT_NAME) -c $(CONFIG_FILE) --test-cert -v
@echo ""
@echo "$(GREEN)╔════════════════════════════════════════════════════════════════╗$(NC)"
@echo "$(GREEN)║ ✓ Тестовый сертификат создан ║$(NC)"
@echo "$(GREEN)╚════════════════════════════════════════════════════════════════╝$(NC)"
@echo ""
@echo "$(YELLOW)Преимущества тестового сертификата:$(NC)"
@echo " • Нет ограничений Let's Encrypt (5 сертификатов в неделю)"
@echo " • Мгновенное создание без DNS-валидации"
@echo " • Идеально для тестирования интеграции с NPM"
@echo " • Можно создавать неограниченное количество раз"
@echo ""
@echo "$(YELLOW)Примечание:$(NC)"
@echo " Тестовый сертификат НЕ доверяется браузерами."
@echo " Используйте только для локальной разработки и тестирования."
@echo ""
# Очистка временных файлов
clean:
@echo "$(YELLOW)→ Очистка временных файлов...$(NC)"
@find . -type f -name "*.pyc" -delete
@find . -type d -name "__pycache__" -delete
@echo "$(GREEN)✓ Очистка завершена$(NC)"
# По умолчанию показываем помощь
.DEFAULT_GOAL := help

202
PROJECT_STRUCTURE.md Normal file
View File

@@ -0,0 +1,202 @@
# 📁 Структура проекта configure_nginx_manager
## Основные скрипты
### Python (Рекомендуется)
- **letsencrypt_regru_api.py** (1,411 строк)
- Полнофункциональный Python скрипт
- Прямая работа с API reg.ru
- Интеграция с Nginx Proxy Manager
- Автоматическая проверка и обновление сертификатов
- Генерация тестовых самоподписанных сертификатов
- Поддержка wildcard доменов
### Bash
- **letsencrypt_regru_dns.sh**
- Bash скрипт с certbot-dns-regru плагином
- Простота использования
- Минимальные зависимости
### PowerShell
- **letsencrypt_regru.ps1**
- Windows версия
- Аналогична Bash скрипту
### Тестирование
- **test_certificate.sh**
- Быстрое создание тестовых сертификатов через OpenSSL
- Автономная работа без Python
- Поддержка wildcard доменов
## Автоматизация
### Makefile
- **Makefile** (415 строк)
- `make install` - Полная установка и настройка
- `make uninstall` - Чистое удаление
- `make status` - Проверка состояния
- `make test-cert` - Создание тестового сертификата
- `make obtain` - Получение Let's Encrypt сертификата
- `make renew` - Обновление сертификата
- `make logs` - Просмотр логов
- `make check-config` - Валидация конфигурации
## Конфигурация
### config.json.example
Пример конфигурации со всеми параметрами:
- Учетные данные reg.ru API
- Настройки домена и email
- Параметры обновления (renewal_days)
- Настройки Nginx Proxy Manager
- Пути к директориям и логам
## Документация
### README.md (1,420+ строк)
Основная документация:
- Введение и возможности
- Быстрый старт
- Установка через Makefile
- Создание тестовых сертификатов
- Требования и установка зависимостей
- Настройка и использование
- Интеграция с NPM
- Автоматическая проверка и обновление
- Автоматизация через cron/systemd
- Устранение неполадок
### TESTING_GUIDE.md (370+ строк)
Руководство по тестированию:
- Зачем нужны тестовые сертификаты
- Обход лимитов Let's Encrypt (5 в неделю)
- Быстрый старт с тестовыми сертификатами
- Сравнение методов создания
- Использование в разработке
- Автоматизация тестирования
- Переход с тестовых на production
- Частые вопросы
- Примеры для CI/CD и Docker
### PROJECT_STRUCTURE.md (этот файл)
- Описание всех файлов проекта
- Краткая характеристика каждого компонента
## Вспомогательные файлы
### Markdown документы
- **Add Let's Encrypt Certificate для провайдера reg.ru.md**
- Первоначальные инструкции
- **Создание и продление SSL сертификата.md**
- Дополнительная информация о процессе
## Возможности
### ✅ Основные
- [x] Создание Let's Encrypt сертификатов через reg.ru DNS API
- [x] Wildcard сертификаты (*.domain.com)
- [x] Автоматическое обновление сертификатов
- [x] DNS-01 валидация
- [x] Интеграция с Nginx Proxy Manager
- [x] Автоматическая загрузка/обновление в NPM
### ✅ Продвинутые
- [x] Автоматическая проверка срока действия
- [x] Настраиваемый порог обновления (renewal_days)
- [x] Systemd service + timer
- [x] Cron автоматизация
- [x] Подробное логирование
- [x] Валидация конфигурации
### 🆕 Тестирование
- [x] Генерация самоподписанных тестовых сертификатов
- [x] Обход лимитов Let's Encrypt (5/неделю)
- [x] Мгновенное создание без DNS
- [x] Интеграция тестовых сертификатов с NPM
- [x] Полная совместимость структуры с Let's Encrypt
## Установка
### Быстрая установка
```bash
sudo make install
sudo nano /etc/letsencrypt/regru_config.json
sudo make test-cert # Для тестирования
sudo make obtain # Для production
```
### Структура после установки
```
/opt/letsencrypt-regru/
├── letsencrypt_regru_api.py
/etc/letsencrypt/
├── regru_config.json
└── live/
└── example.com/
├── privkey.pem
├── cert.pem
├── fullchain.pem
└── chain.pem
/etc/systemd/system/
├── letsencrypt-regru.service
└── letsencrypt-regru.timer
/var/log/letsencrypt/
└── letsencrypt_regru.log
```
## Использование
### Тестирование (без лимитов)
```bash
sudo make test-cert # Создать тестовый сертификат
sudo make status # Проверить статус
```
### Production
```bash
sudo make obtain # Получить Let's Encrypt сертификат
sudo make renew # Обновить сертификат
sudo make run # Автоматический режим
```
### Мониторинг
```bash
sudo make logs # Просмотр логов
sudo make status # Статус служб
sudo make check-config # Проверка конфигурации
```
## Технологии
- **Python 3.6+** - Основной язык
- **Certbot** - Let's Encrypt клиент
- **requests** - HTTP запросы к API
- **cryptography** - Генерация тестовых сертификатов
- **systemd** - Автоматизация запуска
- **cron** - Альтернативная автоматизация
- **Make** - Управление установкой
- **OpenSSL** - Альтернативная генерация сертификатов
## Лицензия
Open Source - свободное использование
## Автор
GitHub Copilot @ 2025
## Поддержка
См. документацию:
- [README.md](README.md) - Основное руководство
- [TESTING_GUIDE.md](TESTING_GUIDE.md) - Руководство по тестированию
---
**Версия**: 2.1
**Дата**: 27 октября 2025
**Статус**: ✅ Production Ready

904
README.md
View File

@@ -1,14 +1,32 @@
# Руководство по использованию скриптов для управления SSL сертификатами Let's Encrypt с DNS-валидацией через API reg.ru # Руководство по использованию скриптов для управления SSL сертификатами Let's Encrypt с DNS-валидацией через API reg.ru
## 🆕 Новое в версии 2.0
**Автоматическая интеграция с Nginx Proxy Manager!**
Python скрипт теперь автоматически загружает созданные сертификаты в Nginx Proxy Manager.
- ✅ Автоматическая загрузка сертификатов в NPM
- ✅ Автоматическое обновление существующих сертификатов
- ✅ Полная интеграция через API NPM
- ✅ Поддержка wildcard сертификатов
---
## Содержание ## Содержание
1. [Введение](#введение) 1. [Введение](#введение)
2. [Требования](#требования) 2. [Быстрый старт](#-быстрый-старт)
3. [Установка зависимостей](#установка-зависимостей) 3. [Установка через Makefile](#-установка-через-makefile)
4. [Настройка](#настройка) 4. [Создание тестовых сертификатов](#-создание-тестового-самоподписанного-сертификата)
5. [Использование Bash скрипта](#использование-bash-скрипта) 5. [Требования](#требования)
6. [Использование Python скрипта](#использование-python-скрипта) 6. [Установка зависимостей](#установка-зависимостей)
7. [Автоматизация обновления](#автоматизация-обновления) 7. [Настройка](#настройка)
8. [Устранение неполадок](#устранение-неполадок) 8. [Использование Bash скрипта](#использование-bash-скрипта)
9. [Использование Python скрипта](#использование-python-скрипта)
10. [Интеграция с Nginx Proxy Manager](#интеграция-с-nginx-proxy-manager)
11. [Автоматическая проверка и обновление сертификатов](#автоматическая-проверка-и-обновление-сертификатов)
12. [Автоматизация обновления](#автоматизация-обновления)
13. [Устранение неполадок](#устранение-неполадок)
--- ---
@@ -17,7 +35,7 @@
В проекте представлены два скрипта для автоматического создания и обновления SSL сертификатов Let's Encrypt с использованием DNS-валидации через API reg.ru: В проекте представлены два скрипта для автоматического создания и обновления SSL сертификатов Let's Encrypt с использованием DNS-валидации через API reg.ru:
1. **letsencrypt_regru_dns.sh** - Bash скрипт с использованием плагина certbot-dns-regru 1. **letsencrypt_regru_dns.sh** - Bash скрипт с использованием плагина certbot-dns-regru
2. **letsencrypt_regru_api.py** - Python скрипт с прямым взаимодействием с API reg.ru 2. **letsencrypt_regru_api.py** - Python скрипт с прямым взаимодействием с API reg.ru и интеграцией с NPM
Оба скрипта поддерживают: Оба скрипта поддерживают:
- Создание wildcard сертификатов (*.domain.com) - Создание wildcard сертификатов (*.domain.com)
@@ -26,6 +44,333 @@
- Логирование всех операций - Логирование всех операций
- Перезагрузку веб-сервера после обновления - Перезагрузку веб-сервера после обновления
**Дополнительно Python скрипт поддерживает:**
- ✨ Автоматическую загрузку в Nginx Proxy Manager
- ✨ Автоматическое обновление сертификатов в NPM
- ✨ API интеграцию с NPM
---
## 🚀 Установка через Makefile
**Самый быстрый способ установки на Linux!**
Makefile автоматизирует весь процесс установки, настройки systemd-сервисов и cron-заданий.
### Быстрая установка
```bash
# 1. Установка (требует root)
sudo make install
# 2. Редактирование конфигурации
sudo nano /etc/letsencrypt/regru_config.json
# 3. Проверка конфигурации
sudo make check-config
# 4. Тестовый запуск
sudo make test-run
```
### Доступные команды Makefile
#### Основные команды
```bash
# Установка всего: создание директорий, копирование скрипта, настройка systemd и cron
sudo make install
# Полное удаление: удаление службы, cron-задания, файлов
sudo make uninstall
# Показать статус установки, systemd и cron
sudo make status
# Справка по всем командам
make help
```
#### Утилиты
```bash
# Проверка JSON конфигурации на валидность
sudo make check-config
# Тестовый запуск без обновления cron/systemd
sudo make test-run
# Просмотр логов
sudo make logs
# Запуск скрипта напрямую
sudo make run
# Получение нового сертификата
sudo make obtain
# Обновление существующего сертификата
sudo make renew
# Создание тестового самоподписанного сертификата
sudo make test-cert
# Очистка логов
sudo make clean
```
### Что делает `make install`
1. **Создает директории**
- `/opt/letsencrypt-regru/` - директория установки
- `/var/log/letsencrypt/` - директория логов
2. **Устанавливает зависимости**
```bash
pip3 install certbot requests cryptography
```
3. **Копирует скрипт**
- Копирует `letsencrypt_regru_api.py` в `/opt/letsencrypt-regru/`
- Устанавливает права на выполнение
4. **Создает конфигурацию**
- Создает `/etc/letsencrypt/regru_config.json` (если не существует)
- Устанавливает права 600 для безопасности
5. **Настраивает systemd**
- Создает `letsencrypt-regru.service` - разовый запуск
- Создает `letsencrypt-regru.timer` - таймер для ежедневного запуска
- Включает и запускает таймер
6. **Настраивает cron**
- Добавляет задание для запуска каждый день в 3:00 AM
```
0 3 * * * /opt/letsencrypt-regru/letsencrypt_regru_api.py --config /etc/letsencrypt/regru_config.json --auto >> /var/log/letsencrypt/letsencrypt_regru.log 2>&1
```
### Что делает `make uninstall`
1. **Останавливает и удаляет службы**
- Останавливает systemd timer и service
- Удаляет файлы служб из `/etc/systemd/system/`
- Перезагружает конфигурацию systemd
2. **Удаляет cron-задание**
- Удаляет запись из crontab
3. **Удаляет файлы** (с подтверждением)
- Удаляет `/opt/letsencrypt-regru/`
- Опционально удаляет конфигурацию и логи
### Пример: Полная установка от А до Я
```bash
# 1. Клонируем или скачиваем проект
cd /tmp
git clone <repository-url>
cd configure_nginx_manager
# 2. Устанавливаем через Makefile
sudo make install
# 3. Редактируем конфигурацию
sudo nano /etc/letsencrypt/regru_config.json
# Вставляем реальные данные:
{
"regru_username": "myuser",
"regru_password": "mypassword",
"domain": "example.com",
"wildcard": true,
"email": "admin@example.com",
"renewal_days": 30,
"npm_enabled": true,
"npm_host": "https://npm.example.com",
"npm_email": "admin@example.com",
"npm_password": "npm_password"
}
# 4. Проверяем конфигурацию
sudo make check-config
# 5. Тестируем
sudo make test-run
# 6. Проверяем статус
sudo make status
# 7. Смотрим логи
sudo make logs
```
### Структура после установки
```
/opt/letsencrypt-regru/
├── letsencrypt_regru_api.py # Основной скрипт
/etc/letsencrypt/
├── regru_config.json # Конфигурация (600)
└── live/ # Сертификаты Let's Encrypt
└── example.com/
├── fullchain.pem
└── privkey.pem
/var/log/letsencrypt/
└── letsencrypt_regru.log # Логи
/etc/systemd/system/
├── letsencrypt-regru.service # Systemd сервис
└── letsencrypt-regru.timer # Systemd таймер (ежедневно)
```
### Проверка работы автоматизации
```bash
# Статус systemd таймера
sudo systemctl status letsencrypt-regru.timer
# Когда будет следующий запуск
sudo systemctl list-timers letsencrypt-regru.timer
# Проверка cron
sudo crontab -l | grep letsencrypt
# Ручной запуск службы (для теста)
sudo systemctl start letsencrypt-regru.service
# Просмотр логов службы
sudo journalctl -u letsencrypt-regru.service -f
```
### Удаление
```bash
# Полное удаление
sudo make uninstall
# Система спросит подтверждение перед удалением конфигурации и логов
```
### 🧪 Создание тестового самоподписанного сертификата
**Идеально для тестирования без ограничений Let's Encrypt!**
Let's Encrypt имеет ограничения на количество сертификатов (5 в неделю на домен). Для тестирования и разработки можно использовать самоподписанные сертификаты.
#### Преимущества тестовых сертификатов
✅ **Нет ограничений** - создавайте сколько угодно сертификатов
✅ **Мгновенное создание** - без DNS-валидации и ожидания
✅ **Тестирование NPM** - проверка интеграции с Nginx Proxy Manager
✅ **Офлайн работа** - не требуется интернет и API reg.ru
✅ **Идентичная структура** - те же файлы, что и Let's Encrypt
⚠️ **Ограничения**: Браузеры не доверяют самоподписанным сертификатам
#### Быстрое создание
```bash
# Создать тестовый сертификат
sudo make test-cert
```
Команда автоматически:
1. Генерирует RSA ключ 2048 бит
2. Создает самоподписанный сертификат на 90 дней
3. Поддерживает wildcard домены (если настроено)
4. Создает все необходимые файлы (privkey.pem, cert.pem, fullchain.pem, chain.pem)
5. Опционально загружает в Nginx Proxy Manager
#### Использование Python скрипта напрямую
```bash
# Создать тестовый сертификат с подробным выводом
sudo python3 /opt/letsencrypt-regru/letsencrypt_regru_api.py \
--config /etc/letsencrypt/regru_config.json \
--test-cert -v
```
#### Что создается
После выполнения команды будут созданы файлы:
```
/etc/letsencrypt/live/example.com/
├── privkey.pem # Приватный ключ RSA 2048 бит
├── cert.pem # Сертификат
├── fullchain.pem # Полная цепочка (для nginx)
└── chain.pem # Цепочка CA (пустой для самоподписанного)
```
#### Интеграция с NPM
Если в конфигурации включена интеграция с NPM (`npm_enabled: true`), тестовый сертификат автоматически загрузится в Nginx Proxy Manager:
```json
{
"npm_enabled": true,
"npm_host": "https://npm.example.com",
"npm_email": "admin@example.com",
"npm_password": "password"
}
```
#### Пример вывода
```
═══════════════════════════════════════════════════════════════
ГЕНЕРАЦИЯ ТЕСТОВОГО САМОПОДПИСАННОГО СЕРТИФИКАТА
═══════════════════════════════════════════════════════════════
Домен: example.com
Wildcard: True
Срок действия: 90 дней
⚠️ ВНИМАНИЕ: Это тестовый сертификат, не для production!
✓ Приватный ключ сохранен: /etc/letsencrypt/live/example.com/privkey.pem
✓ Сертификат сохранен: /etc/letsencrypt/live/example.com/cert.pem
✓ Fullchain сохранен: /etc/letsencrypt/live/example.com/fullchain.pem
✓ Chain файл создан: /etc/letsencrypt/live/example.com/chain.pem
═══════════════════════════════════════════════════════════════
ИНФОРМАЦИЯ О СЕРТИФИКАТЕ
═══════════════════════════════════════════════════════════════
Домен: example.com
Wildcard: *.example.com
Действителен с: 2025-10-27 12:00:00
Действителен до: 2026-01-25 12:00:00
```
#### Когда использовать тестовые сертификаты
**✅ Используйте для:**
- Локальной разработки и тестирования
- Проверки интеграции с Nginx Proxy Manager
- Тестирования автоматизации
- Разработки без доступа к интернету
- Избежания лимитов Let's Encrypt при частом тестировании
**❌ НЕ используйте для:**
- Production окружения
- Публичных веб-сайтов
- Любых случаев, где требуется доверие браузеров
#### Переход с тестового на production
После успешного тестирования легко переключиться на настоящий Let's Encrypt сертификат:
```bash
# 1. Удалить тестовый сертификат
sudo rm -rf /etc/letsencrypt/live/example.com/
# 2. Получить настоящий сертификат
sudo make obtain
# Или автоматически
sudo make run
```
--- ---
## Требования ## Требования
@@ -240,6 +585,531 @@ sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json
--- ---
## 🚀 Быстрый старт
### За 3 простых шага получите SSL сертификат в Nginx Proxy Manager!
#### Шаг 1: Создайте конфигурацию
```bash
sudo python3 letsencrypt_regru_api.py --create-config /etc/letsencrypt/regru_config.json
```
#### Шаг 2: Отредактируйте параметры
```bash
sudo nano /etc/letsencrypt/regru_config.json
```
Заполните:
```json
{
"regru_username": "ваш_логин_regru",
"regru_password": "ваш_пароль_regru",
"domain": "dfv24.com",
"wildcard": true,
"email": "admin@dfv24.com",
"npm_enabled": true,
"npm_host": "http://192.168.10.14:81",
"npm_email": "admin@example.com",
"npm_password": "changeme"
}
```
#### Шаг 3: Получите сертификат
```bash
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json --obtain
```
### ✅ Готово!
Откройте Nginx Proxy Manager → SSL Certificates
Ваш сертификат `*.dfv24.com` готов к использованию! 🎉
**Что произошло:**
1. ✅ Создан wildcard сертификат через Let's Encrypt
2. ✅ Выполнена DNS-валидация через API reg.ru
3. ✅ Сертификат автоматически загружен в Nginx Proxy Manager
4. ✅ Веб-сервер перезагружен
---
## Интеграция с Nginx Proxy Manager
### Обзор возможностей
Скрипт `letsencrypt_regru_api.py` поддерживает автоматическое добавление и обновление SSL сертификатов в Nginx Proxy Manager через его API.
**Возможности:**
- ✅ Автоматическое добавление новых сертификатов в NPM
- ✅ Обновление существующих сертификатов в NPM
- ✅ Поиск сертификатов по доменному имени
- ✅ Поддержка wildcard сертификатов
- ✅ Полная синхронизация после создания/обновления
### Настройка интеграции
#### 1. Параметры конфигурации NPM
| Параметр | Описание | Пример |
|----------|----------|--------|
| `npm_enabled` | Включить интеграцию с NPM | `true` или `false` |
| `npm_host` | URL адрес NPM | `http://192.168.10.14:81` |
| `npm_email` | Email для входа в NPM | `admin@example.com` |
| `npm_password` | Пароль администратора NPM | `changeme` |
#### 2. Получение учетных данных NPM
1. Войдите в Nginx Proxy Manager: `http://192.168.10.14:81`
2. Используйте email и пароль администратора
3. По умолчанию:
- Email: `admin@example.com`
- Password: `changeme`
4. **ВАЖНО:** Измените пароль по умолчанию!
### Использование
#### Автоматическая синхронизация
После создания или обновления сертификата скрипт автоматически:
1. Авторизуется в Nginx Proxy Manager
2. Проверит, существует ли сертификат для домена
3. Создаст новый сертификат или обновит существующий
4. Загрузит файлы сертификата в NPM
#### Создание нового сертификата с автоматической загрузкой в NPM
```bash
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json --obtain
```
**Скрипт выполнит:**
- ✅ Создание сертификата через Let's Encrypt
- ✅ DNS-валидация через reg.ru API
- ✅ Автоматическая загрузка в NPM
- ✅ Перезагрузка веб-сервера
#### Обновление существующего сертификата
```bash
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json --renew
```
**Скрипт выполнит:**
- ✅ Обновление сертификата через certbot
- ✅ Автоматическое обновление в NPM
- ✅ Перезагрузка веб-сервера
#### Автоматический режим
```bash
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json
```
Скрипт автоматически определит:
- Нужно ли создать новый сертификат
- Требуется ли обновление (если осталось < 30 дней)
- Выполнит синхронизацию с NPM
### Работа с API Nginx Proxy Manager
#### Класс NginxProxyManagerAPI
Скрипт использует класс `NginxProxyManagerAPI` для работы с NPM:
```python
from letsencrypt_regru_api import NginxProxyManagerAPI
# Инициализация
npm_api = NginxProxyManagerAPI(
host="http://192.168.10.14:81",
email="admin@example.com",
password="changeme",
logger=logger
)
# Авторизация
npm_api.login()
# Получение списка сертификатов
certificates = npm_api.get_certificates()
# Поиск сертификата по домену
cert = npm_api.find_certificate_by_domain("dfv24.com")
# Синхронизация сертификата
npm_api.sync_certificate("dfv24.com", "/etc/letsencrypt/live/dfv24.com")
```
#### API Endpoints
Скрипт использует следующие endpoints NPM API:
| Endpoint | Метод | Описание |
|----------|-------|----------|
| `/api/tokens` | POST | Авторизация |
| `/api/nginx/certificates` | GET | Список сертификатов |
| `/api/nginx/certificates` | POST | Создание сертификата |
| `/api/nginx/certificates/{id}` | PUT | Обновление сертификата |
### Логи и отладка
#### Просмотр логов
```bash
# Основной лог скрипта
sudo tail -f /var/log/letsencrypt_regru.log
# Подробный режим
sudo python3 letsencrypt_regru_api.py -c config.json --obtain -v
```
#### Примеры логов при успешной синхронизации
```
2025-10-27 10:30:15 - INFO - === Синхронизация сертификата с Nginx Proxy Manager ===
2025-10-27 10:30:15 - INFO - Авторизация в Nginx Proxy Manager...
2025-10-27 10:30:16 - INFO - Авторизация в NPM успешна
2025-10-27 10:30:16 - DEBUG - Получение списка сертификатов из NPM...
2025-10-27 10:30:16 - DEBUG - Получено 3 сертификатов
2025-10-27 10:30:16 - INFO - Создание нового сертификата в NPM
2025-10-27 10:30:16 - INFO - Загрузка сертификата для dfv24.com в NPM...
2025-10-27 10:30:17 - INFO - Сертификат успешно загружен в NPM (ID: 4)
2025-10-27 10:30:17 - INFO - Сертификат успешно добавлен в Nginx Proxy Manager
```
### Устранение неполадок NPM
#### Ошибка: Не удалось авторизоваться в NPM
**Причины:**
- Неверный email или пароль
- NPM недоступен по указанному адресу
- Сетевые проблемы
**Решение:**
```bash
# Проверьте доступность NPM
curl http://192.168.10.14:81/api/
# Проверьте учетные данные
# Войдите в NPM через браузер с теми же учетными данными
```
#### Ошибка: Сертификат не загружен в NPM
**Причины:**
- Файлы сертификата не найдены
- Неправильный формат сертификата
- Проблемы с API NPM
**Решение:**
```bash
# Проверьте наличие файлов сертификата
ls -la /etc/letsencrypt/live/dfv24.com/
# Проверьте права доступа
sudo chmod 644 /etc/letsencrypt/live/dfv24.com/*.pem
# Попробуйте вручную
sudo python3 -c "
from letsencrypt_regru_api import NginxProxyManagerAPI
import logging
logger = logging.getLogger()
npm = NginxProxyManagerAPI('http://192.168.10.14:81', 'admin@example.com', 'changeme', logger)
npm.login()
print(npm.get_certificates())
"
```
#### Ошибка: API NPM возвращает 401 (Unauthorized)
**Решение:**
- Проверьте учетные данные в конфигурации
- Убедитесь, что пароль был изменен с дефолтного
- Попробуйте войти через веб-интерфейс
#### Ошибка: Сертификат создан, но не обновляется в NPM
**Причина:** Скрипт не может найти существующий сертификат
**Решение:**
```bash
# Просмотрите список сертификатов в NPM
# SSL Certificates → найдите сертификат для вашего домена
# Удалите старый сертификат вручную через UI
# Запустите скрипт снова - будет создан новый
```
### Безопасность NPM
#### Защита учетных данных
```bash
# Установите правильные права на конфигурацию
sudo chmod 600 /etc/letsencrypt/regru_config.json
sudo chown root:root /etc/letsencrypt/regru_config.json
```
#### Рекомендации
1. **Измените пароль NPM по умолчанию**
```
Старый пароль: changeme
Новый пароль: надежный_пароль
```
2. **Используйте HTTPS для NPM** (если доступно)
```json
"npm_host": "https://192.168.10.14:443"
```
3. **Ограничьте доступ к API NPM**
- Настройте firewall
- Используйте VPN для удаленного доступа
### Проверка результата
#### В логах скрипта
```bash
sudo tail -n 50 /var/log/letsencrypt_regru.log | grep -i npm
```
#### В веб-интерфейсе NPM
1. Откройте NPM: `http://192.168.10.14:81`
2. Войдите в систему
3. Перейдите в **SSL Certificates**
4. Проверьте наличие сертификата для вашего домена
5. Проверьте дату истечения
#### В командной строке
```bash
# Список сертификатов в NPM через API
curl -X POST http://192.168.10.14:81/api/tokens \
-H "Content-Type: application/json" \
-d '{"identity":"admin@example.com","secret":"changeme"}' \
| jq -r '.token' > /tmp/npm_token
curl -H "Authorization: Bearer $(cat /tmp/npm_token)" \
http://192.168.10.14:81/api/nginx/certificates \
| jq '.'
```
### Дополнительные возможности
#### Отключение синхронизации с NPM
Если нужно временно отключить синхронизацию:
```json
{
"npm_enabled": false
}
```
#### Использование с несколькими доменами
Создайте отдельные конфигурационные файлы:
```bash
# Для домена 1
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/domain1_config.json
# Для домена 2
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/domain2_config.json
```
---
## Автоматическая проверка и обновление сертификатов
### Как это работает
Скрипт в автоматическом режиме (без флагов `--obtain` или `--renew`) выполняет интеллектуальную проверку:
#### 1. Проверка наличия сертификата
```bash
sudo python3 letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json
```
**Если сертификата нет:**
- ✅ Создает новый сертификат через Let's Encrypt
- ✅ Выполняет DNS-валидацию через reg.ru
- ✅ Загружает сертификат в Nginx Proxy Manager (если включено)
- ✅ Перезагружает веб-сервер
#### 2. Проверка срока действия
**Если сертификат существует:**
- 🔍 Проверяет сколько дней осталось до истечения
- 📅 Сравнивает с порогом обновления (по умолчанию 30 дней)
**Если осталось меньше 30 дней:**
- 🔄 Автоматически обновляет сертификат
- ✅ Синхронизирует с Nginx Proxy Manager
- ✅ Перезагружает веб-сервер
**Если сертификат действителен (более 30 дней):**
- Выводит информацию о сертификате
- ✅ Проверяет наличие в NPM и синхронизирует при необходимости
- ⏭️ Завершает работу (обновление не требуется)
### Настройка порога обновления
В конфигурации можно изменить порог обновления:
```json
{
"renewal_days": 30, # За сколько дней до истечения обновлять
}
```
**Рекомендуемые значения:**
- `30` - по умолчанию (рекомендуется)
- `14` - для более консервативного подхода
- `60` - для раннего обновления
### Примеры работы скрипта
#### Сценарий 1: Сертификата нет
```bash
$ sudo python3 letsencrypt_regru_api.py -c config.json
============================================================
АВТОМАТИЧЕСКАЯ ПРОВЕРКА И ОБНОВЛЕНИЕ СЕРТИФИКАТА
============================================================
Порог обновления: 30 дней до истечения
Сертификат не найден
============================================================
СТАТУС: Сертификат не найден
ДЕЙСТВИЕ: Создание нового сертификата
============================================================
=== Запрос нового SSL сертификата ===
...
Сертификат успешно получен!
============================================================
СИНХРОНИЗАЦИЯ С NGINX PROXY MANAGER
============================================================
✅ Сертификат успешно создан в Nginx Proxy Manager
============================================================
ОПЕРАЦИЯ ЗАВЕРШЕНА УСПЕШНО
============================================================
```
#### Сценарий 2: Сертификат истекает через 20 дней
```bash
$ sudo python3 letsencrypt_regru_api.py -c config.json
============================================================
АВТОМАТИЧЕСКАЯ ПРОВЕРКА И ОБНОВЛЕНИЕ СЕРТИФИКАТА
============================================================
Порог обновления: 30 дней до истечения
Сертификат истекает: 2025-11-16
Осталось дней: 20
============================================================
СТАТУС: Сертификат истекает через 20 дней
ДЕЙСТВИЕ: Обновление сертификата (порог: 30 дней)
============================================================
=== Обновление SSL сертификата ===
...
Проверка обновления завершена
============================================================
РЕЗУЛЬТАТ: Сертификат успешно обновлен
============================================================
✅ Сертификат успешно обновлен в Nginx Proxy Manager
```
#### Сценарий 3: Сертификат действителен (60 дней)
```bash
$ sudo python3 letsencrypt_regru_api.py -c config.json
============================================================
АВТОМАТИЧЕСКАЯ ПРОВЕРКА И ОБНОВЛЕНИЕ СЕРТИФИКАТА
============================================================
Порог обновления: 30 дней до истечения
Сертификат истекает: 2025-12-26
Осталось дней: 60
============================================================
СТАТУС: Сертификат действителен (60 дней)
ДЕЙСТВИЕ: Обновление не требуется
============================================================
Проверка синхронизации с Nginx Proxy Manager...
Сертификат найден в NPM (ID: 4)
```
### Ежедневная автоматическая проверка
Для ежедневной проверки и автоматического обновления настройте cron:
```bash
# Редактируем crontab
sudo crontab -e
# Добавляем задачу - проверка каждый день в 3:00 утра
0 3 * * * /usr/bin/python3 /path/to/letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json >> /var/log/letsencrypt_cron.log 2>&1
```
**Что будет происходить каждый день:**
1. 🕒 В 3:00 утра запускается скрипт
2. 🔍 Проверяет наличие и срок действия сертификата
3. 📊 Записывает результат в лог
4. 🔄 Обновляет сертификат только если нужно (< 30 дней)
5. ✅ Синхронизирует с NPM при обновлении
### Мониторинг работы
#### Просмотр логов ежедневной проверки
```bash
# Последние проверки
sudo tail -n 100 /var/log/letsencrypt_cron.log
# Фильтр по статусу
sudo grep "СТАТУС:" /var/log/letsencrypt_cron.log
# Фильтр по действиям
sudo grep "ДЕЙСТВИЕ:" /var/log/letsencrypt_cron.log
# Только успешные операции
sudo grep "ОПЕРАЦИЯ ЗАВЕРШЕНА УСПЕШНО" /var/log/letsencrypt_cron.log
```
#### Проверка следующего запуска cron
```bash
# Список задач cron
sudo crontab -l
# Статус cron службы
sudo systemctl status cron
```
### Уведомления при обновлении
Добавьте email уведомления в cron:
```bash
# В начале crontab добавьте
MAILTO=admin@dfv24.com
# Задача с уведомлениями
0 3 * * * /usr/bin/python3 /path/to/letsencrypt_regru_api.py -c /etc/letsencrypt/regru_config.json 2>&1 | mail -s "SSL Certificate Check - $(date)" admin@dfv24.com
```
---
## Автоматизация обновления ## Автоматизация обновления
Let's Encrypt сертификаты действительны 90 дней. Рекомендуется настроить автоматическое обновление. Let's Encrypt сертификаты действительны 90 дней. Рекомендуется настроить автоматическое обновление.
@@ -506,6 +1376,14 @@ server {
--- ---
## Дополнительная документация
- 📘 **[TESTING_GUIDE.md](TESTING_GUIDE.md)** - Полное руководство по созданию и использованию тестовых сертификатов
- 🚀 **[Makefile](Makefile)** - Автоматизация установки и управления
- 📝 **[config.json.example](config.json.example)** - Пример конфигурации
---
## Поддержка и вопросы ## Поддержка и вопросы
При возникновении проблем: При возникновении проблем:
@@ -515,6 +1393,7 @@ server {
3. Используйте подробный режим: `-v` для Python скрипта 3. Используйте подробный режим: `-v` для Python скрипта
4. Проверьте документацию reg.ru API: https://www.reg.ru/support/api 4. Проверьте документацию reg.ru API: https://www.reg.ru/support/api
5. Проверьте документацию Let's Encrypt: https://letsencrypt.org/docs/ 5. Проверьте документацию Let's Encrypt: https://letsencrypt.org/docs/
6. **Для тестирования**: См. [TESTING_GUIDE.md](TESTING_GUIDE.md)
--- ---
@@ -525,8 +1404,17 @@ server {
**Рекомендации:** **Рекомендации:**
- Используйте Python скрипт для более гибкой настройки и интеграции - Используйте Python скрипт для более гибкой настройки и интеграции
- Используйте Bash скрипт для простоты и минимальных зависимостей - Используйте Bash скрипт для простоты и минимальных зависимостей
- **Используйте тестовые сертификаты для разработки** (без лимитов Let's Encrypt)
- Настройте автоматическое обновление через cron или systemd timer - Настройте автоматическое обновление через cron или systemd timer
- Регулярно проверяйте логи и статус сертификатов - Регулярно проверяйте логи и статус сертификатов
- Храните учетные данные в безопасности (chmod 600) - Храните учетные данные в безопасности (chmod 600)
**Быстрый старт для тестирования:**
```bash
sudo make install # Установка
sudo make test-cert # Создать тестовый сертификат
sudo make obtain # Получить production сертификат
```
Успешной автоматизации! 🔒 Успешной автоматизации! 🔒

382
TESTING_GUIDE.md Normal file
View File

@@ -0,0 +1,382 @@
# 🧪 Руководство по тестированию SSL сертификатов
## Зачем нужны тестовые сертификаты?
Let's Encrypt имеет **строгие ограничения**:
- ⚠️ Максимум **5 сертификатов в неделю** на один домен
- ⚠️ Максимум **50 сертификатов в неделю** на аккаунт
- ⚠️ **Бан на 1 неделю** при превышении лимита
**Решение**: Используйте самоподписанные тестовые сертификаты для разработки!
---
## Быстрый старт
### Вариант 1: Через Makefile (рекомендуется)
```bash
# После установки скрипта (make install)
sudo make test-cert
```
**Результат**: Создан сертификат в `/etc/letsencrypt/live/ваш-домен/`
### Вариант 2: Через Python скрипт
```bash
sudo python3 letsencrypt_regru_api.py \
--config /etc/letsencrypt/regru_config.json \
--test-cert -v
```
### Вариант 3: Через Bash скрипт (автономный)
```bash
# Простой домен
sudo ./test_certificate.sh example.com no
# С wildcard
sudo ./test_certificate.sh example.com yes
```
---
## Сравнение методов
| Метод | Скорость | Требования | NPM интеграция | Лимиты |
|-------|----------|------------|----------------|--------|
| **Let's Encrypt** | 2-5 минут | Internet, DNS | ✅ Да | ⚠️ 5/неделю |
| **Тестовый (Python)** | 1-2 секунды | Только Python | ✅ Да | ✅ Нет |
| **Тестовый (Bash)** | 1-2 секунды | Только OpenSSL | ❌ Ручная | ✅ Нет |
---
## Детальная инструкция
### 1. Подготовка конфигурации
```bash
# Создать конфигурацию
sudo nano /etc/letsencrypt/regru_config.json
```
```json
{
"domain": "test.example.com",
"wildcard": true,
"cert_dir": "/etc/letsencrypt/live",
"npm_enabled": true,
"npm_host": "https://npm.example.com",
"npm_email": "admin@example.com",
"npm_password": "your_password"
}
```
### 2. Создание тестового сертификата
```bash
sudo make test-cert
```
### 3. Проверка созданных файлов
```bash
ls -la /etc/letsencrypt/live/test.example.com/
# Должны быть:
# - privkey.pem (приватный ключ)
# - cert.pem (сертификат)
# - fullchain.pem (полная цепочка)
# - chain.pem (CA цепочка)
```
### 4. Просмотр информации о сертификате
```bash
openssl x509 -in /etc/letsencrypt/live/test.example.com/cert.pem -text -noout
```
---
## Использование в Nginx
### Прямое использование
```nginx
server {
listen 443 ssl;
server_name test.example.com;
ssl_certificate /etc/letsencrypt/live/test.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/test.example.com/privkey.pem;
# ... остальная конфигурация
}
```
### Через Nginx Proxy Manager
Если `npm_enabled: true` в конфигурации, сертификат автоматически загрузится в NPM.
**Проверка в NPM:**
1. Откройте веб-интерфейс NPM
2. Перейдите в **SSL Certificates**
3. Найдите ваш домен в списке
4. ⚠️ Будет помечен как "Custom" (не Let's Encrypt)
---
## Автоматизация тестирования
### Скрипт для CI/CD
```bash
#!/bin/bash
# test_ssl_integration.sh
set -e
echo "🧪 Тестирование SSL интеграции..."
# 1. Создать тестовый сертификат
sudo python3 letsencrypt_regru_api.py \
--config test_config.json \
--test-cert
# 2. Проверить файлы
if [ ! -f "/etc/letsencrypt/live/test.example.com/fullchain.pem" ]; then
echo "❌ Сертификат не создан"
exit 1
fi
# 3. Проверить валидность
openssl x509 -in /etc/letsencrypt/live/test.example.com/cert.pem -noout -checkend 0
if [ $? -eq 0 ]; then
echo "✅ Сертификат валиден"
else
echo "❌ Сертификат невалиден"
exit 1
fi
# 4. Проверить загрузку в NPM (опционально)
# ... ваша проверка через API NPM
echo "✅ Все тесты пройдены"
```
### Makefile для тестирования
```makefile
.PHONY: test-ssl test-npm test-all
test-ssl:
@echo "Создание тестового сертификата..."
sudo make test-cert
@echo "Проверка файлов..."
test -f /etc/letsencrypt/live/$(DOMAIN)/fullchain.pem
@echo "✅ SSL тест пройден"
test-npm:
@echo "Проверка интеграции с NPM..."
# Ваши проверки API NPM
@echo "✅ NPM тест пройден"
test-all: test-ssl test-npm
@echo "✅ Все тесты пройдены"
```
---
## Переход на production
### Шаг 1: Тестирование
```bash
# 1. Создать тестовый сертификат
sudo make test-cert
# 2. Проверить работу с NPM
# Открыть https://ваш-домен и проверить
# 3. Убедиться что все работает
```
### Шаг 2: Переключение на Let's Encrypt
```bash
# 1. Удалить тестовый сертификат
sudo rm -rf /etc/letsencrypt/live/ваш-домен/
# 2. Получить настоящий сертификат
sudo make obtain
# 3. Проверить обновление в NPM
sudo make status
```
---
## Частые вопросы
### Q: Почему браузер показывает предупреждение?
**A:** Самоподписанные сертификаты не доверяются браузерами. Это нормально для тестирования.
Чтобы избежать предупреждения в браузере (только для локального тестирования):
1. Chrome: `chrome://flags/#allow-insecure-localhost`
2. Firefox: Нажмите "Advanced" → "Accept the Risk"
### Q: Можно ли использовать для production?
**A:****НЕТ!** Тестовые сертификаты только для разработки и тестирования.
### Q: Как часто можно создавать тестовые сертификаты?
**A:** ✅ Неограниченно! Нет никаких лимитов.
### Q: Загружаются ли в NPM автоматически?
**A:** ✅ Да, если `npm_enabled: true` в конфигурации.
### Q: Работают ли с wildcard доменами?
**A:** ✅ Да! Просто установите `"wildcard": true` в конфигурации.
### Q: Как проверить срок действия?
```bash
openssl x509 -in /etc/letsencrypt/live/ваш-домен/cert.pem -noout -dates
```
### Q: Как изменить срок действия?
Отредактируйте `validity_days` в функции `generate_self_signed_certificate()`:
```python
validity_days: int = 365 # Изменить на нужное количество дней
```
---
## Устранение проблем
### Ошибка: Permission denied
```bash
# Запускайте с sudo
sudo make test-cert
```
### Ошибка: Module 'cryptography' not found
```bash
# Установите зависимости
sudo pip3 install cryptography
```
### NPM не показывает сертификат
1. Проверьте настройки NPM в конфигурации
2. Проверьте логи: `sudo make logs`
3. Попробуйте загрузить вручную через веб-интерфейс NPM
### Сертификат не создается
```bash
# Проверьте права
ls -la /etc/letsencrypt/live/
# Создайте директорию вручную
sudo mkdir -p /etc/letsencrypt/live/
# Проверьте конфигурацию
sudo make check-config
```
---
## Примеры использования
### Разработка с Docker
```dockerfile
FROM nginx:alpine
# Копировать тестовый сертификат
COPY test-certs/ /etc/nginx/ssl/
# Конфигурация nginx
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 443
```
### Локальное тестирование
```bash
# Создать сертификат для localhost
sudo python3 letsencrypt_regru_api.py --test-cert
# Добавить в /etc/hosts
echo "127.0.0.1 test.example.com" | sudo tee -a /etc/hosts
# Запустить nginx
sudo nginx -t && sudo nginx -s reload
# Открыть в браузере
open https://test.example.com
```
### Автоматическое тестирование перед deployment
```bash
#!/bin/bash
# pre-deploy.sh
# Тестовая проверка SSL
sudo make test-cert
if [ $? -eq 0 ]; then
echo "✅ Тестовый сертификат создан успешно"
echo "✅ Готово к созданию production сертификата"
sudo make obtain
else
echo "❌ Ошибка при создании тестового сертификата"
exit 1
fi
```
---
## Дополнительные ресурсы
- 📘 [Let's Encrypt Rate Limits](https://letsencrypt.org/docs/rate-limits/)
- 📘 [OpenSSL Documentation](https://www.openssl.org/docs/)
- 📘 [Nginx Proxy Manager Docs](https://nginxproxymanager.com/guide/)
---
## Итоговая шпаргалка
```bash
# Установка
sudo make install
# Конфигурация
sudo nano /etc/letsencrypt/regru_config.json
# Создать тестовый сертификат
sudo make test-cert
# Проверить
sudo make check-config
sudo make status
# Переход на production
sudo rm -rf /etc/letsencrypt/live/домен/
sudo make obtain
# Автоматическое обновление
sudo make run
```
**Готово!** 🎉 Теперь вы можете тестировать SSL сертификаты без ограничений!

View File

@@ -8,5 +8,10 @@
"log_file": "/var/log/letsencrypt_regru.log", "log_file": "/var/log/letsencrypt_regru.log",
"dns_propagation_wait": 60, "dns_propagation_wait": 60,
"dns_check_attempts": 10, "dns_check_attempts": 10,
"dns_check_interval": 10 "dns_check_interval": 10,
"renewal_days": 30,
"npm_enabled": true,
"npm_host": "http://192.168.10.14:81",
"npm_email": "admin@example.com",
"npm_password": "changeme"
} }

View File

@@ -83,7 +83,7 @@ function Write-Log {
[string]$Level = "INFO" [string]$Level = "INFO"
) )
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $Timestamp = Get-Date -Format "dd.MM.yyyy HH:mm:ss"
$LogMessage = "[$Timestamp] [$Level] $Message" $LogMessage = "[$Timestamp] [$Level] $Message"
# Вывод в консоль # Вывод в консоль

View File

@@ -40,6 +40,17 @@ except ImportError:
print("Выполните: pip install requests") print("Выполните: pip install requests")
sys.exit(1) sys.exit(1)
try:
from cryptography import x509
from cryptography.x509.oid import NameOID, ExtensionOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend
except ImportError:
print("ОШИБКА: Необходимо установить модуль 'cryptography'")
print("Выполните: pip install cryptography")
sys.exit(1)
# ============================================================================== # ==============================================================================
# КОНФИГУРАЦИЯ # КОНФИГУРАЦИЯ
# ============================================================================== # ==============================================================================
@@ -65,6 +76,15 @@ DEFAULT_CONFIG = {
"dns_propagation_wait": 60, # Время ожидания распространения DNS (секунды) "dns_propagation_wait": 60, # Время ожидания распространения DNS (секунды)
"dns_check_attempts": 10, # Количество попыток проверки DNS "dns_check_attempts": 10, # Количество попыток проверки DNS
"dns_check_interval": 10, # Интервал между проверками DNS (секунды) "dns_check_interval": 10, # Интервал между проверками DNS (секунды)
# Параметры обновления сертификата
"renewal_days": 30, # За сколько дней до истечения обновлять (по умолчанию 30)
# Настройки Nginx Proxy Manager
"npm_enabled": False, # Включить интеграцию с NPM
"npm_host": "http://192.168.10.14:81", # Адрес NPM
"npm_email": "admin@example.com", # Email для входа в NPM
"npm_password": "changeme", # Пароль NPM
} }
# API endpoints для reg.ru # API endpoints для reg.ru
@@ -278,6 +298,454 @@ class RegRuAPI:
return False return False
# ==============================================================================
# КЛАСС ДЛЯ РАБОТЫ С NGINX PROXY MANAGER
# ==============================================================================
class NginxProxyManagerAPI:
"""Класс для работы с API Nginx Proxy Manager"""
def __init__(self, host: str, email: str, password: str, logger: logging.Logger):
"""
Инициализация API клиента NPM
Args:
host: URL адрес NPM (например, http://192.168.10.14:81)
email: Email для входа
password: Пароль
logger: Logger объект
"""
self.host = host.rstrip('/')
self.email = email
self.password = password
self.logger = logger
self.session = requests.Session()
self.token = None
def login(self) -> bool:
"""
Авторизация в Nginx Proxy Manager
Returns:
True если успешно
"""
url = f"{self.host}/api/tokens"
payload = {
"identity": self.email,
"secret": self.password
}
try:
self.logger.info("Авторизация в Nginx Proxy Manager...")
response = self.session.post(url, json=payload, timeout=10)
response.raise_for_status()
data = response.json()
self.token = data.get("token")
if self.token:
# Устанавливаем токен в заголовки для последующих запросов
self.session.headers.update({
"Authorization": f"Bearer {self.token}"
})
self.logger.info("Авторизация в NPM успешна")
return True
else:
self.logger.error("Токен не получен при авторизации")
return False
except requests.exceptions.RequestException as e:
self.logger.error(f"Ошибка при авторизации в NPM: {e}")
return False
def get_certificates(self) -> List[Dict]:
"""
Получение списка сертификатов
Returns:
Список сертификатов
"""
url = f"{self.host}/api/nginx/certificates"
try:
self.logger.debug("Получение списка сертификатов из NPM...")
response = self.session.get(url, timeout=10)
response.raise_for_status()
certificates = response.json()
self.logger.debug(f"Получено {len(certificates)} сертификатов")
return certificates
except requests.exceptions.RequestException as e:
self.logger.error(f"Ошибка при получении списка сертификатов: {e}")
return []
def find_certificate_by_domain(self, domain: str) -> Optional[Dict]:
"""
Поиск сертификата по домену
Args:
domain: Доменное имя
Returns:
Данные сертификата или None
"""
certificates = self.get_certificates()
for cert in certificates:
domains = cert.get("domain_names", [])
if domain in domains or f"*.{domain}" in domains:
self.logger.debug(f"Найден существующий сертификат для {domain}")
return cert
return None
def upload_certificate(self, domain: str, cert_path: str, key_path: str,
chain_path: Optional[str] = None) -> Optional[Dict]:
"""
Загрузка нового сертификата в NPM
Args:
domain: Основной домен
cert_path: Путь к файлу сертификата
key_path: Путь к приватному ключу
chain_path: Путь к цепочке сертификатов (опционально)
Returns:
Данные созданного сертификата или None
"""
url = f"{self.host}/api/nginx/certificates"
try:
# Читаем файлы сертификатов
with open(cert_path, 'r') as f:
certificate = f.read()
with open(key_path, 'r') as f:
certificate_key = f.read()
# Если есть цепочка, объединяем с сертификатом
if chain_path and os.path.exists(chain_path):
with open(chain_path, 'r') as f:
chain = f.read()
# NPM ожидает fullchain (cert + chain)
certificate = certificate + "\n" + chain
# Формируем payload для API
payload = {
"provider": "other",
"nice_name": f"{domain} - Let's Encrypt",
"domain_names": [domain],
"certificate": certificate,
"certificate_key": certificate_key,
"meta": {
"letsencrypt_agree": True,
"dns_challenge": True,
"dns_provider": "reg_ru"
}
}
self.logger.info(f"Загрузка сертификата для {domain} в NPM...")
response = self.session.post(url, json=payload, timeout=30)
response.raise_for_status()
result = response.json()
cert_id = result.get("id")
if cert_id:
self.logger.info(f"Сертификат успешно загружен в NPM (ID: {cert_id})")
return result
else:
self.logger.error("Не удалось получить ID созданного сертификата")
return None
except FileNotFoundError as e:
self.logger.error(f"Файл сертификата не найден: {e}")
return None
except requests.exceptions.RequestException as e:
self.logger.error(f"Ошибка при загрузке сертификата в NPM: {e}")
if hasattr(e.response, 'text'):
self.logger.error(f"Ответ сервера: {e.response.text}")
return None
def update_certificate(self, cert_id: int, cert_path: str, key_path: str,
chain_path: Optional[str] = None) -> bool:
"""
Обновление существующего сертификата
Args:
cert_id: ID сертификата в NPM
cert_path: Путь к файлу сертификата
key_path: Путь к приватному ключу
chain_path: Путь к цепочке сертификатов (опционально)
Returns:
True если успешно
"""
url = f"{self.host}/api/nginx/certificates/{cert_id}"
try:
# Читаем файлы сертификатов
with open(cert_path, 'r') as f:
certificate = f.read()
with open(key_path, 'r') as f:
certificate_key = f.read()
# Если есть цепочка, объединяем с сертификатом
if chain_path and os.path.exists(chain_path):
with open(chain_path, 'r') as f:
chain = f.read()
certificate = certificate + "\n" + chain
# Формируем payload для обновления
payload = {
"certificate": certificate,
"certificate_key": certificate_key
}
self.logger.info(f"Обновление сертификата ID {cert_id} в NPM...")
response = self.session.put(url, json=payload, timeout=30)
response.raise_for_status()
self.logger.info("Сертификат успешно обновлен в NPM")
return True
except FileNotFoundError as e:
self.logger.error(f"Файл сертификата не найден: {e}")
return False
except requests.exceptions.RequestException as e:
self.logger.error(f"Ошибка при обновлении сертификата в NPM: {e}")
if hasattr(e.response, 'text'):
self.logger.error(f"Ответ сервера: {e.response.text}")
return False
def sync_certificate(self, domain: str, cert_dir: str) -> bool:
"""
Синхронизация сертификата с NPM (создание или обновление)
Args:
domain: Доменное имя
cert_dir: Директория с сертификатами Let's Encrypt
Returns:
True если успешно
"""
# Пути к файлам сертификата
cert_path = os.path.join(cert_dir, "cert.pem")
key_path = os.path.join(cert_dir, "privkey.pem")
chain_path = os.path.join(cert_dir, "chain.pem")
fullchain_path = os.path.join(cert_dir, "fullchain.pem")
# Проверяем наличие файлов
if not os.path.exists(cert_path) or not os.path.exists(key_path):
self.logger.error(f"Файлы сертификата не найдены в {cert_dir}")
return False
# Авторизуемся в NPM
if not self.login():
return False
# Проверяем, существует ли уже сертификат для этого домена
existing_cert = self.find_certificate_by_domain(domain)
# Используем fullchain если доступен, иначе cert + chain
if os.path.exists(fullchain_path):
final_cert_path = fullchain_path
final_chain_path = None
else:
final_cert_path = cert_path
final_chain_path = chain_path if os.path.exists(chain_path) else None
if existing_cert:
# Обновляем существующий сертификат
cert_id = existing_cert.get("id")
self.logger.info(f"Обновление существующего сертификата (ID: {cert_id})")
return self.update_certificate(cert_id, final_cert_path, key_path, final_chain_path)
else:
# Создаем новый сертификат
self.logger.info("Создание нового сертификата в NPM")
result = self.upload_certificate(domain, final_cert_path, key_path, final_chain_path)
return result is not None
# ==============================================================================
# КЛАСС ДЛЯ ГЕНЕРАЦИИ ТЕСТОВЫХ СЕРТИФИКАТОВ
# ==============================================================================
class TestCertificateGenerator:
"""Класс для генерации самоподписанных тестовых SSL сертификатов"""
def __init__(self, logger: logging.Logger):
"""
Инициализация генератора тестовых сертификатов
Args:
logger: Logger объект
"""
self.logger = logger
def generate_self_signed_certificate(
self,
domain: str,
wildcard: bool = False,
output_dir: str = "/etc/letsencrypt/live",
validity_days: int = 90
) -> bool:
"""
Генерация самоподписанного SSL сертификата для тестирования
Args:
domain: Основной домен
wildcard: Создать wildcard сертификат
output_dir: Директория для сохранения сертификата
validity_days: Срок действия сертификата в днях (по умолчанию 90)
Returns:
True если сертификат создан успешно, False в противном случае
"""
try:
self.logger.info("=" * 80)
self.logger.info("ГЕНЕРАЦИЯ ТЕСТОВОГО САМОПОДПИСАННОГО СЕРТИФИКАТА")
self.logger.info("=" * 80)
self.logger.info(f"Домен: {domain}")
self.logger.info(f"Wildcard: {wildcard}")
self.logger.info(f"Срок действия: {validity_days} дней")
self.logger.info("⚠️ ВНИМАНИЕ: Это тестовый сертификат, не для production!")
# Создаем директорию для сертификата
cert_dir = os.path.join(output_dir, domain)
os.makedirs(cert_dir, exist_ok=True)
self.logger.info(f"Директория: {cert_dir}")
# Генерируем приватный ключ
self.logger.info("Генерация приватного ключа RSA 2048 бит...")
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
# Сохраняем приватный ключ
key_path = os.path.join(cert_dir, "privkey.pem")
with open(key_path, "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
))
os.chmod(key_path, 0o600)
self.logger.info(f"✓ Приватный ключ сохранен: {key_path}")
# Подготовка данных для сертификата
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, "RU"),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Moscow"),
x509.NameAttribute(NameOID.LOCALITY_NAME, "Moscow"),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Test Certificate"),
x509.NameAttribute(NameOID.COMMON_NAME, domain),
])
# Создаем список альтернативных имен (SAN)
san_list = [x509.DNSName(domain)]
if wildcard:
san_list.append(x509.DNSName(f"*.{domain}"))
# Генерируем сертификат
self.logger.info("Генерация самоподписанного сертификата...")
cert = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(private_key.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.utcnow())
.not_valid_after(datetime.utcnow() + timedelta(days=validity_days))
.add_extension(
x509.SubjectAlternativeName(san_list),
critical=False,
)
.add_extension(
x509.BasicConstraints(ca=False, path_length=None),
critical=True,
)
.add_extension(
x509.KeyUsage(
digital_signature=True,
key_encipherment=True,
content_commitment=False,
data_encipherment=False,
key_agreement=False,
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
decipher_only=False,
),
critical=True,
)
.add_extension(
x509.ExtendedKeyUsage([
x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH,
]),
critical=False,
)
.sign(private_key, hashes.SHA256(), default_backend())
)
# Сохраняем сертификат
cert_path = os.path.join(cert_dir, "cert.pem")
with open(cert_path, "wb") as f:
f.write(cert.public_bytes(serialization.Encoding.PEM))
self.logger.info(f"✓ Сертификат сохранен: {cert_path}")
# Создаем fullchain (для самоподписанного это просто копия cert)
fullchain_path = os.path.join(cert_dir, "fullchain.pem")
with open(fullchain_path, "wb") as f:
f.write(cert.public_bytes(serialization.Encoding.PEM))
self.logger.info(f"✓ Fullchain сохранен: {fullchain_path}")
# Создаем chain.pem (пустой для самоподписанного)
chain_path = os.path.join(cert_dir, "chain.pem")
with open(chain_path, "w") as f:
f.write("")
self.logger.info(f"✓ Chain файл создан: {chain_path}")
# Выводим информацию о сертификате
self.logger.info("")
self.logger.info("=" * 80)
self.logger.info("ИНФОРМАЦИЯ О СЕРТИФИКАТЕ")
self.logger.info("=" * 80)
self.logger.info(f"Домен: {domain}")
if wildcard:
self.logger.info(f"Wildcard: *.{domain}")
self.logger.info(f"Действителен с: {cert.not_valid_before}")
self.logger.info(f"Действителен до: {cert.not_valid_after}")
self.logger.info(f"Серийный номер: {cert.serial_number}")
self.logger.info("")
self.logger.info("📁 Файлы сертификата:")
self.logger.info(f" • Приватный ключ: {key_path}")
self.logger.info(f" • Сертификат: {cert_path}")
self.logger.info(f" • Fullchain: {fullchain_path}")
self.logger.info(f" • Chain: {chain_path}")
self.logger.info("")
self.logger.info("⚠️ ВНИМАНИЕ:")
self.logger.info(" Это самоподписанный тестовый сертификат!")
self.logger.info(" Браузеры будут показывать предупреждение о безопасности.")
self.logger.info(" Используйте ТОЛЬКО для тестирования и разработки!")
self.logger.info(" Для production используйте настоящие Let's Encrypt сертификаты.")
self.logger.info("=" * 80)
return True
except Exception as e:
self.logger.error(f"Ошибка при генерации тестового сертификата: {e}")
import traceback
self.logger.error(traceback.format_exc())
return False
# ============================================================================== # ==============================================================================
# КЛАСС ДЛЯ РАБОТЫ С CERTBOT # КЛАСС ДЛЯ РАБОТЫ С CERTBOT
# ============================================================================== # ==============================================================================
@@ -571,6 +1039,26 @@ class LetsEncryptManager:
except Exception as e: except Exception as e:
self.logger.error(f"Ошибка при чтении сертификата: {e}") self.logger.error(f"Ошибка при чтении сертификата: {e}")
def sync_with_npm(self, npm_api: NginxProxyManagerAPI) -> bool:
"""
Синхронизация сертификата с Nginx Proxy Manager
Args:
npm_api: API клиент NPM
Returns:
True если успешно
"""
self.logger.info("=== Синхронизация сертификата с Nginx Proxy Manager ===")
# Проверяем наличие сертификата
if not os.path.exists(self.cert_dir):
self.logger.error(f"Директория сертификата не найдена: {self.cert_dir}")
return False
# Синхронизируем сертификат
return npm_api.sync_certificate(self.domain, self.cert_dir)
# ============================================================================== # ==============================================================================
# ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ # ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ
@@ -701,6 +1189,16 @@ def main():
help="Подробный вывод", help="Подробный вывод",
action="store_true" action="store_true"
) )
parser.add_argument(
"--auto",
help="Автоматический режим: проверка и обновление при необходимости",
action="store_true"
)
parser.add_argument(
"--test-cert",
help="Создать самоподписанный тестовый сертификат (для разработки и тестирования)",
action="store_true"
)
args = parser.parse_args() args = parser.parse_args()
@@ -715,6 +1213,70 @@ def main():
# Настройка логирования # Настройка логирования
logger = setup_logging(config["log_file"], args.verbose) logger = setup_logging(config["log_file"], args.verbose)
# Генерация тестового сертификата
if args.test_cert:
logger.info("=" * 80)
logger.info("РЕЖИМ: Генерация тестового самоподписанного сертификата")
logger.info("=" * 80)
test_gen = TestCertificateGenerator(logger)
success = test_gen.generate_self_signed_certificate(
domain=config["domain"],
wildcard=config.get("wildcard", False),
output_dir=config["cert_dir"],
validity_days=90
)
if success:
# Опционально загружаем в NPM
if config.get("npm_enabled", False):
logger.info("")
logger.info("=" * 80)
logger.info("ЗАГРУЗКА ТЕСТОВОГО СЕРТИФИКАТА В NGINX PROXY MANAGER")
logger.info("=" * 80)
npm_api = NginxProxyManagerAPI(
config["npm_host"],
config["npm_email"],
config["npm_password"],
logger
)
if npm_api.login():
cert_dir = os.path.join(config["cert_dir"], config["domain"])
cert_path = os.path.join(cert_dir, "fullchain.pem")
key_path = os.path.join(cert_dir, "privkey.pem")
# Проверяем существующий сертификат
existing = npm_api.find_certificate_by_domain(config["domain"])
if existing:
# Обновляем существующий
cert_id = existing.get("id")
logger.info(f"Обновление существующего сертификата в NPM (ID: {cert_id})")
if npm_api.update_certificate(cert_id, cert_path, key_path):
logger.info("✅ Тестовый сертификат успешно обновлен в NPM")
else:
logger.warning("⚠️ Не удалось обновить сертификат в NPM")
else:
# Создаем новый
logger.info("Загрузка нового тестового сертификата в NPM")
if npm_api.upload_certificate(config["domain"], cert_path, key_path):
logger.info("✅ Тестовый сертификат успешно загружен в NPM")
else:
logger.warning("⚠️ Не удалось загрузить сертификат в NPM")
else:
logger.error("Не удалось подключиться к Nginx Proxy Manager")
logger.info("")
logger.info("=" * 80)
logger.info("✅ ТЕСТОВЫЙ СЕРТИФИКАТ УСПЕШНО СОЗДАН")
logger.info("=" * 80)
return 0
else:
logger.error("Не удалось создать тестовый сертификат")
return 1
# Обработка хуков для certbot # Обработка хуков для certbot
if args.auth_hook: if args.auth_hook:
# Certbot передает домен и токен через переменные окружения # Certbot передает домен и токен через переменные окружения
@@ -781,6 +1343,20 @@ def main():
if success: if success:
manager.display_certificate_info() manager.display_certificate_info()
reload_webserver(logger) reload_webserver(logger)
# Синхронизация с Nginx Proxy Manager
if config.get("npm_enabled", False):
npm_api = NginxProxyManagerAPI(
config["npm_host"],
config["npm_email"],
config["npm_password"],
logger
)
if manager.sync_with_npm(npm_api):
logger.info("Сертификат успешно добавлен в Nginx Proxy Manager")
else:
logger.warning("Не удалось синхронизировать сертификат с NPM")
logger.info("Новый сертификат успешно создан") logger.info("Новый сертификат успешно создан")
return 0 return 0
else: else:
@@ -793,6 +1369,20 @@ def main():
if success: if success:
manager.display_certificate_info() manager.display_certificate_info()
reload_webserver(logger) reload_webserver(logger)
# Синхронизация с Nginx Proxy Manager
if config.get("npm_enabled", False):
npm_api = NginxProxyManagerAPI(
config["npm_host"],
config["npm_email"],
config["npm_password"],
logger
)
if manager.sync_with_npm(npm_api):
logger.info("Сертификат успешно обновлен в Nginx Proxy Manager")
else:
logger.warning("Не удалось синхронизировать сертификат с NPM")
logger.info("Сертификат успешно обновлен") logger.info("Сертификат успешно обновлен")
return 0 return 0
else: else:
@@ -801,26 +1391,89 @@ def main():
else: else:
# Автоматический режим: проверка и обновление при необходимости # Автоматический режим: проверка и обновление при необходимости
logger.info("=" * 60)
logger.info("АВТОМАТИЧЕСКАЯ ПРОВЕРКА И ОБНОВЛЕНИЕ СЕРТИФИКАТА")
logger.info("=" * 60)
# Получаем порог для обновления из конфигурации
renewal_days = config.get("renewal_days", 30)
logger.info(f"Порог обновления: {renewal_days} дней до истечения")
# Проверяем срок действия сертификата
days_left = manager.check_certificate_expiry() days_left = manager.check_certificate_expiry()
if days_left is None: if days_left is None:
# Сертификат не существует # Сертификат не существует - создаем новый
logger.info("Сертификат не найден. Создание нового...") logger.info("=" * 60)
logger.info("СТАТУС: Сертификат не найден")
logger.info("ДЕЙСТВИЕ: Создание нового сертификата")
logger.info("=" * 60)
success = manager.obtain_certificate() success = manager.obtain_certificate()
elif days_left < 30: action = "создан"
# Сертификат скоро истекает elif days_left < renewal_days:
logger.info(f"Сертификат истекает через {days_left} дней. Обновление...") # Сертификат скоро истекает - обновляем
logger.info("=" * 60)
logger.info(f"СТАТУС: Сертификат истекает через {days_left} дней")
logger.info(f"ДЕЙСТВИЕ: Обновление сертификата (порог: {renewal_days} дней)")
logger.info("=" * 60)
success = manager.renew_certificate() success = manager.renew_certificate()
action = "обновлен"
else: else:
# Сертификат действителен # Сертификат действителен - ничего не делаем
logger.info(f"Сертификат действителен ({days_left} дней). Обновление не требуется.") logger.info("=" * 60)
logger.info(f"СТАТУС: Сертификат действителен ({days_left} дней)")
logger.info("ДЕЙСТВИЕ: Обновление не требуется")
logger.info("=" * 60)
manager.display_certificate_info() manager.display_certificate_info()
# Проверяем синхронизацию с NPM даже если сертификат действителен
if config.get("npm_enabled", False):
logger.info("Проверка синхронизации с Nginx Proxy Manager...")
npm_api = NginxProxyManagerAPI(
config["npm_host"],
config["npm_email"],
config["npm_password"],
logger
)
existing_cert = npm_api.login() and npm_api.find_certificate_by_domain(manager.domain)
if existing_cert:
logger.info(f"Сертификат найден в NPM (ID: {existing_cert.get('id')})")
else:
logger.info("Сертификат не найден в NPM. Синхронизация...")
if manager.sync_with_npm(npm_api):
logger.info("Сертификат успешно синхронизирован с NPM")
return 0 return 0
# Если был создан или обновлен сертификат
if success: if success:
logger.info("=" * 60)
logger.info(f"РЕЗУЛЬТАТ: Сертификат успешно {action}")
logger.info("=" * 60)
manager.display_certificate_info() manager.display_certificate_info()
reload_webserver(logger) reload_webserver(logger)
logger.info("Операция завершена успешно")
# Синхронизация с Nginx Proxy Manager
if config.get("npm_enabled", False):
logger.info("=" * 60)
logger.info("СИНХРОНИЗАЦИЯ С NGINX PROXY MANAGER")
logger.info("=" * 60)
npm_api = NginxProxyManagerAPI(
config["npm_host"],
config["npm_email"],
config["npm_password"],
logger
)
if manager.sync_with_npm(npm_api):
logger.info(f"✅ Сертификат успешно {action} в Nginx Proxy Manager")
else:
logger.warning("⚠️ Не удалось синхронизировать сертификат с NPM")
logger.info("=" * 60)
logger.info("ОПЕРАЦИЯ ЗАВЕРШЕНА УСПЕШНО")
logger.info("=" * 60)
return 0 return 0
else: else:
logger.error("Операция завершилась с ошибкой") logger.error("Операция завершилась с ошибкой")

143
test_certificate.sh Normal file
View File

@@ -0,0 +1,143 @@
#!/bin/bash
# ==============================================================================
# Скрипт для быстрого создания тестового самоподписанного SSL сертификата
# Использует: openssl (альтернатива Python скрипту)
# ==============================================================================
set -e
# Цвета
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Параметры по умолчанию
DOMAIN="${1:-example.com}"
WILDCARD="${2:-yes}"
CERT_DIR="/etc/letsencrypt/live/${DOMAIN}"
VALIDITY_DAYS=90
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Создание тестового самоподписанного SSL сертификата ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}Параметры:${NC}"
echo -e " Домен: ${GREEN}${DOMAIN}${NC}"
echo -e " Wildcard: ${GREEN}${WILDCARD}${NC}"
echo -e " Срок действия: ${GREEN}${VALIDITY_DAYS} дней${NC}"
echo -e " Директория: ${GREEN}${CERT_DIR}${NC}"
echo ""
echo -e "${YELLOW}⚠️ ВНИМАНИЕ: Это тестовый сертификат для разработки!${NC}"
echo -e "${YELLOW} Браузеры будут показывать предупреждение безопасности.${NC}"
echo ""
# Проверка прав root
if [ "$(id -u)" != "0" ]; then
echo -e "${RED}✗ Требуются права root${NC}"
echo -e "Запустите: sudo $0 $@"
exit 1
fi
# Создание директории
echo -e "${YELLOW}→ Создание директории...${NC}"
mkdir -p "${CERT_DIR}"
cd "${CERT_DIR}"
# Подготовка конфигурации для альтернативных имен (SAN)
if [ "${WILDCARD}" = "yes" ]; then
SAN="DNS:${DOMAIN},DNS:*.${DOMAIN}"
else
SAN="DNS:${DOMAIN}"
fi
# Создание конфигурации OpenSSL
cat > openssl.cnf <<EOF
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req
[dn]
C=RU
ST=Moscow
L=Moscow
O=Test Certificate
CN=${DOMAIN}
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = ${SAN}
EOF
# Генерация приватного ключа
echo -e "${YELLOW}→ Генерация приватного ключа RSA 2048 бит...${NC}"
openssl genrsa -out privkey.pem 2048 2>/dev/null
chmod 600 privkey.pem
echo -e "${GREEN}✓ Приватный ключ сохранен: ${CERT_DIR}/privkey.pem${NC}"
# Генерация сертификата
echo -e "${YELLOW}→ Генерация самоподписанного сертификата...${NC}"
openssl req \
-new \
-x509 \
-key privkey.pem \
-out cert.pem \
-days ${VALIDITY_DAYS} \
-config openssl.cnf \
-extensions v3_req \
2>/dev/null
echo -e "${GREEN}✓ Сертификат сохранен: ${CERT_DIR}/cert.pem${NC}"
# Создание fullchain (копия cert для самоподписанного)
cp cert.pem fullchain.pem
echo -e "${GREEN}✓ Fullchain сохранен: ${CERT_DIR}/fullchain.pem${NC}"
# Создание пустого chain.pem
touch chain.pem
echo -e "${GREEN}✓ Chain файл создан: ${CERT_DIR}/chain.pem${NC}"
# Удаление временного файла конфигурации
rm -f openssl.cnf
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Информация о сертификате ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
# Вывод информации о сертификате
openssl x509 -in cert.pem -noout -subject -dates -ext subjectAltName
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ✓ Тестовый сертификат успешно создан ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}📁 Файлы сертификата:${NC}"
echo -e " • Приватный ключ: ${CERT_DIR}/privkey.pem"
echo -e " • Сертификат: ${CERT_DIR}/cert.pem"
echo -e " • Fullchain: ${CERT_DIR}/fullchain.pem"
echo -e " • Chain: ${CERT_DIR}/chain.pem"
echo ""
echo -e "${YELLOW}⚠️ ВНИМАНИЕ:${NC}"
echo -e " Это самоподписанный тестовый сертификат!"
echo -e " Браузеры будут показывать предупреждение о безопасности."
echo -e " Используйте ТОЛЬКО для тестирования и разработки!"
echo ""
echo -e "${YELLOW}Использование в Nginx:${NC}"
echo -e " ssl_certificate ${CERT_DIR}/fullchain.pem;"
echo -e " ssl_certificate_key ${CERT_DIR}/privkey.pem;"
echo ""
# Предложение загрузить в NPM
echo -e "${YELLOW}Загрузить в Nginx Proxy Manager?${NC}"
echo -e " Используйте Python скрипт с опцией --test-cert"
echo -e " или загрузите вручную через веб-интерфейс NPM"
echo ""