From e8f9c86e2313ff9f7b4019da0bfaf06e2151e14c Mon Sep 17 00:00:00 2001 From: Zhongwei Li Date: Sun, 30 Nov 2025 08:51:55 +0800 Subject: [PATCH] Initial commit --- .claude-plugin/plugin.json | 12 + README.md | 3 + SKILL.md | 768 +++++++++++++++++++++++++++++++++++++ plugin.lock.json | 53 +++ service-templates.md | 723 ++++++++++++++++++++++++++++++++++ validation-rules.md | 76 ++++ 6 files changed, 1635 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 README.md create mode 100644 SKILL.md create mode 100644 plugin.lock.json create mode 100644 service-templates.md create mode 100644 validation-rules.md diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..802907c --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "config-generator", + "description": "Generates service-specific configuration files for GitLab stack projects using .env as primary config source. Creates nginx, PostgreSQL, Redis configs, meta files (CLAUDE.md, .gitignore, .dockerignore), with strict validation for secrets and paths", + "version": "1.0.0", + "author": { + "name": "rknall", + "email": "zhongweili@tubi.tv" + }, + "skills": [ + "./" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d8cff20 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# config-generator + +Generates service-specific configuration files for GitLab stack projects using .env as primary config source. Creates nginx, PostgreSQL, Redis configs, meta files (CLAUDE.md, .gitignore, .dockerignore), with strict validation for secrets and paths diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..eb9292e --- /dev/null +++ b/SKILL.md @@ -0,0 +1,768 @@ +--- +name: "GitLab Stack Config Generator" +description: "Generates service-specific configuration files for GitLab stack projects in ./config directory, using .env as the primary configuration source. Creates nginx, PostgreSQL, Redis, and custom service configs with strict validation for secrets, paths, and Docker best practices. Use when setting up service configurations, creating config templates, or ensuring configs follow stack patterns." +--- + +# GitLab Stack Config Generator + +This skill generates and manages service-specific configuration files for GitLab stack projects, ensuring configurations follow proper patterns, use .env for all variables, and never contain secrets. + +## When to Use This Skill + +Activate this skill when the user requests: +- Generate configuration files for services (nginx, PostgreSQL, Redis, etc.) +- Create config templates for new services +- Set up ./config directory structure +- Validate existing configuration files +- Ensure configs use .env variables correctly +- Check that configs don't contain secrets +- Set up project meta files (CLAUDE.md, .gitignore, .dockerignore) +- Sync .env and .env.example + +## Core Configuration Principles + +**CRITICAL RULES**: + +1. **./env is Configuration Source**: All configuration variables in .env (NOT in config files) +2. **No Secrets in Configs**: NEVER put secrets in configuration files (use secrets-manager) +3. **Service Directories**: Each service gets `./config/service-name/` directory +4. **Flat Inside Service**: Config files flat inside service directory +5. **.env Sync**: .env and .env.example MUST always match +6. **Path Validation**: All referenced paths must exist +7. **Docker Validation**: Use docker-validation skill for Docker configs +8. **Project Meta Files**: CLAUDE.md, .gitignore, .dockerignore required + +## Configuration Workflow + +### Phase 1: Understanding Requirements + +**Step 1: Determine What to Generate** + +Ask the user (or infer): +- Which services need configuration? +- New configs or updating existing? +- Production, development, or both? +- Which templates to use (if any)? + +**Step 2: Check Current State** + +1. Does ./config directory exist? +2. Does .env exist? +3. Does .env.example exist? +4. Do service directories already exist? +5. Are meta files present (CLAUDE.md, .gitignore, .dockerignore)? + +### Phase 2: Directory Structure Setup + +**Step 1: Create ./config Directory** + +```bash +mkdir -p ./config +chmod 755 ./config +``` + +**Step 2: Create Service Directories** + +For each service (e.g., nginx, postgres, redis): + +```bash +mkdir -p ./config/nginx +mkdir -p ./config/postgres +mkdir -p ./config/redis +chmod 755 ./config/* +``` + +**Directory Structure**: +``` +./config/ +├── nginx/ +│ ├── nginx.conf +│ ├── ssl/ +│ │ └── (SSL configs, not certificates) +│ └── conf.d/ +│ └── default.conf +├── postgres/ +│ ├── postgresql.conf +│ └── init.sql +├── redis/ +│ └── redis.conf +└── app/ + └── settings.yml +``` + +**Principles**: +- One directory per service +- Flat structure inside each service directory +- Subdirectories only when logically needed (e.g., nginx/ssl/, nginx/conf.d/) + +### Phase 3: Meta Files Generation + +**CRITICAL**: Always ensure these files exist + +**Step 1: Generate CLAUDE.md** + +Create `CLAUDE.md` in project root: + +```markdown +# CLAUDE.md + +This file provides guidance when working with code in this repository. + +## Repository Purpose + +[Brief description of the stack project] + +## Stack Architecture + +This is a GitLab stack project following these principles: + +- **Configuration**: All variables in .env, configs in ./config +- **Secrets**: All secrets in ./secrets via Docker secrets +- **Structure**: Standard directories (./config, ./secrets, ./_temporary) +- **Docker**: Modern Docker Compose (no version field) +- **Ownership**: No root-owned files + +## Working with This Stack + +### Configuration Files + +All service configurations are in `./config/[service-name]/` directories. +Configuration values are loaded from `.env` file. + +### Environment Variables + +- `.env` contains all configuration (NOT secrets) +- `.env.example` must match `.env` exactly (critical requirement) +- Update both files when adding new variables + +### Secrets Management + +All secrets are managed via Docker secrets: +- Location: `./secrets/` directory +- Never in .env or docker-compose.yml +- Use secrets-manager skill for secret operations + +### Docker Commands + +```bash +# Start stack +docker compose up -d + +# View logs +docker compose logs -f + +# Stop stack +docker compose down +``` + +## Important Rules + +### Git Commits + +**CRITICAL**: When creating commit messages, NEVER mention "Claude" or "Claude Code" in the commit message. + +Good commit messages: +- "Add nginx configuration for SSL termination" +- "Update PostgreSQL settings for production" +- "Fix Redis persistence configuration" + +Bad commit messages: +- "Claude added nginx config" ❌ +- "Asked Claude to update settings" ❌ + +### File Permissions + +All files must be owned by the current user (not root): +```bash +# Check ownership +find . -user root -type f + +# Fix if needed +sudo chown -R $(id -u):$(id -g) . +``` + +### Validation + +Before deployment, always run: +```bash +# Validate entire stack +[validation command] + +# Check secrets +[secrets validation command] +``` + +## Directory Structure + +``` +./ +├── docker-compose.yml # Main compose file (NO version field) +├── .env # Configuration variables +├── .env.example # Template (must match .env) +├── CLAUDE.md # This file +├── .gitignore # Git exclusions +├── .dockerignore # Docker build exclusions +├── config/ # Service configurations +│ ├── nginx/ +│ ├── postgres/ +│ └── redis/ +├── secrets/ # Docker secrets (NOT in git) +│ └── .gitkeep +└── _temporary/ # Transient files (NOT in git) +``` + +## Skills Available + +- **stack-validator**: Validate entire stack before deployment +- **secrets-manager**: Manage Docker secrets securely +- **config-generator**: Generate/update service configurations +- **docker-validation**: Validate Docker configs + +--- + +*Last updated: [date]* +``` + +**Step 2: Generate/Update .gitignore** + +```gitignore +# Secrets - NEVER commit +/secrets/ +/secrets/* +!secrets/.gitkeep + +# Environment +.env +.env.local +.env.*.local + +# Temporary +/_temporary/ +/_temporary/* + +# Docker +.dockerignore + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log +logs/ + +# Build artifacts +dist/ +build/ +node_modules/ +vendor/ + +# Backup files +*.backup +*.old +*.bak +``` + +**Step 3: Generate .dockerignore** + +```dockerignore +# Git +.git/ +.gitignore + +# Environment +.env +.env.* + +# Secrets +secrets/ + +# Temporary +_temporary/ + +# Documentation +*.md +CLAUDE.md + +# IDE +.vscode/ +.idea/ + +# OS +.DS_Store +Thumbs.db + +# Dependencies (if not needed in build) +node_modules/ +vendor/ + +# Logs +*.log +logs/ +``` + +### Phase 4: Service Configuration Generation + +**Common Services**: nginx, PostgreSQL, Redis + +For each service, follow this pattern: + +**Step 1: Determine Configuration Needs** + +Ask user: +- Use template or custom? +- Which features to enable? +- Production or development settings? + +**Step 2: Identify Required .env Variables** + +For each service, list all .env variables needed: + +Example for nginx: +- NGINX_PORT +- NGINX_HOST +- NGINX_SSL_ENABLED +- APP_HOST +- APP_PORT + +**Step 3: Generate Configuration File** + +**CRITICAL**: Use environment variable placeholders (`${VAR_NAME}`) + +Example nginx.conf: +```nginx +# Nginx Configuration +# Loads variables from .env + +upstream app { + server ${APP_HOST}:${APP_PORT}; +} + +server { + listen ${NGINX_PORT}; + server_name ${NGINX_HOST}; + + # SSL configuration + # SSL certificates loaded from Docker secrets + # ssl_certificate /run/secrets/ssl_cert; + # ssl_certificate_key /run/secrets/ssl_key; + + location / { + proxy_pass http://app; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } +} +``` + +**Step 4: Update .env** + +Add all required variables: + +```bash +# Nginx Configuration +NGINX_PORT=80 +NGINX_HOST=localhost +NGINX_SSL_ENABLED=false +APP_HOST=app +APP_PORT=8080 +``` + +**Step 5: Update .env.example** + +**CRITICAL**: Must match .env exactly: + +```bash +# Nginx Configuration +NGINX_PORT=80 +NGINX_HOST=localhost +NGINX_SSL_ENABLED=false +APP_HOST=app +APP_PORT=8080 +``` + +**Step 6: Update docker-compose.yml** + +Add volume mount for config: + +```yaml +services: + nginx: + image: nginx:alpine + ports: + - "${NGINX_PORT}:80" + volumes: + - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + environment: + # Variables loaded from .env automatically + NGINX_HOST: ${NGINX_HOST} + APP_HOST: ${APP_HOST} + APP_PORT: ${APP_PORT} +``` + +### Phase 5: Configuration Validation + +**Step 1: Syntax Validation** + +For each config file type: + +**Nginx**: +```bash +# Test nginx config +docker run --rm -v $(pwd)/config/nginx:/etc/nginx:ro nginx:alpine nginx -t +``` + +**PostgreSQL**: +```bash +# Check SQL syntax +# Parse init.sql for syntax errors +``` + +**Redis**: +```bash +# Test redis config +docker run --rm -v $(pwd)/config/redis:/usr/local/etc/redis:ro redis:alpine redis-server --test-memory 1024 +``` + +**Step 2: Secret Detection** (CRITICAL) + +Scan all config files for secrets: + +```bash +# Check for common secret patterns +grep -r -iE "(password|secret|key|token|api_key)" ./config/ + +# If found, this is CRITICAL SECURITY ISSUE +# Must use secrets-manager to fix +``` + +**Step 3: Path Validation** + +Check that all referenced paths exist: + +1. Config files reference other files? +2. Volume mounts in docker-compose.yml? +3. All paths exist? + +**Step 4: .env Synchronization** (CRITICAL) + +```bash +# Extract variable names from .env +env_vars=$(grep -E "^[A-Z_]+" .env | cut -d'=' -f1 | sort) + +# Extract from .env.example +example_vars=$(grep -E "^[A-Z_]+" .env.example | cut -d'=' -f1 | sort) + +# Compare +diff <(echo "$env_vars") <(echo "$example_vars") + +# If any difference, this is CRITICAL ERROR +``` + +**Step 5: Docker Validation** + +**CRITICAL**: Use docker-validation skill: + +``` +"Validate docker-compose.yml using docker-validation skill" +``` + +Address all findings before completing. + +### Phase 6: Template Selection + +**Step 1: Offer Templates** + +For nginx, PostgreSQL, Redis, offer these options: + +**Nginx Templates**: +1. **Simple Reverse Proxy** (default) + - Basic proxy to backend service + - No SSL + - Minimal config + +2. **SSL Termination** + - HTTPS enabled + - SSL certificates from Docker secrets + - HTTP to HTTPS redirect + +3. **Static + Proxy** + - Serve static files + - Proxy API requests + - Caching headers + +4. **Custom** + - User provides requirements + - Generate custom config + +**PostgreSQL Templates**: +1. **Basic** (default) + - Standard settings + - Simple init.sql + - Development friendly + +2. **Production** + - Optimized settings + - Connection pooling + - Performance tuning + +3. **With Extensions** + - PostGIS, UUID, etc. + - Extension-specific config + - Init scripts for extensions + +4. **Custom** + - User-specified + +**Redis Templates**: +1. **Cache** (default) + - No persistence + - Memory-only + - Fast + +2. **Persistent** + - RDB snapshots + - AOF logging + - Data durability + +3. **Pub/Sub** + - Optimized for messaging + - No persistence + - High throughput + +4. **Custom** + - User requirements + +**Step 2: Generate from Template** + +Based on user selection, generate appropriate config with: +- Required .env variables +- Proper docker-compose.yml integration +- README section documenting the config + +### Phase 7: Validation Report + +After generation, provide comprehensive report: + +``` +📝 Configuration Generation Report +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +✅ Meta Files +✅ CLAUDE.md created +✅ .gitignore updated +✅ .dockerignore created + +✅ Directory Structure +✅ ./config/nginx created +✅ ./config/postgres created +✅ ./config/redis created + +📄 Generated Configurations + +Nginx (Simple Reverse Proxy): +✅ ./config/nginx/nginx.conf +✅ Variables added to .env (3) +✅ .env.example synced +✅ docker-compose.yml updated +✅ Syntax validation: PASS + +PostgreSQL (Basic): +✅ ./config/postgres/postgresql.conf +✅ ./config/postgres/init.sql +✅ Variables added to .env (5) +✅ .env.example synced +✅ docker-compose.yml updated + +Redis (Cache): +✅ ./config/redis/redis.conf +✅ Variables added to .env (2) +✅ .env.example synced +✅ docker-compose.yml updated + +🔐 Security Validation +✅ No secrets in config files +✅ All secrets in ./secrets (via secrets-manager) +✅ Configs use .env variables only + +✅ Path Validation +✅ All referenced paths exist +✅ Volume mounts valid + +✅ .env Synchronization +✅ .env and .env.example match (10 variables) + +🐳 Docker Validation +✅ docker-compose.yml syntax valid +✅ All volume mounts exist +✅ No deprecated syntax + +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +✅ Configuration generation complete! + +Next Steps: +1. Review generated configurations +2. Customize as needed +3. Run: docker compose config (validate) +4. Run: docker compose up -d +``` + +## Service-Specific Patterns + +### Nginx Configuration + +**Always include**: +- Environment variable placeholders +- Upstream backend reference +- Basic security headers +- Logging configuration + +**Never include**: +- Hardcoded IPs or hosts +- SSL certificate content (use Docker secrets) +- Passwords or tokens + +**Example variables**: +```bash +NGINX_PORT=80 +NGINX_HOST=localhost +NGINX_WORKER_PROCESSES=auto +NGINX_WORKER_CONNECTIONS=1024 +APP_BACKEND_HOST=app +APP_BACKEND_PORT=8080 +``` + +### PostgreSQL Configuration + +**Always include**: +- Init scripts for database/user creation +- Basic performance tuning +- Connection limits +- Logging settings + +**Never include**: +- Passwords (use Docker secrets) +- Production database names in dev +- Hardcoded connection strings + +**Example variables**: +```bash +POSTGRES_DB=myapp_db +POSTGRES_USER=myapp_user +# POSTGRES_PASSWORD in ./secrets/db_password +POSTGRES_MAX_CONNECTIONS=100 +POSTGRES_SHARED_BUFFERS=256MB +``` + +### Redis Configuration + +**Always include**: +- Persistence settings +- Memory limits +- Network bindings + +**Never include**: +- Passwords (use Docker secrets if needed) +- Hardcoded master/slave IPs + +**Example variables**: +```bash +REDIS_PORT=6379 +REDIS_MAXMEMORY=256mb +REDIS_MAXMEMORY_POLICY=allkeys-lru +REDIS_SAVE_ENABLED=false +``` + +## Integration with Companion Skills + +### secrets-manager +**When to call**: +- Secrets detected in config files → CRITICAL +- Need to reference secrets in configs +- SSL certificates or private keys needed + +### docker-validation +**When to call**: +- After updating docker-compose.yml (ALWAYS) +- Before completing generation +- User requests validation + +### stack-validator +**When to call**: +- After generation complete +- Validate entire stack +- Ensure all patterns followed + +## Important Notes + +- **No Secrets**: NEVER put secrets in config files +- **.env Source**: All configuration from .env +- **.env Sync**: .env and .env.example must match +- **Docker Validation**: Always use docker-validation skill +- **CLAUDE.md Rule**: Must specify no "Claude" in commit messages +- **Templates Optional**: User chooses defaults or custom +- **Path Validation**: All paths must exist + +## Example Workflow + +``` +User: "Generate nginx and PostgreSQL configs" + +1. Check current state + - ./config missing → create it + - .env exists + - .env.example exists + - CLAUDE.md missing → create it + +2. Generate meta files + - Create CLAUDE.md + - Update .gitignore + - Create .dockerignore + +3. Ask user for templates + "Which templates would you like? + - Nginx: [Simple Reverse Proxy], SSL Termination, Static + Proxy, Custom + - PostgreSQL: [Basic], Production, With Extensions, Custom" + +4. User selects: Simple Reverse Proxy, Basic + +5. Generate nginx config + - Create ./config/nginx/nginx.conf + - Add variables to .env + - Sync .env.example + - Update docker-compose.yml + - Validate syntax + +6. Generate PostgreSQL config + - Create ./config/postgres/postgresql.conf + - Create ./config/postgres/init.sql + - Add variables to .env + - Sync .env.example + - Update docker-compose.yml + +7. Run validations + - Secret detection: PASS + - Path validation: PASS + - .env sync check: PASS + - Docker validation (via docker-validation skill): PASS + +8. Generate report + - Show all created files + - List .env variables added + - Confirmation that validations passed + +9. Next steps + - Suggest testing: docker compose config + - Recommend: docker compose up -d +``` + +--- + +*This skill generates service configurations following GitLab stack patterns with strict validation.* diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..8954046 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,53 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:rknall/claude-skills:config-generator", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "1c9f91730daf95a9bd8854a705542c374616e464", + "treeHash": "ee524b8377d1c84eb64a1bc3c1a0b3684617ce5a3f16e53325c73c31278503bd", + "generatedAt": "2025-11-28T10:27:59.494605Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "config-generator", + "description": "Generates service-specific configuration files for GitLab stack projects using .env as primary config source. Creates nginx, PostgreSQL, Redis configs, meta files (CLAUDE.md, .gitignore, .dockerignore), with strict validation for secrets and paths", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "service-templates.md", + "sha256": "ae499cd15d92b0e219ebf9f41a00462986d8fbfbbd03452696d4e49e6943b065" + }, + { + "path": "validation-rules.md", + "sha256": "e4e02ff6e4a163250503cd4d547f370c98619bfe1bc95e86fafed77900a47da5" + }, + { + "path": "README.md", + "sha256": "b473d5521bc279d8f15f47dd13e4f954d0a5dead0e775ee7a7f578244348aff6" + }, + { + "path": "SKILL.md", + "sha256": "680aae92ccb55944716ece6c687528cf46482a695e5a61e394e8b4b31ffb0936" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "a60ab82c92e39be3473868ae0aec0ee23f3ecddb8ebdcc9077a21270d5fa8b70" + } + ], + "dirSha256": "ee524b8377d1c84eb64a1bc3c1a0b3684617ce5a3f16e53325c73c31278503bd" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/service-templates.md b/service-templates.md new file mode 100644 index 0000000..a3db46e --- /dev/null +++ b/service-templates.md @@ -0,0 +1,723 @@ +# Service Configuration Templates + +This document provides ready-to-use configuration templates for common services in GitLab stack projects. + +## Table of Contents +1. [Nginx Templates](#nginx-templates) +2. [PostgreSQL Templates](#postgresql-templates) +3. [Redis Templates](#redis-templates) +4. [Template Variables Reference](#template-variables-reference) + +--- + +## Nginx Templates + +### Template 1: Simple Reverse Proxy (Default) + +**Use Case**: Basic reverse proxy to backend application + +**Files**: +- `./config/nginx/nginx.conf` + +**nginx.conf**: +```nginx +# Nginx Configuration - Simple Reverse Proxy +# Variables loaded from .env + +events { + worker_connections ${NGINX_WORKER_CONNECTIONS}; +} + +http { + # Basic settings + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Logging + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log warn; + + # Performance + sendfile on; + keepalive_timeout 65; + + # Upstream backend + upstream backend { + server ${APP_BACKEND_HOST}:${APP_BACKEND_PORT}; + } + + server { + listen ${NGINX_PORT}; + server_name ${NGINX_HOST}; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Proxy to backend + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Health check + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + } +} +``` + +**.env variables**: +```bash +# Nginx - Simple Reverse Proxy +NGINX_PORT=80 +NGINX_HOST=localhost +NGINX_WORKER_CONNECTIONS=1024 +APP_BACKEND_HOST=app +APP_BACKEND_PORT=8080 +``` + +**docker-compose.yml**: +```yaml +services: + nginx: + image: nginx:alpine + container_name: ${COMPOSE_PROJECT_NAME}-nginx + restart: unless-stopped + ports: + - "${NGINX_PORT}:80" + volumes: + - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + depends_on: + - app + networks: + - app-network +``` + +--- + +### Template 2: SSL Termination + +**Use Case**: HTTPS with SSL certificate from Docker secrets + +**Files**: +- `./config/nginx/nginx.conf` + +**nginx.conf**: +```nginx +# Nginx Configuration - SSL Termination +# SSL certificates from Docker secrets + +events { + worker_connections ${NGINX_WORKER_CONNECTIONS}; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log warn; + + sendfile on; + keepalive_timeout 65; + + upstream backend { + server ${APP_BACKEND_HOST}:${APP_BACKEND_PORT}; + } + + # HTTP server - redirect to HTTPS + server { + listen 80; + server_name ${NGINX_HOST}; + + location / { + return 301 https://$server_name$request_uri; + } + } + + # HTTPS server + server { + listen 443 ssl http2; + server_name ${NGINX_HOST}; + + # SSL certificates from Docker secrets + ssl_certificate /run/secrets/ssl_cert; + ssl_certificate_key /run/secrets/ssl_key; + + # SSL settings + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256'; + ssl_prefer_server_ciphers off; + + # Security headers + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + } + } +} +``` + +**.env variables**: +```bash +# Nginx - SSL Termination +NGINX_HOST=example.com +NGINX_WORKER_CONNECTIONS=1024 +APP_BACKEND_HOST=app +APP_BACKEND_PORT=8080 +``` + +**Required secrets** (via secrets-manager): +- `ssl_cert` - SSL certificate +- `ssl_key` - SSL private key + +**docker-compose.yml**: +```yaml +services: + nginx: + image: nginx:alpine + container_name: ${COMPOSE_PROJECT_NAME}-nginx + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + secrets: + - ssl_cert + - ssl_key + depends_on: + - app + networks: + - app-network + +secrets: + ssl_cert: + file: ./secrets/ssl_cert.pem + ssl_key: + file: ./secrets/ssl_key.pem +``` + +--- + +### Template 3: Static Files + API Proxy + +**Use Case**: Serve static frontend, proxy API requests to backend + +**Files**: +- `./config/nginx/nginx.conf` + +**nginx.conf**: +```nginx +# Nginx Configuration - Static + API Proxy + +events { + worker_connections ${NGINX_WORKER_CONNECTIONS}; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log warn; + + sendfile on; + tcp_nopush on; + keepalive_timeout 65; + gzip on; + gzip_vary on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml; + + upstream api { + server ${API_BACKEND_HOST}:${API_BACKEND_PORT}; + } + + server { + listen ${NGINX_PORT}; + server_name ${NGINX_HOST}; + root ${NGINX_STATIC_ROOT}; + index index.html; + + # Static files + location / { + try_files $uri $uri/ /index.html; + expires 1h; + add_header Cache-Control "public, immutable"; + } + + # API proxy + location /api/ { + proxy_pass http://api/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # No caching for API + add_header Cache-Control "no-cache, no-store, must-revalidate"; + } + + # Assets with long cache + location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + } +} +``` + +**.env variables**: +```bash +# Nginx - Static + API Proxy +NGINX_PORT=80 +NGINX_HOST=localhost +NGINX_WORKER_CONNECTIONS=1024 +NGINX_STATIC_ROOT=/usr/share/nginx/html +API_BACKEND_HOST=api +API_BACKEND_PORT=3000 +``` + +**docker-compose.yml**: +```yaml +services: + nginx: + image: nginx:alpine + container_name: ${COMPOSE_PROJECT_NAME}-nginx + restart: unless-stopped + ports: + - "${NGINX_PORT}:80" + volumes: + - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + - ./frontend/dist:/usr/share/nginx/html:ro + depends_on: + - api + networks: + - app-network +``` + +--- + +## PostgreSQL Templates + +### Template 1: Basic (Default) + +**Use Case**: Standard PostgreSQL for development + +**Files**: +- `./config/postgres/postgresql.conf` +- `./config/postgres/init.sql` + +**postgresql.conf**: +```conf +# PostgreSQL Configuration - Basic +# Variables from .env where applicable + +# Connection settings +listen_addresses = '*' +max_connections = 100 +shared_buffers = 128MB + +# Logging +log_destination = 'stderr' +logging_collector = on +log_directory = 'log' +log_filename = 'postgresql-%Y-%m-%d.log' +log_statement = 'all' +log_duration = on + +# Performance +effective_cache_size = 256MB +maintenance_work_mem = 64MB +checkpoint_completion_target = 0.9 +wal_buffers = 16MB +default_statistics_target = 100 +``` + +**init.sql**: +```sql +-- PostgreSQL Initialization Script +-- Creates database and user +-- Password loaded from Docker secrets + +-- Note: POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD +-- are set via environment and Docker secrets + +-- Create extensions if needed +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE EXTENSION IF NOT EXISTS "pg_trgm"; + +-- Grant privileges +GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO ${POSTGRES_USER}; +``` + +**.env variables**: +```bash +# PostgreSQL - Basic +POSTGRES_DB=myapp_db +POSTGRES_USER=myapp_user +# POSTGRES_PASSWORD in ./secrets/db_password +POSTGRES_PORT=5432 +``` + +**docker-compose.yml**: +```yaml +services: + postgres: + image: postgres:16-alpine + container_name: ${COMPOSE_PROJECT_NAME}-postgres + restart: unless-stopped + secrets: + - db_password + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD_FILE: /run/secrets/db_password + volumes: + - ./config/postgres/postgresql.conf:/etc/postgresql/postgresql.conf:ro + - ./config/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql:ro + - postgres-data:/var/lib/postgresql/data + ports: + - "${POSTGRES_PORT}:5432" + networks: + - app-network + +volumes: + postgres-data: + +secrets: + db_password: + file: ./secrets/db_password +``` + +--- + +### Template 2: Production + +**Use Case**: Optimized PostgreSQL for production + +**Files**: +- `./config/postgres/postgresql.conf` +- `./config/postgres/init.sql` + +**postgresql.conf**: +```conf +# PostgreSQL Configuration - Production Optimized + +# Connection settings +listen_addresses = '*' +max_connections = 200 +superuser_reserved_connections = 3 + +# Memory settings (adjust based on available RAM) +shared_buffers = 256MB +effective_cache_size = 1GB +work_mem = 16MB +maintenance_work_mem = 128MB +wal_buffers = 16MB + +# Checkpoints +checkpoint_timeout = 15min +checkpoint_completion_target = 0.9 +max_wal_size = 2GB +min_wal_size = 1GB + +# Performance +random_page_cost = 1.1 +effective_io_concurrency = 200 +default_statistics_target = 100 + +# Logging (production level) +log_destination = 'stderr' +logging_collector = on +log_directory = 'log' +log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' +log_rotation_age = 1d +log_rotation_size = 100MB +log_min_duration_statement = 1000 # Log slow queries > 1s +log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h ' +log_checkpoints = on +log_connections = on +log_disconnections = on +log_lock_waits = on + +# Autovacuum (important for production) +autovacuum = on +autovacuum_max_workers = 3 +autovacuum_naptime = 10s + +# Statement timeout (prevent runaway queries) +statement_timeout = 60000 # 60 seconds +``` + +**init.sql**: +```sql +-- PostgreSQL Production Initialization + +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE EXTENSION IF NOT EXISTS "pg_trgm"; +CREATE EXTENSION IF NOT EXISTS "btree_gin"; +CREATE EXTENSION IF NOT EXISTS "btree_gist"; + +-- Performance monitoring +CREATE EXTENSION IF NOT EXISTS "pg_stat_statements"; + +-- Grant privileges +GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO ${POSTGRES_USER}; + +-- Create schema +CREATE SCHEMA IF NOT EXISTS app AUTHORIZATION ${POSTGRES_USER}; +``` + +**.env variables**: +```bash +# PostgreSQL - Production +POSTGRES_DB=prod_db +POSTGRES_USER=app_user +# POSTGRES_PASSWORD in ./secrets/db_password +POSTGRES_PORT=5432 +POSTGRES_MAX_CONNECTIONS=200 +``` + +--- + +## Redis Templates + +### Template 1: Cache (Default) + +**Use Case**: Redis as in-memory cache (no persistence) + +**Files**: +- `./config/redis/redis.conf` + +**redis.conf**: +```conf +# Redis Configuration - Cache (No Persistence) + +# Network +bind 0.0.0.0 +port 6379 +protected-mode no + +# Memory +maxmemory 256mb +maxmemory-policy allkeys-lru + +# Persistence disabled for cache +save "" +appendonly no + +# Performance +tcp-backlog 511 +timeout 0 +tcp-keepalive 300 + +# Logging +loglevel notice +logfile "" + +# Snapshotting disabled +stop-writes-on-bgsave-error no +``` + +**.env variables**: +```bash +# Redis - Cache +REDIS_PORT=6379 +REDIS_MAXMEMORY=256mb +REDIS_MAXMEMORY_POLICY=allkeys-lru +``` + +**docker-compose.yml**: +```yaml +services: + redis: + image: redis:7-alpine + container_name: ${COMPOSE_PROJECT_NAME}-redis + restart: unless-stopped + command: redis-server /usr/local/etc/redis/redis.conf + volumes: + - ./config/redis/redis.conf:/usr/local/etc/redis/redis.conf:ro + ports: + - "${REDIS_PORT}:6379" + networks: + - app-network +``` + +--- + +### Template 2: Persistent + +**Use Case**: Redis with data persistence + +**Files**: +- `./config/redis/redis.conf` + +**redis.conf**: +```conf +# Redis Configuration - Persistent + +# Network +bind 0.0.0.0 +port 6379 +protected-mode no + +# Memory +maxmemory 512mb +maxmemory-policy allkeys-lru + +# RDB Persistence +save 900 1 # Save after 900 sec if 1 key changed +save 300 10 # Save after 300 sec if 10 keys changed +save 60 10000 # Save after 60 sec if 10000 keys changed +stop-writes-on-bgsave-error yes +rdbcompression yes +rdbchecksum yes +dbfilename dump.rdb +dir /data + +# AOF Persistence +appendonly yes +appendfilename "appendonly.aof" +appendfsync everysec +no-appendfsync-on-rewrite no +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb + +# Performance +tcp-backlog 511 +timeout 0 +tcp-keepalive 300 + +# Logging +loglevel notice +logfile "" +``` + +**.env variables**: +```bash +# Redis - Persistent +REDIS_PORT=6379 +REDIS_MAXMEMORY=512mb +REDIS_MAXMEMORY_POLICY=allkeys-lru +``` + +**docker-compose.yml**: +```yaml +services: + redis: + image: redis:7-alpine + container_name: ${COMPOSE_PROJECT_NAME}-redis + restart: unless-stopped + command: redis-server /usr/local/etc/redis/redis.conf + volumes: + - ./config/redis/redis.conf:/usr/local/etc/redis/redis.conf:ro + - redis-data:/data + ports: + - "${REDIS_PORT}:6379" + networks: + - app-network + +volumes: + redis-data: +``` + +--- + +### Template 3: Pub/Sub + +**Use Case**: Redis for messaging/pub-sub (no persistence) + +**Files**: +- `./config/redis/redis.conf` + +**redis.conf**: +```conf +# Redis Configuration - Pub/Sub + +# Network +bind 0.0.0.0 +port 6379 +protected-mode no + +# Memory (higher for message buffers) +maxmemory 1gb +maxmemory-policy noeviction + +# No persistence for pub/sub +save "" +appendonly no + +# Pub/Sub specific +client-output-buffer-limit pubsub 32mb 8mb 60 + +# Performance +tcp-backlog 511 +timeout 0 +tcp-keepalive 60 + +# Logging +loglevel notice +logfile "" +``` + +**.env variables**: +```bash +# Redis - Pub/Sub +REDIS_PORT=6379 +REDIS_MAXMEMORY=1gb +``` + +--- + +## Template Variables Reference + +### Nginx Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| NGINX_PORT | 80 | Port nginx listens on | +| NGINX_HOST | localhost | Server name | +| NGINX_WORKER_CONNECTIONS | 1024 | Max connections per worker | +| NGINX_STATIC_ROOT | /usr/share/nginx/html | Static files root | +| APP_BACKEND_HOST | app | Backend service hostname | +| APP_BACKEND_PORT | 8080 | Backend service port | +| API_BACKEND_HOST | api | API service hostname | +| API_BACKEND_PORT | 3000 | API service port | + +### PostgreSQL Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| POSTGRES_DB | myapp_db | Database name | +| POSTGRES_USER | myapp_user | Database user | +| POSTGRES_PORT | 5432 | Port PostgreSQL listens on | +| POSTGRES_MAX_CONNECTIONS | 100 | Maximum connections | + +### Redis Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| REDIS_PORT | 6379 | Port Redis listens on | +| REDIS_MAXMEMORY | 256mb | Maximum memory | +| REDIS_MAXMEMORY_POLICY | allkeys-lru | Eviction policy | + +--- + +*Use these templates as starting points and customize based on specific requirements.* diff --git a/validation-rules.md b/validation-rules.md new file mode 100644 index 0000000..2fc433d --- /dev/null +++ b/validation-rules.md @@ -0,0 +1,76 @@ +# Configuration Validation Rules + +Comprehensive validation rules for config-generator skill. + +## Critical Validation Rules + +### 1. No Secrets in Config Files (CRITICAL) + +**Rule**: Configuration files MUST NEVER contain secrets + +**Patterns to detect**: +- PASSWORD, SECRET, KEY, TOKEN, API, AUTH, CREDENTIAL +- Long random strings (40+ chars) +- Base64-encoded values +- Private keys, certificates with keys + +**Action**: If detected → Use secrets-manager skill immediately + +--- + +### 2. .env and .env.example Synchronization (CRITICAL) + +**Rule**: Files MUST have identical variable names + +**Validation**: +```bash +diff <(grep -E "^[A-Z_]+" .env | cut -d'=' -f1 | sort) \ + <(grep -E "^[A-Z_]+" .env.example | cut -d'=' -f1 | sort) +``` + +**Action**: If mismatch → Fix synchronization before completing + +--- + +### 3. Path Existence + +**Rule**: All referenced paths must exist + +**Check**: +- Volume mounts in docker-compose.yml +- File references in configs +- Directory references + +--- + +### 4. Docker Validation + +**Rule**: Always validate Docker configs + +**Action**: Use docker-validation skill on docker-compose.yml + +--- + +### 5. CLAUDE.md Requirements + +**Must contain**: +- Statement: "NEVER mention Claude in commit messages" +- Stack architecture overview +- Configuration patterns +- Secrets management rules + +--- + +## Validation Checklist + +- [ ] No secrets in config files +- [ ] .env and .env.example synced +- [ ] All paths exist +- [ ] Docker validation passed +- [ ] CLAUDE.md exists with commit rule +- [ ] .gitignore has secrets/* excluded +- [ ] .dockerignore exists + +--- + +*Strict validation ensures stack security and consistency.*