distribution/cmd/registry/main.go
Stephen J Day 9f5916b2c4 Add native TLS support to registry
This changeset provides simple tls support for a registry instance. Simply
providing a cert and key file are enough to get a tls registry running. If the
certs are trusted by the client, tls can be used throughout the push and pull
process.

If more complex TLS options are required, it is recommend that a proxy be used.
Contributions will be accepted to add more features, if necessary.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2015-02-02 14:38:47 -08:00

144 lines
3.5 KiB
Go

package main
import (
"flag"
"fmt"
"net/http"
_ "net/http/pprof"
"os"
log "github.com/Sirupsen/logrus"
"github.com/bugsnag/bugsnag-go"
"github.com/gorilla/handlers"
"github.com/yvasiyarov/gorelic"
_ "github.com/docker/distribution/auth/silly"
_ "github.com/docker/distribution/auth/token"
"github.com/docker/distribution/configuration"
"github.com/docker/distribution/registry"
_ "github.com/docker/distribution/storagedriver/filesystem"
_ "github.com/docker/distribution/storagedriver/inmemory"
_ "github.com/docker/distribution/storagedriver/s3"
"github.com/docker/distribution/version"
)
var showVersion bool
func init() {
flag.BoolVar(&showVersion, "version", false, "show the version and exit")
}
func main() {
flag.Usage = usage
flag.Parse()
if showVersion {
version.PrintVersion()
return
}
config, err := resolveConfiguration()
if err != nil {
fatalf("configuration error: %v", err)
}
app := registry.NewApp(*config)
handler := configureReporting(app)
handler = handlers.CombinedLoggingHandler(os.Stdout, handler)
log.SetLevel(logLevel(config.Loglevel))
if config.HTTP.TLS.Certificate == "" {
log.Infof("listening on %v", config.HTTP.Addr)
if err := http.ListenAndServe(config.HTTP.Addr, handler); err != nil {
log.Fatalln(err)
}
} else {
log.Infof("listening on %v, tls", config.HTTP.Addr)
if err := http.ListenAndServeTLS(config.HTTP.Addr, config.HTTP.TLS.Certificate, config.HTTP.TLS.Key, handler); err != nil {
log.Fatalln(err)
}
}
}
func usage() {
fmt.Fprintln(os.Stderr, "usage:", os.Args[0], "<config>")
flag.PrintDefaults()
}
func fatalf(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, format+"\n", args...)
usage()
os.Exit(1)
}
func resolveConfiguration() (*configuration.Configuration, error) {
var configurationPath string
if flag.NArg() > 0 {
configurationPath = flag.Arg(0)
} else if os.Getenv("REGISTRY_CONFIGURATION_PATH") != "" {
configurationPath = os.Getenv("REGISTRY_CONFIGURATION_PATH")
}
if configurationPath == "" {
return nil, fmt.Errorf("configuration path unspecified")
}
fp, err := os.Open(configurationPath)
if err != nil {
return nil, err
}
config, err := configuration.Parse(fp)
if err != nil {
return nil, fmt.Errorf("error parsing %s: %v", configurationPath, err)
}
return config, nil
}
func logLevel(level configuration.Loglevel) log.Level {
l, err := log.ParseLevel(string(level))
if err != nil {
log.Warnf("error parsing level %q: %v", level, err)
l = log.InfoLevel
}
return l
}
func configureReporting(app *registry.App) http.Handler {
var handler http.Handler = app
if app.Config.Reporting.Bugsnag.APIKey != "" {
bugsnagConfig := bugsnag.Configuration{
APIKey: app.Config.Reporting.Bugsnag.APIKey,
// TODO(brianbland): provide the registry version here
// AppVersion: "2.0",
}
if app.Config.Reporting.Bugsnag.ReleaseStage != "" {
bugsnagConfig.ReleaseStage = app.Config.Reporting.Bugsnag.ReleaseStage
}
if app.Config.Reporting.Bugsnag.Endpoint != "" {
bugsnagConfig.Endpoint = app.Config.Reporting.Bugsnag.Endpoint
}
bugsnag.Configure(bugsnagConfig)
handler = bugsnag.Handler(handler)
}
if app.Config.Reporting.NewRelic.LicenseKey != "" {
agent := gorelic.NewAgent()
agent.NewrelicLicense = app.Config.Reporting.NewRelic.LicenseKey
if app.Config.Reporting.NewRelic.Name != "" {
agent.NewrelicName = app.Config.Reporting.NewRelic.Name
}
agent.CollectHTTPStat = true
agent.Verbose = true
agent.Run()
handler = agent.WrapHTTPHandler(handler)
}
return handler
}