# Terraform Docker Renovate Module ## Purpose This Terraform module deploys a Renovate bot as a Docker container with the following features: - **Renovate Container**: Automatically updates dependencies in your repositories - **Gitea Integration**: Native support for Gitea platform with proper authentication - **Traefik Integration**: Automatically configures Traefik reverse proxy (optional) - **DNS Management**: Creates DNS CNAME records for the Renovate instance (optional) - **Persistent Storage**: Manages Docker volumes for configuration and cache - **Vault Integration**: Securely retrieves DNS credentials from HashiCorp Vault - **Remote State Backend**: Stores Terraform state in MinIO (S3-compatible storage) - **Resource Limits**: Configurable memory limits for container isolation ## What It Does The module creates and manages the following resources: 1. **Docker Volumes**: - `renovate-config`: Persistent storage for configuration files - `renovate-cache`: Cache storage for improved performance 2. **Renovate Container**: - Runs Renovate bot process - Connects to Traefik network for reverse proxy access (optional) - Configured with resource limits (Memory) - Configured with flexible restart policy - Logs sent to Docker daemon (managed by Loki) 3. **DNS Record** (Optional): - Creates a CNAME record pointing to the hosting server ## What is Renovate? Renovate is an automated dependency update tool that: - **Monitors dependencies** across multiple package managers and platforms - **Creates pull requests** with dependency updates automatically - **Supports semantic versioning** and custom update schedules - **Works with Docker**, Terraform, npm, pip, and many other ecosystems - **Integrates with CI/CD** pipelines for automated testing ### Common Use Cases - Automated Docker image updates with semantic versioning - Terraform module and provider version updates - Application dependency management (npm, pip, composer, etc.) - Security vulnerability patching through automatic updates - Consistent dependency versions across multiple repositories ## Prerequisites Before using this module, ensure you have: 1. **Docker Host**: A Docker daemon accessible via TCP (configured at `192.168.2.170:2376`) 2. **Docker TLS Certificates**: Client certificates in `~/.docker/` directory 3. **Traefik Network**: A Docker network named `traefik_network` must exist 4. **Gitea Instance**: Running Gitea instance with API access 5. **Renovate Bot User**: Dedicated user account in Gitea with appropriate permissions 6. **Gitea Access Token**: Personal Access Token with the following scopes: - `repo`: Read and Write - `user`: Read - `issue`: Read and Write (Gitea ≥ 1.20.0) - `organization`: Read (Gitea ≥ 1.20.0) 7. **HashiCorp Vault**: Running instance with: - AppRole authentication enabled - DNS credentials stored at `secret/dns` - Renovate credentials stored at `secret/renovate` (see Vault Setup section) - Role ID and Secret ID for authentication 8. **MinIO/S3 Backend**: For Terraform state storage 9. **DNS Server**: Supporting dynamic updates (TSIG authentication) - optional ## Gitea Bot Setup ### 1. Create Renovate Bot User In your Gitea instance: 1. Create a new user account (e.g., `renovate-bot`) 2. Configure the user with: - Full name: "Renovate Bot" - Email: `renovate-bot@example.com` 3. Add the bot user as a collaborator to repositories you want to manage ### 2. Generate Personal Access Token 1. Log in as the Renovate bot user 2. Go to Settings → Applications → Generate New Token 3. Token name: "Renovate Token" 4. Select scopes: - `repo` (Read and Write) - `user` (Read) - `issue` (Read and Write) - `organization` (Read) 5. **IMPORTANT**: Copy the token immediately - you won't be able to see it again 6. Save the token securely - you'll need it for Vault storage (next step) ### 3. Store Credentials in Vault **CRITICAL**: All Renovate configuration must be stored in Vault at `secret/renovate` before deploying this module. ```bash # Authenticate to Vault export VAULT_ADDR="https://your-vault-server:8200" vault login -method=approle role_id=YOUR_ROLE_ID secret_id=YOUR_SECRET_ID # Store Renovate credentials in Vault vault kv put secret/renovate \ renovate_platform="gitea" \ renovate_endpoint="https://gitea.example.com/api/v1/" \ renovate_token="YOUR_GITEA_TOKEN_FROM_STEP_2" \ renovate_git_author="Renovate Bot " \ renovate_username="renovate-bot" # Verify the secrets are stored correctly vault kv get secret/renovate ``` **Required Keys in `secret/renovate`:** - `renovate_platform` - Must be "gitea" - `renovate_endpoint` - Your Gitea API endpoint (must end with `/api/v1/`) - `renovate_token` - The Personal Access Token from Step 2 - `renovate_git_author` - Git commit author for Renovate PRs - `renovate_username` - The Gitea username of the bot account **Note**: If you regenerate the Gitea token, you must update it in Vault: ```bash vault kv patch secret/renovate renovate_token="NEW_TOKEN_HERE" ``` ### 4. Configure Repository Access For each repository you want Renovate to manage: 1. Add `renovate-bot` as a collaborator with Write access 2. Or use autodiscovery to automatically find all accessible repositories ## How to Use ### 1. Basic Usage with Gitea ```hcl module "renovate" { source = "./terraform-docker-renovate" # Infrastructure domain = "bsdserver.nl" role_id = var.vault_role_id secret_id = var.vault_secret_id # Gitea Configuration renovate_platform = "gitea" renovate_endpoint = "https://gitea.example.com/api/v1/" renovate_token = var.renovate_token # Store securely in Vault or use env var renovate_git_author = "Renovate Bot " renovate_username = "renovate-bot" } ``` ### 2. Custom Configuration ```hcl module "renovate" { source = "./terraform-docker-renovate" # Infrastructure domain = "bsdserver.nl" role_id = var.vault_role_id secret_id = var.vault_secret_id # Container configuration container_name = "renovate" renovate_image = "renovate/renovate:latest" restart_policy = "unless-stopped" # Resource limits memory_limit = 2048 memory_swap_limit = -1 # Gitea platform configuration renovate_platform = "gitea" renovate_endpoint = "https://gitea.bsdserver.nl/api/v1/" renovate_token = var.renovate_token renovate_git_author = "Renovate Bot " renovate_username = "renovate-bot" renovate_autodiscover = true # Optional GitHub.com token for changelogs github_com_token = var.github_token # Logging log_level = "info" # Additional environment variables extra_env_vars = [ "RENOVATE_REQUIRE_CONFIG=optional" ] } ``` ### 3. Configure Backend (Optional) If using remote state storage (recommended), configure the backend: ```bash # Option 1: Using environment variables export AWS_ACCESS_KEY_ID="your-minio-access-key" export AWS_SECRET_ACCESS_KEY="your-minio-secret-key" terraform init \ -backend-config="endpoints={s3=\"https://minio.example.com:443\"}" \ -backend-config="bucket=terraform-state" \ -backend-config="key=docker/renovate/terraform.tfstate" \ -backend-config="region=main" \ -backend-config="skip_credentials_validation=true" \ -backend-config="skip_metadata_api_check=true" \ -backend-config="skip_requesting_account_id=true" \ -backend-config="skip_region_validation=true" \ -backend-config="use_path_style=true" ``` Or create a `backend.hcl` file: ```hcl # backend.hcl endpoints = { s3 = "https://minio.example.com:443" } bucket = "terraform-state" key = "docker/renovate/terraform.tfstate" region = "main" skip_credentials_validation = true skip_metadata_api_check = true skip_requesting_account_id = true skip_region_validation = true use_path_style = true ``` Then initialize: ```bash export AWS_ACCESS_KEY_ID="your-minio-access-key" export AWS_SECRET_ACCESS_KEY="your-minio-secret-key" terraform init -backend-config=backend.hcl ``` ### 4. Initialize Terraform ```bash # For local state (not recommended for production) terraform init # Or with remote backend (see step 3) terraform init -backend-config=backend.hcl ``` This will: - Download required providers (Docker, Vault, DNS) - Configure the backend for state storage (if specified) ### 5. Plan Deployment ```bash terraform plan ``` Review the planned changes to ensure everything is correct. ### 6. Apply Configuration ```bash terraform apply ``` Confirm the changes to deploy the Renovate bot. ### 7. Verify Deployment After deployment: 1. **Check Container Status**: ```bash docker ps | grep renovate ``` 2. **View Container Logs**: ```bash docker logs renovate -f ``` 3. **Verify Configuration**: ```bash docker exec renovate cat /usr/src/app/config.js ``` ## Repository Configuration ### Adding Renovate to a Repository To enable Renovate in a repository, create a `renovate.json` file in the repository root: ```json { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:recommended" ], "assignees": ["@yourusername"], "labels": ["renovate"], "dependencyDashboard": true, "packageRules": [ { "description": "Automerge minor and patch updates", "matchUpdateTypes": ["minor", "patch"], "automerge": true } ], "docker": { "enabled": true, "pinDigests": false }, "terraform": { "enabled": true } } ``` An example configuration is provided in `files/example-renovate.json`. ### Docker-Compose Repository Example For repositories with `docker-compose.yml` files: ```json { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended"], "docker-compose": { "enabled": true }, "packageRules": [ { "matchDatasources": ["docker"], "matchUpdateTypes": ["major"], "enabled": false } ] } ``` ### Terraform Repository Example For repositories with Terraform code: ```json { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended"], "terraform": { "enabled": true }, "packageRules": [ { "matchDatasources": ["terraform-provider", "terraform-module"], "automerge": false, "schedule": ["before 6am on Monday"] } ] } ``` ## Variables | Variable | Description | Type | Default | Required | |----------|-------------|------|---------|----------| | `container_name` | Name of the Renovate container | `string` | `"renovate"` | No | | `renovate_image` | Docker image for Renovate | `string` | `"renovate/renovate:latest"` | No | | `restart_policy` | Restart policy for the container | `string` | `"unless-stopped"` | No | | `memory_limit` | Memory limit for the container in MB | `number` | `2048` | No | | `memory_swap_limit` | Memory swap limit in MB (-1 for unlimited) | `number` | `-1` | No | | `domain` | Domain name for the application | `string` | `"bsdserver.lan"` | No | | `dns_name` | DNS name for the Renovate service | `string` | `null` (uses container_name) | No | | `create_cname_record` | Whether to create a DNS CNAME record | `bool` | `false` | No | | `renovate_platform` | Git platform to use (gitea, github, gitlab) | `string` | `"gitea"` | No | | `renovate_endpoint` | API endpoint for the git platform | `string` | - | Yes | | `renovate_token` | Personal access token for authentication | `string` | - | Yes | | `renovate_git_author` | Git author for Renovate commits | `string` | `"Renovate Bot "` | No | | `renovate_username` | Username of the Renovate bot account | `string` | `"renovate-bot"` | No | | `renovate_autodiscover` | Enable autodiscovery of repositories | `bool` | `true` | No | | `renovate_onboarding_config` | Onboarding configuration for Renovate | `string` | See variables.tf | No | | `github_com_token` | GitHub.com token for fetching changelogs | `string` | `""` | No | | `log_level` | Log level for Renovate | `string` | `"info"` | No | | `extra_env_vars` | Additional environment variables | `list(string)` | `[]` | No | | `upload_config_file` | Upload a config.js file to the container | `bool` | `true` | No | | `role_id` | Vault AppRole Role ID | `string` | - | Yes | | `secret_id` | Vault AppRole Secret ID | `string` | - | Yes | ## Outputs | Output | Description | |--------|-------------| | `container_id` | ID of the Renovate container | | `container_name` | Name of the Renovate container | | `config_volume` | Name of the config volume | | `cache_volume` | Name of the cache volume | | `renovate_platform` | Platform configured for Renovate | | `renovate_endpoint` | API endpoint configured for Renovate | ## Configuration Details ### Hardcoded Values The following values are hardcoded in `provider.tf` and may need customization: - **Docker Host**: `tcp://192.168.2.170:2376` (provider.tf:26) - **Vault Address**: `https://wbyc-srv-docker01.bsdserver.lan:8200` (provider.tf:33) **Note**: Backend configuration (MinIO/S3) is no longer hardcoded. Configure it via: - Environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` - Command-line flags during `terraform init` (see "Configure Backend" section) - Backend configuration file (`backend.hcl`) ### Security Considerations ✅ **Security Improvements**: 1. **No Privileged Mode**: Container runs without elevated privileges 2. **No Root User**: Runs as standard user 3. **No Docker Socket**: Docker socket is not mounted 4. **Resource Limits**: Memory limits prevent resource exhaustion 5. **Token Security**: Renovate token is marked as sensitive in Terraform 6. **Vault Integration**: DNS credentials stored securely in Vault ⚠️ **Security Notes**: 1. **Backend Credentials**: Use environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`) instead of hardcoding 2. **Token Management**: Store `renovate_token` in Vault or use environment variables 3. **Repository Access**: Ensure bot user only has access to intended repositories 4. **Log Retention**: Logs are sent to Docker daemon - ensure proper retention policies 5. **Network Security**: Renovate connects to external APIs - ensure proper firewall rules ## Providers This module uses the following Terraform providers: - **docker** (kreuzwerker/docker v3.0.2): For Docker resource management - **vault** (hashicorp/vault v3.25.0): For secrets management - **dns**: For DNS record management with TSIG authentication ## Managing Configuration ### Option 1: Use Template File (Recommended) The module includes a `config.js.tpl` template that automatically configures Renovate based on your variables. Set `upload_config_file = true` to use this method. ### Option 2: Manual Configuration Mount a custom config.js file to the config volume: ```bash # Create config.js cat > config.js << 'EOF' module.exports = { platform: 'gitea', endpoint: 'https://gitea.example.com/api/v1/', gitAuthor: 'Renovate Bot ', username: 'renovate-bot', autodiscover: true, onboardingConfig: { $schema: 'https://docs.renovatebot.com/renovate-schema.json', extends: ['config:recommended'], }, }; EOF # Copy to volume docker run --rm -v renovate-config:/config -v $(pwd):/source alpine \ cp /source/config.js /config/ # Restart container docker restart renovate ``` ### Option 3: Environment Variables Only Set `upload_config_file = false` and rely solely on environment variables configured in the module. ## Scheduling Renovate Runs Renovate can be scheduled using various methods: ### Option 1: Cron Job ```bash # Add to crontab to run daily at 2 AM 0 2 * * * docker restart renovate ``` ### Option 2: Gitea Actions/Workflows Create `.gitea/workflows/renovate.yaml` in a dedicated repository: ```yaml name: Renovate on: schedule: - cron: '0 2 * * *' workflow_dispatch: jobs: renovate: runs-on: ubuntu-latest steps: - name: Trigger Renovate run: | docker restart renovate || true ``` ### Option 3: System Timer Create a systemd timer for automated scheduling. ## Troubleshooting ### Container Won't Start ```bash docker logs renovate ``` Check for: - Invalid Gitea endpoint or token - Network connectivity issues - Missing configuration - Resource limit issues ### Renovate Not Creating PRs Verify: 1. Bot user has write access to repositories 2. Gitea token has correct permissions 3. Repositories have valid `renovate.json` configuration 4. Check logs for API errors: `docker logs renovate` ### Authentication Failures - Verify token scopes in Gitea settings - Ensure token hasn't expired - Check endpoint URL is correct (should end with `/api/v1/`) - Verify bot user account is active ### DNS Record Not Created - Verify Vault DNS credentials are correct - Check DNS server allows dynamic updates - Ensure TSIG key has proper permissions ### Rate Limiting Issues If you see rate limit errors: 1. Add `github_com_token` for GitHub.com changelog access 2. Configure `prConcurrentLimit` in repository config 3. Adjust scheduling to reduce API calls ## Maintenance ### Updating Renovate ```bash # Pull latest image docker pull renovate/renovate:latest # Recreate container terraform apply -replace=docker_container.renovate ``` ### Viewing Logs ```bash # Container logs docker logs renovate -f # Filter for specific repository docker logs renovate 2>&1 | grep "repository-name" ``` ### Backup The Renovate data is stored in Docker volumes. To backup: ```bash # Backup config docker run --rm -v renovate-config:/data -v $(pwd):/backup alpine \ tar czf /backup/renovate-config-backup.tar.gz /data # Backup cache docker run --rm -v renovate-cache:/data -v $(pwd):/backup alpine \ tar czf /backup/renovate-cache-backup.tar.gz /data ``` ### Restore ```bash # Restore config docker run --rm -v renovate-config:/data -v $(pwd):/backup alpine \ tar xzf /backup/renovate-config-backup.tar.gz -C / # Restore cache docker run --rm -v renovate-cache:/data -v $(pwd):/backup alpine \ tar xzf /backup/renovate-cache-backup.tar.gz -C / ``` ## Advanced Configuration ### Custom Renovate Image To use a specific version: ```hcl module "renovate" { source = "./terraform-docker-renovate" renovate_image = "renovate/renovate:37.100.0" # ... other variables } ``` ### Multiple Platform Support While this module is optimized for Gitea, you can configure it for other platforms: ```hcl module "renovate_github" { source = "./terraform-docker-renovate" renovate_platform = "github" renovate_endpoint = "https://api.github.com/" renovate_token = var.github_token # ... other variables } ``` ### SonarQube Integration Add SonarQube scanning to Renovate PRs by configuring your repository's `renovate.json`: ```json { "extends": ["config:recommended"], "postUpgradeTasks": { "commands": [ "sonar-scanner -Dsonar.projectKey=myproject" ] } } ``` ## Integration with CI/CD ### Gitea Actions Integration Renovate PRs can automatically trigger Gitea Actions workflows. Example `.gitea/workflows/test.yaml`: ```yaml name: Test Dependencies on: pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run Tests run: | docker-compose up -d docker-compose exec -T app npm test ``` ### Pipeline Configuration For automated testing and deployment: 1. Configure branch protection rules in Gitea 2. Require status checks to pass before merging 3. Enable auto-merge in `renovate.json` for passing PRs ## Best Practices 1. **Start with Manual Approval**: Don't enable automerge until you trust the process 2. **Use Dependency Dashboard**: Enable `"dependencyDashboard": true` for visibility 3. **Schedule Updates**: Use `schedule` to avoid overwhelming your team 4. **Group Updates**: Group related dependencies to reduce PR noise 5. **Test Updates**: Always have CI/CD tests run on Renovate PRs 6. **Monitor Logs**: Regularly check Renovate logs for errors 7. **Pin Versions**: Use semantic versioning tags instead of `latest` ## Example Workflow 1. **Initial Setup**: - Create Renovate bot user in Gitea - Generate access token with required scopes - Deploy this Terraform module - Add bot as collaborator to repositories 2. **Repository Configuration**: - Add `renovate.json` to repository root - Configure package rules and schedules - Enable dependency dashboard 3. **First Run**: - Renovate creates onboarding PR - Review and merge onboarding PR - Renovate starts scanning dependencies 4. **Ongoing**: - Renovate creates PRs for updates - CI/CD tests run automatically - Review and merge PRs - Monitor dependency dashboard ## Resources - [Renovate Documentation](https://docs.renovatebot.com/) - [Gitea Platform Configuration](https://docs.renovatebot.com/modules/platform/gitea/) - [Self-Hosting Renovate](https://docs.renovatebot.com/examples/self-hosting/) - [Configuration Options](https://docs.renovatebot.com/configuration-options/) - [Renovate Docker Hub](https://hub.docker.com/r/renovate/renovate) ## License This module is part of the webuildyourcloud automation infrastructure. ## Contributing When contributing, ensure: - Terraform code follows best practices - Variables are properly documented - Security implications are considered - State backend configuration is tested - Configuration examples are validated