Проблема: контейнер bbb-graphql-server-1 был помечен как unhealthy из-за неправильного healthcheck (проверял порт 8080 вместо 8085). Решение: - Добавлен правильный healthcheck в docker-compose.yml для порта 8085 - Обновлен CLAUDE.md с информацией о BigBlueButton, Vault и Syncthing troubleshooting - Добавлена документация по Odoo custom addons (bbb_connector, virtual_meeting) Результат: контейнер теперь healthy, FailingStreak снизился с 2693 до 0. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
329 lines
No EOL
11 KiB
Markdown
329 lines
No EOL
11 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Project Overview
|
||
|
||
This is a production infrastructure for AI-Impress, running on OVH server (ubuntu@51.89.231.46). The project uses a three-tier synchronization system:
|
||
|
||
1. **Syncthing** - Real-time bidirectional sync between Mac and server (10-30 seconds)
|
||
2. **GitHub** - Version control at git@github.com:SamoilenkoVadym/OVHserver.git
|
||
3. **rsync** - Full system backup for disaster recovery
|
||
|
||
**Critical:** You work with LOCAL files on Mac at `/Volumes/SSD/Aimpress_Cloud_Prod/`. Syncthing automatically syncs changes to the server. Never SSH into the server to make changes - always work locally.
|
||
|
||
## Architecture
|
||
|
||
### Directory Structure
|
||
|
||
```
|
||
/Volumes/SSD/Aimpress_Cloud_Prod/
|
||
├── opt/ # Main services (synced to server /opt)
|
||
│ ├── 00-infrastructure/ # Core: Traefik, PostgreSQL, Redis, Vault, RabbitMQ, Loki
|
||
│ ├── 01-security/ # Authentik (SSO), Vaultwarden
|
||
│ ├── 02-core/ # n8n (automation), Evolution API (WhatsApp), Supabase, BigBlueButton
|
||
│ ├── 03-business/ # Odoo (ERP), Outline (wiki), Documenso, Wiki.js
|
||
│ ├── 04-tools/ # Portainer, Grafana, Prometheus, Uptime Kuma
|
||
│ ├── 05-backups/ # Backup scripts and data (NOT in Git)
|
||
│ └── 06-webflow/ # Landing pages
|
||
├── data/ # Application data (synced to server /data)
|
||
├── home/ # Ubuntu user files (synced to server /home/ubuntu)
|
||
└── mnt/ # Mounted disks, backups, PostgreSQL data (synced to server /mnt)
|
||
```
|
||
|
||
### Technology Stack
|
||
|
||
- **Orchestration:** Docker + Docker Compose (all services are containerized)
|
||
- **Reverse Proxy:** Traefik with automatic SSL (Let's Encrypt via Cloudflare)
|
||
- **Databases:** PostgreSQL (shared: postgres-main), Redis (redis-main), RabbitMQ
|
||
- **Secrets:** HashiCorp Vault (do NOT commit secrets)
|
||
- **SSO:** Authentik (Single Sign-On for all services)
|
||
- **Monitoring:** Prometheus + Grafana + Loki + Uptime Kuma
|
||
- **Networks:** Docker networks - `traefik-public` (external), `database-internal` (external)
|
||
|
||
### Service Dependencies
|
||
|
||
Services MUST start in this order:
|
||
1. Traefik
|
||
2. PostgreSQL, Redis, RabbitMQ
|
||
3. Vault
|
||
4. Authentik
|
||
5. All other services
|
||
|
||
## Common Development Commands
|
||
|
||
### Docker Operations
|
||
|
||
```bash
|
||
# View running containers on server
|
||
ssh ubuntu@51.89.231.46 "docker ps"
|
||
|
||
# View logs for a container
|
||
ssh ubuntu@51.89.231.46 "docker logs <container_name>"
|
||
|
||
# Restart a service (via docker-compose)
|
||
ssh ubuntu@51.89.231.46 "cd /opt/<category>/<service> && docker compose restart"
|
||
|
||
# View service status
|
||
ssh ubuntu@51.89.231.46 "cd /opt/<category>/<service> && docker compose ps"
|
||
```
|
||
|
||
### Managing Services
|
||
|
||
Each service has a `docker-compose.yml` file in its directory:
|
||
- Traefik: `/opt/00-infrastructure/traefik/docker-compose.yml`
|
||
- n8n-shared: `/opt/02-core/n8n-shared/docker-compose.yml` (includes 4 workers)
|
||
- Odoo: `/opt/03-business/odoo/docker-compose.yml`
|
||
- etc.
|
||
|
||
To deploy/update a service:
|
||
1. Edit the `docker-compose.yml` locally
|
||
2. Wait for Syncthing sync (10-30 seconds)
|
||
3. SSH to server: `ssh ubuntu@51.89.231.46 "cd /opt/<path> && docker compose up -d"`
|
||
|
||
### Syncthing Operations
|
||
|
||
```bash
|
||
# Check Syncthing status on Mac
|
||
brew services list | grep syncthing
|
||
|
||
# Check Syncthing status on server
|
||
ssh ubuntu@51.89.231.46 "systemctl --user status syncthing"
|
||
|
||
# View sync size
|
||
du -sh /Volumes/SSD/Aimpress_Cloud_Prod/{opt,data,home,mnt}
|
||
|
||
# Force rescan of a folder
|
||
ssh ubuntu@51.89.231.46 "curl -X POST http://localhost:8384/rest/db/scan?folder=opt -H 'X-API-Key: \$(grep apikey ~/.local/state/syncthing/config.xml | sed 's/.*<apikey>\(.*\)<\/apikey>.*/\1/')'"
|
||
|
||
# Check folder status via API
|
||
ssh ubuntu@51.89.231.46 "curl -s http://localhost:8384/rest/db/status?folder=opt -H 'X-API-Key: \$(grep apikey ~/.local/state/syncthing/config.xml | sed 's/.*<apikey>\(.*\)<\/apikey>.*/\1/')' | python3 -m json.tool"
|
||
```
|
||
|
||
### Backup Operations
|
||
|
||
Backup scripts are in `/opt/05-backups/scripts/`:
|
||
- `backup-full-enhanced.sh` - Comprehensive backup with auto-discovery
|
||
- Scripts use Restic for incremental backups to Cloudflare R2
|
||
- See `/opt/05-backups/SCRIPTS-REGISTRY.md` for full script inventory
|
||
|
||
### Vault Operations
|
||
|
||
```bash
|
||
# Read a secret from Vault
|
||
ssh ubuntu@51.89.231.46 "docker exec vault vault kv get secret/myapp"
|
||
|
||
# Write a secret to Vault
|
||
ssh ubuntu@51.89.231.46 "docker exec vault vault kv put secret/myapp key=value"
|
||
|
||
# List all secrets
|
||
ssh ubuntu@51.89.231.46 "docker exec vault vault kv list secret/"
|
||
|
||
# Export secrets (use with caution)
|
||
ssh ubuntu@51.89.231.46 "cd /opt/05-backups/scripts && ./export-vault-secrets.sh"
|
||
```
|
||
|
||
**Important:** Vault integration in docker-compose uses environment variables:
|
||
```yaml
|
||
environment:
|
||
- DB_PASSWORD=${VAULT_DB_PASSWORD} # Read from Vault via script
|
||
```
|
||
|
||
## Git Workflow
|
||
|
||
### Automated Git Hooks
|
||
|
||
**pre-commit hook:**
|
||
- Blocks commits containing `.env`, `.key`, `.pem` files
|
||
- Warns about potential secrets
|
||
- Can override with `--no-verify` (use carefully)
|
||
|
||
**post-commit hook:**
|
||
- Automatically pushes every commit to GitHub
|
||
- Works with main/master branches
|
||
|
||
### Commit Message Format
|
||
|
||
```
|
||
<type>: <short description>
|
||
|
||
<optional detailed explanation>
|
||
|
||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||
|
||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||
```
|
||
|
||
**Types:**
|
||
- `feat:` - New feature
|
||
- `fix:` - Bug fix
|
||
- `refactor:` - Code refactoring
|
||
- `docs:` - Documentation
|
||
- `chore:` - Maintenance (configs, dependencies)
|
||
- `perf:` - Performance improvement
|
||
|
||
### What NOT to Commit
|
||
|
||
Excluded via `.gitignore`:
|
||
- Dependencies: `node_modules/`, `__pycache__/`, `venv/`
|
||
- Secrets: `.env`, `*.key`, `*.pem`, `credentials.json`
|
||
- Backups: `opt/05-backups/`, `*.sql.gz`, `*.tar.gz`
|
||
- Data: `**/docker-data/`, `**/volumes/`
|
||
- Logs: `*.log`, `logs/`
|
||
- System: `.DS_Store`, `.cache/`
|
||
|
||
## Key Configuration Patterns
|
||
|
||
### Traefik Labels
|
||
|
||
Services use Traefik labels for routing:
|
||
|
||
```yaml
|
||
labels:
|
||
- "traefik.enable=true"
|
||
- "traefik.http.routers.<service>.rule=Host(`<service>.ai-impress.com`)"
|
||
- "traefik.http.routers.<service>.entrypoints=websecure"
|
||
- "traefik.http.routers.<service>.tls.certresolver=cloudflare"
|
||
- "traefik.http.services.<service>.loadbalancer.server.port=<port>"
|
||
```
|
||
|
||
### Environment Variables
|
||
|
||
Services use `.env` files (NOT committed to Git):
|
||
- Database credentials reference shared PostgreSQL: `postgres-main`
|
||
- Redis credentials reference shared Redis: `redis-main`
|
||
- Passwords stored as `${VAR_NAME}` in docker-compose.yml
|
||
|
||
### Network Configuration
|
||
|
||
Services connect to external Docker networks:
|
||
```yaml
|
||
networks:
|
||
traefik-public:
|
||
external: true
|
||
database-internal:
|
||
external: true
|
||
```
|
||
|
||
## Important Architecture Notes
|
||
|
||
### n8n Configuration
|
||
|
||
n8n-shared runs in queue mode with Redis:
|
||
- 1 main instance (n8n-shared) handles UI and API
|
||
- 4 worker instances process jobs from Redis queue
|
||
- Workers 1-2: High concurrency (20 jobs)
|
||
- Workers 3-4: Medium concurrency (15 jobs)
|
||
- Webhooks and OAuth endpoints bypass authentication for external access
|
||
|
||
### BigBlueButton Configuration
|
||
|
||
BigBlueButton is deployed for workshops and webinars:
|
||
- Multi-container setup with separate services (HTML5, Freeswitch, Kurento, etc.)
|
||
- GraphQL API for real-time data
|
||
- Integration with Odoo via `bbb_connector` addon
|
||
- Webhooks for meeting events
|
||
- Data stored in `/opt/02-core/bigbluebutton/`
|
||
|
||
### Odoo Custom Addons
|
||
|
||
Odoo supports custom addons in `/opt/03-business/odoo/extra-addons/`:
|
||
- `bbb_connector/` - BigBlueButton integration
|
||
- `virtual_meeting/` - Virtual meeting management
|
||
- Addons are automatically discovered on Odoo restart
|
||
- Add addon path to `odoo.conf`: `addons_path = /mnt/extra-addons`
|
||
|
||
### Database Architecture
|
||
|
||
- Single PostgreSQL instance (`postgres-main`) serves multiple services
|
||
- Each service has its own database (e.g., `n8n_shared`, `odoo_db`)
|
||
- Connection via `database-internal` network
|
||
- Data stored in `/mnt/psql-data/`
|
||
|
||
### SSL & Domain Management
|
||
|
||
All services use:
|
||
- Domain: `*.ai-impress.com`
|
||
- SSL via Traefik + Cloudflare DNS challenge
|
||
- Certificates stored in `/opt/00-infrastructure/traefik/acme/`
|
||
|
||
## Workflow for Claude Code
|
||
|
||
When making changes:
|
||
|
||
1. **Read** local files from `/Volumes/SSD/Aimpress_Cloud_Prod/`
|
||
2. **Edit** files locally (never SSH to make changes)
|
||
3. **Wait** 10-30 seconds for Syncthing to sync to server
|
||
4. **Commit** with descriptive message using format above
|
||
5. **Verify** changes on server if needed (via SSH to view logs/status)
|
||
|
||
When adding new services:
|
||
|
||
1. Create directory in appropriate `/opt/<category>/` folder
|
||
2. Create `docker-compose.yml` with Traefik labels
|
||
3. Create `.env` file (will be auto-ignored by Git)
|
||
4. Add to appropriate Docker networks
|
||
5. Document in project structure files
|
||
6. Test on server, then commit
|
||
|
||
## Important Security Notes
|
||
|
||
- **Never commit secrets** - pre-commit hook will block `.env` files
|
||
- **Use Vault** for sensitive credentials when possible
|
||
- **Authentik SSO** protects most admin interfaces
|
||
- **Traefik middleware** can add authentication to services
|
||
- Database passwords are in `.env` files, referenced as `${VAR_NAME}`
|
||
|
||
## Troubleshooting
|
||
|
||
### Service Won't Start
|
||
|
||
1. Check logs: `ssh ubuntu@51.89.231.46 "docker logs <container>"`
|
||
2. Verify networks exist: `ssh ubuntu@51.89.231.46 "docker network ls"`
|
||
3. Check if port is already in use
|
||
4. Verify Traefik is running first
|
||
|
||
### Syncthing Issues
|
||
|
||
1. Check status on both Mac and server
|
||
2. View sync conflicts in Syncthing UI
|
||
3. Check `.stignore` for exclusion patterns
|
||
4. Verify folder permissions
|
||
|
||
### Database Connection Issues
|
||
|
||
1. Ensure `postgres-main` container is running
|
||
2. Check `database-internal` network exists
|
||
3. Verify credentials in `.env` file
|
||
4. Check PostgreSQL logs: `ssh ubuntu@51.89.231.46 "docker logs postgres-main"`
|
||
|
||
## Reference Documentation
|
||
|
||
- Detailed structure: `.claude/project-structure.md`
|
||
- Workflow details: `.claude/workflow.md`
|
||
- Backup scripts: `opt/05-backups/SCRIPTS-REGISTRY.md`
|
||
- Main README: `README.md`
|
||
|
||
---
|
||
|
||
## 🚨 КРИТИЧЕСКИ ВАЖНО: Выбор модели
|
||
|
||
**ВСЕГДА используй Haiku (`model: "haiku"`) для:**
|
||
- ✅ Работы в терминале (Bash, ssh команды)
|
||
- ✅ Чтения и редактирования файлов (Read, Edit, Write)
|
||
- ✅ Поиска в коде (Grep, Glob)
|
||
- ✅ Работы с Docker/Git
|
||
- ✅ Отладки и исправления ошибок
|
||
- ✅ Любых практических задач по коддингу
|
||
|
||
**Используй Sonnet ТОЛЬКО для:**
|
||
- 📊 Сложного планирования архитектуры
|
||
- 📋 Анализа требований пользователя
|
||
- 🎯 Принятия стратегических решений
|
||
- 🔍 Глубокого анализа проблем
|
||
|
||
**Примеры:**
|
||
```
|
||
❌ НЕПРАВИЛЬНО: Task(subagent_type="general-purpose", prompt="собери credentials")
|
||
✅ ПРАВИЛЬНО: Task(subagent_type="general-purpose", model="haiku", prompt="собери credentials")
|
||
``` |