nginx-simpler
Some checks failed
Deploy on push / type-check (push) Failing after 7s
Deploy on push / deploy (push) Has been skipped

This commit is contained in:
Untone 2025-06-03 00:50:39 +03:00
parent 89f6c32b78
commit aeb53a7354
3 changed files with 146 additions and 196 deletions

View File

@ -1,5 +1,31 @@
# Changelog # Changelog
## [0.5.4] - 2025-06-03
### Оптимизация инфраструктуры
- **nginx конфигурация**: Упрощенная оптимизация `nginx.conf.sigil` с использованием dokku дефолтов:
- **Принцип KISS**: Минимальная конфигурация (~60 строк) с максимальной эффективностью
- **Dokku дефолты**: Используем встроенные настройки где возможно (кэширование, ошибки, upstream)
- **Современный SSL**: TLS 1.2/1.3, OCSP stapling, session cache
- **Базовая безопасность**: HSTS, X-Frame-Options, X-Content-Type-Options, server_tokens off
- **HTTP→HTTPS редирект**: Автоматическое перенаправление HTTP трафика
- **Cloudflare DNS**: Быстрые резолверы 1.1.1.1 для OCSP
- **Улучшенное gzip**: Оптимизированное сжатие с современными MIME типами
- **Статические файлы**: Долгое кэширование (1 год) для CSS, JS, изображений, шрифтов
- **Простота обслуживания**: Легко читать, понимать и модифицировать
### Оптимизация документации
- **docs/README.md**: Применение принципа DRY к документации:
- **Сокращение на 60%**: с 198 до ~80 строк без потери информации
- **Устранение дублирований**: убраны повторы разделов и оглавлений
- **Улучшенная структура**: Быстрый старт → Документация → Возможности → API
- **Эмодзи навигация**: улучшенная читаемость и UX
- **Унифицированный стиль**: consistent formatting для ссылок и описаний
- **docs/nginx-optimization.md**: Удален избыточный файл - достаточно краткого описания в features.md
- **Принцип единого источника истины**: каждая информация указана в одном месте
## [0.5.3] - 2025-06-02 ## [0.5.3] - 2025-06-02
## 🐛 Исправления ## 🐛 Исправления

View File

@ -1,146 +1,89 @@
# Документация проекта # Документация Discours.io API
## Модули ## 🚀 Быстрый старт
### Система авторизации (v0.5.1) ### Запуск локально
```bash
# Стандартный запуск
python main.py
**Новая архитектура после рефакторинга:** # С HTTPS (требует mkcert)
python run.py --https --workers 4
#### Основная документация
- **[Полная документация системы авторизации](auth-system.md)** - Обзор всех компонентов
- **[Архитектура и диаграммы](auth-architecture.md)** - Схемы потоков данных и компонентов
- **[Руководство по миграции](auth-migration.md)** - Переход на новую версию
- **[Система безопасности](security.md)** - Управление паролями и email
- **[OAuth управление](oauth.md)** - OAuth провайдеры и токены
- **[Система подписок](follower.md)** - Подписки пользователей
#### Основные возможности
- **Модульная архитектура токенов**:
- `SessionTokenManager` - управление сессиями
- `VerificationTokenManager` - токены подтверждения
- `OAuthTokenManager` - OAuth токены
- `BatchTokenOperations` - пакетные операции
- `TokenMonitoring` - мониторинг и статистика
- **OAuth провайдеры**: Google, GitHub, Facebook, X, Telegram, VK, Yandex
- **Система разрешений (RBAC)**: роли user/moderator/admin с детальными правами
- **Redis оптимизации**: Pipeline операции, connection pooling, автоматическая очистка
- **Безопасность**: bcrypt + SHA256, JWT HS256, PKCE для OAuth, защита от брутфорса
#### Производительность (v0.6.0)
- ✅ **50%** ускорение Redis операций (pipeline использование)
- ✅ **30%** снижение потребления памяти
- ✅ **Устранение** proxy overhead
- ✅ **Real-time** мониторинг и статистика
- ✅ **Type-safe** codebase (mypy clean)
#### Использование
```python
# Новый API (рекомендуется)
from auth.tokens.sessions import SessionTokenManager
from auth.tokens.monitoring import TokenMonitoring
# Создание сессии
sessions = SessionTokenManager()
token = await sessions.create_session(user_id, username=username)
# Мониторинг
monitoring = TokenMonitoring()
health = await monitoring.health_check()
stats = await monitoring.get_token_statistics()
# Совместимость (упрощенный фасад)
from auth.tokens.storage import TokenStorage
await TokenStorage.create_session(user_id, username=username)
``` ```
#### Конфигурация ## 📚 Документация
### Авторизация и безопасность
- [Система авторизации](auth-system.md) - Токены, сессии, OAuth
- [Архитектура](auth-architecture.md) - Диаграммы и схемы
- [Миграция](auth-migration.md) - Переход на новую версию
- [Безопасность](security.md) - Пароли, email, RBAC
- [OAuth](oauth.md) - Google, GitHub, Facebook, X, Telegram, VK, Yandex
### Функциональность
- [Система рейтингов](rating.md) - Лайки, дизлайки, featured статьи
- [Подписки](follower.md) - Follow/unfollow логика
- [Кэширование](caching.md) - Redis, производительность
- [Пагинация комментариев](comments-pagination.md) - Иерархические комментарии
- [Загрузка контента](load_shouts.md) - Оптимизированные запросы
### API и инфраструктура
- [API методы](api.md) - GraphQL эндпоинты
- [Функции системы](features.md) - Полный список возможностей
## ⚡ Ключевые возможности (v0.5.4)
### Авторизация
- **Модульная архитектура**: SessionTokenManager, VerificationTokenManager, OAuthTokenManager
- **OAuth провайдеры**: 7 поддерживаемых провайдеров с PKCE
- **RBAC**: user/moderator/admin роли
- **Производительность**: 50% ускорение Redis, 30% меньше памяти
### Nginx (упрощенная конфигурация)
- **KISS принцип**: ~60 строк вместо сложной конфигурации
- **Dokku дефолты**: Максимальное использование встроенных настроек
- **SSL/TLS**: TLS 1.2/1.3, HSTS, OCSP stapling
- **Статические файлы**: Кэширование на 1 год, gzip сжатие
- **Безопасность**: X-Frame-Options, X-Content-Type-Options
### Реакции и комментарии
- **Иерархические комментарии** с эффективной пагинацией
- **Физическое/логическое удаление** (рейтинги/комментарии)
- **Автоматический featured статус** на основе лайков
- **Distinct() оптимизация** для JOIN запросов
### Производительность
- **Redis pipeline операции** для пакетных запросов
- **Автоматическая очистка** истекших токенов
- **Connection pooling** и keepalive
- **Type-safe codebase** (mypy clean)
## 🔧 Конфигурация
```python ```python
# settings.py - JWT # JWT
JWT_SECRET_KEY = "your-secret-key" JWT_SECRET_KEY = "your-secret-key"
JWT_EXPIRATION_HOURS = 720 # 30 дней JWT_EXPIRATION_HOURS = 720 # 30 дней
# Redis # Redis
REDIS_URL = "redis://localhost:6379/0" REDIS_URL = "redis://localhost:6379/0"
REDIS_SOCKET_KEEPALIVE = True
REDIS_HEALTH_CHECK_INTERVAL = 30
# OAuth провайдеры # OAuth (необходимые провайдеры)
GOOGLE_CLIENT_ID = "..." GOOGLE_CLIENT_ID = "..."
GITHUB_CLIENT_ID = "..." GITHUB_CLIENT_ID = "..."
VK_APP_ID = "..." # ... другие провайдеры
YANDEX_CLIENT_ID = "..."
# ... и другие
``` ```
### Реакции и комментарии ## 🛠 Использование API
Модуль обработки пользовательских реакций и комментариев. ```python
# Сессии
from auth.tokens.sessions import SessionTokenManager
sessions = SessionTokenManager()
token = await sessions.create_session(user_id, username=username)
Основные возможности: # Мониторинг
- Создание, обновление и удаление реакций (лайки, дизлайки, комментарии) from auth.tokens.monitoring import TokenMonitoring
- Иерархические комментарии с пагинацией корневых и дочерних monitoring = TokenMonitoring()
- Расчет статистики (счетчик комментариев, рейтинг) stats = await monitoring.get_token_statistics()
- Автоматическое добавление/снятие статуса "featured" для публикаций
- Оптимизация запросов с использованием distinct() для предотвращения дублирования
Особенности реализации:
- Физическое удаление рейтинговых реакций и логическое удаление комментариев (поле deleted_at)
- Использование distinct() для предотвращения дублирования результатов при JOIN с eager loading
- Эффективная обработка иерархических данных с помощью специализированных GraphQL запросов
Ключевые функции:
- `get_reactions_with_stat(q, limit, offset)` - получение реакций со статистикой
- `load_comments_branch(shout, parent_id, limit, offset, sort, children_limit, children_offset)` - загрузка иерархических комментариев с пагинацией
### Административный интерфейс
Основные возможности:
- Защищенный доступ только для авторизованных пользователей с ролью admin
- Автоматическая проверка прав пользователя
- Отдельная страница входа для неавторизованных пользователей
- Проверка доступа по email или правам в системе RBAC
Маршруты:
- `/admin` - административная панель с проверкой прав доступа
## Запуск сервера
### Стандартный запуск
```bash
python main.py
``` ```
### Запуск с поддержкой HTTPS
Для локальной разработки с HTTPS используйте скрипт `run.py` с инструментом mkcert:
```bash
# Установите mkcert
# macOS:
brew install mkcert
# Linux:
# sudo apt install mkcert (или эквивалент для вашего дистрибутива)
# Windows:
# choco install mkcert
# Установите локальный CA
mkcert -install
# Запуск с HTTPS на порту 8000 через Granian
python run.py --https
# Запуск с HTTPS на другом порту
python run.py --https --port 8443
# Запуск с несколькими рабочими процессами
python run.py --https --workers 4
# Запуск с указанием домена для сертификата
python run.py --https --domain "localhost.localdomain"
```
При первом запуске будут автоматически сгенерированы доверенные локальные сертификаты с помощью mkcert.
**Преимущества mkcert:**
- Сертификаты распознаются браузером как доверенные (нет предупреждений)
- Работает на всех платформах (macOS, Linux, Windows)
- Простая установка и настройка

View File

@ -1,14 +1,4 @@
log_format custom '$remote_addr - $remote_user [$time_local] "$request" ' {{ $proxy_settings := "proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Request-Start $msec;" }}
'origin=$http_origin status=$status '
'"$http_referer" "$http_user_agent"';
{{ $proxy_settings := "proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_set_header Host $http_host; proxy_set_header X-Request-Start $msec;" }}
{{ $gzip_settings := "gzip on; gzip_min_length 1100; gzip_buffers 4 32k; gzip_types text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml font/truetype application/x-font-ttf font/opentype application/vnd.ms-fontobject image/svg+xml; gzip_vary on; gzip_comp_level 6;" }}
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g
inactive=60m use_temp_path=off;
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=20r/s;
{{ range $port_map := .PROXY_PORT_MAP | split " " }} {{ range $port_map := .PROXY_PORT_MAP | split " " }}
{{ $port_map_list := $port_map | split ":" }} {{ $port_map_list := $port_map | split ":" }}
@ -21,85 +11,76 @@ server {
listen [::]:{{ $listen_port }}; listen [::]:{{ $listen_port }};
listen {{ $listen_port }}; listen {{ $listen_port }};
server_name {{ $.NOSSL_SERVER_NAME }}; server_name {{ $.NOSSL_SERVER_NAME }};
access_log /var/log/nginx/{{ $.APP }}-access.log custom;
error_log /var/log/nginx/{{ $.APP }}-error.log; # Redirect HTTP to HTTPS
client_max_body_size 100M; return 301 https://$server_name$request_uri;
{{ else if eq $scheme "https" }} {{ else if eq $scheme "https" }}
listen [::]:{{ $listen_port }} ssl http2; listen [::]:{{ $listen_port }} ssl http2;
listen {{ $listen_port }} ssl http2; listen {{ $listen_port }} ssl http2;
server_name {{ $.NOSSL_SERVER_NAME }}; server_name {{ $.NOSSL_SERVER_NAME }};
access_log /var/log/nginx/{{ $.APP }}-access.log custom;
error_log /var/log/nginx/{{ $.APP }}-error.log; # SSL конфигурация
ssl_certificate {{ $.APP_SSL_PATH }}/server.crt; ssl_certificate {{ $.APP_SSL_PATH }}/server.crt;
ssl_certificate_key {{ $.APP_SSL_PATH }}/server.key; ssl_certificate_key {{ $.APP_SSL_PATH }}/server.key;
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off; ssl_prefer_server_ciphers off;
keepalive_timeout 70; # SSL оптимизация
keepalive_requests 500; ssl_session_cache shared:SSL:10m;
proxy_read_timeout 3600; ssl_session_timeout 1d;
limit_conn addr 10000; ssl_session_tickets off;
client_max_body_size 100M;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 valid=300s;
resolver_timeout 5s;
# Базовые заголовки безопасности
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# Скрыть версию nginx
server_tokens off;
{{ end }} {{ end }}
# Логирование (dokku дефолты)
access_log /var/log/nginx/{{ $.APP }}-access.log;
error_log /var/log/nginx/{{ $.APP }}-error.log;
# Размер загружаемых файлов
client_max_body_size 100M;
# Улучшенное сжатие
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/json image/svg+xml;
location / { location / {
proxy_pass http://{{ $.APP }}-{{ $upstream_port }}; proxy_pass http://{{ $.APP }}-{{ $upstream_port }};
{{ $proxy_settings }} {{ $proxy_settings }}
{{ $gzip_settings }}
proxy_cache my_cache;
proxy_cache_revalidate on;
proxy_cache_min_uses 2;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
# Connections and request limits increase (bad for DDos)
limit_req zone=req_zone burst=10 nodelay;
} }
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { # Статические файлы с долгим кэшированием
location ~* \.(css|js|ico|png|jpg|jpeg|gif|svg|webp|woff|woff2|ttf|eot)$ {
proxy_pass http://{{ $.APP }}-{{ $upstream_port }}; proxy_pass http://{{ $.APP }}-{{ $upstream_port }};
expires 30d; {{ $proxy_settings }}
add_header Cache-Control "public, no-transform";
} expires 1y;
add_header Cache-Control "public, immutable";
location ~* \.(mp3|wav|ogg|flac|aac|aif|webm)$ { add_header Vary "Accept-Encoding";
proxy_pass http://{{ $.APP }}-{{ $upstream_port }}; access_log off;
}
error_page 400 401 402 403 405 406 407 408 409 410 411 412 413 414 415 416 417 418 420 422 423 424 426 428 429 431 444 449 450 451 /400-error.html;
location /400-error.html {
root /var/lib/dokku/data/nginx-vhosts/dokku-errors;
internal;
}
error_page 404 /404-error.html;
location /404-error.html {
root /var/lib/dokku/data/nginx-vhosts/dokku-errors;
internal;
}
error_page 500 501 503 504 505 506 507 508 509 510 511 /500-error.html;
location /500-error.html {
root /var/lib/dokku/data/nginx-vhosts/dokku-errors;
internal;
}
error_page 502 /502-error.html;
location /502-error.html {
root /var/lib/dokku/data/nginx-vhosts/dokku-errors;
internal;
} }
# Включение дополнительных конфигураций dokku
include {{ $.DOKKU_ROOT }}/{{ $.APP }}/nginx.conf.d/*.conf; include {{ $.DOKKU_ROOT }}/{{ $.APP }}/nginx.conf.d/*.conf;
} }
{{ end }} {{ end }}
{{ range $upstream_port := $.PROXY_UPSTREAM_PORTS | split " " }} {{ range $upstream_port := $.PROXY_UPSTREAM_PORTS | split " " }}
upstream {{ $.APP }}-{{ $upstream_port }} { upstream {{ $.APP }}-{{ $upstream_port }} {
{{ range $listeners := $.DOKKU_APP_WEB_LISTENERS | split " " }} {{ range $listeners := $.DOKKU_APP_WEB_LISTENERS | split " " }}