Reusable CI/CD pipeline template with integrated security scanning. Designed to work on AWS, on-premise, or local environments. Licensed under AGPL-3.0.
- App: Python/Flask sample service in
app/(replace with your own) - Local/on-prem: Docker Compose + Nginx (TLS, rate limiting, security headers)
- AWS (optional): Terraform modules for VPC, ALB, ECS Fargate in
terraform/ - Security pipeline: GitHub Actions with 6 gates (Semgrep, Trivy, Hadolint, Gitleaks, Checkov, Conftest)
- Policies as code: OPA/Rego in
policies/
- Trunk-based:
mainis the single source of truth - Feature branches: short-lived branches off
main, merged via PR - PRs target
maindirectly - Commits: human style, no AI attribution, no co-authored-by tags
- Author: Adur 26388026+adurrr@users.noreply.github.com
# Local test (Python only)
cd app && python main.py # runs on :8080
# Local test (Docker)
./scripts/generate-certs.sh # one-time TLS cert setup
docker-compose up -d --build # or: docker compose up -d --build
# Security scans
./scripts/scan.sh # runs all installed scanners
# Terraform
cd terraform/environments/dev
terraform init && terraform plan- SAST: Semgrep (config:
.semgrep.yml) - IaC: Checkov (config:
.checkov.yml— 4 documented env-dependent skips) - Secrets: Gitleaks (pre-commit hook via
scripts/setup-hooks.sh) - Container: Trivy + Hadolint
- Policy: Conftest with Rego policies in
policies/
GET /healthz— liveness checkGET /readyz— readiness checkGET /api/v1/info— service metadata
scripts/scan.shgracefully skips tools that aren't installedscripts/deploy.shsupportslocal,staging, andproductiontargets- Docker Compose works with both v1 (
docker-compose) and v2 (docker compose) - Terraform
kms_key_arnandwaf_acl_arnare optional — pass them in tfvars for production hardening
- Do not use
aquasecurity/trivy-action— it fails on GitHub API rate limits in CI - Use the official install script instead:
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \ | sudo sh -s -- -b /usr/local/bin - Always set
continue-on-error: trueon Trivy scan steps so the pipeline doesn't hard-fail before SARIF upload - Guard SARIF uploads with
if: always() && hashFiles('trivy-sca.sarif') != ''
- Requires full git history — checkout with
fetch-depth: 0in thesecurity-scanjob - Without this, gitleaks fails with "ambiguous argument / unknown revision"
- Must use OPA v1 syntax:
import rego.v1,deny contains msg if { ... },warn contains msg if { ... } - Use
some ifor iterator variables ininput[i]expressions - Do NOT use
some containerorsome rulebefore a:=assignment — that's a duplicate declaration error - Helper rules (e.g.
has_user) use bareif { ... }body, nocontains
- Deploy jobs must guard on
vars.AWS_REGION != ''so they are skipped when AWS is not configured - Do not add
environment: staging/environment: productionto jobs — GitHub creates failed deployment records even when the job is skipped
- App runs with
read_only: true; gunicorn needs/tmpfor worker temp files - Required:
tmpfs: - /tmpunder the app service, or gunicorn will crash on startup