River Pro is distributed as a private Go module via a private Go proxy. This page describes how to configure it for an existing Go project, along with recommendations for managing GOPROXY
/GONOSUMDB
environment variables.
Go proxies and checksum databases
All Go modules are distributed via a module proxy. When running a Go command like go build
or go get
, Go's toolchain communicates to proxies controlled by the GOPROXY
environment variable. Its default value is:
GOPROXY="https://proxy.golang.org,direct"
proxy.golang.org
is the main Go module proxy, run by Google. Its placement as a default provides benefits for security and availability. In case of an offline third party code repository, Google's proxy is very likely to still be up, and can return a cached version of any third party module being requested so that builds don't fail.
Go proxies are augmented by a checksum database, normally served by Google from sum.golang.org
. The database persists an immutable checksum for known Go modules which Go's toolchain can compare against fetched modules to verify that they haven't been tampered with, even if the modules came in by way of a third party Go proxy.
Private modules like River Pro are not publicly available to other Go module proxies and therefore cannot appear in the checksum database. For this reason, private modules prefixes must be added to the GONOSUMDB
environment variable to prevent Go from attempting to verify checksums for them.
Fetching River Pro modules
River Pro is distributed via a private Go proxy hosted at riverqueue.com/goproxy
. It requires a customer-specific private credential obtained during the Pro subscription process that looks like river_secret_<secret>
.
export RIVER_PRO_SECRET=river_secret_...
export GOPROXY=https://proxy.golang.org,https://river:$RIVER_PRO_SECRET@riverqueue.com/goproxy,direct
export GONOSUMDB=riverqueue.com/riverpro,$GONOSUMDB
go get riverqueue.com/riverpro
go get riverqueue.com/riverpro/driver/riverpropgxv5
# install riverpro CLI:
go install riverqueue.com/riverpro/cmd/riverpro@latest
Assuming everything worked, Go will have updated the project's go.mod
and go.sum
files with new entries for River Pro.
Notably, the recommendation for GOPROXY
above installs River's module proxy as second priority after proxy.golang.org
. Module fetches will prefer Google's main proxy and only fall back to River's for modules that couldn't be found.
See also installing in CI and build environments.
Sustainably managing Go environment
Storing secrets in .netrc
The instructions above recommended a value for GOPROXY
like:
GOPROXY=https://proxy.golang.org,https://river:$RIVER_PRO_SECRET@riverqueue.com/goproxy,direct
This requires the presence of the RIVER_PRO_SECRET
in the environment. Keeping secrets in a shell environment is generally undesirable because there needs to be a mechanism for the secret to get there in the first place, and there's a higher likelihood that it can accidentally leak.
Go supports configuring proxy credentials in a ~/.netrc
file, a standard supported by other tools like cURL and Git. Add an entry containing a River secret like the following:
machine riverqueue.com
login river
password river_secret_...
This makes it possible to use GOPROXY
without an inline key:
export GOPROXY=https://proxy.golang.org,https://riverqueue.com/goproxy,direct
export GONOSUMDB=riverqueue.com/riverpro,$GONOSUMDB
go get riverqueue.com/riverpro
go get riverqueue.com/riverpro/driver/riverpropgxv5
Setting variables with go env
GOPROXY
and GONOSUMDB
are normal environment variables, and can be configured in a shell env/RC file like ~/.zshenv
or ~/.zshrc
.
Another option is to use the Go toolchain's built-in go env
for managing variables that'll be scoped specifically to Go commands.
go env -w GOPROXY=https://proxy.golang.org,https://riverqueue.com/goproxy,direct
go env -w GONOSUMDB=riverqueue.com/riverpro
# or, with a secret inline instead of being read from `~/.netrc`
go env -w GOPROXY=https://proxy.golang.org,https://river:river_secret_...@riverqueue.com/goproxy,direct
go get riverqueue.com/riverpro
go get riverqueue.com/riverpro/driver/riverpropgxv5
A River secret is still required, and may be configured in ~/.netrc
above, or set directly as a static string with go env -w GOPROXY=
.
`go env` configuration is global
Setting configuration with go env -w
will set environment variables for all go
invocations, including where it's invoked in projects. Custom configuration is stored to the file returned by go env GOENV
.
Using direnv for project-specific configuration
Setting GOPROXY
/GONOSUMDB
to either a shell RC file or with go env -w
has a less-than-optimal side effect of making the new configuration global across all your Go projects. This isn't harmful, but this sort of configuration leakage is generally not considered best practice.
Projects can avoid this by using a tool like direnv to manage project-specific environment variables:
# contents of `~/.envrc` is a project directory
export GOPROXY=https://proxy.golang.org,https://riverqueue.com/goproxy,direct
export GONOSUMDB=riverqueue.com/riverpro,$GONOSUMDB
# or, with secret inline instead of being read from `~/.netrc`
export GOPROXY=https://proxy.golang.org,https://river:river_secret_...@riverqueue.com/goproxy,direct
This approach has the downside that all developers will need to have direnv installed for it to work, but the upside that especially when using a private Git repository, an .envrc
file can be checked in to enable configuration-free Go builds that need only a git clone ... && cd ... && go build
.
Installing in CI and build environments
GitHub Actions
If you're using River Pro, you will also need it to be available in a CI environment like GitHub Actions so it can run a test suite that uses features specific to River Pro. This can be accomplished by adding a Pro key as a GitHub repository secret, then observing the usual GOPROXY
/GONOSUMDB
environment variables:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "stable"
check-latest: true
- name: Install River Pro CLI
run: go install riverqueue.com/riverpro/cmd/riverpro@latest
env:
GOPROXY: https://proxy.golang.org,https://river:${{ secrets.RIVER_PRO_SECRET }}@riverqueue.com/goproxy,direct
GONOSUMDB: riverqueue.com/riverpro
- name: Migrate River
run: |
riverpro migrate-up --database-url "$DATABASE_URL"
riverpro migrate-up --database-url "$DATABASE_URL" --line workflow
- name: Go test
run: go test ./...
env:
GOPROXY: https://proxy.golang.org,https://river:${{ secrets.RIVER_PRO_SECRET }}@riverqueue.com/goproxy,direct
GONOSUMDB: riverqueue.com/riverpro
Docker
In order to deploy a River Pro app, you may need to build it within a Docker image. Using River's module proxy in a Dockerfile is typically done by mounting a secret into the container:
COPY go.mod go.sum ./
RUN \
sh -c 'GOPROXY=https://proxy.golang.org,https://river:$(cat /etc/secrets/river_pro_secret)@riverqueue.com/goproxy,direct \
go mod download'
When building the Docker image, you'll need to pass the secret to the build command with a source such as env
or file
:
docker build --secret id=river_pro_secret,env=RIVER_PRO_SECRET ...