# 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 " # Restart a service (via docker-compose) ssh ubuntu@51.89.231.46 "cd /opt// && docker compose restart" # View service status ssh ubuntu@51.89.231.46 "cd /opt// && 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/ && 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>.*/\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>.*/\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 ``` : 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude ``` **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..rule=Host(`.ai-impress.com`)" - "traefik.http.routers..entrypoints=websecure" - "traefik.http.routers..tls.certresolver=cloudflare" - "traefik.http.services..loadbalancer.server.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//` 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 "` 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") ```