# Repository Guidelines ## Project Structure & Module Organization This is a multi-service Docker Compose infrastructure project organized as follows: - **Root**: `compose.yaml` (orchestrates all services), `arty.yml` (centralized configuration) - **Service Directories**: Each service has its own folder (`core/`, `sexy/`, `proxy/`, `ai/`, etc.) containing: - `compose.yaml`: Service-specific Docker Compose configuration - Service-specific configuration files and initialization scripts - **Shared Infrastructure**: `core/` provides PostgreSQL 16 and Redis 7 for all services - **Proxy**: `proxy/` contains Traefik reverse proxy with dynamic security configurations in `proxy/dynamic/` All services connect to a single external Docker network (`falcon_network`) defined by `$NETWORK_NAME`. ## Build, Test, and Development Commands All commands use `pnpm arty` (leveraging scripts defined in `arty.yml`): - `pnpm arty up` - Start all services in detached mode - `pnpm arty down` - Stop and remove all containers - `pnpm arty ps` - List running containers - `pnpm arty logs` - Follow logs for all services - `pnpm arty restart` - Restart all services - `pnpm arty pull` - Pull latest images for all services - `pnpm arty config` - View rendered configuration with variables substituted - `pnpm arty net/create` - Create the external Docker network (required before first run) ## Coding Style & Naming Conventions **Environment Variables:** - Pattern: `{SERVICE}_COMPOSE_PROJECT_NAME`, `{SERVICE}_TRAEFIK_HOST`, `{SERVICE}_DOCKER_IMAGE` - Defined in `arty.yml` under `envs.default` with sensible defaults - Sensitive values stored in `.env` (passwords, secrets, API keys) **Service Configuration:** - Use `${VARIABLE:-default_value}` syntax for environment variable references - Container names: `${SERVICE_COMPOSE_PROJECT_NAME}_app` or `${SERVICE_COMPOSE_PROJECT_NAME}_component` - Volume names: `${SERVICE_COMPOSE_PROJECT_NAME}_volume_name` **Traefik Labels:** - HTTP → HTTPS redirect on `web` entrypoint (port 80) - SSL termination on `web-secure` entrypoint (port 443) - All routers scoped to `${NETWORK_NAME}` network - Use middleware pattern: `${SERVICE_COMPOSE_PROJECT_NAME}-middleware-name` **File Organization:** - Database initialization scripts: `core/postgres/init/*.sh` - Dynamic Traefik configuration: `proxy/dynamic/*.yaml` - Service data exports: `{service}/` (e.g., `sexy/directus.yaml`) ## Testing Guidelines This is an infrastructure project with no automated test suite. Validation is done through: **Service Health Checks:** - Most services include healthcheck definitions in their `compose.yaml` - Check service health: `docker ps` (look for "healthy" status) - Inspect specific service: `docker inspect ` **Manual Verification:** - Access services via configured hostnames (e.g., `https://sexy.pivoine.art`) - Check Traefik dashboard: `https://proxy.pivoine.art` (requires HTTP Basic Auth) - Test SSL certificates: `curl -I https://.pivoine.art` - Monitor logs: `pnpm arty logs` or `docker logs ` **Troubleshooting:** - Database connectivity: `docker exec core_postgres psql -U $DB_USER -l` - Network exists: `docker network ls | grep falcon` - Check configuration rendering: `pnpm arty config` ## Commit & Pull Request Guidelines **Commit Message Format:** - Follow conventional commits: `type: description` - Types: `feat`, `fix`, `docs`, `refactor`, `chore` - Keep description concise and imperative mood - Add detailed explanation in commit body when needed - Include co-author attribution: `Co-Authored-By: Claude ` - Add generation marker: `🤖 Generated with [Claude Code](https://claude.com/claude-code)` **Examples:** ``` feat: add sexy/bundle/update script to refresh Directus extensions Added arty script to update Directus extension bundle from the latest sexy_frontend image. This ensures the API container always has the latest extensions when the frontend image is rebuilt. ``` ``` fix: enable email functionality in Linkwarden with correct SMTP configuration - Add NEXT_PUBLIC_EMAIL_PROVIDER=true to enable email features - Change EMAIL_SERVER protocol from smtp:// to smtps:// for port 465 ``` **Changes to Make:** - Update `arty.yml` for new environment variables or scripts - Update service `compose.yaml` files for container configuration - Add initialization scripts to `core/postgres/init/` for new databases - Document new services in README.md - Never commit secrets - they belong in `.env` only ## Security & Configuration Tips **Secrets Management:** - Store all secrets in `.env` (never committed to git) - Use Apache htpasswd format for HTTP Basic Auth: `openssl passwd -apr1 'password'` - Escape `$` signs with `$$` in `.env` files for Docker Compose compatibility **Security Headers:** - Global security settings: `proxy/dynamic/security.yaml` - Automatically reloaded by Traefik (no restart needed) - Includes HSTS, X-Frame-Options, CSP, and rate limiting **Database Access:** - PostgreSQL exposed on port 5432 for local development - All databases use shared credentials: `$DB_USER` and `$DB_PASSWORD` - Database initialization: `core/postgres/init/01-init-databases.sh` **SSL Certificates:** - Automatic Let's Encrypt via Traefik ACME - Requires `ADMIN_EMAIL` in `.env` - Certificates stored in `proxy_letsencrypt_data` volume **Network Architecture:** - All services must connect to external network: `${NETWORK_NAME}` - Create network before first run: `pnpm arty net/create` - Network must be external and created separately from compose stacks