ci: add Renovate (autodiscover) and Trivy CVE scan workflows
- renovate.json: gitea platform, weekly schedule on Monday, pins ranges, manages docker-compose images + dockerfile + github-actions. Critical-infra packages get extra labels for review. - .forgejo/workflows/renovate.yml: runs Mondays 04:00 UTC, autodiscover Richard/* so the same workflow covers both this repo and the Hugo companion. Requires RENOVATE_TOKEN secret (instructions in README). - .forgejo/workflows/trivy.yml: daily 05:00 UTC + on-push. Scans both IaC configs in infrastructure/ and every image referenced in docker-compose.yml for HIGH/CRITICAL CVEs (fixable only). - Pin Traefik (3.6.7) and traefik-crowdsec-bouncer (0.5.0) so Renovate has a baseline to bump.
This commit is contained in:
parent
a87db639eb
commit
456e3e5614
5 changed files with 163 additions and 2 deletions
27
.forgejo/workflows/renovate.yml
Normal file
27
.forgejo/workflows/renovate.yml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
name: renovate
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 4 * * 1" # Monday 04:00 UTC (~01:00 America/Sao_Paulo)
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
renovate:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/renovatebot/renovate:39
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: run renovate
|
||||
env:
|
||||
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
|
||||
RENOVATE_PLATFORM: gitea
|
||||
RENOVATE_ENDPOINT: https://git.richardnixon.dev/api/v1/
|
||||
RENOVATE_AUTODISCOVER: "true"
|
||||
RENOVATE_AUTODISCOVER_FILTER: "Richard/*"
|
||||
RENOVATE_GIT_AUTHOR: "Renovate Bot <renovate@richardnixon.dev>"
|
||||
RENOVATE_REPOSITORY_CACHE: "enabled"
|
||||
LOG_LEVEL: info
|
||||
run: renovate
|
||||
60
.forgejo/workflows/trivy.yml
Normal file
60
.forgejo/workflows/trivy.yml
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
name: trivy
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 5 * * *" # daily 05:00 UTC
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "infrastructure/docker-compose.yml"
|
||||
- ".forgejo/workflows/trivy.yml"
|
||||
|
||||
jobs:
|
||||
config-scan:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: aquasec/trivy:0.59.1
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: scan IaC configs (HIGH/CRITICAL misconfigs only)
|
||||
run: |
|
||||
trivy config \
|
||||
--severity HIGH,CRITICAL \
|
||||
--exit-code 0 \
|
||||
--format table \
|
||||
infrastructure/
|
||||
|
||||
image-scan:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: aquasec/trivy:0.59.1
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: extract images and scan each
|
||||
run: |
|
||||
set -e
|
||||
images=$(grep -oE 'image:[[:space:]]*[^[:space:]]+' infrastructure/docker-compose.yml \
|
||||
| awk '{print $2}' | sort -u)
|
||||
echo "scanning $(echo "$images" | wc -l) images"
|
||||
failed=0
|
||||
for img in $images; do
|
||||
echo "::group::$img"
|
||||
if ! trivy image \
|
||||
--severity HIGH,CRITICAL \
|
||||
--exit-code 1 \
|
||||
--ignore-unfixed \
|
||||
--no-progress \
|
||||
--timeout 5m \
|
||||
"$img"; then
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
echo "::endgroup::"
|
||||
done
|
||||
echo "$failed image(s) have fixable HIGH/CRITICAL CVEs"
|
||||
# We don't fail the job on findings (info only); flip to: [ "$failed" -eq 0 ]
|
||||
exit 0
|
||||
19
README.md
19
README.md
|
|
@ -177,6 +177,25 @@ URL: https://status.richardnixon.dev
|
|||
| valheim | valheim-metrics:3903 | Game server metrics |
|
||||
| forgejo | forgejo:3000 | Git forge metrics (repos, users, HTTP) |
|
||||
|
||||
## Dependency updates and CVE scanning
|
||||
|
||||
Two automated workflows run via Forgejo Actions:
|
||||
|
||||
- **Renovate** (`.forgejo/workflows/renovate.yml`) — opens PRs every Monday with version bumps for Docker images, Forgejo Actions, Hugo submodules, and Hugo binary. Config in `renovate.json` at the root of each repo. Uses `RENOVATE_AUTODISCOVER` to handle both `Richard/richardnixon.dev` and `Richard/richardnixon.dev-hugo` from a single workflow.
|
||||
- **Trivy** (`.forgejo/workflows/trivy.yml`) — scans the compose images and IaC configs daily for HIGH/CRITICAL CVEs. Same scan also runs on every push that touches the compose file.
|
||||
|
||||
### Required secret: `RENOVATE_TOKEN`
|
||||
|
||||
Both repos need a Forgejo PAT with `write:repository` scope:
|
||||
|
||||
1. `https://git.richardnixon.dev/user/settings/applications` → Generate New Token (name: `renovate`, scope: `write:repository`).
|
||||
2. Add it as a **secret** named `RENOVATE_TOKEN` in each repo:
|
||||
- `https://git.richardnixon.dev/Richard/richardnixon.dev/settings/actions/secrets`
|
||||
- `https://git.richardnixon.dev/Richard/richardnixon.dev-hugo/settings/actions/secrets`
|
||||
3. Trigger a first run manually via the workflow dispatch button to confirm Renovate authenticates.
|
||||
|
||||
A "Dependency Dashboard" issue will be opened in each repo summarizing pending updates.
|
||||
|
||||
## Forgejo Actions (Hugo blog CI)
|
||||
|
||||
The `forgejo-runner` service registers itself on first boot using `FORGEJO_RUNNER_REGISTRATION_TOKEN` and joins the `forgejo-internal` network so job containers can resolve the internal `forgejo` hostname for `actions/checkout`.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ services:
|
|||
# NGINX PROXY + SSL (Traefik)
|
||||
# ===========================================
|
||||
traefik:
|
||||
image: traefik:latest
|
||||
image: traefik:v3.6.7
|
||||
container_name: traefik
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
|
|
@ -274,7 +274,7 @@ services:
|
|||
- monitoring
|
||||
|
||||
crowdsec-bouncer:
|
||||
image: fbonalair/traefik-crowdsec-bouncer:latest
|
||||
image: fbonalair/traefik-crowdsec-bouncer:0.5.0
|
||||
container_name: crowdsec-bouncer
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
|
|
|
|||
55
renovate.json
Normal file
55
renovate.json
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:recommended",
|
||||
":semanticCommits",
|
||||
":dependencyDashboard"
|
||||
],
|
||||
"platform": "gitea",
|
||||
"endpoint": "https://git.richardnixon.dev/api/v1/",
|
||||
"gitAuthor": "Renovate Bot <renovate@richardnixon.dev>",
|
||||
"labels": ["renovate"],
|
||||
"schedule": ["before 5am on Monday"],
|
||||
"timezone": "America/Sao_Paulo",
|
||||
"prHourlyLimit": 4,
|
||||
"prConcurrentLimit": 10,
|
||||
"rangeStrategy": "pin",
|
||||
"lockFileMaintenance": {
|
||||
"enabled": true,
|
||||
"schedule": ["before 5am on the first day of the month"]
|
||||
},
|
||||
"docker-compose": {
|
||||
"enabled": true,
|
||||
"fileMatch": ["docker-compose\\.ya?ml$", "infrastructure/docker-compose\\.ya?ml$"]
|
||||
},
|
||||
"dockerfile": { "enabled": true },
|
||||
"github-actions": { "enabled": true },
|
||||
"packageRules": [
|
||||
{
|
||||
"matchDatasources": ["docker"],
|
||||
"matchUpdateTypes": ["digest"],
|
||||
"automerge": false,
|
||||
"addLabels": ["digest-pin"]
|
||||
},
|
||||
{
|
||||
"matchDatasources": ["docker"],
|
||||
"matchPackageNames": [
|
||||
"traefik",
|
||||
"codeberg.org/forgejo/forgejo",
|
||||
"code.forgejo.org/forgejo/runner",
|
||||
"ghcr.io/goauthentik/server"
|
||||
],
|
||||
"addLabels": ["critical-infra"],
|
||||
"reviewers": ["Richard"]
|
||||
},
|
||||
{
|
||||
"matchUpdateTypes": ["minor", "patch"],
|
||||
"matchDepTypes": ["devDependencies"],
|
||||
"automerge": true
|
||||
}
|
||||
],
|
||||
"vulnerabilityAlerts": {
|
||||
"labels": ["security"],
|
||||
"automerge": false
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue