
Gitlab Stack Validator
- 240 installs
- 56 repo stars
- Updated October 20, 2025
- rknall/claude-skills
Use gitlab stack validator for development tasks
About
gitlab stack validator: A skill for development. This provides functionality for development workflows.
- gitlab stack validator
Gitlab Stack Validator by the numbers
- 240 all-time installs (skills.sh)
- +9 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,635 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/rknall/claude-skills --skill gitlab-stack-validatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 240 |
|---|---|
| repo stars | ★ 56 |
| Last updated | October 20, 2025 |
| Repository | rknall/claude-skills ↗ |
What it does
Use gitlab stack validator for development tasks
Files
GitLab Stack Validator
This skill validates GitLab stack projects to ensure they follow proper architecture patterns and are ready for deployment. It focuses on detection and reporting of issues, working alongside companion skills (stack-creator, secrets-manager) for remediation.
When to Use This Skill
Activate this skill when the user requests:
- Validate a GitLab stack project
- Check stack configuration before deployment
- Verify stack architecture and structure
- Audit stack for best practices compliance
- Ensure stack follows proper patterns
- Pre-deployment validation checks
- Stack health check or readiness verification
Core Validation Principles
This skill validates stacks that follow these architecture principles:
1. Configuration Management: All configuration through docker-compose.yml and ./config directory 2. Secrets Management: Secrets stored in ./secrets and referenced via Docker secrets 3. Environment Variables: .env file with matching .env.example template 4. Minimal Custom Scripts: docker-entrypoint.sh only when containers don't support native secrets 5. Proper Ownership: No root-owned files (all files owned by Docker user) 6. Temporary Files: _temporary directory for transient files that are cleaned up after use 7. Docker Best Practices: Leverage docker-validation skill for Docker-specific checks
Validation Workflow
When a user requests stack validation, follow this comprehensive workflow:
Phase 1: Pre-flight Checks
Step 1: Verify Stack Project 1. Check if current directory appears to be a stack project 2. Look for key indicators:
- docker-compose.yml exists
- Presence of ./config, ./secrets, or ./_temporary directories
- .env file exists
3. If not a stack project, report findings and ask if user wants to initialize one
Step 2: Gather Context 1. Ask user for validation scope (if needed):
- Full validation or targeted checks?
- Strict mode or permissive mode?
- Output format preference (text report vs JSON)?
2. Check if .stack-validator.yml exists for custom rules 3. Note the working directory for reporting
Phase 2: Directory Structure Validation
Step 1: Required Directories 1. Check for required directories:
./config- Configuration files directory./secrets- Secrets storage directory./_temporary- Temporary files directory
2. For each missing directory, record:
- Directory name
- Purpose and why it's required
- Impact on stack functionality
Step 2: Directory Permissions 1. Check ./secrets has restricted permissions (700 or 600) 2. Verify other directories have appropriate permissions 3. Report any permission issues with security implications
Step 3: Directory Ownership 1. Scan all project directories for ownership 2. Flag any root-owned directories:
- Directory path
- Current owner
- Expected owner (current user or docker user)
3. Flag any files with unexpected ownership
Step 4: .gitignore Validation 1. Check if .gitignore exists 2. Verify it excludes:
./secretsor./secrets/*./_temporaryor./_temporary/*.env(should not be in git)
3. Report missing exclusions with security implications
Phase 3: Environment Variables Validation
Step 1: .env File Validation 1. Check if .env file exists 2. Parse .env file for:
- Syntax errors
- Duplicate variable definitions
- Empty values that might be required
3. Record all environment variable names found
Step 2: .env.example Validation 1. Check if .env.example exists 2. If missing, this is a critical issue - document why it's needed 3. Parse .env.example for variable names
Step 3: .env Synchronization Check 1. Compare variables in .env with .env.example:
- Variables in .env but NOT in .env.example
- Variables in .env.example but NOT in .env
2. This is a critical validation point - they must match 3. Report any mismatches with specific variable names
Step 4: Environment Variable Security 1. Scan .env for potential secrets:
- Variables with names containing: password, secret, key, token, api
- Base64-encoded looking values
- Long random strings
2. If secrets detected in .env, flag as security issue 3. Suggest moving to ./secrets and Docker secrets instead
Phase 4: Docker Configuration Validation
Step 1: Invoke docker-validation Skill 1. Use the docker-validation skill to validate:
- docker-compose.yml syntax and best practices
- Dockerfile(s) if present
- Multi-stage builds
- Security configurations
2. Collect all findings from docker-validation 3. Integrate into overall stack validation report
Step 2: Stack-Specific Docker Checks 1. Review docker-compose.yml for stack patterns:
- Secrets are defined in top-level
secrets:section - Services reference secrets via
secrets:key (not environment variables) - Volume mounts follow patterns (./config, ./secrets, ./_temporary)
- Networks are properly defined if multi-service
- Service dependencies use
depends_oncorrectly
Step 3: Version Check 1. Ensure docker-compose.yml does NOT have version field at top 2. This follows modern Docker Compose specification 3. If version field present, flag for removal
Phase 5: Secrets Management Validation
Step 1: Secrets Directory Check 1. Verify ./secrets directory exists 2. Check permissions are restrictive (700) 3. Verify it's excluded from git
Step 2: Docker Secrets Validation 1. Parse docker-compose.yml for secrets definitions 2. For each secret definition:
- Verify the secret file exists in ./secrets
- Check file permissions (600 or 400)
- Verify not tracked by git
3. Report missing secret files
Step 3: Secret References Validation 1. Check each service's secrets: section 2. Verify referenced secrets are defined in top-level secrets 3. Flag any undefined secret references
Step 4: Environment Variables vs Secrets 1. Scan service environment variables for potential secrets 2. Look for patterns like:
- *_PASSWORD
- *_SECRET
- *_KEY
- *_TOKEN
- API_*
3. If sensitive data in environment, suggest using secrets instead
Step 5: Secret Exposure Check 1. Check for secrets in:
- docker-compose.yml (hardcoded values)
- .env file (should be in ./secrets instead)
- Configuration files in ./config
- Any shell scripts
2. Report any exposed secrets as critical security issues
Phase 6: Configuration Files Validation
Step 1: Config Directory Structure 1. List all files in ./config directory 2. Organize by service (if applicable) 3. Check for proper organization
Step 2: Config File Validation 1. For common config file types, validate syntax:
- YAML files (.yml, .yaml)
- JSON files (.json)
- INI files (.ini, .conf)
- TOML files (.toml)
2. Report any syntax errors
Step 3: Config vs Secrets Separation 1. Scan config files for potential secrets 2. Look for hardcoded passwords, tokens, keys 3. Flag any secrets that should be in ./secrets instead
Step 4: Config Ownership 1. Check all config files for ownership 2. Flag any root-owned config files 3. Report expected ownership (current user)
Phase 7: Script Validation
Step 1: docker-entrypoint.sh Detection 1. Search for docker-entrypoint.sh files 2. For each found:
- Document location
- Check if truly necessary
3. Validate it's only used when container doesn't support native secrets
Step 2: Script Permissions 1. Check docker-entrypoint.sh is executable (chmod +x) 2. Verify ownership (should not be root) 3. Report permission issues
Step 3: Script Content Validation 1. Scan script for:
- Hardcoded secrets (critical issue)
- Proper secret handling from /run/secrets/
- Error handling
- Syntax errors (if bash/sh)
2. Report any issues found
Step 4: Necessity Check 1. Review if docker-entrypoint.sh is truly needed 2. Check if service supports native Docker secrets 3. Suggest removal if unnecessary
Phase 8: Temporary Directory Validation
Step 1: Directory Check 1. Verify ./_temporary exists 2. Check it's in .gitignore 3. Verify permissions
Step 2: Content Check 1. List contents of ./_temporary 2. Check for:
- Leftover files that should be cleaned
- Large files consuming space
- Old files (> 7 days old)
3. Report if not empty with details
Step 3: Usage Validation 1. Check if ./_temporary is properly mounted in docker-compose.yml 2. Verify services use it for temporary files 3. Flag if not being utilized
Phase 9: File Ownership Audit
Step 1: Comprehensive Ownership Scan 1. Use find . -type f -user root 2>/dev/null to find root-owned files 2. Exclude expected directories (.git, node_modules, vendor) 3. List all root-owned files found
Step 2: Categorize Issues 1. Group by directory:
- ./config files owned by root
- ./secrets files owned by root
- Application files owned by root
2. Report with specific paths
Step 3: Impact Assessment 1. For each root-owned file:
- Explain why this is problematic
- Impact on stack operations
- Potential errors that may occur
Phase 10: Report Generation
Step 1: Compile All Findings 1. Organize findings by category:
- Directory Structure
- Environment Variables (.env sync)
- Docker Configuration
- Secrets Management
- Configuration Files
- Scripts (docker-entrypoint.sh)
- Temporary Directory
- File Ownership
2. Assign severity levels:
- ❌ CRITICAL: Security issues, missing required components, .env mismatch
- ⚠️ WARNING: Best practice violations, potential issues
- ✅ PASS: No issues found
Step 2: Generate Validation Report
Create a comprehensive report with this structure:
🔍 GitLab Stack Validation Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Stack: [directory name]
Date: [timestamp]
Mode: [strict/permissive]
📊 SUMMARY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Passed: [count]
⚠️ Warnings: [count]
❌ Critical: [count]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 DETAILED FINDINGS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[For each validation category]
[Category Icon] [Category Name]: [STATUS]
[If issues found:]
❌ [Issue description]
Location: [file/directory path]
Impact: [what this affects]
Details: [specific information]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎯 OVERALL STATUS: [PASSED/FAILED/WARNINGS]
[If failures or warnings:]
🔧 RECOMMENDED ACTIONS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Prioritized list of actions needed]
1. [Most critical action]
2. [Next action]
...
💡 NEXT STEPS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- Use stack-creator skill to fix structural issues
- Use secrets-manager skill to properly configure secrets
- Re-run validation after fixesStep 3: Provide Actionable Guidance 1. For each issue, provide:
- Clear description of the problem
- Why it matters
- Which companion skill can help fix it
- General guidance (but not actual fix commands)
2. Prioritize issues by severity 3. Group related issues together
Step 4: Export Options 1. If user requested JSON output, export as:
{
"stack": "directory-name",
"timestamp": "ISO-8601",
"summary": {
"passed": 5,
"warnings": 2,
"critical": 1,
"status": "failed"
},
"findings": [
{
"category": "environment-variables",
"status": "critical",
"issues": [...]
}
]
}Validation Categories Reference
1. Directory Structure
- Required directories exist
- Proper permissions
- .gitignore coverage
- Ownership correctness
2. Environment Variables
- .env file exists and valid
- .env.example exists
- CRITICAL: .env and .env.example are synchronized
- No secrets in .env
3. Docker Configuration
- docker-compose.yml valid (via docker-validation skill)
- No version field
- Secrets properly defined
- Volumes follow patterns
- Service dependencies correct
4. Secrets Management
- ./secrets directory secure
- All referenced secrets exist
- Proper permissions
- No exposed secrets
- Environment variables don't contain secrets
5. Configuration Files
- Proper organization
- Valid syntax
- No embedded secrets
- Correct ownership
6. Scripts
- docker-entrypoint.sh only when necessary
- Executable permissions
- No hardcoded secrets
- Proper secret handling
7. Temporary Directory
- Exists and in .gitignore
- Empty or contains only expected transient files
- Properly utilized in compose file
8. File Ownership
- No root-owned files
- Consistent ownership
- Proper user/group
Integration with Companion Skills
stack-creator
- Recommend for: Creating missing directories, initializing structure
- Handles: Setting up new stacks, fixing structural issues
secrets-manager
- Recommend for: Secrets configuration, secret file management
- Handles: Creating/updating secrets, proper secret setup
docker-validation
- Used directly during validation for Docker-specific checks
- Provides: Docker Compose and Dockerfile validation
- Integrated into stack validation report
Validation Modes
Standard Mode (Default)
- Report all issues as warnings or errors
- Provide comprehensive findings
- Suggest improvements
Strict Mode
- Fail on warnings
- Require all best practices
- Zero tolerance for deviations
Permissive Mode
- Only fail on critical issues
- Allow warnings
- More lenient on best practices
Configuration Support
If .stack-validator.yml exists in project root, respect these settings:
# Validation mode
strict_mode: false
# Whether warnings should fail validation
fail_on_warnings: false
# Paths to exclude from validation
exclude_paths:
- ./vendor
- ./node_modules
- ./_temporary/cache
# Custom validation scripts to run
custom_checks:
- ./scripts/custom-validation.sh
# Specific checks to skip
skip_checks:
- temporary-directory-emptyCommunication Style
When reporting validation results:
1. Be Clear and Direct: State issues plainly without hedging 2. Be Specific: Include exact file paths, line numbers, variable names 3. Be Actionable: Explain what needs to be done (without doing it) 4. Be Helpful: Point to companion skills that can fix issues 5. Be Organized: Group related issues, prioritize by severity 6. Be Educational: Explain why something is an issue 7. Be Concise: Don't overwhelm with details, but be thorough
Critical Validation Points
These are must-pass criteria for production stacks:
1. ✅ .env and .env.example are fully synchronized 2. ✅ No secrets in docker-compose.yml environment variables 3. ✅ ./secrets directory exists and has restrictive permissions 4. ✅ All referenced secrets exist 5. ✅ ./secrets and ./_temporary are in .gitignore 6. ✅ No root-owned files 7. ✅ docker-compose.yml passes docker-validation 8. ✅ No secrets exposed in git 9. ✅ .env file is not tracked by git
Important Notes
- Read-Only: This skill NEVER modifies files - validation only
- Detection-Focused: Report issues, don't fix them
- Comprehensive: Check all aspects systematically
- Fast: Complete validation in seconds
- Integrative: Use docker-validation skill for Docker checks
- Companion-Aware: Direct users to appropriate skills for fixes
Example Validation Flow
User: "Validate my stack"
1. Check if docker-compose.yml exists ✅
2. Verify directory structure
- ./config ✅
- ./secrets ✅
- ./_temporary ⚠️ (not in .gitignore)
3. Validate .env configuration
- .env exists ✅
- .env.example exists ❌ CRITICAL
4. Run docker-validation skill
- docker-compose.yml syntax ✅
- Secrets configuration ⚠️ (using environment vars)
5. Check secrets management
- ./secrets permissions ✅
- Secret files exist ✅
6. Scan for ownership issues
- Found 3 root-owned files in ./config ❌
7. Generate report with findings
8. Suggest: Use stack-creator to add .env.example and fix .gitignore---
This skill ensures stack quality, security, and deployment readiness through comprehensive validation.
Common Stack Validation Issues
This guide documents common issues found during stack validation, their causes, impacts, and remediation guidance.
Table of Contents
1. Critical Issues 2. Security Issues 3. Configuration Issues 4. Structural Issues 5. Docker Issues 6. Ownership Issues
---
Critical Issues
1. Missing .env.example File
Issue: .env file exists but .env.example is missing
Impact:
- New developers don't know which environment variables are required
- No template for setting up new environments
- Difficult to understand configuration requirements
- Potential for missing critical variables in deployments
Detection:
❌ Environment Variables: CRITICAL
- .env.example file not found
- Required for documenting environment configurationWhy This Matters: The .env.example file serves as documentation and a template for all required environment variables. Without it, setting up the stack in a new environment is error-prone.
Remediation: Use stack-creator skill to generate .env.example from current .env file:
claude "Use stack-creator to add .env.example"- Or manually create .env.example with all variables from .env
---
2. .env and .env.example Out of Sync
Issue: Variables in .env don't match .env.example
Impact:
- Deployments may fail due to missing variables
- Documentation is inaccurate
- Team members may have different configurations
- Difficult to identify required vs optional variables
Detection:
❌ Environment Variables: CRITICAL
- Variables in .env but NOT in .env.example:
* API_TIMEOUT
* MAX_CONNECTIONS
- Variables in .env.example but NOT in .env:
* CACHE_TTLWhy This Matters: The two files MUST be synchronized. .env.example is the source of truth for required variables.
Remediation: 1. Manually sync the files - add missing variables 2. Use stack-creator to regenerate .env.example 3. Review if any variables should be removed
---
3. Secrets in .env File
Issue: Passwords, API keys, or tokens in .env
Impact:
- Security risk if .env is accidentally committed
- Secrets not properly isolated
- Violates security best practices
- Difficult to rotate secrets
Detection:
❌ Environment Variables: CRITICAL
- Potential secrets detected in .env:
* DB_PASSWORD (contains password pattern)
* API_KEY (contains key pattern)
* JWT_SECRET (contains secret pattern)Why This Matters: Secrets should NEVER be in .env files. They should be in ./secrets and managed via Docker secrets.
Remediation: Use secrets-manager skill to properly configure secrets: 1. Move secrets to ./secrets directory 2. Update docker-compose.yml to use Docker secrets 3. Remove secrets from .env 4. Update applications to read from /run/secrets/
---
Security Issues
4. ./secrets Directory Not in .gitignore
Issue: Secrets directory not excluded from git
Impact:
- CRITICAL SECURITY RISK: Secrets may be committed to git
- Secret exposure in version control
- Compliance violations
- Potential data breach
Detection:
❌ Directory Structure: CRITICAL
- ./secrets not found in .gitignore
- Risk of committing secrets to version controlWhy This Matters: Once secrets are committed to git, they remain in history forever, even after removal.
Remediation: 1. Add to .gitignore immediately:
/secrets/
/secrets/*2. Check git status: git status - ensure no secrets staged 3. If secrets were committed, rotate all secrets immediately 4. Use BFG Repo-Cleaner to remove from git history (if needed)
---
5. Secrets in docker-compose.yml Environment Variables
Issue: Hardcoded secrets in environment variables
Impact:
- Secrets exposed in docker-compose.yml (may be in git)
- Violates security best practices
- Difficult to rotate secrets
- Potential compliance issues
Detection:
❌ Secrets Management: CRITICAL
- Service 'app' has potential secrets in environment:
* DB_PASSWORD=supersecret123 (hardcoded password)
- Use Docker secrets insteadWhy This Matters: docker-compose.yml is often committed to git. Any secrets in it are exposed.
Remediation: Use secrets-manager skill: 1. Move secrets to ./secrets/ 2. Define in top-level secrets section 3. Reference via secrets key in services 4. Update app to read from /run/secrets/
---
6. Insecure ./secrets Directory Permissions
Issue: ./secrets directory readable by others (e.g., 755 instead of 700)
Impact:
- Other users on system can read secrets
- Security compliance violation
- Unnecessary exposure of sensitive data
Detection:
⚠️ Secrets Management: WARNING
- ./secrets directory permissions: 755
- Should be 700 (owner only)Why This Matters: Secrets should only be readable by the user running the stack.
Remediation:
chmod 700 ./secrets/
chmod 600 ./secrets/*---
7. .env File Tracked in Git
Issue: .env file is committed to version control
Impact:
- Configuration values exposed in git
- May contain secrets (critical if so)
- Environment-specific config in wrong place
- Difficult to manage per-environment settings
Detection:
❌ Directory Structure: CRITICAL
- .env is tracked by git (run: git ls-files .env)
- Must be added to .gitignoreWhy This Matters: .env files often contain environment-specific and sensitive data.
Remediation: 1. Add .env to .gitignore 2. Remove from git: git rm --cached .env 3. Commit the removal 4. Review .env for any secrets - rotate if found
---
Configuration Issues
8. Docker Compose Version Field Present
Issue: docker-compose.yml includes version field
Impact:
- Using deprecated syntax
- May cause warnings in modern Docker
- Not following current best practices
Detection:
⚠️ Docker Configuration: WARNING
- docker-compose.yml contains 'version' field
- Modern Compose files should omit versionWhy This Matters: Docker Compose Specification removed version field requirement. Modern files don't need it.
Remediation: Manually remove the version line:
# ❌ Remove this
version: '3.8'
# ✅ Start directly with services
services:
app:
...---
9. Secrets Defined but Files Missing
Issue: docker-compose.yml references secrets that don't exist
Impact:
- Stack will fail to start
- Docker will show "secret not found" errors
- Service initialization failures
Detection:
❌ Secrets Management: CRITICAL
- Secret 'db_password' defined but file not found:
Expected: ./secrets/db_password
- Secret 'api_key' defined but file not found:
Expected: ./secrets/api_keyWhy This Matters: Docker requires all referenced secret files to exist before starting services.
Remediation: Use secrets-manager skill to create missing secrets: 1. Create secret files: echo -n "value" > ./secrets/db_password 2. Set proper permissions: chmod 600 ./secrets/db_password 3. Verify all secrets exist before starting stack
---
10. Undefined Secret References
Issue: Service references secret not defined in top-level secrets section
Impact:
- Docker Compose validation will fail
- Stack won't start
- Error messages: "service X references undefined secret"
Detection:
❌ Docker Configuration: CRITICAL
- Service 'app' references undefined secret: jwt_secret
- Secret must be defined in top-level 'secrets' sectionWhy This Matters: All secrets used by services must be declared in the top-level secrets section.
Remediation: Add secret definition to docker-compose.yml:
secrets:
jwt_secret:
file: ./secrets/jwt_secret---
Structural Issues
11. Missing Required Directories
Issue: Required directories (./config, ./secrets, ./_temporary) don't exist
Impact:
- Stack may fail to start
- Volume mounts will fail
- Application errors
- Inconsistent structure
Detection:
❌ Directory Structure: CRITICAL
- Required directory './secrets' not found
- Required directory './_temporary' not foundWhy This Matters: Standard stack architecture requires these directories for proper organization.
Remediation: Use stack-creator skill to create missing directories:
mkdir -p config secrets _temporary
chmod 700 secrets---
12. Incomplete .gitignore
Issue: .gitignore doesn't exclude required paths
Impact:
- Risk of committing secrets or temporary files
- Large repository size
- Cluttered git status
- Security risks
Detection:
⚠️ Directory Structure: WARNING
- .gitignore missing exclusion: /secrets/
- .gitignore missing exclusion: /_temporary/
- .gitignore missing exclusion: .envWhy This Matters: Without proper exclusions, sensitive files may be accidentally committed.
Remediation: Add to .gitignore:
# Secrets
/secrets/
/secrets/*
# Environment
.env
# Temporary
/_temporary/
/_temporary/*---
13. ./_temporary Directory Not Empty
Issue: Temporary directory contains leftover files
Impact:
- Disk space waste
- Stale cached data
- Potential application issues
- Poor housekeeping
Detection:
⚠️ Temporary Directory: WARNING
- ./_temporary is not empty:
* cache/sessions/old_session.dat (modified 15 days ago)
* uploads/temp_file.jpg (modified 3 days ago)
- Should be cleaned after useWhy This Matters: Temporary directories should be cleaned regularly to avoid accumulating stale data.
Remediation: Manually clean the directory:
rm -rf ./_temporary/*---
Docker Issues
14. Invalid docker-compose.yml Syntax
Issue: YAML syntax errors in docker-compose.yml
Impact:
- Stack cannot start
- Docker Compose validation fails
- Difficult to troubleshoot
- Deployment failures
Detection:
❌ Docker Configuration: CRITICAL
- docker-compose.yml syntax error at line 23
- Error: mapping values are not allowed hereWhy This Matters: Invalid YAML prevents Docker Compose from parsing the file.
Remediation: 1. Fix YAML syntax errors 2. Validate with: docker compose config 3. Use YAML linter for complex files
---
15. Missing Service Dependencies
Issue: Services don't declare depends_on for required services
Impact:
- Services may start in wrong order
- Application errors on startup
- Race conditions
- Connection failures
Detection:
⚠️ Docker Configuration: WARNING
- Service 'app' uses DB but doesn't declare depends_on: postgres
- May cause startup ordering issuesWhy This Matters: Docker doesn't guarantee service start order without depends_on.
Remediation: Add depends_on to service:
services:
app:
depends_on:
- postgres
- redis---
16. No Restart Policy
Issue: Services missing restart policy
Impact:
- Services don't recover from crashes
- Manual intervention needed
- Poor reliability
- Downtime
Detection:
⚠️ Docker Configuration: WARNING
- Service 'app' has no restart policy
- Recommend: restart: unless-stoppedWhy This Matters: Production services should automatically restart on failure.
Remediation: Add restart policy:
services:
app:
restart: unless-stopped---
Ownership Issues
17. Root-Owned Configuration Files
Issue: Files in ./config owned by root
Impact:
- Cannot modify config without sudo
- Inconsistent permissions
- Potential deployment issues
- Bad practice
Detection:
❌ File Ownership: CRITICAL
- Root-owned files found:
* ./config/nginx/nginx.conf (owner: root)
* ./config/app/settings.yml (owner: root)Why This Matters: All stack files should be owned by the Docker user, not root.
Remediation: Fix ownership:
sudo chown -R $(id -u):$(id -g) ./config/To prevent: Ensure containers don't run as root, or don't mount config as writable.
---
18. Root-Owned Files in _temporary
Issue: Files in ./_temporary created by containers as root
Impact:
- Cannot clean directory without sudo
- Disk space issues
- Permission problems
Detection:
⚠️ File Ownership: WARNING
- Root-owned files in ./_temporary:
* ./_temporary/cache/app_cache.db (owner: root)Why This Matters: Temporary files should be cleanable by the user.
Remediation: 1. Fix current files: sudo chown -R $(id -u):$(id -g) ./_temporary/ 2. Prevent future issues: Run containers as current user:
services:
app:
user: "${UID}:${GID}"---
19. Root-Owned Secret Files
Issue: Files in ./secrets owned by root
Impact:
- Cannot update secrets without sudo
- Security risk (root has access)
- Operational difficulties
Detection:
❌ File Ownership: CRITICAL
- Root-owned files in ./secrets:
* ./secrets/db_password (owner: root)Why This Matters: Secret files should be owned by the Docker user with restricted permissions.
Remediation:
sudo chown $(id -u):$(id -g) ./secrets/*
chmod 600 ./secrets/*---
Script Issues
20. Unnecessary docker-entrypoint.sh
Issue: docker-entrypoint.sh exists but container supports native secrets
Impact:
- Unnecessary complexity
- Maintenance overhead
- Potential bugs
- Not following best practices
Detection:
⚠️ Scripts: WARNING
- docker-entrypoint.sh found for service 'postgres'
- PostgreSQL supports native Docker secrets via *_FILE variables
- Consider removing custom entrypointWhy This Matters: Many modern containers support Docker secrets natively. Custom entrypoints add complexity.
Remediation: 1. Check if container supports *_FILE environment variables 2. If yes, remove docker-entrypoint.sh 3. Use native secret support:
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password---
21. docker-entrypoint.sh Not Executable
Issue: Script exists but doesn't have execute permissions
Impact:
- Container will fail to start
- Permission denied errors
- Deployment failures
Detection:
❌ Scripts: CRITICAL
- docker-entrypoint.sh is not executable
- Current permissions: -rw-r--r--
- Required: -rwxr-xr-xWhy This Matters: Docker needs execute permission to run entrypoint scripts.
Remediation:
chmod +x docker-entrypoint.sh---
22. Hardcoded Secrets in Scripts
Issue: Secrets hardcoded in docker-entrypoint.sh or other scripts
Impact:
- CRITICAL SECURITY RISK
- Secrets exposed in git
- Difficult to rotate
- Compliance violations
Detection:
❌ Scripts: CRITICAL
- Hardcoded secret detected in docker-entrypoint.sh:
Line 15: export DB_PASSWORD="supersecret123"
- Secrets must be read from /run/secrets/Why This Matters: Scripts are often committed to git. Hardcoded secrets = exposed secrets.
Remediation: Read secrets from Docker secrets:
# ❌ BAD
export DB_PASSWORD="supersecret123"
# ✅ GOOD
export DB_PASSWORD=$(cat /run/secrets/db_password)---
Summary: Issue Severity Levels
Critical (Must Fix Before Deployment)
- Missing .env.example
- .env/.env.example out of sync
- Secrets in .env
- ./secrets not in .gitignore
- Secrets in docker-compose.yml
- Missing secret files
- Root-owned files
- Invalid docker-compose.yml syntax
High (Fix Soon)
- .env tracked in git
- Insecure secrets permissions
- Missing required directories
- Hardcoded secrets in scripts
Medium (Should Fix)
- Docker Compose version field
- Missing restart policies
- Missing dependencies
- Incomplete .gitignore
Low (Nice to Fix)
- ./_temporary not empty
- Unnecessary docker-entrypoint.sh
- Suboptimal configurations
---
Quick Reference: Issue to Skill Mapping
| Issue Category | Recommended Skill |
|---|---|
| Missing .env.example | stack-creator |
| Directory structure | stack-creator |
| Secrets management | secrets-manager |
| Docker configuration | docker-validation (auto-used) |
| File ownership | Manual fix (chown) |
| .gitignore issues | stack-creator |
| .env sync | Manual + stack-creator |
---
This guide helps identify and understand common stack validation issues for faster remediation.
GitLab Stack Validator
Comprehensive validation for GitLab stack projects to ensure deployment readiness and best practices compliance
Overview
The GitLab Stack Validator skill provides thorough validation of stack projects before deployment. It checks directory structure, environment variable configuration, secrets management, Docker configuration, and file ownership to ensure your stack follows proper architecture patterns and is ready for production.
Key Focus: Detection and reporting of issues (not automatic fixes)
Features
- Comprehensive Validation: 8 validation categories covering all aspects of stack configuration
- Environment Variable Synchronization: Critical .env and .env.example sync checking
- Secrets Security: Ensures secrets are properly isolated and secured
- Docker Best Practices: Leverages docker-validation skill for Docker-specific checks
- File Ownership Auditing: Detects problematic root-owned files
- Detailed Reporting: Clear, actionable findings with severity levels
- Integration Ready: Works alongside stack-creator and secrets-manager skills
When to Use
Use this skill when you need to:
- Validate a GitLab stack project before deployment
- Verify stack configuration and architecture
- Audit stack for security and best practices compliance
- Pre-deployment health checks
- Ensure stack follows proper patterns
- Identify configuration issues before they cause problems
Installation
# Install the skill marketplace
/plugin marketplace add rknall/Skills
# Install the stack-validator skill
/plugin install stack-validatorQuick Start
Basic Validation
# Validate current directory
claude "validate this stack"
# Validate specific directory
claude "validate the stack in /path/to/my-stack"Full Validation Example
# In your stack directory
cd ~/projects/my-stack
# Run validation
claude "validate this stack"Example Output:
🔍 GitLab Stack Validation Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Stack: my-stack
Date: 2025-01-15 14:30:22
Mode: standard
📊 SUMMARY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Passed: 5
⚠️ Warnings: 2
❌ Critical: 1
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 DETAILED FINDINGS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Directory Structure: PASS
❌ Environment Variables: CRITICAL
❌ .env.example file not found
Impact: No template for environment setup
Details: Required for documenting configuration
⚠️ File Ownership: WARNING
⚠️ Root-owned files detected
Location: ./config/nginx.conf
Impact: Cannot modify without sudo
Details: Owner: root, Expected: user
✅ Docker Configuration: PASS
✅ Secrets Management: PASS
✅ Configuration Files: PASS
✅ Scripts: PASS
✅ Temporary Directory: PASS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎯 OVERALL STATUS: FAILED
🔧 RECOMMENDED ACTIONS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Create .env.example file (use stack-creator skill)
2. Fix ownership of ./config/nginx.conf:
sudo chown $(id -u):$(id -g) ./config/nginx.conf
💡 NEXT STEPS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- Use stack-creator skill to generate .env.example
- Re-run validation after fixesWhat Gets Validated
1. Directory Structure
- ✅ Required directories exist (./config, ./secrets, ./_temporary)
- ✅ Proper permissions on ./secrets (700)
- ✅ .gitignore excludes secrets and temporary files
- ✅ No root-owned directories
2. Environment Variables
- ✅ .env file exists and is valid
- ✅ .env.example exists and is valid
- ✅ CRITICAL: .env and .env.example are synchronized
- ✅ No secrets detected in .env
- ✅ .env is not tracked by git
3. Docker Configuration
- ✅ docker-compose.yml valid (via docker-validation skill)
- ✅ No deprecated version field
- ✅ Secrets properly defined in top-level section
- ✅ Services reference secrets correctly
- ✅ Volume mounts follow patterns
- ✅ Service dependencies declared
4. Secrets Management
- ✅ ./secrets directory exists and secure (700 permissions)
- ✅ All referenced secret files exist
- ✅ Secret files have proper permissions (600)
- ✅ No secrets in environment variables
- ✅ No hardcoded secrets anywhere
5. Configuration Files
- ✅ Proper organization in ./config
- ✅ Valid syntax (YAML, JSON, INI, TOML)
- ✅ No embedded secrets
- ✅ Correct file ownership
6. Scripts
- ✅ docker-entrypoint.sh only when necessary
- ✅ Executable permissions set
- ✅ No hardcoded secrets
- ✅ Proper error handling
7. Temporary Directory
- ✅ ./_temporary exists
- ✅ Excluded from git
- ✅ Empty or contains only expected files
- ✅ Properly utilized in compose file
8. File Ownership
- ✅ No root-owned files
- ✅ Consistent ownership (Docker user)
- ✅ Proper permissions throughout
Validation Modes
Standard Mode (Default)
Reports all issues as warnings or errors with full details.
claude "validate this stack"Strict Mode
Fails on any warnings - zero tolerance for deviations.
claude "validate this stack in strict mode"Targeted Validation
Validate specific categories only.
# Validate only secrets
claude "validate secrets configuration"
# Validate only environment variables
claude "check .env configuration"
# Validate only Docker setup
claude "validate docker configuration"Critical Validation Points
These are must-pass criteria for production deployment:
1. ✅ .env and .env.example are fully synchronized 2. ✅ No secrets in docker-compose.yml environment variables 3. ✅ ./secrets directory exists with restrictive permissions (700) 4. ✅ All referenced secrets exist in ./secrets 5. ✅ ./secrets and ./_temporary are in .gitignore 6. ✅ No root-owned files in project 7. ✅ docker-compose.yml passes docker-validation checks 8. ✅ No secrets exposed in git 9. ✅ .env file is not tracked by git
Integration with Companion Skills
stack-creator
When to Use: Fix structural issues, create missing files
# After validation finds missing .env.example
claude "use stack-creator to add .env.example"
# Fix directory structure
claude "use stack-creator to set up required directories"secrets-manager
When to Use: Configure secrets, fix secret-related issues
# After validation finds secret issues
claude "use secrets-manager to properly configure db_password"
# Move secrets from .env to Docker secrets
claude "use secrets-manager to migrate secrets from .env"docker-validation
Automatic Integration: Automatically invoked during stack validation
The stack-validator automatically uses the docker-validation skill to check:
- docker-compose.yml syntax and best practices
- Dockerfile validation (if present)
- Multi-stage build verification
- Security configurations
Common Issues and Fixes
Issue: .env.example Missing
Validation Output:
❌ Environment Variables: CRITICAL
- .env.example file not foundFix:
claude "use stack-creator to generate .env.example from my .env"---
Issue: .env and .env.example Out of Sync
Validation Output:
❌ Environment Variables: CRITICAL
- Variables in .env but NOT in .env.example:
* API_TIMEOUT
- Variables in .env.example but NOT in .env:
* CACHE_TTLFix: Manually add missing variables to both files, or:
claude "use stack-creator to synchronize .env.example with .env"---
Issue: Secrets in .env File
Validation Output:
❌ Environment Variables: CRITICAL
- Potential secrets detected in .env:
* DB_PASSWORD
* API_KEYFix:
claude "use secrets-manager to move DB_PASSWORD and API_KEY to Docker secrets"---
Issue: Root-Owned Files
Validation Output:
❌ File Ownership: CRITICAL
- Root-owned files:
* ./config/nginx.confFix:
sudo chown $(id -u):$(id -g) ./config/nginx.conf---
Issue: Missing ./secrets Directory
Validation Output:
❌ Directory Structure: CRITICAL
- Required directory './secrets' not foundFix:
claude "use stack-creator to create required directories"---
Custom Validation Rules
Create .stack-validator.yml in your project root to customize validation:
# Validation mode
strict_mode: false
# Whether warnings should fail validation
fail_on_warnings: false
# Paths to exclude from validation
exclude_paths:
- ./vendor
- ./node_modules
- ./_temporary/cache
# Specific checks to skip
skip_checks:
- temporary-directory-emptyOutput Formats
Text Report (Default)
Human-readable validation report with colored output and formatting.
claude "validate this stack"JSON Output
Machine-readable format for CI/CD integration.
claude "validate this stack and output JSON"JSON Structure:
{
"stack": "my-stack",
"timestamp": "2025-01-15T14:30:22Z",
"summary": {
"passed": 5,
"warnings": 2,
"critical": 1,
"status": "failed"
},
"findings": [
{
"category": "environment-variables",
"status": "critical",
"issues": [
{
"severity": "critical",
"message": ".env.example file not found",
"impact": "No template for environment setup"
}
]
}
]
}CI/CD Integration
GitLab CI Example
validate-stack:
stage: validate
image: anthropic/claude-code:latest
script:
- cd $CI_PROJECT_DIR
- claude "validate this stack in strict mode"
only:
- merge_requests
- mainGitHub Actions Example
- name: Validate Stack
run: |
cd $GITHUB_WORKSPACE
claude "validate this stack"Architecture Patterns
This skill validates stacks following these principles:
1. Configuration Management: All configuration in docker-compose.yml and ./config 2. Secrets Isolation: Secrets in ./secrets via Docker secrets 3. Environment Variables: .env with matching .env.example 4. Minimal Scripts: docker-entrypoint.sh only when necessary 5. Proper Ownership: No root-owned files 6. Temporary Files: ./_temporary for transient data 7. Docker Best Practices: Modern compose syntax, proper volume mounts
See validation-patterns.md for detailed patterns and examples.
Troubleshooting
Validation Says "Not a Stack Project"
Cause: Missing docker-compose.yml or stack indicators
Fix:
- Ensure you're in the correct directory
- Check that docker-compose.yml exists
- Initialize a new stack with stack-creator if needed
---
Validation Finds Many Root-Owned Files
Cause: Containers running as root and creating files in mounted volumes
Fix: 1. Fix existing files: sudo chown -R $(id -u):$(id -g) . 2. Prevent future issues: Run containers as current user
services:
app:
user: "${UID}:${GID}"---
Docker Validation Fails
Cause: docker-compose.yml has syntax or best practice issues
Fix: The docker-validation skill will provide specific guidance. Follow its recommendations.
---
Reference Documentation
- SKILL.md - Complete skill workflow and implementation
- validation-patterns.md - Architecture patterns and examples
- common-issues.md - Detailed issue explanations and fixes
Version History
v1.0.0 (2025-01-15)
- Initial release
- 8 comprehensive validation categories
- .env and .env.example synchronization checking
- Integration with docker-validation skill
- Support for companion skills (stack-creator, secrets-manager)
- Custom validation rules support
- JSON output format
Contributing
Found an issue or have a suggestion? This skill is part of the rknall-custom-skills marketplace.
License
Part of the rknall-custom-skills marketplace for Claude Code.
---
Ensure your GitLab stacks are secure, compliant, and deployment-ready with comprehensive validation.
Stack Validation Patterns
This document outlines the architecture patterns and validation criteria for GitLab stack projects.
Table of Contents
1. Directory Structure Patterns 2. Environment Variable Patterns 3. Secrets Management Patterns 4. Docker Compose Patterns 5. Configuration Patterns 6. File Ownership Patterns
---
Directory Structure Patterns
Standard Stack Directory Layout
my-stack/
├── docker-compose.yml # Main compose file (NO version field)
├── .env # Environment variables (NOT in git)
├── .env.example # Environment template (IN git)
├── .gitignore # Must exclude secrets, .env, _temporary
├── .stack-validator.yml # Optional: Custom validation rules
├── config/ # Configuration files
│ ├── nginx/
│ │ └── nginx.conf
│ ├── app/
│ │ └── settings.yml
│ └── db/
│ └── init.sql
├── secrets/ # Secret files (NOT in git)
│ ├── db_password
│ ├── api_key
│ └── jwt_secret
└── _temporary/ # Transient files (NOT in git)
└── (cleaned after use)Required Directories
| Directory | Purpose | Git Status | Permissions |
|---|---|---|---|
./config | Configuration files | Tracked | 755 |
./secrets | Secret files | NOT tracked | 700 |
./_temporary | Temporary/cache files | NOT tracked | 755 |
.gitignore Requirements
MUST contain:
# Secrets - never commit
/secrets/
/secrets/*
# Environment variables - never commit
.env
# Temporary files
/_temporary/
/_temporary/*
# Common exclusions
*.log
.DS_Store---
Environment Variable Patterns
.env File Structure
Purpose: Define environment-specific variables for stack deployment
Example .env:
# Application
APP_NAME=my-application
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com
# Database
DB_HOST=postgres
DB_PORT=5432
DB_NAME=app_database
DB_USER=app_user
# NOTE: DB_PASSWORD should be in ./secrets/db_password, not here!
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
# Ports
WEB_PORT=80
API_PORT=8080
# Docker
COMPOSE_PROJECT_NAME=my-stack.env.example File Structure
Purpose: Template for required environment variables
CRITICAL RULE: .env.example MUST contain ALL variables from .env and vice versa
Example .env.example:
# Application
APP_NAME=my-application
APP_ENV=development
APP_DEBUG=true
APP_URL=http://localhost
# Database
DB_HOST=postgres
DB_PORT=5432
DB_NAME=app_database
DB_USER=app_user
# NOTE: DB_PASSWORD is managed via Docker secrets in ./secrets/
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
# Ports - Customize for your environment
WEB_PORT=80
API_PORT=8080
# Docker
COMPOSE_PROJECT_NAME=my-stackEnvironment Variable Validation Rules
1. Synchronization: Every variable in .env MUST be in .env.example 2. Documentation: .env.example should have comments explaining each variable 3. No Secrets: .env should NOT contain passwords, API keys, tokens, or secrets 4. Default Values: .env.example should have safe defaults for development 5. Required Variables: Both files must define all required variables
Variables That Should NOT Be in .env
Move these to ./secrets and use Docker secrets:
# ❌ BAD - Don't put these in .env
DB_PASSWORD=supersecret123
API_KEY=sk_live_abc123xyz
JWT_SECRET=my-jwt-secret-key
STRIPE_SECRET_KEY=sk_test_123
OAUTH_CLIENT_SECRET=abc123xyz
# ✅ GOOD - Reference via Docker secrets instead
# See docker-compose.yml secrets section
# Secrets are in ./secrets/ directory---
Secrets Management Patterns
Secrets Directory Structure
secrets/
├── db_password # PostgreSQL password
├── db_root_password # Root password (if needed)
├── api_key # External API key
├── jwt_secret # JWT signing secret
└── oauth_client_secret # OAuth secretSecret File Format
Single-line, no trailing newline:
# Create secret (no newline)
echo -n "my-secret-value" > ./secrets/db_password
# ✅ Correct: 16 bytes
# ❌ Wrong: 17 bytes (includes newline)Secret File Permissions
# Directory
chmod 700 ./secrets/
# Individual files
chmod 600 ./secrets/db_password
chmod 600 ./secrets/api_keyDocker Compose Secrets Pattern
Top-level secrets definition:
secrets:
db_password:
file: ./secrets/db_password
api_key:
file: ./secrets/api_key
jwt_secret:
file: ./secrets/jwt_secretService secrets reference:
services:
app:
image: myapp:latest
secrets:
- db_password
- api_key
- jwt_secret
environment:
# ✅ GOOD - Reference location, not value
DB_PASSWORD_FILE: /run/secrets/db_password
API_KEY_FILE: /run/secrets/api_key
# ❌ BAD - Don't put actual secrets here
# DB_PASSWORD: supersecret123Application Secret Usage
In application code:
# Read secret from Docker secrets mount
def get_secret(secret_name):
secret_path = f'/run/secrets/{secret_name}'
with open(secret_path, 'r') as f:
return f.read().strip()
# Usage
db_password = get_secret('db_password')
api_key = get_secret('api_key')---
Docker Compose Patterns
Modern Docker Compose Format
❌ DON'T use version field:
# ❌ OLD - Don't include version
version: '3.8'✅ DO use modern format:
# ✅ MODERN - No version field
services:
app:
image: myapp:latestComplete Stack Example
services:
app:
image: myapp:latest
container_name: my-app
restart: unless-stopped
depends_on:
- postgres
- redis
secrets:
- db_password
- api_key
environment:
APP_ENV: ${APP_ENV}
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT}
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASSWORD_FILE: /run/secrets/db_password
API_KEY_FILE: /run/secrets/api_key
volumes:
- ./config/app:/app/config:ro
- app-data:/app/data
networks:
- app-network
ports:
- "${WEB_PORT}:80"
postgres:
image: postgres:16-alpine
container_name: my-postgres
restart: unless-stopped
secrets:
- db_password
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
volumes:
- ./config/db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
redis:
image: redis:7-alpine
container_name: my-redis
restart: unless-stopped
volumes:
- redis-data:/data
networks:
- app-network
volumes:
app-data:
postgres-data:
redis-data:
networks:
app-network:
driver: bridge
secrets:
db_password:
file: ./secrets/db_password
api_key:
file: ./secrets/api_keyVolume Mount Patterns
Configuration files (read-only):
volumes:
- ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./config/app/settings.yml:/app/config/settings.yml:roSecrets (via Docker secrets - automatic mount):
secrets:
- db_password # Mounted at /run/secrets/db_passwordPersistent data (named volumes):
volumes:
- postgres-data:/var/lib/postgresql/data
- redis-data:/dataTemporary files (local directory):
volumes:
- ./_temporary/cache:/app/cache
- ./_temporary/uploads:/app/uploads---
Configuration Patterns
Configuration File Organization
By service:
config/
├── nginx/
│ ├── nginx.conf
│ └── ssl/
│ ├── cert.pem
│ └── key.pem
├── app/
│ ├── settings.yml
│ └── logging.conf
└── db/
└── init.sqlConfiguration vs Secrets Separation
✅ Configuration (in ./config):
- Server hostnames
- Port numbers
- Feature flags
- Logging levels
- Public certificates
- Database names
- Cache settings
❌ NOT Configuration (in ./secrets):
- Passwords
- API keys
- Tokens
- Private keys
- OAuth secrets
- JWT secrets
- Encryption keys
Example Configuration File
config/app/settings.yml:
# Application Settings
app:
name: ${APP_NAME}
environment: ${APP_ENV}
debug: ${APP_DEBUG}
url: ${APP_URL}
# Database (connection info, NOT credentials)
database:
host: ${DB_HOST}
port: ${DB_PORT}
name: ${DB_NAME}
user: ${DB_USER}
# Password loaded from /run/secrets/db_password
# Redis
cache:
driver: redis
host: ${REDIS_HOST}
port: ${REDIS_PORT}
# Logging
logging:
level: info
output: stdout
format: json---
File Ownership Patterns
Correct Ownership
All stack files should be owned by the Docker user (current user), NOT root.
Check ownership:
# List all files with ownership
eza -la --tree
# Find root-owned files (should return nothing)
find . -type f -user root 2>/dev/nullCommon Ownership Issues
Problem: Files created by Docker containers as root
Example scenario:
# Container runs as root, creates files in mounted volume
services:
app:
image: nginx:latest # Runs as root by default
volumes:
- ./config/nginx.conf:/etc/nginx/nginx.conf
- ./_temporary/cache:/var/cache/nginx # ⚠️ Creates files as root!Fix: Ensure containers run as non-root user
services:
app:
image: nginx:latest
user: "${UID}:${GID}" # Run as current user
volumes:
- ./config/nginx.conf:/etc/nginx/nginx.conf
- ./_temporary/cache:/var/cache/nginxFixing Ownership
Stack-validator detects ownership issues but doesn't fix them.
Manual fix (user action):
# Fix ownership of specific file
sudo chown $(id -u):$(id -g) ./config/nginx.conf
# Fix ownership of entire directory
sudo chown -R $(id -u):$(id -g) ./config/
# Fix ownership of all project files
sudo chown -R $(id -u):$(id -g) .Prevention: Use stack-creator skill to properly initialize stacks with correct ownership from the start.
---
Validation Checklist
Pre-Deployment Validation
Use this checklist to ensure stack readiness:
- [ ] Directory Structure
- [ ] ./config directory exists
- [ ] ./secrets directory exists with 700 permissions
- [ ] ./_temporary directory exists
- [ ] .gitignore excludes secrets, .env, _temporary
- [ ] Environment Variables
- [ ] .env file exists and is valid
- [ ] .env.example exists and is valid
- [ ] .env and .env.example are synchronized
- [ ] No secrets in .env file
- [ ] .env is in .gitignore
- [ ] Docker Configuration
- [ ] docker-compose.yml has no version field
- [ ] docker-compose.yml passes docker-validation
- [ ] Secrets defined in top-level secrets section
- [ ] Services reference secrets via secrets key
- [ ] Volume mounts follow patterns
- [ ] Secrets Management
- [ ] All secret files exist in ./secrets
- [ ] Secret files have 600 permissions
- [ ] ./secrets directory has 700 permissions
- [ ] No secrets in docker-compose.yml environment
- [ ] No secrets in git
- [ ] File Ownership
- [ ] No root-owned files in project
- [ ] All files owned by Docker user
- [ ] Config files have correct ownership
- [ ] Configuration
- [ ] Config files properly organized
- [ ] No secrets in config files
- [ ] Config file syntax valid
---
Reference: Common Validation Failures
| Issue | Category | Severity | Fix With |
|---|---|---|---|
| Missing .env.example | Environment | Critical | stack-creator |
| .env/.env.example mismatch | Environment | Critical | Manual sync + stack-creator |
| Secrets in .env | Security | Critical | secrets-manager |
| ./secrets not in .gitignore | Security | Critical | stack-creator |
| Root-owned files | Ownership | High | Manual chown |
| Missing ./secrets directory | Secrets | High | stack-creator |
| docker-compose.yml has version | Docker | Medium | Manual edit |
| Secrets in environment vars | Security | Critical | secrets-manager |
| Missing required directory | Structure | High | stack-creator |
| ./_temporary not empty | Cleanup | Low | Manual cleanup |
---
These patterns ensure consistent, secure, and maintainable GitLab stack projects.