Own domains for Go code

As you know I host my Go projects at GitHub. So the import path for the Tideland Go packages also contains github.com as a part. But GitHub has been bought by Microsoft a few weeks ago. Soon I realized I want to be more flexible in the future. But I still want to use the platform GitHub as it is powerful and well known, especially in the world of open-source.

Remote Import Paths

Thankfully the Go tools also allow to define remote import paths. It allows to provide URLs in the web leading to repositories located at other URLs. So my goal has been the special domain tideland.one with import paths like tideland.one/goaudit/asserts for the according package located in the repository at https://github.com/tideland/goaudit/. Little second goal has been that in case of somebody opening the URL with the browser it should be redirected to the repository landing page at GitHub.

Now Go 1.11 with its initial support of modules has been the kick-off for me to start this project. I run a server for my web sites and some other services too. All these services are inside of Docker containers, mostly behind the NGINX proxy container by Jason Wilder. So I created a little NGINX based container with directories and index.html files for each module. You’ll find it at as an example at GitHub. This way the Go tool as well as browsers are happy.

The content of each index.html is not very large.

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="tideland.one/goaudit git https://github.com/tideland/goaudit"/>
<meta http-equiv="refresh" content="0; url=https://github.com/tideland/goaudit"/>
<p>Redirecting to Tideland GoAudit, please wait ...</p>

The interesting part for the remote import paths is the meta tag with the name go-import. Here the content contains the import prefix of the modules from the perspective of the importing Go program. In my example here tideland.one/goaudit for all packages imported as tideland.one/goaudit/<package>. Second part is the version control system, here git, others are bzr, fossil, hg, or svn. Third and final part is the root of the version control system and in my case leads to the location at GitHub. And this is the benefit, when e.g. moving from GitHub to GitLab or an own Gitea or Gogs installation. In all cases the users import path stays the same, in this example tideland.on/goaudit.

Another meta tag is the http-equiv="refresh". That’s the one for the redirection of browsers to the GitHub page of that repository, where the README.md with more information is displayed. The text of the index.html is only for the short time while the browser redirects. Alternatively you surely can present the information about your module here directly.

Deploying that container after configuring the domain worked fine for browsers. But sadly there has been one problem with Go. It requires—for good reason—the usage of HTTS. Thankfully there’s Let’s Encrypt providing a free and open Certificate Authority. And also thankfully there’s the Let’s Encrypt NGINX proxy companion container by Yves Blusseau. It’s wonderfully cooperating with the NGINX proxy container mentioned above. So it fulfilled this requirement too.

But still the tests didn’t worked. When trying a go get it complains different domains for certificate and code. Something for me so far not known has been the missing Certification Authority Authorization (CAA) record in the DNS. I had quickly to check how to enter it at my DNS provider. The entry now is

tideland.one.   CAA 0 issue "letsencrypt.org"

After adding this entry the go get worked.


Second half of the whole activity has been the change of the code to modules. The reason for starting with Tideland GoAudit is that it has no dependencies. So the changes of the code as well as the documentation has been pretty small. But for a clean start I had to remove all releases and tags on GitHub. Also negative is, that the link to GoDoc does not work with remote import paths. Here the result sadly is inconsistent.

Now I’m continuing adding the next packages one by one. Removing tags on GitHub, fixing code and imports, and call e.g.

$ go mod init tideland.one/gotogether
$ go mod tidy

Then only adding go.mod and go.sum to the repository, commit, and push. Done.


One little hint which makes it simple for my. So far I only provide only modules with different packages for one topic. Testing, concurrency, data structures, RESTful applications, and more. And all of these depend on no external packages or only others that I provide too. Surely existing dependencies to other external modules/projects will lead to more troubles.