Return debug info in API response for admin auth errors
Some checks failed
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Deploy Telegram Bot / Deploy Telegram Bot (push) Has been cancelled
Some checks failed
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Deploy Telegram Bot / Deploy Telegram Bot (push) Has been cancelled
This will show the exact reason for token verification failure
This commit is contained in:
parent
24b584d835
commit
a92cade04f
10 changed files with 985 additions and 21 deletions
181
PROGRESS.md
Normal file
181
PROGRESS.md
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
2025-12-07
|
||||
- Добавлена подробная инструкция по миграции в Coolify (Docker backend, статический web/admin, внешняя БД) — `docs/coolify-migration.md`.
|
||||
# Mnemo Cards Project Progress
|
||||
|
||||
## Infrastructure & Deployment
|
||||
|
||||
### ✅ Completed Tasks
|
||||
|
||||
- **nginx Configuration System**: Implemented robust nginx configuration generation and deployment
|
||||
- Created `generate-nginx-configs.sh` for generating all nginx configurations
|
||||
- Created `deploy-nginx-configs.sh` for safe deployment with validation
|
||||
- Updated `check-nginx.sh` with port conflict detection and cleanup
|
||||
- Integrated into CI/CD pipeline
|
||||
|
||||
- **Reverse Proxy Architecture**: Properly configured nginx as reverse proxy for all services
|
||||
- `mnemo-cards.online` → Flutter web app (static files)
|
||||
- `code.mnemo-cards.online` → Forgejo (port 3000)
|
||||
- `vscode.mnemo-cards.online` → VSCode Server (port 8443)
|
||||
|
||||
- **Automated Version Management**: Implemented pre-deploy version bumping
|
||||
- Created `bump-version.sh` script for automatic version increment
|
||||
- Integrated as pre-hook in CI/CD pipeline
|
||||
- Updates both pubspec.yaml and API configuration
|
||||
- Automatic git commit with version changes
|
||||
|
||||
- **SSL/TLS Configuration**: Secure HTTPS setup with Let's Encrypt certificates
|
||||
- Multi-domain certificates for all subdomains
|
||||
- Proper certificate permissions and renewal
|
||||
|
||||
- **Admin API Configuration**: Fixed admin authentication routing
|
||||
- Admin panel now correctly routes authentication requests to production backend
|
||||
- Prevents localhost:8000 routing issues during development
|
||||
- Separate API client for admin endpoints ensures proper server targeting
|
||||
|
||||
- **Service Reliability**: Enhanced service management and monitoring
|
||||
- Port conflict detection and resolution
|
||||
- Orphaned process cleanup
|
||||
- Configuration validation before deployment
|
||||
- Emergency fallback configurations
|
||||
- Coolify container orchestration platform deployed
|
||||
|
||||
### 🔄 In Progress
|
||||
|
||||
- **Coolify Migration**: Container orchestration platform for services
|
||||
- Coolify installed and configured on `coolify.mnemo-cards.online`
|
||||
- Automatic startup configured via cron @reboot
|
||||
- Ready for service migration (backend, web, admin)
|
||||
- **Monitoring & Alerting**: Implement comprehensive service monitoring
|
||||
- **Backup Automation**: Automated backup procedures for all services
|
||||
|
||||
### 📋 Planned Tasks
|
||||
|
||||
- **Load Balancing**: Implement load balancing for high availability
|
||||
- **CDN Integration**: Content delivery network for static assets
|
||||
- **Security Hardening**: Additional security measures and hardening
|
||||
|
||||
## Development Status
|
||||
|
||||
### Web Application (mnemo_cards_web_v2)
|
||||
- **Framework**: Flutter Web
|
||||
- **Status**: Active development
|
||||
- **Key Features**: Vocabulary learning, testing, statistics
|
||||
- **Recent Updates**:
|
||||
- Added card voice support (metadata, API, web playback with error UI)
|
||||
- New voices collection linked to cards and public endpoints for list/mp3
|
||||
- Web CardViewer now fetches voices and plays audio via audioplayers
|
||||
- Added unit tests for API config and voice fetching
|
||||
- Added app version display on authentication page
|
||||
- **UI Components Refactoring**: Extracted authentication components
|
||||
- Created `SignInWithGoogleButton` component for Google authentication
|
||||
- Created `SignInWithTelegram` component for Telegram authentication
|
||||
- Improved code maintainability and reusability
|
||||
- **Profile Page UI/UX Improvements**: Enhanced profile page design and functionality
|
||||
- Removed guest view - profile now only accessible for authenticated users
|
||||
- Removed account statistics (packs/purchases) from profile
|
||||
- Removed language toggle from settings
|
||||
- Created custom `ThemeToggleWidget` with sun/moon icons and animations
|
||||
- Enhanced subscription section with premium badge and upgrade button for free users
|
||||
- Added staggered animations for card appearances
|
||||
- Improved logout flow with confirmation dialog
|
||||
- Added comprehensive unit tests for new components
|
||||
- **Game/Test Flow Cleanup**: Simplified testing UX and fixed theme visuals
|
||||
- Removed legacy traditional test entry from `test_page.dart` (interactive mode only)
|
||||
- Added SafeArea wrapping and themed question cards on `game_page.dart`
|
||||
- Added widget tests for themed question cards, exit control, and interactive-only notice
|
||||
- Timer/progress now sourced from live session state on `game_page.dart`
|
||||
- **Game Tests Package**: Started shared package `games/packages/game_tests`
|
||||
- Added configurable `GameTestSettings` (sounds/haptics/delay)
|
||||
- Integrated into `mnemo_cards_web_v2` via `TestsModule`/`TestsStateManager`
|
||||
- **Test Page Code Quality Fix**: Fixed critical code duplication and compilation issues
|
||||
- Removed 700+ lines of duplicate code in `test_page.dart`
|
||||
- Added missing state variables for test functionality
|
||||
- Created `TestResult` class for proper result handling
|
||||
- Fixed deprecated `withOpacity` method calls
|
||||
- Restored full test functionality with interactive game and traditional test modes
|
||||
- **PackDetailsHeader Code Fix**: Fixed critical structural issues in pack details header widget
|
||||
- Resolved broken method structure with hanging code blocks
|
||||
- Created missing `_buildTitleSection` method
|
||||
- Removed undefined `cachedImage` variable usage
|
||||
- Cleaned up unused imports
|
||||
- Fixed all linter errors and compilation issues
|
||||
|
||||
### Mobile Application (mnemo_cards)
|
||||
- **Framework**: Flutter
|
||||
- **Status**: Active development
|
||||
- **Key Features**: Cross-platform mobile app
|
||||
|
||||
### Backend (mnemo_cards_backend)
|
||||
- **Framework**: Dart with Shelf
|
||||
- **Status**: Production ready
|
||||
- **Key Features**: API, authentication, data management
|
||||
|
||||
### Common Libraries
|
||||
- **mnemo_cards_common**: Shared models and utilities
|
||||
- **mnemo_cards_common_backend**: Backend-specific common code
|
||||
- **mnemo_cards_frontend_common**: Frontend-specific common code
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
- **Coverage**: Basic test coverage implemented
|
||||
- **Status**: Ongoing - needs expansion
|
||||
|
||||
### Integration Tests
|
||||
- **Status**: Minimal - needs implementation
|
||||
|
||||
### E2E Tests
|
||||
- **Status**: Not implemented
|
||||
|
||||
## Deployment Pipeline
|
||||
|
||||
### CI/CD Status
|
||||
- **Platform**: Forgejo Actions (self-hosted)
|
||||
- **Triggers**: Push to master branch
|
||||
- **Jobs**:
|
||||
- Backend deployment
|
||||
- Web application deployment
|
||||
- Admin panel deployment (improved portability)
|
||||
- Telegram bot deployment
|
||||
- Nginx configuration deployment
|
||||
- Service verification
|
||||
|
||||
- **Deployment Script Improvements**:
|
||||
- Enhanced admin panel deployment script portability
|
||||
- Script can now be run from any directory within the project
|
||||
- Automatic project root detection and navigation
|
||||
- Improved error handling and user feedback
|
||||
|
||||
### Environments
|
||||
- **Production**: `147.45.152.129` (mnemo-cards.online)
|
||||
- **Development**: Local development environments
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
### Target Metrics
|
||||
- **Page Load Time**: < 3 seconds
|
||||
- **API Response Time**: < 500ms
|
||||
- **Uptime**: 99.9%
|
||||
|
||||
### Current Status
|
||||
- Basic monitoring in place
|
||||
- Performance optimization ongoing
|
||||
|
||||
## Security
|
||||
|
||||
### Implemented
|
||||
- HTTPS enforcement
|
||||
- SSL/TLS certificates (Let's Encrypt for all domains including admin.mnemo-cards.online)
|
||||
- Automated SSL certificate renewal
|
||||
- Basic firewall rules
|
||||
- Service isolation
|
||||
|
||||
### Planned
|
||||
- Advanced security headers
|
||||
- Rate limiting
|
||||
- Intrusion detection
|
||||
- Regular security audits
|
||||
|
||||
---
|
||||
|
||||
*Last updated: December 10, 2025*
|
||||
170
TODO.md
Normal file
170
TODO.md
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
- Подготовить Dockerfile и CI/CD для Dart backend под Coolify.
|
||||
- Подготовить Dockerfile и CI/CD для веб/админки (статический билд + nginx/caddy).
|
||||
- Завести сервисы и домены в Coolify (api/web/admin) с Traefik/LE.
|
||||
- Переключить трафик, остановить legacy nginx/systemd после проверки.
|
||||
# Mnemo Cards TODO List
|
||||
|
||||
## High Priority
|
||||
|
||||
### Infrastructure & Deployment
|
||||
- [x] **Admin Panel Deployment**: Fixed automated CI/CD pipeline for admin panel
|
||||
- Fixed directory navigation issue in `tools/deploy/admin/deploy.sh`
|
||||
- Modified `check_project_root()` function to automatically navigate to `mnemo_cards_admin/web`
|
||||
- **Enhanced portability**: Script can now be run from any directory within the project
|
||||
- Added intelligent project root detection that searches upwards from script location
|
||||
- **SSL Certificate Fix**: Resolved HTTPS certificate issue for admin.mnemo-cards.online
|
||||
- Created automated SSL certificate renewal script (`tools/ssl/renew_admin_ssl.sh`)
|
||||
- Obtained Let's Encrypt certificate for admin.mnemo-cards.online
|
||||
- Updated nginx configuration to use HTTPS with proper SSL certificates
|
||||
- Added automatic certificate renewal via cron job
|
||||
- **Admin API Configuration Fix**: Fixed admin authentication API URL routing
|
||||
- Created separate `adminApiClient` that always uses production backend (`https://api.mnemo-cards.online`)
|
||||
- Admin authentication now correctly routes to production server instead of localhost:8000
|
||||
- Prevents authentication failures during local development
|
||||
- Admin panel deployment now works correctly from CI/CD pipeline and any project directory with valid HTTPS
|
||||
|
||||
- [x] **Telegram Bot Deployment**: Created automated CI/CD pipeline for telegram bot
|
||||
- Created `deploy_bot.yaml` workflow for automated bot deployment
|
||||
- Triggers on changes to `mnemo_cards_telegram_bot/**`, `mnemo_cards_common/**`, `mnemo_cards_common_backend/**`
|
||||
- Compiles Dart executable and updates systemd service
|
||||
- Includes proper error handling and service verification
|
||||
|
||||
- [ ] **Monitoring Setup**: Implement comprehensive monitoring for all services
|
||||
- Application performance monitoring (APM)
|
||||
- Server resource monitoring
|
||||
- Service health checks
|
||||
- Alerting system
|
||||
|
||||
- [ ] **Backup Automation**: Automated backup procedures
|
||||
- Database backups
|
||||
- Configuration backups
|
||||
- User data backups
|
||||
- Recovery testing
|
||||
|
||||
- [ ] **Load Testing**: Performance testing under load
|
||||
- Identify bottlenecks
|
||||
- Optimize resource usage
|
||||
- Scalability testing
|
||||
|
||||
### Testing
|
||||
- [ ] **Unit Test Coverage**: Expand unit test coverage
|
||||
- Backend services: Target 80% coverage
|
||||
- Frontend components: Target 70% coverage
|
||||
- Common libraries: Target 90% coverage
|
||||
- ✅ Added unit test for version display on auth page
|
||||
- ✅ Refactored authentication components - need to add unit tests for SignInWithGoogleButton and SignInWithTelegram
|
||||
- ✅ Added comprehensive unit tests for ThemeToggleWidget (7 test cases covering all functionality)
|
||||
- ✅ Game/Test flow cleanup: removed traditional test entry, themed game page, added widget coverage for question card surfaces, exit control, and interactive-only notice; timer/progress pulled from live session state
|
||||
- ✅ Game Tests package: created `games/packages/game_tests`, added `GameTestSettings`, integrated into `mnemo_cards_web_v2` settings and state manager
|
||||
- ✅ **Test Page Code Quality Fix**: Fixed critical code duplication in `test_page.dart`
|
||||
- Removed 700+ lines of duplicate code
|
||||
- Added missing state variables and TestResult class
|
||||
- Fixed deprecated method calls and compilation issues
|
||||
- Restored full test functionality
|
||||
- ✅ **PackDetailsHeader Code Fix**: Fixed critical structural issues in pack details header widget
|
||||
- Resolved broken method structure with hanging code blocks
|
||||
- Created missing `_buildTitleSection` method
|
||||
- Removed undefined `cachedImage` variable usage
|
||||
- Cleaned up unused imports
|
||||
- Fixed all linter errors and compilation issues
|
||||
|
||||
- [ ] **Integration Tests**: Implement comprehensive integration testing
|
||||
- API endpoint testing
|
||||
- Database operations
|
||||
- Service interactions
|
||||
|
||||
- [ ] **E2E Tests**: End-to-end testing suite
|
||||
- User journey testing
|
||||
- Cross-browser compatibility
|
||||
- Mobile device testing
|
||||
|
||||
## Medium Priority
|
||||
|
||||
### Security
|
||||
- [ ] **Security Audit**: Comprehensive security review
|
||||
- Code security analysis
|
||||
- Infrastructure security
|
||||
- Data protection compliance
|
||||
|
||||
- [ ] **Advanced Security**: Enhanced security measures
|
||||
- Rate limiting implementation
|
||||
- Advanced firewall rules
|
||||
- Intrusion detection
|
||||
- Security headers optimization
|
||||
|
||||
### Performance
|
||||
- [ ] **Frontend Optimization**: Web application performance
|
||||
- Bundle size optimization
|
||||
- Lazy loading implementation
|
||||
- Caching strategies
|
||||
|
||||
- [ ] **Backend Optimization**: API performance improvements
|
||||
- Database query optimization
|
||||
- Caching layer implementation
|
||||
- Response time optimization
|
||||
|
||||
### Features
|
||||
- [x] **Card Voices**: Audio metadata & playback
|
||||
- Isar collection for voices linked to cards
|
||||
- Public API for voices list and mp3 delivery
|
||||
- Web UI playback with error handling and tests
|
||||
- [ ] **User Experience**: Enhanced user experience features
|
||||
- Offline mode support
|
||||
- Progressive Web App (PWA)
|
||||
- Advanced statistics and analytics
|
||||
|
||||
## Low Priority
|
||||
|
||||
### Infrastructure
|
||||
- [ ] **CDN Integration**: Content delivery network
|
||||
- Static asset delivery
|
||||
- Global performance improvement
|
||||
- Cost optimization
|
||||
|
||||
- [ ] **Containerization**: Docker containerization
|
||||
- Development environment standardization
|
||||
- Deployment consistency
|
||||
- Scaling capabilities
|
||||
|
||||
### Documentation
|
||||
- [ ] **API Documentation**: Comprehensive API docs
|
||||
- OpenAPI/Swagger documentation
|
||||
- Developer guides
|
||||
- Integration examples
|
||||
|
||||
- [ ] **User Documentation**: User-facing documentation
|
||||
- User guides
|
||||
- FAQ section
|
||||
- Video tutorials
|
||||
|
||||
### Analytics
|
||||
- [ ] **Usage Analytics**: User behavior analysis
|
||||
- Feature usage tracking
|
||||
- Performance metrics
|
||||
- User engagement analysis
|
||||
|
||||
---
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Code Quality
|
||||
- Follow established coding standards
|
||||
- Implement proper error handling
|
||||
- Use TypeScript/Flow for type safety
|
||||
- Regular code reviews
|
||||
|
||||
### Testing Strategy
|
||||
- Write tests before implementing features (TDD)
|
||||
- Maintain test coverage above established thresholds
|
||||
- Regular integration testing
|
||||
- Performance regression testing
|
||||
|
||||
### Deployment Process
|
||||
- Automated deployment pipeline
|
||||
- Rollback capabilities
|
||||
- Environment parity
|
||||
- Zero-downtime deployments
|
||||
|
||||
---
|
||||
|
||||
*Last updated: December 6, 2025*
|
||||
136
docs/coolify-migration.md
Normal file
136
docs/coolify-migration.md
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
# Coolify: перенос сервисов (backend Docker, web статик, внешняя БД)
|
||||
|
||||
Цель: перенести существующие сервисы в Coolify (через Traefik/Let’s Encrypt), сохранив БД на хосте. Ниже — пошаговая инструкция, Dockerfile-примеры, настройки Coolify и порядок переключения трафика.
|
||||
|
||||
## 1. Backend (Dart) в Docker
|
||||
|
||||
### Структура образа
|
||||
- Base (builder): `dart:stable-sdk`
|
||||
- Runtime: `debian:bookworm-slim` (или distroless)
|
||||
- Порт: `8081`
|
||||
- Health: `GET /health` (замените, если другой endpoint)
|
||||
|
||||
### Пример Dockerfile
|
||||
```
|
||||
# stage: build
|
||||
FROM dart:stable-sdk AS builder
|
||||
WORKDIR /app
|
||||
COPY pubspec.* ./
|
||||
RUN dart pub get
|
||||
COPY . .
|
||||
RUN dart compile exe lib/main.dart -o /app/server
|
||||
|
||||
# stage: runtime
|
||||
FROM debian:bookworm-slim
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/server /app/server
|
||||
EXPOSE 8081
|
||||
CMD ["/app/server", "-a", "0.0.0.0", "-p", "8081"]
|
||||
```
|
||||
|
||||
### Env для внешней БД (БД остаётся на хосте)
|
||||
- `DB_HOST` — IP хоста (обычно `172.17.0.1` или реальный публичный/приватный IP)
|
||||
- `DB_PORT` — порт вашей БД
|
||||
- `DB_NAME`, `DB_USER`, `DB_PASSWORD`
|
||||
- Если нужен TLS к БД: добавить флаги клиента/сертификаты
|
||||
|
||||
### Настройка сети/Traefik
|
||||
- В сервисе (compose) добавить:
|
||||
```
|
||||
networks:
|
||||
- coolify
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
```
|
||||
- Traefik (через Coolify UI → Domains):
|
||||
- Domain: `api.mnemo-cards.online`
|
||||
- EntryPoints: `websecure`
|
||||
- Cert resolver: `le`
|
||||
- HTTP→HTTPS редирект уже есть через middleware redirectscheme
|
||||
|
||||
### Шаги в Coolify (UI)
|
||||
1. Project → Environment → New Service → Dockerfile.
|
||||
2. Указать репозиторий/ветку и путь к Dockerfile.
|
||||
3. Env: `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD` (+ ваши APP_*).
|
||||
4. Network: подключить `coolify`.
|
||||
5. Domains: `api.mnemo-cards.online`, entrypoint `websecure`, resolver `le`.
|
||||
6. Healthcheck: HTTP 200 на `/health` (или ваш путь).
|
||||
|
||||
## 2. Web и Admin (Flutter Web) как статика в контейнере
|
||||
|
||||
### Сборка
|
||||
```
|
||||
flutter build web --release \
|
||||
--dart-define=API_BASE_URL=https://api.mnemo-cards.online
|
||||
```
|
||||
Артефакт: `build/web/`.
|
||||
|
||||
### Пример Dockerfile (nginx)
|
||||
```
|
||||
FROM nginx:1.27-alpine
|
||||
COPY build/web/ /usr/share/nginx/html/
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
COPY default.conf /etc/nginx/conf.d/default.conf
|
||||
EXPOSE 80
|
||||
```
|
||||
|
||||
`default.conf`:
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
location /assets/ {
|
||||
try_files $uri =404;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Разделение сервисов
|
||||
- Web: домен `mnemo-cards.online`
|
||||
- Admin: домен `admin.mnemo-cards.online`
|
||||
Рекомендуется два сервиса в Coolify (два образа или один образ + разные домены).
|
||||
|
||||
### Шаги в Coolify
|
||||
1. New Service → Dockerfile/Image (web).
|
||||
2. Network: `coolify`.
|
||||
3. Domains:
|
||||
- web: `mnemo-cards.online` → entrypoint `websecure`, resolver `le`.
|
||||
- admin: `admin.mnemo-cards.online` (отдельный сервис либо второй домен).
|
||||
4. Healthcheck: HEAD `/` (200/301/302).
|
||||
|
||||
## 3. Traefik/LE (уже поднят)
|
||||
- Порты 80/443 заняты Traefik.
|
||||
- Все сервисы должны быть в сети `coolify`.
|
||||
- Для каждого домена в Coolify задать entrypoint `websecure` и resolver `le`; HTTP→HTTPS редирект активен.
|
||||
|
||||
## 4. Порядок миграции/катовера
|
||||
1) Собрать и запушить образы:
|
||||
- backend (Dart) → registry.
|
||||
- web/admin статика → отдельные образы.
|
||||
2) Создать сервисы в Coolify (backend, web, admin) c env и доменами.
|
||||
3) Протестировать:
|
||||
- Временно через hosts или временный домен (Coolify supports additional domain).
|
||||
- Проверить доступ к БД из контейнера (psql/curl).
|
||||
4) Подключить боевые домены:
|
||||
- `api.mnemo-cards.online`, `mnemo-cards.online`, `admin.mnemo-cards.online`.
|
||||
5) Переключить трафик:
|
||||
- Остановить legacy systemd backend и nginx, когда новые сервисы отвечают.
|
||||
6) Мониторинг/откат:
|
||||
- При проблемах: стартануть старый systemd/nginx (бэкап конфигов: `/root/pre-coolify-backup-2025-12-07.tar.gz`).
|
||||
|
||||
## 5. Проверки после миграции
|
||||
- HTTPS: `curl -I https://api.mnemo-cards.online`, `https://mnemo-cards.online`, `https://admin.mnemo-cards.online` → 200/301/302, валидный LE.
|
||||
- Health: все сервисы green в Coolify; backend `/health` 200.
|
||||
- БД: приложение читает/пишет (прогнать базовый сценарий).
|
||||
- Логи: нет ошибок подключения к БД/Redis.
|
||||
- Сеть: наружу открыты только 80/443 (Traefik); внутренние порты не публиковать.
|
||||
|
||||
## 6. Что остаётся на хосте
|
||||
- База данных остаётся на сервере; контейнеры подключаются как к внешнему ресурсу (`DB_HOST` = IP хоста).
|
||||
- Traefik/LE уже работают в Docker, используется resolver `le`.
|
||||
BIN
mnemo_cards.zip
Normal file
BIN
mnemo_cards.zip
Normal file
Binary file not shown.
40
mnemo_cards_backend/ENV_VARIABLES.md
Normal file
40
mnemo_cards_backend/ENV_VARIABLES.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Environment Variables для Coolify
|
||||
|
||||
## Обязательные переменные (опциональны, есть значения по умолчанию)
|
||||
|
||||
```
|
||||
ISAR_DIR=isar
|
||||
BACKUP_DIR=../mnemo_cards_telegram_bot/backups/
|
||||
WORK_DIR=/root/mnemo_cards_backend
|
||||
DEBUG=false
|
||||
SERVER_ADDRESS=
|
||||
PORT=3000
|
||||
ADMIN_IDS=
|
||||
```
|
||||
|
||||
## Описание переменных
|
||||
|
||||
- **ISAR_DIR** - Директория для базы данных Isar (по умолчанию: `isar`)
|
||||
- **BACKUP_DIR** - Директория для хранения бэкапов (по умолчанию: `../mnemo_cards_telegram_bot/backups/`)
|
||||
- **WORK_DIR** - Рабочая директория приложения (по умолчанию: `/root/mnemo_cards_backend`)
|
||||
- **DEBUG** - Режим отладки Isar Inspector (`true` или `1` для включения, по умолчанию: `false`)
|
||||
- **SERVER_ADDRESS** - IP адрес для привязки сервера (по умолчанию: `0.0.0.0` - все интерфейсы)
|
||||
- **PORT** - Порт для HTTP сервера (по умолчанию: `3000`)
|
||||
- **ADMIN_IDS** - Список Telegram ID админов, разделенных запятой (например: `123456789,987654321`). Если не задано, читается из файла `admins` (каждая строка - один ID)
|
||||
|
||||
## Примеры конфигурации
|
||||
|
||||
### Coolify (рекомендуется)
|
||||
**Важно:** Coolify использует reverse proxy (Traefik/Caddy) для обработки SSL/TLS.
|
||||
Приложение внутри контейнера работает только по HTTP.
|
||||
```
|
||||
PORT=3000
|
||||
SERVER_ADDRESS=0.0.0.0
|
||||
```
|
||||
Coolify автоматически обрабатывает HTTPS на уровне reverse proxy.
|
||||
|
||||
### Разработка
|
||||
```
|
||||
PORT=8080
|
||||
SERVER_ADDRESS=0.0.0.0
|
||||
```
|
||||
112
mnemo_cards_backend/docs/ADMIN_AUTH_SECURITY.md
Normal file
112
mnemo_cards_backend/docs/ADMIN_AUTH_SECURITY.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# Анализ безопасности админских endpoints авторизации
|
||||
|
||||
## Текущие публичные endpoints
|
||||
|
||||
1. `POST /api/v2/admin/auth/request-code` - генерация кода
|
||||
2. `POST /api/v2/admin/auth/verify-code` - верификация кода и получение токена
|
||||
3. `GET /api/v2/admin/auth/code-status/<code>` - проверка статуса кода
|
||||
|
||||
## Анализ безопасности
|
||||
|
||||
### ✅ Существующие защиты
|
||||
|
||||
1. **Двухфакторная аутентификация через Telegram**
|
||||
- Код должен быть заявлен админом в Telegram боте
|
||||
- Проверка, что `telegramUserId` находится в списке админов
|
||||
- Без доступа к Telegram аккаунту админа невозможно получить доступ
|
||||
|
||||
2. **Ограничения кода**
|
||||
- Код одноразовый (`isUsed`)
|
||||
- Срок действия 5 минут
|
||||
- Код генерируется случайно (100000-999999)
|
||||
|
||||
3. **Проверка прав доступа**
|
||||
- Даже если код заявлен, проверяется, что пользователь имеет `admin=true` в БД
|
||||
- Новые пользователи не получают админские права автоматически
|
||||
|
||||
### ⚠️ Потенциальные уязвимости
|
||||
|
||||
1. **Отсутствие rate limiting**
|
||||
- Можно генерировать неограниченное количество кодов
|
||||
- Можно делать множество попыток верификации (брутфорс)
|
||||
- Можно часто проверять статус кодов
|
||||
|
||||
2. **Брутфорс кода**
|
||||
- 6-значный код = 900,000 возможных комбинаций
|
||||
- Без rate limiting можно перебрать все коды за несколько часов
|
||||
- **НО**: код должен быть заявлен админом, что защищает от брутфорса
|
||||
|
||||
3. **Утечка информации через code-status**
|
||||
- Можно проверять статус любых кодов
|
||||
- Раскрывает информацию о существовании кодов
|
||||
- Может помочь в брутфорсе (если знать, что код существует)
|
||||
|
||||
4. **Отсутствие защиты от перехвата**
|
||||
- Код передается открыто (но это необходимо для UX)
|
||||
- HTTPS должен использоваться обязательно
|
||||
|
||||
## Рекомендации по улучшению
|
||||
|
||||
### 1. Добавить Rate Limiting (КРИТИЧНО)
|
||||
|
||||
Создан файл `admin_auth_rate_limiter.dart` с реализацией:
|
||||
|
||||
- **Генерация кодов**: максимум 10 кодов в час с одного IP
|
||||
- **Верификация**: максимум 20 попыток в час с одного IP
|
||||
- **Проверка статуса**: максимум 30 запросов в минуту с одного IP
|
||||
|
||||
**Как применить:**
|
||||
```dart
|
||||
// В main.dart или где настраивается middleware
|
||||
final rateLimiter = AdminAuthRateLimiter();
|
||||
final app = Pipeline()
|
||||
.addMiddleware(adminAuthRateLimit(rateLimiter))
|
||||
.addMiddleware(/* другие middleware */)
|
||||
.addHandler(router);
|
||||
```
|
||||
|
||||
### 2. Усилить защиту от брутфорса
|
||||
|
||||
- Добавить задержку после неудачных попыток верификации
|
||||
- Логировать все попытки верификации для мониторинга
|
||||
- Блокировать IP после N неудачных попыток
|
||||
|
||||
### 3. Ограничить доступ к code-status
|
||||
|
||||
- Требовать минимальную авторизацию (например, по IP whitelist)
|
||||
- Или использовать временный токен для проверки статуса
|
||||
- Или ограничить проверку только для кодов, созданных с того же IP
|
||||
|
||||
### 4. Мониторинг и алертинг
|
||||
|
||||
- Логировать все попытки генерации кодов
|
||||
- Логировать все попытки верификации (успешные и неуспешные)
|
||||
- Отправлять алерты при подозрительной активности
|
||||
|
||||
### 5. Дополнительные меры
|
||||
|
||||
- Использовать CAPTCHA для генерации кодов (опционально)
|
||||
- Добавить проверку User-Agent и других заголовков
|
||||
- Использовать более длинные коды (8-10 цифр) для большей энтропии
|
||||
|
||||
## Оценка текущего уровня безопасности
|
||||
|
||||
**Текущий уровень: СРЕДНИЙ**
|
||||
|
||||
### Почему не КРИТИЧНО небезопасно:
|
||||
|
||||
1. **Основная защита работает**: код должен быть заявлен админом в Telegram
|
||||
2. **Брутфорс неэффективен**: даже если перебрать все коды, они не будут заявлены админом
|
||||
3. **Одноразовость**: использованный код нельзя использовать повторно
|
||||
|
||||
### Почему нужно улучшить:
|
||||
|
||||
1. **DoS атаки**: можно перегрузить сервер запросами
|
||||
2. **Информационная утечка**: code-status раскрывает информацию
|
||||
3. **Лучшие практики**: rate limiting - стандартная практика безопасности
|
||||
|
||||
## Вывод
|
||||
|
||||
**Текущая реализация достаточно безопасна для production**, но **настоятельно рекомендуется добавить rate limiting** для защиты от DoS атак и улучшения общей безопасности.
|
||||
|
||||
Основная защита (требование заявки кода админом) работает корректно и защищает от несанкционированного доступа даже без rate limiting.
|
||||
|
|
@ -110,6 +110,15 @@ Middleware authorizeV2(UserManager userManager, JwtService jwtService) {
|
|||
if (isOptionalAuthGet) {
|
||||
return await innerHandler(request);
|
||||
}
|
||||
// For admin endpoints, show what headers we received
|
||||
if (isAdminEndpoint) {
|
||||
final headerKeys = request.headers.keys.toList();
|
||||
return Response(
|
||||
401,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: '{"error":"Unauthorized","message":"Bearer token required","debug":"authHeader=${authHeader ?? 'null'}, headers=$headerKeys"}',
|
||||
);
|
||||
}
|
||||
return Response(
|
||||
401,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
|
|
@ -130,26 +139,33 @@ Middleware authorizeV2(UserManager userManager, JwtService jwtService) {
|
|||
final userId = jwtService.verifyAccessToken(token, debug: isAdminPath);
|
||||
|
||||
if (userId == null) {
|
||||
// Additional debug info for admin endpoints
|
||||
// For admin endpoints, return detailed debug info in response
|
||||
if (isAdminPath) {
|
||||
print('[AUTH DEBUG] Token verification failed for path: $normalizedPath');
|
||||
// Try to extract payload to see what's wrong
|
||||
final verifyError = jwtService.lastVerificationError ?? 'Unknown';
|
||||
String debugInfo = 'verifyError: $verifyError';
|
||||
try {
|
||||
final payload = jwtService.extractPayload(token);
|
||||
print('[AUTH DEBUG] Extracted payload: $payload');
|
||||
if (payload != null) {
|
||||
final exp = payload['exp'] as int?;
|
||||
final tokenType = payload['type'];
|
||||
final tokenUserId = payload['userId'];
|
||||
|
||||
if (exp != null) {
|
||||
final expiryTime = DateTime.fromMillisecondsSinceEpoch(exp * 1000);
|
||||
print('[AUTH DEBUG] Token expires at: $expiryTime');
|
||||
print('[AUTH DEBUG] Current time: ${DateTime.now()}');
|
||||
print('[AUTH DEBUG] Is expired: ${DateTime.now().isAfter(expiryTime)}');
|
||||
final now = DateTime.now();
|
||||
debugInfo += ', payload: type=$tokenType, userId=$tokenUserId, '
|
||||
'exp=$expiryTime, now=$now';
|
||||
}
|
||||
print('[AUTH DEBUG] Token type: ${payload['type']}');
|
||||
}
|
||||
} catch (e) {
|
||||
print('[AUTH DEBUG] Could not extract payload: $e');
|
||||
debugInfo += ', extractError: $e';
|
||||
}
|
||||
|
||||
return Response(
|
||||
401,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: '{"error":"Unauthorized","message":"Invalid or expired token","debug":"$debugInfo"}',
|
||||
);
|
||||
}
|
||||
return Response(
|
||||
401,
|
||||
|
|
|
|||
|
|
@ -62,12 +62,16 @@ class JwtService {
|
|||
);
|
||||
}
|
||||
|
||||
// Store last verification failure reason for debugging
|
||||
String? lastVerificationError;
|
||||
|
||||
/// Verify access token and return user ID
|
||||
String? verifyAccessToken(String token, {bool debug = false}) {
|
||||
lastVerificationError = null;
|
||||
try {
|
||||
final payload = _verifySimpleJwt(token, debug: debug);
|
||||
if (payload == null) {
|
||||
if (debug) print('[JWT DEBUG] _verifySimpleJwt returned null');
|
||||
lastVerificationError = lastVerificationError ?? 'Signature verification failed';
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -76,20 +80,20 @@ class JwtService {
|
|||
if (exp != null) {
|
||||
final expiryTime = DateTime.fromMillisecondsSinceEpoch(exp * 1000);
|
||||
if (DateTime.now().isAfter(expiryTime)) {
|
||||
if (debug) print('[JWT DEBUG] Token expired at $expiryTime, now: ${DateTime.now()}');
|
||||
lastVerificationError = 'Token expired at $expiryTime';
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Check token type
|
||||
if (payload['type'] != 'access') {
|
||||
if (debug) print('[JWT DEBUG] Wrong token type: ${payload['type']}');
|
||||
lastVerificationError = 'Wrong token type: ${payload['type']}';
|
||||
return null;
|
||||
}
|
||||
|
||||
return payload['userId']?.toString();
|
||||
} catch (e) {
|
||||
if (debug) print('[JWT DEBUG] Exception in verifyAccessToken: $e');
|
||||
lastVerificationError = 'Exception: $e';
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -150,7 +154,7 @@ class JwtService {
|
|||
try {
|
||||
final parts = token.split('.');
|
||||
if (parts.length != 3) {
|
||||
if (debug) print('[JWT DEBUG] Invalid token format: ${parts.length} parts');
|
||||
lastVerificationError = 'Invalid token format: ${parts.length} parts';
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -165,12 +169,8 @@ class JwtService {
|
|||
final expectedSignatureB64 = base64UrlEncode(expectedSignature);
|
||||
|
||||
if (signatureB64 != expectedSignatureB64) {
|
||||
if (debug) {
|
||||
print('[JWT DEBUG] Signature mismatch!');
|
||||
print('[JWT DEBUG] Got signature: $signatureB64');
|
||||
print('[JWT DEBUG] Expected signature: $expectedSignatureB64');
|
||||
print('[JWT DEBUG] Secret key length: ${_secretKey.length}');
|
||||
}
|
||||
lastVerificationError = 'Signature mismatch: got ${signatureB64.substring(0, 10)}..., '
|
||||
'expected ${expectedSignatureB64.substring(0, 10)}...';
|
||||
return null; // Invalid signature
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ class JwtService {
|
|||
final payloadJson = utf8.decode(base64Url.decode(payloadB64));
|
||||
return jsonDecode(payloadJson) as Map<String, dynamic>;
|
||||
} catch (e) {
|
||||
if (debug) print('[JWT DEBUG] Exception during verification: $e');
|
||||
lastVerificationError = 'Parse exception: $e';
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
103
mnemo_cards_telegram_bot/MIGRATION.md
Normal file
103
mnemo_cards_telegram_bot/MIGRATION.md
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
# Миграция Telegram бота с Isar DB на Backend API
|
||||
|
||||
## Обзор
|
||||
|
||||
Telegram бот был мигрирован с прямого доступа к Isar базе данных на использование Backend API через HTTP запросы. Это обеспечивает:
|
||||
- Централизованное управление данными
|
||||
- Упрощение развертывания (не нужна локальная БД)
|
||||
- Единую точку доступа к данным
|
||||
|
||||
## Изменения
|
||||
|
||||
### Бэкенд
|
||||
|
||||
1. **Middleware для API ключа** (`telegram_bot_auth_middleware.dart`)
|
||||
- Проверяет заголовок `X-API-Key`
|
||||
- Использует переменную окружения `TELEGRAM_BOT_API_KEY`
|
||||
|
||||
2. **API эндпоинты для бота** (`telegram_bot_api_v2.dart`)
|
||||
- `GET /api/v2/telegram-bot/random-card` - получить случайную карточку
|
||||
- `POST /api/v2/telegram-bot/share/check-limit` - проверить лимит шаринга
|
||||
- `POST /api/v2/telegram-bot/share/record` - записать факт шаринга
|
||||
- `GET /api/v2/telegram-bot/users/info` - информация о пользователях
|
||||
- `GET /api/v2/telegram-bot/words` - список всех слов
|
||||
|
||||
### Телеграм бот
|
||||
|
||||
1. **HTTP клиент** (`backend_client.dart`)
|
||||
- Заменяет `DBManager`
|
||||
- Поддерживает retry логику с экспоненциальной задержкой
|
||||
- Использует API ключ для аутентификации
|
||||
|
||||
2. **Удалены зависимости**
|
||||
- Удалена зависимость `isar` из `pubspec.yaml`
|
||||
- Удалена зависимость `args` из `pubspec.yaml` (CLI аргументы больше не используются)
|
||||
- Удален файл `db_manager.dart`
|
||||
- Удалена опция `--isar` из конфигурации
|
||||
|
||||
3. **Конфигурация через переменные окружения**
|
||||
- CLI аргументы заменены на переменные окружения
|
||||
- Все настройки теперь читаются из `Platform.environment`
|
||||
- Добавлена переменная `TELEGRAM_BOT_TOKEN` для токена бота
|
||||
|
||||
## Настройка
|
||||
|
||||
### Переменные окружения
|
||||
|
||||
**Бэкенд:**
|
||||
```bash
|
||||
TELEGRAM_BOT_API_KEY=your-secret-api-key-here
|
||||
```
|
||||
|
||||
**Бот (все обязательны):**
|
||||
```bash
|
||||
TELEGRAM_BOT_TOKEN=your-telegram-bot-token # Токен бота от BotFather
|
||||
TELEGRAM_BOT_API_KEY=your-secret-api-key-here # Должен совпадать с бэкендом
|
||||
BACKEND_URL=https://api.mnemo-cards.online # Опционально, по умолчанию используется значение по умолчанию
|
||||
BOT_SHARE_DAILY_LIMIT=1 # Опционально, по умолчанию 1
|
||||
```
|
||||
|
||||
**Примечание:** Бот теперь использует только переменные окружения. CLI аргументы больше не поддерживаются.
|
||||
|
||||
### Docker
|
||||
|
||||
В `Dockerfile` бота определены переменные окружения:
|
||||
```dockerfile
|
||||
ENV BACKEND_URL=https://api.mnemo-cards.online \
|
||||
BOT_SHARE_DAILY_LIMIT=1 \
|
||||
TELEGRAM_BOT_API_KEY= \
|
||||
TELEGRAM_BOT_TOKEN=
|
||||
```
|
||||
|
||||
Установите значения при запуске контейнера:
|
||||
```bash
|
||||
docker run \
|
||||
-e TELEGRAM_BOT_TOKEN=your-bot-token \
|
||||
-e TELEGRAM_BOT_API_KEY=your-api-key \
|
||||
...
|
||||
```
|
||||
|
||||
## Использование
|
||||
|
||||
Бот работает так же, как и раньше, но теперь все операции выполняются через API:
|
||||
|
||||
- `/start`, `/login`, `/code` - генерация кодов авторизации
|
||||
- `/share` - шаринг карточек с проверкой лимитов
|
||||
- `/info`, `/user`, `/words` - административные команды
|
||||
|
||||
Все данные теперь хранятся и обрабатываются на бэкенде.
|
||||
|
||||
## Безопасность
|
||||
|
||||
- API ключ передается через заголовок `X-API-Key`
|
||||
- Ключ должен быть достаточно длинным и случайным
|
||||
- Рекомендуется использовать переменные окружения, а не хардкодить ключ
|
||||
- API ключ должен совпадать в бэкенде и боте
|
||||
|
||||
## Откат
|
||||
|
||||
Если нужно вернуться к использованию Isar:
|
||||
1. Восстановите файл `db_manager.dart` из git истории
|
||||
2. Верните зависимость `isar` в `pubspec.yaml`
|
||||
3. Замените `BackendClient` на `DBManager` в `main.dart`
|
||||
4. Обновите конфигурацию для использования пути к Isar БД
|
||||
206
nginx_issues.md
Normal file
206
nginx_issues.md
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
Причина сейчас не в нагрузке, а в битой и дублирующейся конфигурации nginx. Лог прямым текстом говорит, почему он периодически падает / не стартует.
|
||||
|
||||
Разберём по кускам.
|
||||
|
||||
⸻
|
||||
|
||||
1. Старые ошибки с портами
|
||||
|
||||
Вот это:
|
||||
|
||||
bind() to 0.0.0.0:80 failed (98: Unknown error)
|
||||
bind() to 0.0.0.0:443 failed (98: Unknown error)
|
||||
still could not bind()
|
||||
|
||||
Это означает: кто-то уже слушает 80/443, а новый процесс nginx пытается занять те же порты и падает с EADDRINUSE.
|
||||
|
||||
Типичный сценарий:
|
||||
• уже запущен nginx (через systemd),
|
||||
• ты запускаешь ещё один (например nginx -c ... руками),
|
||||
• второй не может забиндиться и падает.
|
||||
|
||||
Но это полбеды. Сейчас у тебя ещё серьёзнее: конфиг.
|
||||
|
||||
⸻
|
||||
|
||||
2. Главная проблема: конфиг nginx сломан/подключён неправильно
|
||||
|
||||
Вот основное:
|
||||
|
||||
"server" directive is not allowed here in /root/mnemo_cards/tools/deploy/generated_configs/code.mnemo-cards.online.conf:5
|
||||
...
|
||||
"location" directive is not allowed here in /etc/nginx/sites-enabled/code.mnemo-cards.online.conf:55
|
||||
"gzip" directive is duplicate in /etc/nginx/sites-enabled/code.mnemo-cards.online.conf:53
|
||||
"limit_req_zone" directive is not allowed here in /etc/nginx/sites-enabled/vscode.mnemo-cards.online.conf:24
|
||||
|
||||
Эти сообщения означают:
|
||||
1. server в “не том месте”
|
||||
Файлы из /root/mnemo_cards/tools/deploy/generated_configs/*.conf подключены так, будто это не server-блоки, а часть верхнего уровня.
|
||||
• Директива server { ... } допустима только внутри блока http { ... }.
|
||||
• Если ты где-то делаешь include /root/.../generated_configs/*.conf; ВНЕ http {}, nginx и ругается:
|
||||
"server" directive is not allowed here
|
||||
2. location в “не том месте”
|
||||
Сообщения:
|
||||
|
||||
"location" directive is not allowed here in /etc/nginx/sites-enabled/code.mnemo-cards.online.conf:55
|
||||
"location" directive is not allowed here in /etc/nginx/sites-enabled/mnemo-cards.online.conf:53
|
||||
|
||||
Значит в этих файлах:
|
||||
• либо location стоит вне server {},
|
||||
• либо у тебя “поехали” скобки } (какой-то server блок раньше закрылся слишком рано).
|
||||
|
||||
3. дублирующийся gzip и limit_req_zone не там
|
||||
|
||||
"gzip" directive is duplicate in /etc/nginx/sites-enabled/code.mnemo-cards.online.conf:53
|
||||
"limit_req_zone" directive is not allowed here in /etc/nginx/sites-enabled/vscode.mnemo-cards.online.conf:24
|
||||
|
||||
• gzip обычно задаётся один раз на уровне http {}.
|
||||
Ты, скорее всего, прописал его и в nginx.conf, и ещё раз внутри vhost.
|
||||
• limit_req_zone нельзя писать внутри server или location, только на уровне http.
|
||||
|
||||
4. конфликты доменов
|
||||
|
||||
conflicting server name "vscode.mnemo-cards.online" on 0.0.0.0:80, ignored
|
||||
...
|
||||
ignored
|
||||
|
||||
Это “мягкая” проблема: у тебя несколько server-блоков с одинаковым server_name и listen 80/443.
|
||||
nginx один использует, остальные игнорирует. Не фатально, но говорит, что конфиг дублируется (скорее всего: и в /etc/nginx/sites-enabled, и в /root/.../generated_configs).
|
||||
|
||||
Итог: nginx периодически не может прочитать конфиг и/или ты пытаешься стартовать его с альтернативным конфигом, где все эти server и location подключены в неправильном месте. Отсюда и “то работает, то нет”.
|
||||
|
||||
⸻
|
||||
|
||||
3. Почему “иногда работает, иногда нет”
|
||||
|
||||
Скорее всего:
|
||||
• Есть один “старый” рабочий nginx, запущенный с нормальным /etc/nginx/nginx.conf.
|
||||
• Ты запускаешь свою тулзу /root/mnemo_cards/tools/deploy/..., которая:
|
||||
• генерирует конфиги в /root/mnemo_cards/tools/deploy/generated_configs/*.conf,
|
||||
• пробует сделать nginx -s reload с другим config-path или включает эти файлы как главные.
|
||||
• nginx читает новый конфиг → натыкается на server/ location not allowed here → reload не удаётся, в лучшем случае остаётся старый воркер, в худшем — nginx падает и systemd его мучительно перезапускает.
|
||||
• В логе при этом сыпятся emerg и bind() failed, а снаружи ты видишь “иногда сайты отваливаются”.
|
||||
|
||||
⸻
|
||||
|
||||
4. Что сейчас является непосредственной причиной “опять не работает”
|
||||
|
||||
Прямо из хвоста лога:
|
||||
|
||||
2025/11/23 03:24:43 [emerg] ... "server" directive is not allowed here in /root/mnemo_cards/tools/deploy/generated_configs/...
|
||||
2025/11/23 03:24:43 [warn] ... conflicting server name "vscode.mnemo-cards.online" ...
|
||||
|
||||
Т.е. на текущий момент nginx не может нормально перечитать конфиг из-за:
|
||||
• включения /root/mnemo_cards/tools/deploy/generated_configs/*.conf не в том месте;
|
||||
• раздвоения конфигов (одни в /etc/nginx/sites-enabled/*.conf, другие в /root/.../generated_configs).
|
||||
|
||||
⸻
|
||||
|
||||
5. Что делать, чтобы это прекратилось
|
||||
|
||||
Шаг 1. Перестать запускать nginx “как попало”
|
||||
1. Остановить nginx:
|
||||
|
||||
systemctl stop nginx
|
||||
ps aux | grep nginx
|
||||
# убедиться, что живых процессов nginx не осталось
|
||||
|
||||
2. Дальше всегда управлять только так:
|
||||
|
||||
nginx -t # проверить конфиг
|
||||
systemctl start nginx
|
||||
systemctl reload nginx
|
||||
|
||||
Никаких nginx -c /root/... и прочего.
|
||||
|
||||
⸻
|
||||
|
||||
Шаг 2. Навести порядок в структуре конфига
|
||||
|
||||
Базовый скелет /etc/nginx/nginx.conf должен быть примерно таким:
|
||||
|
||||
user www-data;
|
||||
worker_processes auto;
|
||||
pid /run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 4096;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
sendfile on;
|
||||
|
||||
# глобальные gzip / limit_req_zone / и т.д.
|
||||
# gzip on;
|
||||
# limit_req_zone ...;
|
||||
|
||||
include /etc/nginx/conf.d/*.conf;
|
||||
include /etc/nginx/sites-enabled/*.conf;
|
||||
}
|
||||
|
||||
Критично:
|
||||
• server {} — только внутри блока http {};
|
||||
• location — только внутри server {};
|
||||
• limit_req_zone и подобные — только на уровне http {}, не внутри server.
|
||||
|
||||
⸻
|
||||
|
||||
Шаг 3. Разобраться с generated_configs
|
||||
|
||||
Сейчас файлы вида:
|
||||
• /root/mnemo_cards/tools/deploy/generated_configs/code.mnemo-cards.online.conf
|
||||
• /root/mnemo_cards/tools/deploy/generated_configs/mnemo-cards.online.conf
|
||||
• /root/mnemo_cards/tools/deploy/generated_configs/vscode.mnemo-cards.online.conf
|
||||
|
||||
подключаются так, что nginx видит там server не в http контексте.
|
||||
|
||||
Тебе нужно одно из:
|
||||
• либо перестать включать эти файлы напрямую (пусть тулза генерирует сразу в /etc/nginx/sites-available/sites-enabled),
|
||||
• либо включать их изнутри http {}:
|
||||
|
||||
http {
|
||||
...
|
||||
include /root/mnemo_cards/tools/deploy/generated_configs/*.conf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Но не одновременно с их копиями в /etc/nginx/sites-enabled/, иначе будешь получать конфликтующие server_name vscode.mnemo-cards.online.
|
||||
|
||||
Сделай так:
|
||||
1. Реши, где “истина” для vhost’ов:
|
||||
• либо /etc/nginx/sites-enabled/*.conf,
|
||||
• либо /root/.../generated_configs/*.conf.
|
||||
2. Второй вариант выключи:
|
||||
• удаляешь/комментируешь include на ненужный путь;
|
||||
• или временно переименовываешь файлы (например, .conf.disabled).
|
||||
|
||||
⸻
|
||||
|
||||
Шаг 4. Починить структуру самих vhost-файлов
|
||||
|
||||
Внутри каждого *.conf из sites-enabled должно быть:
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name vscode.mnemo-cards.online;
|
||||
|
||||
# тут уже location'ы
|
||||
location / {
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
Никаких location вне server, никаких limit_req_zone/gzip внутри отдельных vhost’ов (если они уже есть глобально).
|
||||
|
||||
⸻
|
||||
|
||||
TL;DR
|
||||
|
||||
Причина, почему “опять не работает”, по логу такая:
|
||||
|
||||
nginx сейчас либо не может корректно перезапуститься, либо работает с битой конфигурацией, потому что ты одновременно используешь автогенерённые конфиги из /root/mnemo_cards/tools/deploy/generated_configs/*.conf и ручные в /etc/nginx/sites-enabled/*.conf, причём часть из них подключена в неправильный контекст (server и location “не там”). Плюс периодически пытаешься поднять второй nginx поверх первого, откуда bind() failed (98).
|
||||
|
||||
Loading…
Reference in a new issue