16 Commits

Author SHA1 Message Date
benvin 64880870e7 Add iplocate IP database remote
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
2026-07-21 22:16:23 +10:00
benvin 8735cc7e74 Merge pull request 'rpm: proxy RPM Fusion free/nonfree remotes' (#7) from benvin/rpmfusion-remotes into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #7
2026-07-18 14:29:45 +10:00
unkinben e71eb90101 rpm: drop repodata from rpmfusion immutable_patterns
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
repodata is regenerated upstream, so it must stay mutable (mutable_ttl)
rather than being cached as immutable.

Claude-Session: https://claude.ai/code/session_01VZ81u2JtjvaPq8Z3EDTSMb
2026-07-18 14:18:35 +10:00
unkinben 79f4d244e8 Merge pull request 'remote_rpm: stop caching repodata as immutable' (#8) from benvin/rpm-repodata-mutable into main
ci/woodpecker/push/apply Pipeline was successful
2026-07-18 14:15:52 +10:00
unkinben d168962f82 remote_rpm: stop caching repodata as immutable
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
repodata (repomd.xml and its referenced index files) is a mutable index that
upstream RPM repos rotate frequently. Marking it immutable (immutable_ttl: 0)
makes artifactapi cache repomd.xml forever: classifier.go checks
immutable_patterns before the RPM provider's own rule (which already classifies
repodata/ as mutable), and SetTTL with ttl=0 writes a Redis key with no expiry.
The result is a stale repomd.xml that keeps pointing at checksum-named metadata
files upstream has already deleted -> 404 on dnf metadata refresh. This broke
rpmbuilder's almalinux8 builds via the epel remote and would eventually hit any
rolling RPM remote.

Remove the repodata immutable patterns from every remote_rpm config so repodata
falls through to the provider's Mutable classification and is re-fetched every
mutable_ttl. RPMs, noarch, GPG keys and .img files stay immutable.

- Drop ".*/repodata/.*\.{xml,sqlite,yaml}.*$" from all config/remote_rpm/*.yaml
  (14 files, 20 lines).

After apply, the already-cached stale repodata entries must be evicted (they
have no expiry); that is done per-remote as a follow-up.
2026-07-18 14:12:02 +10:00
unkinben 04617699aa rpm: proxy RPM Fusion free/nonfree remotes
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
The rpmfusion-free / rpmfusion-nonfree repos have no artifactapi remote,
so nodes still point at the retired packagerepo.service.consul mirror and
dnf fails to fetch repomd.xml.

Add caching remote proxies for both trees, pointed at the upstream
download1.rpmfusion.org origin, so el nodes can install RPM Fusion
packages (ffmpeg, etc.) through artifactapi.

Claude-Session: https://claude.ai/code/session_01VZ81u2JtjvaPq8Z3EDTSMb
2026-07-18 14:03:41 +10:00
benvin 53c26160f1 Merge pull request 'Add per-distro rpm-vendor local RPM repos' (#6) from benvin/rpm-vendor into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #6
2026-07-18 11:19:38 +10:00
unkinben 7bdb30d8d4 Add per-distro rpm-vendor local RPM repos
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
rpmbuilder publishes vendored third-party RPMs (vault, consul, helm, ...)
which currently go to Gitea's RPM registry. Move them onto artifactapi so
they live in real yum repos alongside rpm-internal, and keep vendored
packages separate from in-house software. rpmbuilder targets EL8, EL9 and
Fedora 42/43/44, so each distro gets its own repo to avoid EL/Fedora RPMs
colliding in a single repodata set.

- Add config/local_rpm/rpm-vendor-el8.yaml
- Add config/local_rpm/rpm-vendor-el9.yaml
- Add config/local_rpm/rpm-vendor-f42.yaml
- Add config/local_rpm/rpm-vendor-f43.yaml
- Add config/local_rpm/rpm-vendor-f44.yaml

config.hcl already globs local_rpm/*.yaml, so no wiring change is needed.
2026-07-18 00:08:58 +10:00
benvin 834a04a034 Merge pull request 'dockerhub: proxy grafana/ images' (#5) from benvin/grafana-images into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #5
2026-07-06 23:52:55 +10:00
unkinben 7ce31f864c dockerhub: proxy grafana/ images
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
The grafana-operator creates Grafana pods from docker.io/grafana/grafana,
which the dockerhub remote did not allow, so the pods would ImagePullBackOff.
Add the ^grafana/ pattern so the grafana image (and image-renderer) proxy
through artifactapi.
2026-07-06 22:11:47 +10:00
benvin 78caca1d69 Merge pull request 'feat: manage local docker registries' (#4) from benvin/local-docker into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #4
2026-07-05 22:43:12 +10:00
unkinben c42826c6de feat: manage local docker registries
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
ArtifactAPI now serves local docker repos as real container registries and the
provider exposes an artifactapi_local_docker resource, but this config had no
way to declare one.

- Add a local_docker variable, module resource, config loader wiring, and
  terragrunt input, mirroring the other local_* kinds.
- Declare a docker-internal registry.
- Expand the README to cover the local_* and virtual kinds.

Depends on a terraform-provider-artifactapi release exposing
artifactapi_local_docker (and a matching .terraform.lock.hcl bump) before apply.
2026-07-05 17:16:17 +10:00
benvin 38ab457ac1 Merge pull request 'feat: initial commit' (#3) from benvin/add-missing-registries into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #3
2026-07-03 23:35:30 +10:00
unkinben 9351ea30a9 fix: declare provider requirement in the artifactapi module
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful
pre-commit runs `tofu validate`/tflint on modules/artifactapi standalone, where
no required_providers was declared, so OpenTofu inferred hashicorp/artifactapi
and failed (and tflint flagged missing required_version/version constraint).

- add modules/artifactapi/versions.tf declaring required_version and the
  artifactapi provider (source = the registry, version >= 0.1.2)
- drop the now-duplicate required_providers from root.hcl's generated backend.tf;
  keep the provider config block + backend. Declaring it in both the module and
  the generated root would be a "Duplicate required providers" error at runtime.

Also revert the earlier init lock-cleanup: the CI failure was stale provider
references in state (fixed with `tofu state replace-provider`), not the lock.
2026-07-03 23:34:19 +10:00
unkinben 292392a024 fix(ci): clear stale provider locks before init
ci/woodpecker/pr/pre-commit Pipeline failed
ci/woodpecker/pr/plan Pipeline failed
The provider source moved from git.unkin.net/unkin/artifactapi to
artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/artifactapi. .terraform.lock.hcl
is gitignored, so a CI runner reusing a workspace/cache keeps a lock pinning the
old source; some OpenTofu versions then try to re-resolve git.unkin.net (which
isn't a registry) instead of dropping it, failing init.

Delete any .terraform.lock.hcl before `terragrunt run --all init -- -upgrade` so
providers resolve purely from config.
2026-07-03 21:48:57 +10:00
unkinben 9058eb3f59 feat: initial commit
ci/woodpecker/pr/pre-commit Pipeline failed
ci/woodpecker/pr/plan Pipeline was successful
- add modules
- add config
- add environments
- add .gitignore
- add makefile

Wire up config.hcl, variables, and terragrunt inputs for all new types.
2026-07-03 21:29:02 +10:00
80 changed files with 1034 additions and 1 deletions
+4
View File
@@ -0,0 +1,4 @@
.terraform
.terraform.lock.hcl
.terragrunt-cache
env
+24
View File
@@ -0,0 +1,24 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: end-of-file-fixer
types: [yaml]
- id: trailing-whitespace
types: [yaml]
- repo: https://github.com/gruntwork-io/pre-commit
rev: v0.1.30
hooks:
- id: tofu-fmt
- id: tofu-validate
- id: tflint
- id: terragrunt-hcl-fmt
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.37.1
hooks:
- id: yamllint
args:
[
"-d {extends: relaxed, rules: {line-length: disable}, ignore: chart}",
"-s",
]
+23
View File
@@ -0,0 +1,23 @@
when:
- event: push
branch: main
steps:
- name: apply
image: git.unkin.net/unkin/almalinux9-opentofu:20260606
environment:
VAULT_AUTH_METHOD: kubernetes
commands:
- dnf install vault -y
- make plan
- make apply
backend_options:
kubernetes:
serviceAccountName: terraform-artifactapi
resources:
requests:
memory: 512Mi
cpu: 1
limits:
memory: 2Gi
cpu: 2
+21
View File
@@ -0,0 +1,21 @@
when:
- event: pull_request
steps:
- name: plan
image: git.unkin.net/unkin/almalinux9-opentofu:20260606
environment:
VAULT_AUTH_METHOD: kubernetes
commands:
- dnf install vault -y
- make plan
backend_options:
kubernetes:
serviceAccountName: terraform-artifactapi
resources:
requests:
memory: 512Mi
cpu: 1
limits:
memory: 2Gi
cpu: 2
+18
View File
@@ -0,0 +1,18 @@
when:
- event: pull_request
steps:
- name: pre-commit
image: git.unkin.net/unkin/almalinux9-opentofu:20260606
commands:
- uvx pre-commit run --all-files
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 512Mi
cpu: 1
limits:
memory: 2Gi
cpu: 2
+34
View File
@@ -0,0 +1,34 @@
.PHONY: init plan apply format
VAULT_AUTH_METHOD ?= approle
VAULT_K8S_ROLE ?= woodpecker_terraform_artifactapi
VAULT_K8S_MOUNT ?= auth/k8s/au/syd1
VAULT_K8S_JWT_PATH ?= /var/run/secrets/kubernetes.io/serviceaccount/token
define vault_env
@export VAULT_ADDR="https://vault.service.consul:8200" && \
if [ "$(VAULT_AUTH_METHOD)" = "kubernetes" ]; then \
export VAULT_TOKEN=$$(vault write -field=token $(VAULT_K8S_MOUNT)/login role=$(VAULT_K8S_ROLE) jwt=$$(cat $(VAULT_K8S_JWT_PATH))); \
else \
export VAULT_TOKEN=$$(vault write -field=token auth/approle/login role_id=$$VAULT_ROLEID); \
fi && \
export CONSUL_HTTP_TOKEN=$$(vault read -field=token consul_root/au/syd1/creds/terraform-artifactapi)
endef
init:
@$(call vault_env) && \
terragrunt run --all --non-interactive init -- -upgrade
plan: init
@$(call vault_env) && \
terragrunt run --all --parallelism 4 --non-interactive plan
apply: init
@$(call vault_env) && \
terragrunt run --all --parallelism 2 --non-interactive apply
format:
@echo "Formatting OpenTofu files..."
@tofu fmt -recursive .
@echo "Formatting Terragrunt files..."
@terragrunt hcl fmt
+9 -1
View File
@@ -1,3 +1,11 @@
# terraform-artifactapi
Terraform configuration for managing ArtifactAPI remote and virtual repositories
Terraform configuration for managing ArtifactAPI remote, local, and virtual repositories.
Repositories are declared as YAML files under `config/<kind>/<name>.yaml`, where the
filename is the repository name. `make plan` / `make apply` (via Terragrunt) reconcile
them against the ArtifactAPI instance.
Kinds: `remote_*` (caching proxies of an upstream), `local_*` (real registries hosted
directly — `local_docker`, `local_pypi`, `local_rpm`, `local_terraform`), and `virtual`
(merged views over members of one package type).
+71
View File
@@ -0,0 +1,71 @@
locals {
config_files = fileset(".", "**/*.yaml")
all_configs = {
for file_path in local.config_files :
file_path => yamldecode(file(file_path))
}
config = {
remote_alpine = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "remote_alpine/")
}
remote_docker = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "remote_docker/")
}
remote_generic = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "remote_generic/")
}
remote_goproxy = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "remote_goproxy/")
}
remote_helm = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "remote_helm/")
}
remote_pypi = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "remote_pypi/")
}
remote_rpm = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "remote_rpm/")
}
local_terraform = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "local_terraform/")
}
local_pypi = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "local_pypi/")
}
local_rpm = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "local_rpm/")
}
local_docker = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "local_docker/")
}
virtual = {
for file_path, content in local.all_configs :
trimsuffix(basename(file_path), ".yaml") => content
if startswith(file_path, "virtual/")
}
}
}
+1
View File
@@ -0,0 +1 @@
description: "Internal container image registry"
+1
View File
@@ -0,0 +1 @@
description: "Internal PyPI packages"
+1
View File
@@ -0,0 +1 @@
description: "Internal RPM packages for Enterprise Linux 10 (RHEL/AlmaLinux/Rocky 10)"
+1
View File
@@ -0,0 +1 @@
description: "Internal RPM packages for Enterprise Linux 8 (RHEL/AlmaLinux/Rocky 8)"
+1
View File
@@ -0,0 +1 @@
description: "Internal RPM packages for Enterprise Linux 9 (RHEL/AlmaLinux/Rocky 9)"
+1
View File
@@ -0,0 +1 @@
description: "Internal RPM packages for Fedora 42"
+1
View File
@@ -0,0 +1 @@
description: "Internal RPM packages for Fedora 43"
+1
View File
@@ -0,0 +1 @@
description: "Internal RPM packages for Fedora 44"
+1
View File
@@ -0,0 +1 @@
description: "Internal RPM packages (distribution-agnostic)"
+1
View File
@@ -0,0 +1 @@
description: "Vendored third-party RPM packages for Enterprise Linux 8 (RHEL/AlmaLinux/Rocky 8), built by rpmbuilder"
+1
View File
@@ -0,0 +1 @@
description: "Vendored third-party RPM packages for Enterprise Linux 9 (RHEL/AlmaLinux/Rocky 9), built by rpmbuilder"
+1
View File
@@ -0,0 +1 @@
description: "Vendored third-party RPM packages for Fedora 42, built by rpmbuilder"
+1
View File
@@ -0,0 +1 @@
description: "Vendored third-party RPM packages for Fedora 43, built by rpmbuilder"
+1
View File
@@ -0,0 +1 @@
description: "Vendored third-party RPM packages for Fedora 44, built by rpmbuilder"
@@ -0,0 +1 @@
description: "Unkin Terraform modules"
+6
View File
@@ -0,0 +1,6 @@
base_url: https://dl-cdn.alpinelinux.org
description: Alpine Linux APK package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*/x86_64/.*\\.apk$"
+36
View File
@@ -0,0 +1,36 @@
base_url: https://registry-1.docker.io
description: Docker Hub registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^alpine/"
- "^library/almalinux"
- "^library/alpine"
- "^library/busybox"
- "^library/debian"
- "^library/fedora"
- "^library/nginx"
- "^library/postgres"
- "^library/redis"
- "^beats/filebeat"
- "^bitnami/"
- "^curlimages/curl"
- "^emberstack/kubernetes-reflector"
- "^grafana/"
- "^hashicorp/consul"
- "^hashicorp/vault"
- "^intel/"
- "^internetsystemsconsortium/bind9"
- "^jfrog/"
- "^jpgouin/"
- "^kanidm/"
- "^osixia/"
- "^rancher/"
- "^rspamd/rspamd"
- "^tiredofit/"
- "^tozd/postfix"
- "^traefik/"
- "^valkey/valkey"
- "^ubi9/ubi-minimal"
- "^victoriametrics/"
- "^woodpeckerci/"
+6
View File
@@ -0,0 +1,6 @@
base_url: https://public.ecr.aws
description: Amazon ECR Public registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^docker/library/"
+6
View File
@@ -0,0 +1,6 @@
base_url: https://docker.elastic.co
description: Elastic container registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^eck/eck-operator"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://gcr.io
description: Google Container Registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^k8s-staging-nfd/charts"
- "^k8s-staging-nfd/node-feature-discovery"
+21
View File
@@ -0,0 +1,21 @@
base_url: https://ghcr.io
description: GitHub Container Registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^cloudnative-pg/"
- "^dexidp/"
- "^emberstack/helm-charts"
- "^fallenbagel/"
- "^goauthentik/"
- "^home-operations/"
- "^jellyfin/"
- "^onedr0p/"
- "^open-webui/open-webui"
- "^openvoxproject/"
- "^paperclipai/"
- "^plexguide/"
- "^stakater/reloader"
- "^stalwartlabs/stalwart"
- "^voxpupuli/puppetboard"
- "^woodpecker-ci/helm"
+6
View File
@@ -0,0 +1,6 @@
base_url: https://registry.gitlab.com
description: GitLab container registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^purelb/purelb"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://registry.k8s.io
description: Kubernetes container registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^external-dns/external-dns"
- "^sig-storage/"
+6
View File
@@ -0,0 +1,6 @@
base_url: https://docker.litellm.ai
description: LiteLLM container registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^berriai/"
+9
View File
@@ -0,0 +1,9 @@
base_url: https://quay.io
description: Quay.io container registry
immutable_ttl: 0
mutable_ttl: 300
patterns:
- "^argoproj/"
- "^brancz/kube-rbac-proxy"
- "^cephcsi/cephcsi"
- "^jetstack/cert-manager-"
+11
View File
@@ -0,0 +1,11 @@
base_url: https://downloads.claude.ai
description: Anthropic Claude Code binary releases
immutable_ttl: 0
mutable_ttl: 7200
mutable_patterns:
- "claude-code-releases/.*/manifest.json$"
patterns:
- "claude-code-releases/.*/linux-x64/claude$"
- "claude-code-releases/.*/linux-arm64/claude$"
- "claude-code-releases/.*/linux-x64-musl/claude$"
- "claude-code-releases/.*/linux-arm64-musl/claude$"
+9
View File
@@ -0,0 +1,9 @@
base_url: https://dl.gitea.com
description: Gitea download site
immutable_ttl: 0
mutable_ttl: 7200
patterns:
- "act_runner/.*/act_runner-.*-linux-amd64$"
- "gitea/.*/gitea-.*-linux-amd64$"
- "gitea/.*/gitea-.*-linux-amd64.xz$"
- "tea/.*/tea-.*-linux-amd64$"
+60
View File
@@ -0,0 +1,60 @@
base_url: https://github.com
description: GitHub releases and files
immutable_ttl: 0
mutable_ttl: 7200
mutable_patterns:
- ".*/archive/refs/heads/.*.tar.gz$"
- "stalwartlabs/webadmin/releases/latest/download/webadmin.zip$"
patterns:
- ".*/archive/refs/tags/.*.tar.gz$"
- "ahmetb/kubectx/.*/kubectx_.*_linux_x86_64.tar.gz$"
- "ahmetb/kubectx/.*/kubens_.*_linux_x86_64.tar.gz$"
- "apple/foundationdb/.*/libfdb_c.x86_64.so$"
- "astral-sh/ruff/.*/ruff-x86_64-unknown-linux-gnu.tar.gz$"
- "astral-sh/uv/.*/uv-x86_64-unknown-linux-gnu.tar.gz$"
- "camptocamp/prometheus-puppetdb-exporter/.*/prometheus-puppetdb-exporter-.*.linux-amd64.tar.gz$"
- "coder/code-server/.*/code-server-.*-amd64.rpm$"
- "containernetworking/plugins/.*/cni-plugins-linux-amd64-.*.tgz"
- "dandavison/delta/.*/delta-.*-x86_64-unknown-linux-musl.tar.gz$"
- "ducaale/xh/.*/xh-.*-x86_64-unknown-linux-musl.tar.gz$"
- "etcd-io/etcd/.*/etcd-.*-linux-amd64.tar.gz$"
- "getsops/sops/.*/sops-v.*\\.linux\\.amd64$"
- "grafana/jsonnet-language-server/.*/jsonnet-language-server_.*_linux_amd64$"
- "gruntwork-io/boilerplate/.*/boilerplate_linux_amd64$"
- "gruntwork-io/terragrunt/.*terragrunt_linux_amd64.*"
- "hadolint/hadolint/.*/hadolint-linux-x86_64$"
- "helmfile/helmfile/.*/helmfile_.*_linux_amd64.tar.gz$"
- "helmfile/vals/.*/vals_.*_linux_amd64.tar.gz$"
- "jesseduffield/lazydocker/.*/lazydocker_.*_Linux_x86_64.tar.gz$"
- "kubecolor/kubecolor/.*/kubecolor_.*_linux_amd64.tar.gz$"
- "kubernetes-sigs/gateway-api/.*/standard-install.yaml$"
- "kubernetes-sigs/kustomize/.*/kustomize_.*_linux_amd64.tar.gz$"
- "lxc/incus/.*.tar.gz$"
- "mikefarah/yq/.*/yq_linux_amd64$"
- "neovim/neovim-releases/.*/nvim-linux-x86_64.tar.gz$"
- "neovim/neovim/.*/nvim-linux-x86_64.tar.gz$"
- "nzbgetcom/nzbget/.*/nzbget-.*.x86_64.rpm$"
- "onedr0p/exportarr/.*/exportarr_.*_linux_amd64.tar.gz$"
- "open-policy-agent/conftest/.*/conftest_.*_Linux_x86_64.tar.gz$"
- "openbao/openbao-plugins/.*/openbao-plugin-secrets-consul_linux_amd64_.*.tar.gz$"
- "openbao/openbao-plugins/.*/openbao-plugin-secrets-nomad_linux_amd64_.*.tar.gz$"
- "prometheus-community/bind_exporter/.*/bind_exporter-.*.linux-amd64.tar.gz$"
- "prometheus-community/pgbouncer_exporter/.*/pgbouncer_exporter-.*.linux-amd64.tar.gz$"
- "prometheus-community/postgres_exporter/.*/postgres_exporter-.*.linux-amd64.tar.gz$"
- "prometheus/node_exporter/.*/node_exporter-.*.linux-amd64.tar.gz$"
- "rancher/rke2/.*/rke2-images.linux-amd64.tar.zst$"
- "stalwartlabs/stalwart/.*/stalwart-cli-x86_64-unknown-linux-gnu.tar.gz$"
- "stalwartlabs/stalwart/.*/stalwart-foundationdb-x86_64-unknown-linux-gnu.tar.gz$"
- "stalwartlabs/stalwart/.*/stalwart-x86_64-unknown-linux-gnu.tar.gz$"
- "starship/starship/.*/starship-x86_64-unknown-linux-musl.tar.gz$"
- "stern/stern/.*/stern_.*_linux_amd64.tar.gz$"
- "terraform-linters/tflint/.*/tflint_linux_amd64.zip$"
- "tynany/frr_exporter/.*/frr_exporter-.*.linux-amd64.tar.gz$"
- "VictoriaMetrics/VictoriaLogs/.*/victoria-logs-linux-amd64-.*.tar.gz$"
- "VictoriaMetrics/VictoriaLogs/.*/vlutils-linux-amd64-.*.tar.gz$"
- "VictoriaMetrics/VictoriaMetrics/.*/victoria-logs-linux-amd64-.*.tar.gz$"
- "VictoriaMetrics/VictoriaMetrics/.*/victoria-metrics-linux-amd64-.*-cluster.tar.gz$"
- "VictoriaMetrics/VictoriaMetrics/.*/vlutils-linux-amd64-.*.tar.gz$"
- "VictoriaMetrics/VictoriaMetrics/.*/vmutils-linux-amd64-.*.tar.gz$"
- "xorpaul/g10k/.*/g10k-.*-linux-amd64.zip$"
- "yannh/kubeconform/.*/kubeconform-linux-amd64.tar.gz$"
+9
View File
@@ -0,0 +1,9 @@
base_url: https://raw.githubusercontent.com
description: GitHub User Content
immutable_ttl: 0
mutable_ttl: 7200
patterns:
- "argoproj/argo-cd/.*.yaml$"
- "datreeio/CRDs-catalog/main/.*.json$"
- "kubernetes/kubernetes/.*.json$"
- "yannh/kubernetes-json-schema/master/.*.json$"
@@ -0,0 +1,16 @@
base_url: https://releases.hashicorp.com
description: HashiCorp product releases
immutable_ttl: 0
mutable_ttl: 7200
patterns:
- "terraform/.*terraform_.*_linux_amd64\\.zip$"
- "terraform/.*terraform_.*_windows_amd64\\.zip$"
- "terraform/.*terraform_.*_darwin_amd64\\.zip$"
- "vault/.*vault_.*_linux_amd64\\.zip$"
- "vault/.*vault_.*_windows_amd64\\.zip$"
- "vault/.*vault_.*_darwin_amd64\\.zip$"
- "consul-cni/.*/consul-cni_.*_linux_amd64\\.zip$"
- "consul/.*/consul_.*_linux_amd64\\.zip$"
- "nomad-autoscaler/.*/nomad-autoscaler_.*_linux_amd64\\.zip$"
- "nomad/.*/nomad_.*_linux_amd64\\.zip$"
- "packer/.*/packer_.*_linux_amd64\\.zip$"
+10
View File
@@ -0,0 +1,10 @@
base_url: https://media.githubusercontent.com
description: iplocate IP address databases (ip-to-asn / ip-to-country), served via GitHub LFS media
immutable_ttl: 0
# The databases update on the main branch; re-check upstream daily (matches the
# ASN expander's cache cadence).
mutable_ttl: 86400
mutable_patterns:
# LFS objects are served from media.githubusercontent.com/media/<owner>/<repo>/<ref>/<path>.
- "media/iplocate/ip-address-databases/.*/ip-to-asn/.*"
- "media/iplocate/ip-address-databases/.*/ip-to-country/.*"
+6
View File
@@ -0,0 +1,6 @@
base_url: https://www.rarlab.com
description: RARLab
immutable_ttl: 0
mutable_ttl: 7200
patterns:
- "rar/rarlinux-x64-.*.tar.gz"
+4
View File
@@ -0,0 +1,4 @@
base_url: https://proxy.golang.org
description: Go module proxy
immutable_ttl: 0
mutable_ttl: 300
+7
View File
@@ -0,0 +1,7 @@
base_url: https://argoproj.github.io/argo-helm
description: Argo Project Helm charts (ArgoCD, Image Updater, Rollouts, etc.)
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://charts.goauthentik.io
description: Authentik Charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://ceph.github.io/csi-charts
description: Ceph CSI driver Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://cloudnative-pg.github.io/charts
description: CloudNativePG operator Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://helm.elastic.co
description: Elastic stack Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://kubernetes-sigs.github.io/external-dns/
description: ExternalDNS Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://grafana.github.io/helm-charts
description: Grafana Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://helm.releases.hashicorp.com
description: HashiCorp Helm charts (Vault Secrets Operator, etc.)
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://intel.github.io/helm-charts/
description: Intel Helm charts (device plugins)
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://charts.jetstack.io
description: Jetstack Helm charts (cert-manager)
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://gitlab.com/api/v4/projects/20400619/packages/helm/stable
description: PureLB load balancer Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://releases.rancher.com/server-charts/stable
description: Rancher stable Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://stakater.github.io/stakater-charts
description: Stakater Helm charts (Reloader)
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://traefik.github.io/charts
description: Traefik Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://victoriametrics.github.io/helm-charts/
description: VictoriaMetrics observability Helm charts
immutable_ttl: 0
mutable_ttl: 3600
check_mutable: true
immutable_patterns:
- "\\.tgz$"
+5
View File
@@ -0,0 +1,5 @@
base_url: https://pypi.org
description: "PyPI — Python Package Index"
immutable_ttl: 0
mutable_ttl: 3600
stale_on_error: true
+11
View File
@@ -0,0 +1,11 @@
base_url: https://vault.almalinux.org
description: AlmaLinux Vault RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
- ".*/install.img"
- ".*/squashfs.img"
- ".*/updates.img"
- ".*/RPM-GPG-KEY-.*$"
+11
View File
@@ -0,0 +1,11 @@
base_url: https://gsl-syd.mm.fcix.net/almalinux
description: AlmaLinux RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
- ".*/install.img"
- ".*/squashfs.img"
- ".*/updates.img"
- ".*/RPM-GPG-KEY-.*$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://download.ceph.com/rpm-reef/
description: Ceph Reef 18
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://download.ceph.com/rpm-squid/
description: Ceph Squid 19
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://download.ceph.com/rpm-tentacle/
description: Ceph Tentacle 20
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
+5
View File
@@ -0,0 +1,5 @@
base_url: "https://downloads.claude.ai/claude-code/rpm/stable"
description: "Claude Code RPM repository"
immutable_patterns:
- ".*/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
+8
View File
@@ -0,0 +1,8 @@
base_url: https://gsl-syd.mm.fcix.net/epel
description: EPEL (Extra Packages for Enterprise Linux)
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*/Everything/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
- "RPM-GPG-KEY-.*$"
+9
View File
@@ -0,0 +1,9 @@
base_url: https://gsl-syd.mm.fcix.net/fedora/linux
description: Fedora Linux RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- "releases/.*/Everything/x86_64/.*\\.rpm$"
- "updates/.*/Everything/x86_64/.*\\.rpm$"
- "development/.*/Everything/x86_64/.*\\.rpm$"
- ".*/noarch/.*\\.rpm$"
+6
View File
@@ -0,0 +1,6 @@
base_url: https://rpm.frrouting.org/repo
description: FRR RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*\\.rpm$"
+7
View File
@@ -0,0 +1,7 @@
base_url: http://mariadb.mirror.digitalpacific.com.au/yum
description: MariaDB RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*\\.rpm$"
- ".*/RPM-GPG-KEY-.*$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://yum.voxpupuli.org
description: OpenVox RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*\\.rpm$"
- "GPG-KEY-.*$"
+8
View File
@@ -0,0 +1,8 @@
base_url: https://download.postgresql.org/pub/repos/yum
description: PostgreSQL RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*\\.rpm$"
- ".*/RPM-GPG-KEY-.*$"
- ".*/PGDG-RPM-GPG-KEY-.*$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://rpm.rancher.io
description: RKE2 RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*\\.rpm$"
- "public.key$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://download1.rpmfusion.org/free
description: RPM Fusion free RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*\\.rpm$"
- "RPM-GPG-KEY-.*$"
+7
View File
@@ -0,0 +1,7 @@
base_url: https://download1.rpmfusion.org/nonfree
description: RPM Fusion nonfree RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*\\.rpm$"
- "RPM-GPG-KEY-.*$"
+6
View File
@@ -0,0 +1,6 @@
base_url: http://download.zfsonlinux.org
description: ZFS RPM package repository
immutable_ttl: 0
mutable_ttl: 7200
immutable_patterns:
- ".*\\.rpm$"
+18
View File
@@ -0,0 +1,18 @@
package_type: helm
description: "Virtual repository merging all helm remotes — member order is priority order for duplicate chart+version"
members:
- authentik
- ceph-csi
- cnpg
- elastic-helm
- external-dns
- grafana
- hashicorp-helm
- intel-helm
- jetstack
- purelb
- rancher-stable
- stakater
- traefik
- victoriametrics
- argo-helm
+5
View File
@@ -0,0 +1,5 @@
package_type: pypi
description: "Virtual PyPI repository merging internal packages and upstream PyPI"
members:
- pypi-internal
- pypi
@@ -0,0 +1,32 @@
include "root" {
path = find_in_parent_folders("root.hcl")
expose = true
}
include "config" {
path = "${get_repo_root()}/config/config.hcl"
expose = true
}
locals {
config = include.config.locals.config
}
terraform {
source = "../../modules/artifactapi"
}
inputs = {
remote_alpine = local.config.remote_alpine
remote_docker = local.config.remote_docker
remote_generic = local.config.remote_generic
remote_goproxy = local.config.remote_goproxy
remote_helm = local.config.remote_helm
remote_pypi = local.config.remote_pypi
remote_rpm = local.config.remote_rpm
local_terraform = local.config.local_terraform
local_pypi = local.config.local_pypi
local_rpm = local.config.local_rpm
local_docker = local.config.local_docker
virtual = local.config.virtual
}
+20
View File
@@ -0,0 +1,20 @@
generate "backend" {
path = "backend.tf"
if_exists = "overwrite"
contents = <<EOF
provider "artifactapi" {
endpoint = "https://${path_relative_to_include()}"
}
terraform {
backend "consul" {
address = "https://consul.service.consul"
path = "infra/terraform/artifactapi/${path_relative_to_include()}/state"
scheme = "https"
lock = true
ca_file = "/etc/pki/tls/certs/ca-bundle.crt"
}
required_version = ">= 1.10"
}
EOF
}
+127
View File
@@ -0,0 +1,127 @@
resource "artifactapi_remote_alpine" "this" {
for_each = var.remote_alpine
name = each.key
base_url = each.value.base_url
description = each.value.description
immutable_ttl = each.value.immutable_ttl
mutable_ttl = each.value.mutable_ttl
immutable_patterns = each.value.immutable_patterns
mutable_patterns = each.value.mutable_patterns
stale_on_error = each.value.stale_on_error
}
resource "artifactapi_remote_docker" "this" {
for_each = var.remote_docker
name = each.key
base_url = each.value.base_url
description = each.value.description
immutable_ttl = each.value.immutable_ttl
mutable_ttl = each.value.mutable_ttl
patterns = each.value.patterns
mutable_patterns = each.value.mutable_patterns
stale_on_error = each.value.stale_on_error
ban_tags_enabled = each.value.ban_tags_enabled
ban_tags = each.value.ban_tags
}
resource "artifactapi_remote_generic" "this" {
for_each = var.remote_generic
name = each.key
base_url = each.value.base_url
description = each.value.description
immutable_ttl = each.value.immutable_ttl
mutable_ttl = each.value.mutable_ttl
patterns = each.value.patterns
mutable_patterns = each.value.mutable_patterns
stale_on_error = each.value.stale_on_error
}
resource "artifactapi_remote_goproxy" "this" {
for_each = var.remote_goproxy
name = each.key
base_url = each.value.base_url
description = each.value.description
immutable_ttl = each.value.immutable_ttl
mutable_ttl = each.value.mutable_ttl
stale_on_error = each.value.stale_on_error
}
resource "artifactapi_remote_helm" "this" {
for_each = var.remote_helm
name = each.key
base_url = each.value.base_url
description = each.value.description
immutable_ttl = each.value.immutable_ttl
mutable_ttl = each.value.mutable_ttl
check_mutable = each.value.check_mutable
immutable_patterns = each.value.immutable_patterns
stale_on_error = each.value.stale_on_error
}
resource "artifactapi_remote_rpm" "this" {
for_each = var.remote_rpm
name = each.key
base_url = each.value.base_url
description = each.value.description
immutable_ttl = each.value.immutable_ttl
mutable_ttl = each.value.mutable_ttl
immutable_patterns = each.value.immutable_patterns
mutable_patterns = each.value.mutable_patterns
stale_on_error = each.value.stale_on_error
}
resource "artifactapi_remote_pypi" "this" {
for_each = var.remote_pypi
name = each.key
base_url = each.value.base_url
description = each.value.description
immutable_ttl = each.value.immutable_ttl
mutable_ttl = each.value.mutable_ttl
patterns = each.value.patterns
mutable_patterns = each.value.mutable_patterns
stale_on_error = each.value.stale_on_error
}
resource "artifactapi_local_terraform" "this" {
for_each = var.local_terraform
name = each.key
description = each.value.description
}
resource "artifactapi_local_pypi" "this" {
for_each = var.local_pypi
name = each.key
description = each.value.description
}
resource "artifactapi_local_rpm" "this" {
for_each = var.local_rpm
name = each.key
description = each.value.description
}
resource "artifactapi_local_docker" "this" {
for_each = var.local_docker
name = each.key
description = each.value.description
}
resource "artifactapi_virtual" "this" {
for_each = var.virtual
name = each.key
package_type = each.value.package_type
description = each.value.description
members = each.value.members
}
+139
View File
@@ -0,0 +1,139 @@
variable "remote_alpine" {
description = "Map of Alpine remote repositories"
type = map(object({
base_url = string
description = optional(string, "")
immutable_ttl = optional(number, 0)
mutable_ttl = optional(number, 7200)
immutable_patterns = optional(list(string), [])
mutable_patterns = optional(list(string), [])
stale_on_error = optional(bool, true)
}))
default = {}
}
variable "remote_docker" {
description = "Map of Docker remote repositories"
type = map(object({
base_url = string
description = optional(string, "")
immutable_ttl = optional(number, 0)
mutable_ttl = optional(number, 300)
patterns = optional(list(string), [])
mutable_patterns = optional(list(string), [])
stale_on_error = optional(bool, true)
ban_tags_enabled = optional(bool, false)
ban_tags = optional(list(string), [])
}))
default = {}
}
variable "remote_generic" {
description = "Map of generic remote repositories"
type = map(object({
base_url = string
description = optional(string, "")
immutable_ttl = optional(number, 0)
mutable_ttl = optional(number, 7200)
patterns = optional(list(string), [])
mutable_patterns = optional(list(string), [])
stale_on_error = optional(bool, true)
}))
default = {}
}
variable "remote_goproxy" {
description = "Map of Go module proxy remote repositories"
type = map(object({
base_url = string
description = optional(string, "")
immutable_ttl = optional(number, 0)
mutable_ttl = optional(number, 300)
stale_on_error = optional(bool, true)
}))
default = {}
}
variable "remote_helm" {
description = "Map of Helm chart remote repositories"
type = map(object({
base_url = string
description = optional(string, "")
immutable_ttl = optional(number, 0)
mutable_ttl = optional(number, 3600)
check_mutable = optional(bool, true)
immutable_patterns = optional(list(string), [])
stale_on_error = optional(bool, true)
}))
default = {}
}
variable "remote_rpm" {
description = "Map of RPM remote repositories"
type = map(object({
base_url = string
description = optional(string, "")
immutable_ttl = optional(number, 0)
mutable_ttl = optional(number, 7200)
immutable_patterns = optional(list(string), [])
mutable_patterns = optional(list(string), [])
stale_on_error = optional(bool, true)
}))
default = {}
}
variable "remote_pypi" {
description = "Map of PyPI remote repositories"
type = map(object({
base_url = string
description = optional(string, "")
immutable_ttl = optional(number, 0)
mutable_ttl = optional(number, 3600)
patterns = optional(list(string), [])
mutable_patterns = optional(list(string), [])
stale_on_error = optional(bool, true)
}))
default = {}
}
variable "local_pypi" {
description = "Map of local PyPI repositories"
type = map(object({
description = optional(string, "")
}))
default = {}
}
variable "local_rpm" {
description = "Map of local RPM repositories"
type = map(object({
description = optional(string, "")
}))
default = {}
}
variable "local_terraform" {
description = "Map of local Terraform repositories"
type = map(object({
description = optional(string, "")
}))
default = {}
}
variable "local_docker" {
description = "Map of local Docker repositories (real container registries)"
type = map(object({
description = optional(string, "")
}))
default = {}
}
variable "virtual" {
description = "Map of virtual repositories"
type = map(object({
package_type = string
description = optional(string, "")
members = list(string)
}))
default = {}
}
+9
View File
@@ -0,0 +1,9 @@
terraform {
required_version = ">= 1.10"
required_providers {
artifactapi = {
source = "artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/artifactapi"
version = "0.1.3"
}
}
}