Go Private Module

Sooner or later as a Go developer, you will need to build a module for reusing common code across the applications. If your module is public, that's quite straight forward, just create a public repository in GitHub or GitLab, make sure go.mod is defined correctly and you're ready. But if your module is private, there are some steps that need to be done so that Go Module works correctly. This post is all about initializing and setting up a private Go module.

Init Module With Git Full Qualify Domain Name #

Normally you should name your module to match with where your repository is located in your Git server.

If your your code located at: https://gitlab.mycompany.com/my-module, your go.mod should be:

module gitlab.mycompany.com/my-module

go 1.21.0

Since your module name already included Git full qualify domain name, Go Module know exactly where to download your module, hence you can use the module name directly in other modules:

module my-application

go 1.21.0

require gitlab.mycompany.com/my-module v0.0.1

Init Module With Custom Name #

If for some reasons, you don't want to include the full qualify domain name in your module name, you can define your module as below:

module my-module

go 1.21.0

And to use it, you need to tell Go Module where to download your module. One of the solution is using replace directive:

module my-application

go 1.21.0

require my-module v0.0.1

replace my-module => gitlab.mycompany.com/my-module v0.0.1

And if during the development, you want to use local/unpublished code of my-module right away in other module for testing, you can also use the replace directive to point directly to where the module is located:

module my-application

go 1.21.0

require my-module v0.0.1

replace my-module => ../relative/or/absolute/path/to/my-module

Local Development #

To build the code locally, the first step is to tell Go Module that your module is private so that it doesn't use its proxy or checksum database against your module.

This can be done by using the GOPRIVATE environment variable. And if your company Git server doesn't use certified certificates, you might consider to use GOINSECURE to ignore certificates verification issues while downloading the module:

go env -w GOPRIVATE=gitlab.mycompany.com/*
go env -w GOINSECURE=gitlab.mycompany.com/*

Go Module uses Git under the hood. Hence you need to set up your Git client to allow downloading your module without prompting for username/password. This can be done by set an environment variable named NETRC or a file .netrc at your home directory:

machine <url> login <username> password <token>

After finishing this step, you're ready to go get your private module

CI/CD #

You can apply the same steps of local development to the CI/CD pipeline. Below is an example of using GitLab CI:

variables:
GOPRIVATE: gitlab.mycompany.com/*
GOINSECURE: gitlab.mycompany.com/*

build:
image:
name: golang:1.21.0
pull_policy: if-not-present
before_script:
- printf "machine gitlab.mycompany.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc
script:
- go build ./...

And now your pipeline is ready to download your private module.