Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consider setting up a fallback mechanism to serve existing versions of Go modules in case of provider outage #38

dmitshur opened this issue Feb 13, 2020 · 1 comment


Copy link

@dmitshur dmitshur commented Feb 13, 2020

If the server that is hosting the website is unavailable due to an outage of its current server provider (as has happened recently in #37), it may be worth considering a fallback plan.

It can be a quick-to-start second instance, or perhaps a more static page that makes use of the Go module versions already cached by and serving those instead.

This is the tracking issue to investigate and implement this.

Note that as more and more people update to Go 1.13 or newer, which uses by default, the benefit from doing this will diminish.


This comment has been minimized.

Copy link
Member Author

@dmitshur dmitshur commented Feb 18, 2020

or perhaps a more static page that makes use of the Go module versions already cached by and serving those instead.

I've tested out the following simple approach locally (by adding a→ override to /etc/hosts and using @FiloSottile's mkcert to serve the replacement site over https), and confirmed that it would work as I expected:

// Play with a fallback solution for serving modules,
// when the main server is completely unavailable.
// The fallback solution is to host a very simple site that just temporarily
// points to the modules that have already been mirrored by
package main

import (


func main() {
	err := run()
	if err != nil {

func run() error {
	h := httputil.ErrorHandler(nil, func(w http.ResponseWriter, req *http.Request) error {
		if req.URL.RawQuery != "go-get=1" {
			return os.ErrNotExist
		if err := httputil.AllowMethods(req, http.MethodGet); err != nil {
			return err
		w.Header().Set("Content-Type", "text/plain; charset=utf-8")
		err := html.Render(w, &html.Node{
			Type: html.ElementNode, Data: "meta",
			Attr: []html.Attribute{
				{Key: "name", Val: "go-import"},
				{Key: "content", Val: (&url.URL{Path: "" + req.URL.Path}).String() +
					" mod"},
		return err
	return http.ListenAndServeTLS(":https", "", "", h)

It's not quite static because it needs to serve multiple paths corresponding to package import paths, not just the root. But still very simple and doesn't need knowledge of what packages/modules exist or not. It just redirects everything, and the module mirror serves only the modules that do exist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.