Проблема: контейнер 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>
11 KiB
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:
- Syncthing - Real-time bidirectional sync between Mac and server (10-30 seconds)
- GitHub - Version control at git@github.com:SamoilenkoVadym/OVHserver.git
- 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:
- Traefik
- PostgreSQL, Redis, RabbitMQ
- Vault
- Authentik
- All other services
Common Development Commands
Docker Operations
# 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:
- Edit the
docker-compose.ymllocally - Wait for Syncthing sync (10-30 seconds)
- SSH to server:
ssh ubuntu@51.89.231.46 "cd /opt/<path> && docker compose up -d"
Syncthing Operations
# 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.mdfor full script inventory
Vault Operations
# 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:
environment:
- DB_PASSWORD=${VAULT_DB_PASSWORD} # Read from Vault via script
Git Workflow
Automated Git Hooks
pre-commit hook:
- Blocks commits containing
.env,.key,.pemfiles - 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 featurefix:- Bug fixrefactor:- Code refactoringdocs:- Documentationchore:- 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:
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:
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_connectoraddon - 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 integrationvirtual_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-internalnetwork - 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:
- Read local files from
/Volumes/SSD/Aimpress_Cloud_Prod/ - Edit files locally (never SSH to make changes)
- Wait 10-30 seconds for Syncthing to sync to server
- Commit with descriptive message using format above
- Verify changes on server if needed (via SSH to view logs/status)
When adding new services:
- Create directory in appropriate
/opt/<category>/folder - Create
docker-compose.ymlwith Traefik labels - Create
.envfile (will be auto-ignored by Git) - Add to appropriate Docker networks
- Document in project structure files
- Test on server, then commit
Important Security Notes
- Never commit secrets - pre-commit hook will block
.envfiles - Use Vault for sensitive credentials when possible
- Authentik SSO protects most admin interfaces
- Traefik middleware can add authentication to services
- Database passwords are in
.envfiles, referenced as${VAR_NAME}
Troubleshooting
Service Won't Start
- Check logs:
ssh ubuntu@51.89.231.46 "docker logs <container>" - Verify networks exist:
ssh ubuntu@51.89.231.46 "docker network ls" - Check if port is already in use
- Verify Traefik is running first
Syncthing Issues
- Check status on both Mac and server
- View sync conflicts in Syncthing UI
- Check
.stignorefor exclusion patterns - Verify folder permissions
Database Connection Issues
- Ensure
postgres-maincontainer is running - Check
database-internalnetwork exists - Verify credentials in
.envfile - 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")