# Go

SlowShield serves Go modules at `https://slowshield.example.com/go` as a `GOPROXY`, and passes the checksum database (sum.golang.org) through, so the go command needs no other route out.

## Set it up

### Go

*command (writes go env)*

```
go env -w GOPROXY=https://slowshield.example.com/go
```

*private modules: fetched directly, not through SlowShield*

```
go env -w GOPRIVATE=git.example.com/*
```

Or the `GOPROXY` line in your shell profile, with the other package managers (the Setup page has bash on macOS, zsh and fish too):

```
cat >> ~/.bashrc <<'EOF'
export PIP_INDEX_URL=https://slowshield.example.com/pypi/simple/
export UV_DEFAULT_INDEX=https://slowshield.example.com/pypi/simple/
export npm_config_registry=https://slowshield.example.com/npm/
export GOPROXY=https://slowshield.example.com/go
export PIP_UPLOADED_PRIOR_TO=P3D
export npm_config_min_release_age=3
EOF
source ~/.bashrc
```

- **No `,direct` and no `|`.** With `,direct`, the go command fetches from the origin whenever the proxy answers 404 or 410; with `|`, on any error. SlowShield never answers a refusal with 404 or 410, but a module it can't find would still go around it.

- **`GOSUMDB` stays at its default.** SlowShield answers `/go/sumdb/sum.golang.org/supported`, so the go command sends its checksum-database requests through SlowShield too.

- **Private modules** keep bypassing the proxy through `GOPRIVATE`.

## What changes

- **The publish time** is when proxy.golang.org first stored the version (the `Last-Modified` of its `.mod`). The commit time in `.info` is set by the author and can be backdated, so it is never used.

- **`go get pkg@latest`** and version queries pick the newest version that is old enough: newer ones are left out of `@v/list` and `@latest`.

- **go.mod pins exact versions.** A requirement that is too new fails with `403` instead of picking an older version. The go command prints SlowShield's message:
   ```
   go: example.com/hello@v1.2.0: reading https://slowshield.example.com/go/example.com/hello/@v/v1.2.0.info: 403 Forbidden
   	server response:
   	slowshield: example.com/hello@v1.2.0 is too new.
   	It was published 2026-10-03T08:21:51Z (2.0 days ago); this proxy requires 7 days.
   	It becomes available at 2026-10-10T08:21:51Z.
   	Use an older version, or ask your SlowShield administrator for an exception.
   ```

- **Malware and tampering** are refused with `451`. Every `.mod` and `.zip` is checked against the checksum database and the fingerprint SlowShield recorded the first time, which also protects builds that set `GOSUMDB=off`.

## The second layer

The go command has no release-age setting, so SlowShield is the only layer.

## In Docker and CI

```
FROM golang:1.25 AS build
ARG GOPROXY=https://slowshield.example.com/go
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app .
```

The official images don't set `GOPROXY`, so the `ARG` is what the go command uses. [Building images](https://slowshield.org/docs/container-builds/) covers the base image too, and how to check that nothing in a build goes around SlowShield.

## Limits

- Toolchain downloads (`GOTOOLCHAIN` switching to a newer Go) are modules too, so they come through SlowShield like any other.

- Block proxy.golang.org and sum.golang.org at the firewall for machines that should only use SlowShield.

---

This page as HTML: https://slowshield.org/docs/go/. All of the guide in one file: https://slowshield.org/llms-full.txt
