// Copyright (c) 2013 CloudFlare, Inc. package main import ( "flag" "fmt" "log" "net" "net/http" "os" "strings" "github.com/cloudflare/redoctober/config" "github.com/cloudflare/redoctober/core" "github.com/cloudflare/redoctober/report" "github.com/cloudflare/redoctober/server" "github.com/prometheus/client_golang/prometheus/promhttp" ) // initPrometheus starts a goroutine with a Prometheus listener that // listens on localhost:metricsPort. If the Prometheus handler can't // be started, a log.Fatal call is made. func initPrometheus() { srv := &http.Server{ Addr: net.JoinHostPort(cfg.Metrics.Host, cfg.Metrics.Port), Handler: promhttp.Handler(), } log.Printf("metrics.init start: addr=%s", srv.Addr) go func() { err := srv.ListenAndServe() report.Check(err, nil) log.Fatal(err.Error()) }() } const usage = `Usage: redoctober -static -vaultpath -addr -certs [,,...] -keys [,,...] [-ca ] single-cert example: redoctober -vaultpath diskrecord.json -addr localhost:8080 -certs cert.pem -keys cert.key multi-cert example: redoctober -vaultpath diskrecord.json -addr localhost:8080 -certs cert1.pem,cert2.pem -keys cert1.key,cert2.key ` var ( cfg, cli *config.Config confFile string vaultPath string ) const ( defaultAddr = "localhost:8080" defaultMetricsHost = "localhost" defaultMetricsPort = "8081" ) func registerCli() { // cli contains the configuration set by the command line // options, and cfg is the actual Red October config. cli = config.New() cfg = config.New() // customized the default index html with auto generated content server.DefaultIndexHTML = indexHTML cli.Server.Addr = defaultAddr cli.Metrics.Host = defaultMetricsHost cli.Metrics.Port = defaultMetricsPort flag.Usage = func() { fmt.Fprint(os.Stderr, "main usage dump\n") fmt.Fprint(os.Stderr, usage) flag.PrintDefaults() os.Exit(2) } flag.StringVar(&confFile, "f", "", "path to config file") flag.StringVar(&cli.Server.Addr, "addr", cli.Server.Addr, "Server and port separated by :") flag.StringVar(&cli.Server.CAPath, "ca", cli.Server.CAPath, "Path of TLS CA for client authentication (optional)") flag.StringVar(&cli.Server.CertPaths, "certs", cli.Server.CertPaths, "Path(s) of TLS certificate in PEM format, comma-separated") flag.StringVar(&cli.HipChat.Host, "hchost", cli.HipChat.Host, "Hipchat Url Base (ex: hipchat.com)") flag.StringVar(&cli.HipChat.APIKey, "hckey", cli.HipChat.APIKey, "Hipchat API Key") flag.StringVar(&cli.HipChat.Room, "hcroom", cli.HipChat.Room, "Hipchat Room ID") flag.StringVar(&cli.Server.KeyPaths, "keys", cli.Server.KeyPaths, "Comma-separated list of PEM-encoded TLS private keys in the same order as certs") flag.StringVar(&cli.Metrics.Host, "metrics-host", cli.Metrics.Host, "The `host` the metrics endpoint should listen on.") flag.StringVar(&cli.Metrics.Port, "metrics-port", cli.Metrics.Port, "The `port` the metrics endpoint should listen on.") flag.StringVar(&cli.UI.Root, "rohost", cli.UI.Root, "RedOctober URL Base (ex: localhost:8080)") flag.StringVar(&cli.UI.Static, "static", cli.UI.Static, "Path to override built-in index.html") flag.BoolVar(&cli.Server.Systemd, "systemdfds", cli.Server.Systemd, "Use systemd socket activation to listen on a file. Useful for binding privileged sockets.") flag.StringVar(&vaultPath, "vaultpath", "diskrecord.json", "Path to the the disk vault") flag.Parse() } //go:generate go run generate.go func main() { registerCli() var err error if confFile != "" { cfg, err = config.Load(confFile) if err != nil { log.Fatal(err) } } else { cfg = cli } report.Init(cfg) if vaultPath == "" || !cfg.Valid() { if !cfg.Valid() { fmt.Fprintf(os.Stderr, "Invalid config.\n") } fmt.Fprint(os.Stderr, usage) flag.PrintDefaults() os.Exit(2) } if err := core.Init(vaultPath, cfg); err != nil { report.Check(err, nil) log.Fatal(err) } initPrometheus() cpaths := strings.Split(cfg.Server.CertPaths, ",") kpaths := strings.Split(cfg.Server.KeyPaths, ",") s, l, err := server.NewServer(cfg.UI.Static, cfg.Server.Addr, cfg.Server.CAPath, cpaths, kpaths, cfg.Server.Systemd) if err != nil { report.Check(err, nil) log.Fatalf("Error starting redoctober server: %s\n", err) } log.Printf("http.serve start: addr=%s", cfg.Server.Addr) report.Recover(func() { err := s.Serve(l) report.Check(err, nil) log.Fatal(err.Error()) }) }