Hosting Private Go Modules on GitLab

February 10, 2021
go gitlab

There are a few hoops to jump through to host private go modules on GitLab. Firstly, we have to include .git in the module path, otherwise go get has trouble finding a repository in a nested subgroup.

For example, say we have a repository hosted at; to create a go module in this repository, we need to do:

go mod init

In the consumer, we need to import it as:

import ""

To consume a subpackage in the module, we simply do:

import ""

Secondly, we have to define the GOPRIVATE environment variable to prevent go get from trying to download the module from a public proxy:


Finally, we need to configure authentication. For local development, create a personal access token with read_repository permission, and add the following to ~/.netrc:

login oauth2
password ${TOKEN}

We can now run go get to fetch modules from our private repositories.

For GitLab CI/CD, every job has an automatic variable called $CI_JOB_TOKEN that we can write to a .netrc file in a before_script. Here’s a minimal working .gitlab-ci.yml:


  image: golang:1.15-buster
    - echo -e "machine\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc
    - go build ./...

Note: if you define a group-level GOPRIVATE variable in GitLab there is no need to include the variable in the CI config.

Go Concurrency

Go mutex vs atomic increment.

Solving Sudoku Puzzles with Go

A tutorial I delivered to Cambridge Gophers
go tutorial