The module proxy protocol, complete
OrbitalReg answers the GOPROXY protocol the go command speaks: @v/list, @latest, and .info, .mod and .zip per version. go get, go mod download and go build work against it with no plugins and no wrapper scripts.
Registry formats · Go modules
Publish your internal modules, cache proxy.golang.org, and resolve both
through a single GOPROXY.
OrbitalReg relays sum.golang.org so checksum verification works behind a
firewall, holds brand-new upstream releases back until they have aged,
and checks module files against your blocks and policies before a build
sees them, in the same registry as your images, npm, PyPI and Maven
packages.
Three environment variables
Every repository lives at
/go/<project>/<repo>.
Point GOPROXY at a
virtual repo that federates your published modules with a cached
proxy.golang.org, and leave it at that one URL.
A trailing ,direct or
,https://proxy.golang.org
looks harmless, but it lets the go command walk around the registry
whenever a module is missing or refused, and everything the registry
enforces goes with it.
# one proxy for internal and public modules
$ go env -w GOPROXY=https://registry.example.com/go/acme/all-go
# checksums: sum.golang.org, relayed by the registry
$ go env -w GOSUMDB=sum.golang.org
# your own module paths are not in the public checksum database
$ go env -w GONOSUMDB=git.example.com/*
# credentials for the registry host
$ cat ~/.netrc
machine registry.example.com login ci password $ORBITALREG_TOKEN # not this: the fallback skips every check the registry makes
GOPROXY=https://registry.example.com/go/acme/all-go,direct Release-hold
A compromised maintainer account or a poisoned tag is usually caught within hours. Release-hold makes sure your builds aren't the ones that find out first: upstream versions younger than the hold are refused, measured from the time proxy.golang.org reports for the version, not from when you cached it.
Held versions drop out of @v/list,
and @latest points at the
newest released version, so ordinary upgrades keep working. A go.mod
that pins a held version gets a 403 with the reason and a
Retry-After, never a silent substitute. Your own published modules
are never held.
# upstream: v1.8.0 published 2 hours ago, hold 24 h
GET /go/acme/all-go/example.com/lib/@v/list
v1.7.2
v1.7.3
(v1.8.0 held)
GET /go/acme/all-go/example.com/lib/@latest
{"Version":"v1.7.3", …} # a go.mod that already pins the new version
GET /go/acme/all-go/example.com/lib/@v/v1.8.0.zip
HTTP/1.1 403
X-Orbital-PullGate-Decision: block
Retry-After: 79200 What you get
OrbitalReg answers the GOPROXY protocol the go command speaks: @v/list, @latest, and .info, .mod and .zip per version. go get, go mod download and go build work against it with no plugins and no wrapper scripts.
A virtual repo federates your published modules with a cached proxy.golang.org. If a module path has versions in a local repo, upstream versions are never mixed in, so nobody can take over your module path by publishing a higher version upstream.
A remote repo fetches a module version from proxy.golang.org the first time it is asked for and serves it locally after that. Module versions are immutable, so every later build gets the cached copy, served locally even when the upstream is slow or unreachable.
Upstream module files are checked before they are served: security blocks by path or exact SHA-256 and the optional pull-gate, including your own Rego rules. A blocked module is never served to the build.
Versions younger than N hours are refused, measured from the time in the upstream .info. Held versions drop out of @v/list and @latest points at the newest released version, so go get pkg@latest keeps working. New installs start with a 24-hour hold.
Behind a firewall, go mod download often fails only because the client can't reach sum.golang.org. OrbitalReg answers the GOPROXY sumdb probe and relays checksum-database lookups to sum.golang.org, and only there, so client machines need no outbound access.
Upload a version's .info, .mod and .zip with a PUT to the same paths the go command reads. Builds then resolve your internal modules by version from the registry instead of cloning from the Git host on every CI run.
Upstream module fetches and the sumdb relay are separate egress channels, both off on a fresh install. Allow them per remote repository when you want them; a disconnected site keeps serving whatever is already cached and published.
Why not a Go-only proxy
Athens and similar proxies are good at one job: caching Go modules. A Go service rarely ships as just a module, though. It is built into a container image from a base image, deployed by a Helm chart, often next to a frontend with its own npm dependencies. In OrbitalReg the Go adapter is one GA format among 40+, so all of those share one set of projects and roles, one blocklist, one pull-gate and one append-only audit log.
See the container registry and Helm chart repository pages for the rest of that path, the dependency confusion case study for why one URL matters, and the pricing page for what is free.
Questions
Set GOPROXY to a virtual repository: GOPROXY=https://<host>/go/<project>/<repo>. Use only that URL. Appending ,https://proxy.golang.org or ,direct lets the go command go around the registry when a module is missing or blocked, which skips release-hold, blocks and the pull-gate.
For modules you publish to OrbitalReg, use GONOSUMDB with your module path pattern. sum.golang.org can't know your private versions, so they must be excluded from the checksum database, but they should still be fetched through GOPROXY. GOPRIVATE would also set GONOPROXY and send the go command straight to your Git host.
Yes, once the sumdb egress channel is allowed: OrbitalReg answers the go command's sumdb probe and relays lookups to sum.golang.org, so only the registry needs outbound access. In a fully disconnected install, set GOSUMDB=off or GONOSUMDB for the affected paths on the clients instead.
The held version disappears from @v/list and @latest, so a go get without a version picks the previous release. A go.mod that pins the held version gets a 403 with a Retry-After header and the reason, never a different version. Admins can approve a single held release early when it is needed.
For caching proxy.golang.org and serving private modules, yes. Athens is a solid, Go-only module proxy. OrbitalReg adds release-hold, security blocks and the pull-gate on the same path, and keeps Go modules next to your container images, npm, PyPI and Maven packages under one set of projects, roles and audit log.
Build the module zip as the go command expects it (golang.org/x/mod/zip), then PUT the .info, .mod and .zip to <module>/@v/<version>.<ext> in a local repository with a token that has the developer role. The version must be valid semver; once published, it resolves like any other module version.
Documentation: Go modules reference · pull-gate and release-hold · air-gapped operations and sumdb · format support matrix
Free forever · no contract
One Helm chart, one Go binary, Postgres and S3-compatible storage. Release-hold, security blocks, the sumdb relay and the pull-gate are part of the free version.