惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
aimingoo的专栏
aimingoo的专栏
B
Blog RSS Feed
V
Visual Studio Blog
P
Proofpoint News Feed
云风的 BLOG
云风的 BLOG
博客园 - 【当耐特】
大猫的无限游戏
大猫的无限游戏
Application and Cybersecurity Blog
Application and Cybersecurity Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
The Cloudflare Blog
B
Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Apple Machine Learning Research
Apple Machine Learning Research
M
MIT News - Artificial intelligence
Know Your Adversary
Know Your Adversary
I
InfoQ
T
The Exploit Database - CXSecurity.com
V
Vulnerabilities – Threatpost
C
Cisco Blogs
Spread Privacy
Spread Privacy
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Palo Alto Networks Blog
Simon Willison's Weblog
Simon Willison's Weblog
月光博客
月光博客
博客园 - Franky
Project Zero
Project Zero
G
Google Developers Blog
S
SegmentFault 最新的问题
博客园 - 聂微东
P
Privacy & Cybersecurity Law Blog
The GitHub Blog
The GitHub Blog
阮一峰的网络日志
阮一峰的网络日志
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
S
Schneier on Security
Microsoft Security Blog
Microsoft Security Blog
G
GRAHAM CLULEY
S
Security @ Cisco Blogs
Martin Fowler
Martin Fowler
A
Arctic Wolf
T
Tenable Blog
L
LINUX DO - 最新话题
TaoSecurity Blog
TaoSecurity Blog
Hugging Face - Blog
Hugging Face - Blog
有赞技术团队
有赞技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
I got tired of paying JFrog for a secure OpenTofu / Terraform registry so I built my own
Anthony Owens · 2026-05-26 · via DEV Community

Anthony Owens

View on GitHub

It's a tale as old as time — you want to implement a secure, centralized storage system to easily distribute these awesome IaC modules that your team has developed, but you quickly find that enterprise-grade comes with an enterprise price. You could stick with the good ol' GitHub refs, but you soon realize this doesn't scale well. Delivering critical security updates to developers becomes a tedious process. You then think to yourself "if only I could use OpenTofu version constraints!" Those constraints, like the pessimistic version constraint ~> v1.0.0 for modules, make delivering security patches at scale significantly less challenging, however, you only get access to them through the registry protocol.

So you spend late-nights scouring GitHub and Reddit looking for open-source registry projects hoping that you don't have to "pay the piper." Before you know it, you've spent months implementing several different open-source systems only to find each one either had a painful deployment process, no turn-key migration path, missing key features, or inconsistent authentication. You feel defeated — you have deadlines, after all, so you decide to "pony up" and "pay the man" just for peace of mind so you can mark your feature done.

I, for one, hate surrendering to the corporate SaaS overlords in this manner! From that painful journey I put my poor team through, and the lessons I learned along the way, I realized this was an opportunity to give back to the open-source community. That's when I first came up with the idea for OpenDepot!

The Solution

OpenDepot is an enterprise-grade OpenTofu / Terraform module and provider registry built entirely to be Kubernetes native. OpenDepot uses first-class Kubernetes primitives like Custom Resource Definitions and operators to streamline and modernize the module and provider pipeline. Instead of "pushing and praying" like I had to do with other registries, especially enterprise-grade solutions like Artifactory, OpenDepot is entirely declarative and offers administrators complete control over their supply chain.

The GitOps Way

The preferred method to deliver a new module version is by using GitOps with ArgoCD / Flux. This allows you to keep your registry manifest in the same repo as the module itself. When it's time to update or add new features to your module, the same pull request process you already use for module code is now tied-in with its release process:

terraform-aws-eks/
└── opendepot/
    └── terraform-aws-eks.yaml

OpenDepot Module

apiVersion: opendepot.defdev.io/v1alpha1
kind: Module
metadata:
  name: terraform-aws-eks
  namespace: opendepot-system
spec:
  moduleConfig:
    name: terraform-aws-eks
    provider: aws
    repoOwner: my-org
    repoUrl: https://github.com/my-org/terraform-aws-eks
    fileFormat: zip
    immutable: false
    storageConfig:
      s3:
        bucket: my-org-opendepot-modules
        region: us-west-2
    githubClientConfig:
      useAuthenticatedClient: true
  versions:
    - version: "21.10.1"
    - version: "21.11.0"
    - version: "21.12.0"
    - version: "21.13.0"   # added in PR #42

ArgoCD Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: terraform-aws-eks
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/my-org/terraform-aws-eks
    targetRevision: main
    path: opendepot
  destination:
    server: https://kubernetes.default.svc
    namespace: opendepot-system
  syncPolicy:
    automated:
      prune: false
      selfHeal: true

The release workflow then looks like this:

  1. A developer opens a PR against their OpenTofu module repository with the code changes
  2. The same PR includes an update to the OpenDepot Module manifest, adding the new version to spec.versions
  3. The team reviews both the module code and the registry manifest in a single PR
  4. On approval and merge, Argo CD detects the change and syncs the Module resource to the cluster
  5. OpenDepot takes over — the Module controller creates a Version resource, and the Version controller fetches the archive from GitHub and uploads it to storage. Once completed, a SHA256 checksum of the archive is stored in the status field before marking the Version as synced.

Tip: You can also use a centralized repo that hosts all your OpenDepot manifests, with a single ArgoCD application that gives you a visual overview of your entire registry.

Storage Configuration

OpenDepot supports all three major cloud provider storage backends as well as local filesystem storage:

AWS S3

storageConfig:
  s3:
    bucket: opendepot-modules
    region: us-west-2

Azure Blob

storageConfig:
  azureBlob:
    accountName: opendepotmodules
    accountUrl: https://opendepotmodules.blob.core.windows.net
    subscriptionID: 00000000-0000-0000-0000-000000000000
    resourceGroup: opendepot-rg

Google Cloud

storageConfig:
  gcs:
    bucket: opendepot-modules

Filesystem

storageConfig:
  filesystem:
    path: /data/opendepot

Extensible by design: I designed OpenDepot to leverage a Go interface for storage. Adding and testing new providers is straightforward — provide a concrete implementation for the interface, update the API, regenerate new CRDs, and you're ready to start testing. See CONTRIBUTING.md for more details.

Pre-signed URLs allow you to offload large egress costs (AWS providers can be ~700MB) by redirecting clients to pull directly from cloud storage instead of proxying through your infrastructure. Configure per-module, per-provider, or globally through the Depot:

storageConfig:
  s3:
    bucket: opendepot-providers
    region: us-west-2
  presign:
    enabled: true
    ttl: "15m"
    fallbackToProxy: true

Fallback behavior: When fallbackToProxy is true, if a pre-signed URL cannot be generated the server proxies the download itself. Set it to false to enforce that all downloads always use pre-signed URLs and never pass through your infrastructure.

Filesystem storage is backed by a Kubernetes Persistent Volume with any StorageClass that supports ReadWriteMany. The Version controller needs to write artifacts to the same volume the Server serves them from — hence the ReadWriteMany requirement.

Init container privileges: On startup, an init container runs as root to chown/chgrp the directory mount so that user/group 65532 (the user the containers run as) can read/write to it. This is the only point where elevated privileges are required — otherwise, OpenDepot runs as non-root across the board.

The Depot (Pull-Based)

If you don't follow a GitOps process, no worries! The Depot resource allows you to pull down modules and providers using version constraints, creating a private mirror for public providers with a fully defined release process:

apiVersion: opendepot.defdev.io/v1alpha1
kind: Depot
metadata:
  name: my-team-depot
  namespace: opendepot-system
spec:
  global:
    githubClientConfig:
      useAuthenticatedClient: true
    moduleConfig:
      fileFormat: zip
      immutable: false
    storageConfig:
      s3:
        bucket: opendepot-registry
        region: us-west-2
  moduleConfigs:
    - name: terraform-aws-eks
      provider: aws
      repoOwner: terraform-aws-modules
      versionConstraints: ">= 21.10.1, != 21.13.0"
    - name: terraform-azurerm-aks
      provider: azurerm
      repoOwner: azure
      versionConstraints: ">= 10.0.0"
  providerConfigs:
    - name: aws
      operatingSystems:
        - linux
        - darwin
      architectures:
        - amd64
        - arm64
      versionConstraints: ">= 5.80.0, < 6.0.0"
      storageConfig:
        s3:
          bucket: opendepot-registry
          region: us-west-2
  pollingIntervalMinutes: 60

This Depot will:

  1. Query the terraform-aws-modules/terraform-aws-eks and azure/terraform-azurerm-aks GitHub repositories for releases
  2. Filter releases matching the version constraints and create Module resources
  3. Query the HashiCorp Releases API for the aws provider and create a Provider resource for matching versions
  4. The Module and Provider controllers create Version resources for each discovered version and OS/architecture
  5. The Version controller fetches archives from GitHub (modules) or HashiCorp (providers) and uploads them to the S3 bucket
  6. Re-check for new releases every 60 minutes

Since your registry configuration is codified via the Depot, it now follows the same review process as other services in your stack!

Migrating from an existing registry: The Depot is a very handy migration tool. Point it at your GitHub repos with a version constraint that covers your existing versions, let it ingest everything, then delete the Depot. Removing the Depot resource does not delete any Modules or Providers — it's simply a centralized interface to ingest multiple artifacts.

The CI/CD Workflow (Push-based)

You also have the option for an entirely push-based CI/CD workflow:

OpenDepot Manifest

apiVersion: opendepot.defdev.io/v1alpha1
kind: Module
metadata:
  name: terraform-aws-eks
  namespace: opendepot-system
spec:
  moduleConfig:
    name: terraform-aws-eks
    provider: aws
    repoOwner: terraform-aws-modules
    repoUrl: https://github.com/terraform-aws-modules/terraform-aws-eks
    fileFormat: zip
    immutable: true
    storageConfig:
      s3:
        bucket: opendepot-modules
        region: us-west-2
    githubClientConfig:
      useAuthenticatedClient: true
  versions:
    - version: "21.10.1"
    - version: "21.11.0"
    - version: "21.12.0"
    - version: "21.13.0"  # added in PR #42

GitHub Actions Workflow

name: Publish Module Version

on:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::<AWS_ACCOUNT_ID>:role/opendepot-github-actions-role
          aws-region: us-west-2

      - name: Setup kubeconfig
        run: aws eks update-kubeconfig --name my-cluster --region us-west-2

      - name: Publish module version
        run: |
          kubectl apply -f "opendepot/terraform-aws-eks.yaml"

Security Features

Checksum Validation Every Reconcile

Kubernetes operators constantly reconcile resources and act on changes to any resources they manage. When a module version is being added, all previous versions are also reconciled. To ensure OpenDepot is not re-downloading providers or modules every reconciliation loop, the Version resource stores a status.checksum of each archive.

If the checksum metadata in storage doesn't match this field, the controller first attempts to pull it from source and revalidate the checksum. If the checksum from source is still not a match, the controller stops reconciling and emits errors.

Tamper protection: The Server will not serve any modules whose checksums do not match. The Version controller continuously reconciles storage so that any tampered archive is re-fetched and restored to its known-good state.

GPG Keys

OpenDepot supports GPG signing for providers. When serving provider binaries, the registry protocol requires that each binary is accompanied by a SHA256 checksum file and a GPG signature so that OpenTofu and Terraform can verify the integrity of what they download. Configure OpenDepot with your GPG key via a Kubernetes Secret referenced by server.gpg.secretName in the Helm chart. Once set, the Server automatically signs provider checksum files on the fly with your private key. Clients that have your public key in their trust store can verify every provider binary they pull is untampered and came from your registry.

Trivy Vulnerability Scans

OpenDepot has the option to perform security scans using a separate Version controller image that comes bundled with Trivy. Trivy will perform a configuration scan of modules and store findings in the module.status field. For providers, Trivy will scan the binary for each operating system and architecture, and OpenDepot will attempt to find and scan the source code, deduplicate findings, then store each in the provider.status field.

Blocking policy: You can configure OpenDepot to block CRITICAL and HIGH vulnerabilities to ensure that only modules and providers with a good security posture can be reconciled and stored in your registry.

Dex OIDC Integration

OpenDepot's Helm chart bundles Dex as a subchart to handle OIDC authentication with an upstream IdP like Entra ID, GitHub, Okta, and many more. This is the recommended authentication method since it doesn't require cluster access or expose endpoints used to modify resources.

With OIDC enabled you can leverage fine-grained access control through GroupBinding custom resources. Use the Expr language to bind the groups claim in a user's JWT to specific modules or providers. The moduleResources field also supports glob patterns:

apiVersion: opendepot.defdev.io/v1alpha1
kind: GroupBinding
metadata:
  name: "01-aws-platform-team"
  namespace: opendepot-system
spec:
  expression: '"aws-platform-team" in groups'
  moduleResources:
    - "terraform-aws-*"
  providerResources:
    - "aws"

Native tofu login support: OIDC with Dex is the only method that supports the native tofu login opendepot.defdev.io command.

Other Authentication Methods

  • Kubernetes service account token — Use Kubernetes RBAC permissions to control access per module or provider. Bypasses GroupBinding in favor of native Kubernetes RBAC.
  • Base64-encoded kubeconfig — Convenient for local kind clusters.
  • Anonymous auth — Enable via a single Helm chart flag to host a public registry. The Server's own Service Account is used for fetching, and clients don't need an access token.

Kubeconfig - local use only: A base64-encoded Kubernetes kubeconfig should never be used in production. It is convenient for local kind cluster testing only.

Fetching Artifacts

The Server implements both the Module and Provider Registry protocols so that OpenTofu and Terraform can use OpenDepot as a drop-in registry. Crucially, the Server is completely read-only — it provides no endpoints that allow modifications. All changes to resources require strict Kubernetes access.

Reference your modules and providers in code, then run tofu init:

Module

module "eks" {
  source  = "opendepot.defdev.io/opendepot-system/terraform-aws-key-pair/aws"
  version = "~> 21.0.0"
}

Provider

terraform {
  required_providers {
    aws = {
      source  = "opendepot.defdev.io/opendepot-system/aws"
      version = "~> 5.80"
    }
    azurerm = {
      source  = "opendepot.defdev.io/opendepot-system/azurerm"
      version = ">= 4.0.0"
    }
  }
}

Configure your .tofurc to point at OpenDepot:

host "opendepot.defdev.io" {
  services = {
    "modules.v1"   = "https://opendepot.defdev.io/opendepot/modules/v1/"
    "providers.v1" = "https://opendepot.defdev.io/opendepot/providers/v1/"
  }
}

With Dex configured, the full tofu login + tofu init flow looks like this:

$ tofu login opendepot.defdev.io
$ tofu init

Initializing the backend...
Initializing modules...
Downloading opendepot.defdev.io/opendepot-system/terraform-aws-key-pair/aws 2.0.3 for key_pair...
- key_pair in .terraform/modules/key_pair

Initializing provider plugins...

OpenTofu has been successfully initialized!

You may now begin working with OpenTofu. Try running "tofu plan" to see
any changes that are required for your infrastructure. All OpenTofu commands
should now work.

If you ever set or change modules or backend configuration for OpenTofu,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

That's all there is to it on the consuming side! It's simple and easy to get started with OpenDepot! I ask that you try it today and share your experiences. If you have any questions, see any issues, or just want to talk about Cloud Native tooling in general — feel free to reach out to me anytime!


  • Full Documentation - Everything you need to get set up, configured, and running your own registry.
  • Local Quickstart - Run a fully functional registry on your laptop with kind in minutes, no cloud account needed.
  • Installation Guide - Deploy OpenDepot to your cluster with Helm.