Patrick de Ruiter 1cca7c9267
All checks were successful
Code Quality & Security Scan / TFLint (push) Successful in 23s
Code Quality & Security Scan / Terraform Destroy (push) Has been skipped
Code Quality & Security Scan / Tfsec Security Scan (push) Successful in 31s
Code Quality & Security Scan / Checkov Security Scan (push) Successful in 33s
Code Quality & Security Scan / Terraform Validate (push) Successful in 35s
Code Quality & Security Scan / SonarQube Scan (push) Successful in 45s
Code Quality & Security Scan / Terraform Plan (push) Successful in 1m16s
Code Quality & Security Scan / Terraform Apply (push) Successful in 1m35s
fix: Remove unused TF_VAR_renovate_* variables from pipeline
The renovate_endpoint and renovate_token values are retrieved from
Vault (secret/renovate) via data sources in the Terraform code, not
passed as Terraform variables.

Changes:
- Commented out TF_VAR_renovate_endpoint in all pipeline stages
- Commented out TF_VAR_renovate_token in all pipeline stages
- These values are properly sourced from Vault data sources

This fixes the container restart issue where Renovate couldn't find
the Gitea personal access token because the environment variable
wasn't being set correctly from Vault data.

Affected stages:
- terraform-validate (init and validate steps)
- terraform-plan (init and plan steps)
- terraform-apply (init and apply steps)
- terraform-destroy (init, plan, and execute steps)
2025-11-19 13:32:59 +01:00
2025-11-19 00:23:12 +01:00
2025-11-19 00:41:13 +01:00

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
    • 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. Save the token securely - you'll need it for the renovate_token variable

3. 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

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-bot@example.com>"
  renovate_username  = "renovate-bot"
}

2. Custom Configuration

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-bot@bsdserver.nl>"
  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:

# 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:

# 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:

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

# 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

terraform plan

Review the planned changes to ensure everything is correct.

6. Apply Configuration

terraform apply

Confirm the changes to deploy the Renovate bot.

7. Verify Deployment

After deployment:

  1. Check Container Status:

    docker ps | grep renovate
    
  2. View Container Logs:

    docker logs renovate -f
    
  3. Verify Configuration:

    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:

{
  "$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:

{
  "$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:

{
  "$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 <renovate-bot@example.com>" 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

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:

# Create config.js
cat > config.js << 'EOF'
module.exports = {
  platform: 'gitea',
  endpoint: 'https://gitea.example.com/api/v1/',
  gitAuthor: 'Renovate Bot <renovate-bot@example.com>',
  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

# 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:

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

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

# Pull latest image
docker pull renovate/renovate:latest

# Recreate container
terraform apply -replace=docker_container.renovate

Viewing Logs

# 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:

# 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

# 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:

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:

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:

{
  "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:

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

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
Description
Terraform module for deploying Renovate bot with Gitea integration for automated dependency management
Readme 181 KiB
Languages
HCL 81.8%
Smarty 13.1%
Shell 5.1%