Skip to content

XOps Blog

One GitHub Action to Run Four Security Scanners and an AI Risk Analyst

TL;DR: I packaged Gitleaks, Trivy, Semgrep, and Checkov into a single reusable GitHub Action with AI-powered risk analysis and a self-contained HTML dashboard.

The Problem

Security scanning in most CI pipelines is bolted on as an afterthought -- a separate workflow per tool, each with its own output format, its own failure threshold, and its own results that nobody reads. Developers get alert fatigue, and real vulnerabilities hide in the noise. I wanted a single step that runs everything, normalizes the results, and tells me what actually matters.

What I Built

devsecops-pipeline is a comprehensive security scanning platform that orchestrates four industry-standard scanners in parallel, feeds the combined results into AWS Bedrock for AI risk analysis, and renders everything into a self-contained HTML dashboard. It ships as a reusable GitHub Action, a Docker image, and a standalone CLI.

  • 4 scanners in one step -- Gitleaks (secrets), Trivy (CVEs in dependencies and containers), Semgrep (SAST/code patterns), and Checkov (Terraform/CloudFormation misconfigurations)
  • AI risk analysis -- AWS Bedrock analyzes combined findings, prioritizes by actual exploitability, and generates remediation guidance
  • Self-contained HTML dashboard -- a single file with no external dependencies; drop it into any PR comment or artifact
  • Configurable fail thresholds -- fail the build on critical findings only, or set custom severity gates
  • Deployable to AWS -- Terraform module provisions Lambda + S3 + SNS for scheduled organization-wide scans

Tech Stack

Python, GitHub Actions, Docker, Gitleaks, Trivy, Semgrep, Checkov, AWS Bedrock, Terraform, HTML/CSS

Usage

# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: basel5001/devsecops-pipeline@v1
        with:
          path: '.'
          fail-on-critical: 'true'
          ai-analysis: 'true'

Or scan locally with Docker:

SCAN_PATH=/path/to/repo docker compose up --build
# Results appear in ./reports/

Results

Four tools, one workflow step, one dashboard. The AI analysis cut triage time by roughly 60% -- instead of scrolling through 200 raw findings, developers get a prioritized list with context. Critical secrets and high-severity CVEs block the merge; informational findings surface without breaking flow.


GitHub: https://github.com/basel5001/devsecops-pipeline

Automating AWS Disaster Recovery with AI-Generated Runbooks

TL;DR: I built a Terraform-managed AWS disaster recovery system with cross-region replication, automated failover, scheduled DR drills that measure RTO/RPO, and AI-generated runbooks via Bedrock.

The Problem

Every team says they have a DR plan. Few have tested it. Fewer still can tell you their actual RTO and RPO numbers. Manual failover runbooks go stale the moment the infrastructure changes. I needed DR that tests itself, measures itself, and keeps its own documentation current.

What I Built

disaster-recovery-aws is a complete DR automation platform spanning two AWS regions. The primary region (us-east-1) replicates data to a DR region (us-west-2) across S3, RDS, and DynamoDB. Lambda functions continuously monitor health, execute failover when thresholds breach, and run scheduled DR drills that produce hard RTO/RPO measurements.

  • Cross-region replication -- S3 CRR, RDS read replicas with automatic promotion, DynamoDB global tables
  • Automated failover -- Lambda detects health check failures and executes DNS switchover, RDS promotion, and ECS scaling without human intervention
  • Scheduled DR drills -- EventBridge triggers simulated failures; each drill measures actual recovery time and data loss, then reports via SNS
  • AI runbook generation -- AWS Bedrock generates step-by-step runbooks tailored to the current infrastructure state, not a static wiki page
  • Full observability -- CloudWatch alarms, a unified dashboard, and Synthetics canaries for external endpoint monitoring

Tech Stack

Terraform, Python, AWS (Lambda, RDS, S3, DynamoDB, Route53, ECS, ALB, CloudWatch, EventBridge, SNS, Bedrock)

Usage

# Deploy the full DR stack
cd terraform
cp backend.tf.example backend.tf
terraform init && terraform plan

# Run a manual DR drill
aws lambda invoke --function-name dr-drill-runner \
  --payload '{"scenario": "rds-failover"}' response.json

# Generate a runbook for a specific scenario
aws lambda invoke --function-name dr-runbook-generator \
  --payload '{"scenario": "full-region-failure"}' runbook.json

Results

DR drills now run weekly on a schedule. The first automated drill revealed an RTO of 12 minutes -- twice what we assumed. After tuning, we consistently hit under 5 minutes. AI-generated runbooks stay current because they query live infrastructure state each time. The biggest win: confidence. When an actual us-east-1 degradation occurred, the system detected it and began failover within 90 seconds.


GitHub: https://github.com/basel5001/disaster-recovery-aws

How I Centralized CI/CD Governance Across 22+ Repos with a Single Repository

TL;DR: I built a single "infrastructure" repo that owns every reusable GitHub Actions workflow, composite action, and repository setting across my entire GitHub organization.

The Problem

Managing CI/CD pipelines across dozens of repositories is painful. Every repo had its own copy of linting configs, security scans, and Docker build steps. A single change -- like upgrading a scanner version -- meant opening 20+ PRs. Drift was inevitable, and nobody could answer "which repos actually run secret scanning?"

What I Built

githubinfra is a mono-repo that treats GitHub itself as infrastructure. Every workflow is a reusable workflow that any repo can reference with a one-liner. Repository settings (branch protection, merge strategies, topics, descriptions) are declared in a single repos.yml and synced via a TypeScript management tool.

  • 11 reusable workflows covering CI, linting, secret scanning, IOC/supply-chain checks, Docker builds, Terraform validation, SBOM generation, stale management, release notifications, branch copying, and label enforcement
  • 3 composite actions for environment setup (Python/Node/Go with caching), Docker Buildx builds, and Discord/Slack notifications
  • Declarative repo management -- edit repos.yml, run npm run sync, and every repo's settings converge to the desired state
  • Diff & dry-run modes so I can preview exactly what will change before applying
  • Automated workflow assignment -- new repos inherit the right pipelines from day one

Tech Stack

GitHub Actions, TypeScript, Terraform, GitHub REST API, YAML

Usage

Any repo references a shared workflow with two lines:

jobs:
  ci:
    uses: basel5001/githubinfra/.github/workflows/ci.yml@main
    with:
      language: python

To sync repository settings:

cd management && npm install
GITHUB_TOKEN=ghp_xxx npm run diff    # preview
GITHUB_TOKEN=ghp_xxx npm run sync    # apply

Results

What used to require touching 20+ repos now takes a single PR. Workflow updates roll out instantly to every consumer. The repos.yml file serves as a living inventory of the entire organization -- I can answer "what scanning does repo X run?" by reading one file. Onboarding a new repo takes under a minute: add it to repos.yml, push, done.


GitHub: https://github.com/basel5001/githubinfra

Building a Full GitOps Platform with Progressive Delivery

TL;DR: I built a production-grade GitOps platform on Kubernetes using ArgoCD, Crossplane, Kyverno, and Argo Rollouts -- enabling multi-environment promotion with policy enforcement and canary/blue-green deployments.

The Problem

Kubernetes gives you primitives, not a platform. After the cluster is running, you still need to answer: How do deployments promote from dev to prod? Who enforces that every pod has resource limits? How do you provision cloud resources without leaving the Git workflow? I needed a complete platform, not a collection of tools.

What I Built

gitops-cluster is a fully integrated GitOps platform where Git is the single source of truth for both application manifests and infrastructure. ArgoCD syncs the desired state, Crossplane provisions cloud resources as Kubernetes CRDs, Kyverno enforces policies at admission time, and Argo Rollouts handles progressive delivery with canary and blue-green strategies.

  • Multi-environment promotion -- dev uses canary rollouts (automatic), staging uses blue-green (auto-promote), prod uses blue-green (manual gate)
  • Infrastructure as CRDs -- Crossplane compositions provision S3 buckets, RDS instances, and IAM roles via kubectl apply
  • Policy enforcement -- Kyverno blocks deployments without resource limits, requires labels, enforces image pull policies, and restricts privilege escalation
  • App-of-Apps pattern -- a single ArgoCD Application bootstraps the entire platform; adding a new service is a YAML file in the right directory
  • Local development -- kind create cluster && make bootstrap gives you the full platform locally

Tech Stack

Kubernetes, ArgoCD, Crossplane, Kyverno, Argo Rollouts, Terraform (EKS bootstrap), Helm, Kustomize

Usage

# Local: bootstrap a kind cluster with the full platform
kind create cluster --name gitops-cluster
make bootstrap

# AWS: provision EKS, then bootstrap
cd terraform && terraform apply
make bootstrap-eks

# Deploy an app: just add a manifest and push
cat > apps/dev/my-service.yml <<EOF
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-service
spec:
  strategy:
    canary:
      steps:
        - setWeight: 20
        - pause: {duration: 30s}
        - setWeight: 50
        - pause: {duration: 30s}
EOF
git add . && git commit -m "deploy my-service" && git push

Results

Deployments flow from dev to prod through a Git-driven pipeline with automatic canary analysis. Kyverno has blocked over 40 non-compliant deployments in staging before they reached production. Crossplane eliminated the context switch between "I need a Kubernetes deployment" and "I need an RDS database" -- both are just YAML in the same repo.


GitHub: https://github.com/basel5001/gitops-cluster

5 Free Ways to Expose Your Local Server to the Internet

TL;DR: I documented and automated five free methods to tunnel local services to the public internet -- Cloudflare Tunnel, DuckDNS + Let's Encrypt, WireGuard, FRP, Rathole, and SSH -- so you never pay for ngrok again.

The Problem

You are building a webhook integration and Stripe needs to reach your local development server. Or you are self-hosting a home lab service and want to access it remotely. Or you are demoing an app to a client and need a public URL in 30 seconds. The go-to solution is ngrok, but the free tier is limited and the paid plans add up. There are at least five completely free alternatives, but each has different tradeoffs and setup complexity. I wanted a single repo that documents and automates all of them.

What I Built

local-tunnel-server is a reference repository with configuration files, scripts, and step-by-step guides for five different tunneling methods. Each method includes a working setup, a one-command deploy script, and honest documentation of its strengths and limitations.

  • Cloudflare Tunnel -- the easiest option; install cloudflared, run one command, get a public HTTPS URL backed by Cloudflare's network. Zero port forwarding, free custom domains with Cloudflare DNS
  • DuckDNS + Let's Encrypt -- free dynamic DNS with automated TLS certificates. Best for persistent home lab services that need a stable hostname
  • WireGuard VPN + Reverse Proxy -- tunnel traffic through a cheap VPS running WireGuard. Gives you a static IP and full control over routing
  • FRP (Fast Reverse Proxy) -- open-source reverse proxy with a lightweight server/client architecture. Supports TCP, UDP, HTTP, and HTTPS tunnels with dashboard monitoring
  • Rathole -- a Rust-based alternative to FRP with lower resource usage. Ideal for constrained environments like Raspberry Pi
  • SSH Reverse Tunnel -- the classic approach; requires only an SSH server. No additional software, works everywhere, but lacks automatic reconnection without tooling

Tech Stack

Cloudflare Tunnel, WireGuard, FRP, Rathole, DuckDNS, Let's Encrypt, SSH, Nginx, Docker, Bash

Usage

# Cloudflare Tunnel (fastest setup)
cloudflared tunnel --url http://localhost:3000

# FRP (self-hosted)
docker compose -f frp/docker-compose.yml up -d

# WireGuard + reverse proxy
./scripts/setup-wireguard.sh
./scripts/setup-nginx-proxy.sh

Results

Cloudflare Tunnel is the winner for quick development tunnels -- zero config, free HTTPS, and sub-100ms latency overhead. For permanent home lab exposure, WireGuard + a $3.50/month VPS provides the most flexibility and performance. FRP hits the sweet spot for teams that want a self-hosted ngrok alternative with a management dashboard. This repo has become my go-to reference every time I need to expose a local service.


GitHub: https://github.com/basel5001/local-tunnel-server

Bootstrapping an AWS Organization with Terraform

TL;DR: I built a Terraform-managed AWS landing zone that provisions an entire Organization -- OUs, accounts, SCPs, SSO, GuardDuty, Security Hub, and an account vending machine -- from a single terraform apply.

The Problem

Starting a new AWS Organization the right way involves dozens of manual steps: create OUs, attach SCPs, enable security services in every account, set up SSO, configure networking, establish CloudTrail. Do it by hand and you'll forget something. Do it with ClickOps and there's no audit trail. Every account you add later needs the same baseline applied, and drift is silent.

What I Built

multi-cloud-landing-zone is a Terraform codebase that bootstraps an AWS Organization with enterprise-grade security guardrails. It creates the OU hierarchy, attaches service control policies, enables security services across all accounts, configures IAM Identity Center (SSO), provisions shared networking, and includes an account vending machine that creates new accounts with a full baseline.

  • Service Control Policies -- region restriction (us-east-1 + eu-west-1), root account denial in member accounts, mandatory encryption for S3/EBS/RDS
  • Security services everywhere -- GuardDuty, Security Hub (CIS benchmarks), AWS Config, IAM Access Analyzer, and Macie enabled across all accounts with centralized findings
  • IAM Identity Center (SSO) -- four permission sets (Admin, ReadOnly, Developer, SecurityAudit) federated across all accounts
  • Account vending machine -- add an account definition to terraform.tfvars and the pipeline creates it with baseline IAM roles, CloudTrail, VPC, and Config rules
  • Shared networking -- Transit Gateway, centralized VPC flow logs, and private Route53 hosted zones

Tech Stack

Terraform, AWS Organizations, AWS IAM Identity Center, GuardDuty, Security Hub, AWS Config, SCPs, Transit Gateway, Python (policy tests)

Usage

# terraform.tfvars -- add a new account
vended_accounts = {
  team-alpha-dev = {
    email = "aws+alpha-dev@company.com"
    ou    = "Workloads"
    tags  = { Team = "alpha", Environment = "dev" }
  }
}
# Bootstrap the entire organization
cp .env.example .env && source .env
make init && make plan && make apply

# Validate SCPs
make test-policies

Results

A new AWS account goes from zero to fully baselined in under 15 minutes -- CloudTrail enabled, GuardDuty active, VPC provisioned, SSO configured. SCPs enforce encryption and region restrictions at the organizational level, so individual teams can't bypass them. The entire org structure is version-controlled: every change goes through a PR, gets reviewed, and is applied via CI.


GitHub: https://github.com/basel5001/multi-cloud-landing-zone

Autopilot Social Media: How n8n and AI Publish Content While I Sleep

TL;DR: I built an n8n automation that generates social media posts with GPT-4o, schedules them, and publishes across Facebook, Twitter, LinkedIn, and Instagram -- completely hands-free.

The Problem

Maintaining a consistent social media presence across four platforms is a full-time job. Each platform has different optimal posting times, character limits, and content styles. Hiring a social media manager is expensive. Using scheduling tools like Buffer or Hootsuite still requires you to write every post manually. I wanted something that generates the content, adapts it per platform, and publishes on schedule -- without me touching it after initial setup.

What I Built

n8n-social-automation is a self-hosted n8n workflow that uses GPT-4o to generate platform-specific social media content from a topic list, then publishes it on a schedule via each platform's API. The entire pipeline -- from content generation to publishing -- runs in Docker with zero manual intervention.

  • AI content generation -- GPT-4o writes posts tailored to each platform's style: professional for LinkedIn, punchy for Twitter, conversational for Facebook, visual-caption style for Instagram
  • Topic queue -- maintain a simple list of topics or RSS feeds; the workflow picks the next topic and generates fresh content
  • Multi-platform publishing -- posts to Facebook Pages, Twitter/X, LinkedIn company pages, and Instagram via their respective APIs
  • Scheduling -- configurable posting schedule per platform with timezone awareness
  • Image generation -- optionally generates accompanying images using DALL-E for visual platforms
  • Content review mode -- optional approval step that sends drafts to Slack before publishing
  • Analytics webhook -- receives engagement data back into n8n for tracking performance

Tech Stack

n8n, OpenAI GPT-4o, Docker, Facebook Graph API, Twitter API v2, LinkedIn API, Instagram API, Node.js

Usage

# Start n8n with Docker
git clone https://github.com/basel5001/n8n-social-automation.git
cd n8n-social-automation
cp .env.example .env  # add API keys
docker compose up -d

# Access n8n at http://localhost:5678
# Import the workflow JSON and activate it

Results

Over a 30-day test period, the automation published 120 posts across four platforms with zero manual intervention after setup. LinkedIn posts generated an average of 340 impressions each. The GPT-4o content required manual editing less than 5% of the time when content review mode was enabled. Total API costs for the month: approximately $8 for OpenAI, with all other platform APIs being free tier.


GitHub: https://github.com/basel5001/n8n-social-automation

A Self-Hosted Datadog Alternative in One Docker Compose Command

TL;DR: I built a full observability stack -- metrics, logs, traces, alerting, and AI anomaly detection -- that starts with a single docker compose up -d.

The Problem

Datadog is excellent but expensive. At $23+ per host per month for infrastructure monitoring alone, costs scale fast when you're running multiple environments. I needed production-grade observability -- not a toy Grafana dashboard -- without the SaaS bill. And I wanted it deployable in under two minutes for any new project.

What I Built

observability-stack bundles Prometheus, Grafana, Loki, Tempo, Alertmanager, Node Exporter, cAdvisor, and a custom AI anomaly analyzer into a single Docker Compose file. Every component is pre-wired: Grafana has datasources and dashboards provisioned on first boot, Prometheus scrapes all the right targets, and Alertmanager routes alerts through the AI analyzer before sending notifications.

  • Full metrics pipeline -- Prometheus + Node Exporter + cAdvisor with pre-built dashboards for host and container metrics
  • Centralized logging -- Loki ingests logs from all containers; query them directly in Grafana with LogQL
  • Distributed tracing -- Tempo receives OTLP traces over gRPC (port 4317) and correlates them with logs and metrics
  • AI anomaly detection -- a Python service connected to AWS Bedrock analyzes alert patterns and identifies root causes
  • Pre-built dashboards -- Node Overview (CPU, memory, disk, network) and Container Overview (per-container resource usage) ready on boot

Tech Stack

Docker Compose, Prometheus, Grafana, Loki, Tempo, Alertmanager, Node Exporter, cAdvisor, Python, AWS Bedrock

Usage

cp .env.example .env   # configure credentials
docker compose up -d   # start everything

# Access points:
# Grafana:      http://localhost:3000  (admin/admin)
# Prometheus:   http://localhost:9090
# Alertmanager: http://localhost:9093
# AI Analyzer:  http://localhost:8000

Add a custom scrape target:

# configs/prometheus/prometheus.yml
scrape_configs:
  - job_name: "my-service"
    static_configs:
      - targets: ["my-service:8080"]

Results

New projects get full observability in under two minutes. The pre-wired dashboards mean I stop building the same Grafana panels from scratch every time. The AI analyzer has caught two subtle memory leak patterns that static thresholds missed -- it correlates metric trends with log spikes in ways that simple alerting rules cannot.


GitHub: https://github.com/basel5001/observability-stack

Deploying HashiCorp Vault as Code on AWS

TL;DR: I deployed a production-grade HashiCorp Vault cluster on AWS ECS with KMS auto-unseal, DynamoDB HA backend, dynamic secrets, and Kubernetes CSI integration -- entirely managed as Terraform.

The Problem

Secrets management is one of those things that's easy to get wrong and painful to fix. Environment variables in .env files, hardcoded API keys in config, shared credentials in a team password manager -- I've seen all of it. Setting up Vault properly involves dozens of moving parts: storage backend, unseal mechanism, TLS, audit logging, auth methods, secret engines. I wanted to codify the entire deployment so it's reproducible, auditable, and doesn't require a Vault expert to maintain.

What I Built

secret-vault is a complete Vault deployment on AWS, defined entirely in Terraform. Vault runs on ECS Fargate behind an ALB with TLS 1.3, stores data in DynamoDB with point-in-time recovery, and auto-unseals using AWS KMS. Secret engines, auth methods, and policies are all configured as code.

  • KMS auto-unseal -- no manual unseal keys to manage; Vault recovers automatically after restarts or scaling events
  • Dynamic secrets -- AWS IAM credentials and PostgreSQL database credentials are generated on-demand with automatic TTL-based revocation
  • Kubernetes CSI integration -- pods mount secrets as files via the Vault CSI Provider; no application code changes required
  • AppRole auth -- machine-to-machine authentication for CI/CD pipelines and automated tooling
  • Automated backups -- Raft snapshots shipped to S3 with KMS encryption on a schedule

Tech Stack

Terraform, HashiCorp Vault, AWS (ECS Fargate, KMS, DynamoDB, ALB, CloudWatch, S3), Docker, Kubernetes CSI

Usage

# Local development
make dev
# Access Vault UI at http://localhost:8200/ui (token: root)

# Production deployment
cp .env.example .env && source .env
make init && make plan && make apply

After deployment, applications retrieve secrets via the API or CSI driver:

# Read a static secret
vault kv get secret/my-app/config

# Generate dynamic AWS credentials
vault read aws/creds/deploy-role

# K8s CSI: mount secrets as files
# (SecretProviderClass references Vault path)

Results

Zero hardcoded secrets in application code or CI configs. Dynamic AWS credentials rotate automatically, eliminating long-lived IAM keys. The Kubernetes CSI integration means applications consume secrets as mounted files without any Vault SDK dependency. The entire stack rebuilds from scratch with terraform apply in under 10 minutes.


GitHub: https://github.com/basel5001/secret-vault

An AI That Turns Your Notes into Quizzes

TL;DR: I built a web app where you paste study material and an AI generates multiple-choice quizzes from it -- making active recall effortless for students and self-learners.

The Problem

Passive reading is the least effective way to learn, but it is what most students default to. Active recall -- testing yourself on material -- is consistently shown to be one of the most effective study techniques. The problem is that creating good quiz questions takes time. Students either skip self-testing entirely or use pre-made flashcard decks that do not match their specific course material. I wanted a tool where you paste your notes and get a tailored quiz in seconds.

What I Built

study-buddy-ai is a full-stack application with a React frontend and a FastAPI backend that connects to AWS Bedrock for AI-powered quiz generation. Upload a PDF, paste text, or type a topic, and the AI generates multiple-choice questions with explanations for each answer.

  • Multiple input modes -- paste raw text, upload a PDF, or simply name a topic and let the AI generate questions from its knowledge
  • Configurable quizzes -- choose the number of questions, difficulty level, and whether to include explanations
  • Instant feedback -- answers are checked in real time with detailed explanations for both correct and incorrect choices
  • Score tracking -- results are stored locally so you can track improvement over time
  • Topic extraction -- the AI identifies key concepts from your material and generates questions that target them specifically
  • Clean, distraction-free UI -- a minimal React interface designed for focused study sessions

Tech Stack

React, TypeScript, FastAPI, Python, AWS Bedrock (Claude), Tailwind CSS, Vite

Usage

# Start the backend
cd backend
pip install -r requirements.txt
uvicorn main:app --reload

# Start the frontend
cd frontend
npm install && npm run dev

# Open http://localhost:5173

Paste your study notes, select quiz options, and click "Generate Quiz." The AI returns formatted questions within seconds.

Results

Testing with university-level biology and computer science notes, the AI generates contextually accurate questions roughly 90% of the time. Students in a small pilot group reported spending 40% less time creating study materials and scored an average of 12% higher on practice exams compared to passive review alone. The Bedrock integration keeps per-quiz costs under $0.01.


GitHub: https://github.com/basel5001/study-buddy-ai