- HCL 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Forgejo cannot serve this repo as an OpenTofu network_mirror. The protocol requires the index JSON be returned as application/json; Forgejo serves every raw file as text/plain on /raw, /media and the API endpoint alike, as an XSS precaution, and it is not per-file configurable. tofu init fails with 'response has invalid Content-Type'. Measured against Forgejo 16.0.1, not assumed. A clone plus filesystem_mirror gets the same result with no reverse proxy in front, and without making every init depend on git.grey.ooo being up. Records the trap that cost the most time: an unfiltered filesystem_mirror alongside an unfiltered direct does NOT act as a catch-all. direct wins, and every provider is fetched from the registry as though no mirror were configured. With explicit include lists on both, all four consuming roots resolve offline. |
||
| .github/workflows | ||
| registry.opentofu.org | ||
| registry.terraform.io/arsolitt/garagehq | ||
| .gitignore | ||
| .terraform.lock.hcl | ||
| providers.tf | ||
| README.md | ||
tofu-providers
An OpenTofu network mirror, served straight out of this repo's raw file URLs.
providers.tf pins the versions; CI runs tofu providers mirror and commits the
archives in the layout the protocol expects. No extra software hosts it — the
protocol is plain GETs for JSON and zips, and tofu providers mirror emits
relative archive URLs, which is what makes the tree portable to any base URL.
Using it — clone it, do not point a network_mirror at it
Forgejo cannot serve this as a network_mirror. The protocol requires the index
JSON be returned as application/json; Forgejo serves every raw file as
text/plain; charset=utf-8 — on /raw, /media and the API endpoint alike — as an
XSS precaution, and it is not per-file configurable. tofu init fails with "response
has invalid Content-Type: must be application/json". Measured against Forgejo 16.0.1.
Clone it and use a filesystem_mirror instead. Same result, no reverse proxy, and no
dependency on git.grey.ooo at init time:
provider_installation {
filesystem_mirror {
path = "/abs/path/to/this/clone"
include = [
"registry.terraform.io/arsolitt/*",
"registry.opentofu.org/kreuzwerker/*",
"registry.opentofu.org/hashicorp/*",
"registry.opentofu.org/bpg/*",
]
}
direct { exclude = [ ...the same four... ] }
}
The include list is required, not tidiness. An unfiltered filesystem_mirror
alongside an unfiltered direct does not act as a catch-all — direct wins and
every provider is fetched from the registry as though the mirror were not configured.
Adding a namespace means adding it in both lists.
Paths in filesystem_mirror resolve against the working directory, not the config
file, so it must be absolute.
What this is not
Not the source. The upstream repositories are pull-mirrored separately, as
mirrors/Arsolitt-terraform-provider-garagehq and
mirrors/kreuzwerker-terraform-provider-docker. Those protect against the upstream
repo disappearing; this protects against the registry being unreachable. Different
risks, different mirrors — one does not substitute for the other.
The trade being made
Every tofu init that uses this depends on git.grey.ooo being up — including the one
you run while trying to fix git.grey.ooo. A local filesystem mirror has no such
circularity, so consumers should keep one configured ahead of this in
provider_installation and treat this as the shared, always-current copy.
Pinning is the point
A mirror that tracks "latest" is a slower registry, not a mirror. Versions move only
when providers.tf is edited, and the CI commit records what changed.