Добавлены новые документы и скрипты для автоматизации создания и управления SSL сертификатами Let's Encrypt с использованием API reg.ru и Nginx Proxy Manager. Обновлены инструкции по тестированию, настройке и использованию сертификатов, включая создание тестовых сертификатов и интеграцию с NPM. Включены примеры использования и устранения неполадок, а также улучшена структура проекта.
This commit is contained in:
153
CHANGELOG.md
Normal file
153
CHANGELOG.md
Normal 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
263
CHEATSHEET.md
Normal 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
410
Makefile
Normal 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
202
PROJECT_STRUCTURE.md
Normal 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
904
README.md
@@ -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
382
TESTING_GUIDE.md
Normal 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 сертификаты без ограничений!
|
||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
# Вывод в консоль
|
# Вывод в консоль
|
||||||
|
|||||||
@@ -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
143
test_certificate.sh
Normal 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 ""
|
||||||
Reference in New Issue
Block a user