func Run() {
	flag.Parse()
	module := getBuildModule()
	cleanModVersion := strings.TrimPrefix(module.Version, "v")
	casket.AppName = appName
	casket.AppVersion = module.Version
	casket.OnProcessExit = append(casket.OnProcessExit, certmagic.CleanUpOwnLocks)
	certmagic.UserAgent = appName + "/" + cleanModVersion
	if !logTimestamps {
		log.SetFlags(0)
	}
	switch logfile {
	case "stdout":
		log.SetOutput(os.Stdout)
	case "stderr":
		log.SetOutput(os.Stderr)
	case "":
		log.SetOutput(ioutil.Discard)
	default:
		if logRollMB > 0 {
			log.SetOutput(&lumberjack.Logger{
				Filename:   logfile,
				MaxSize:    logRollMB,
				MaxAge:     14,
				MaxBackups: 10,
				Compress:   logRollCompress,
			})
		} else {
			err := os.MkdirAll(filepath.Dir(logfile), 0755)
			if err != nil {
				mustLogFatalf("%v", err)
			}
			f, err := os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				mustLogFatalf("%v", err)
			}
			log.SetOutput(f)
		}
	}
	if err := LoadEnvFromFile(envFile); err != nil {
		mustLogFatalf("%v", err)
	}
	if printEnv {
		for _, v := range os.Environ() {
			fmt.Println(v)
		}
	}
	if EnableTelemetry {
		err := initTelemetry()
		if err != nil {
			mustLogFatalf("[ERROR] Initializing telemetry: %v", err)
		}
	} else if disabledMetrics != "" {
		mustLogFatalf("[ERROR] Cannot disable specific metrics because telemetry is disabled")
	}
	if revoke != "" {
		err := caskettls.Revoke(revoke)
		if err != nil {
			mustLogFatalf("%v", err)
		}
		fmt.Printf("Revoked certificate for %s\n", revoke)
		os.Exit(0)
	}
	if version {
		if module.Sum != "" {
			fmt.Printf("Casket %s (%s)\n", module.Version, module.Sum)
		} else {
			fmt.Println(module.Version)
		}
		os.Exit(0)
	}
	if plugins {
		fmt.Println(casket.DescribePlugins())
		os.Exit(0)
	}
	checkJSONCasketfile()
	err := setCPU(cpu)
	if err != nil {
		mustLogFatalf("%v", err)
	}
	casket.EmitEvent(casket.StartupEvent, nil)
	casketfileinput, err := casket.LoadCasketfile(serverType)
	if err != nil {
		mustLogFatalf("%v", err)
	}
	if validate {
		err := casket.ValidateAndExecuteDirectives(casketfileinput, nil, true)
		if err != nil {
			mustLogFatalf("%v", err)
		}
		msg := "Casketfile is valid"
		fmt.Println(msg)
		log.Printf("[INFO] %s", msg)
		os.Exit(0)
	}
	log.Printf("[INFO] Casket version: %s", module.Version)
	instance, err := casket.Start(casketfileinput)
	if err != nil {
		mustLogFatalf("%v", err)
	}
	telemetry.Set("casket_version", module.Version)
	telemetry.Set("num_listeners", len(instance.Servers()))
	telemetry.Set("server_type", serverType)
	telemetry.Set("os", runtime.GOOS)
	telemetry.Set("arch", runtime.GOARCH)
	telemetry.Set("cpu", struct {
		BrandName  string `json:"brand_name,omitempty"`
		NumLogical int    `json:"num_logical,omitempty"`
		AESNI      bool   `json:"aes_ni,omitempty"`
	}{
		BrandName:  cpuid.CPU.BrandName,
		NumLogical: runtime.NumCPU(),
		AESNI:      cpuid.CPU.AesNi(),
	})
	if containerized := detectContainer(); containerized {
		telemetry.Set("container", containerized)
	}
	telemetry.StartEmitting()
	instance.Wait()
}
Run is Casket's main() function.
package casketmain
import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"runtime/debug"
	"strconv"
	"strings"
	"github.com/google/uuid"
	"github.com/klauspost/cpuid"
	"github.com/tmpim/casket"
	"github.com/tmpim/casket/casketfile"
	"github.com/tmpim/casket/caskettls"
	"github.com/tmpim/casket/telemetry"
	"github.com/tmpim/certmagic"
	lumberjack "gopkg.in/natefinch/lumberjack.v2"
	_ "github.com/tmpim/casket/caskethttp"  
)
func init() {
	casket.TrapSignals()
	flag.BoolVar(&certmagic.Default.Agreed, "agree", true, "Agree to the CA's Subscriber Agreement")
	flag.StringVar(&certmagic.Default.CA, "ca", certmagic.Default.CA, "URL to certificate authority's ACME server directory")
	flag.StringVar(&certmagic.Default.DefaultServerName, "default-sni", certmagic.Default.DefaultServerName, "If a ClientHello ServerName is empty, use this ServerName to choose a TLS certificate")
	flag.BoolVar(&certmagic.Default.DisableHTTPChallenge, "disable-http-challenge", certmagic.Default.DisableHTTPChallenge, "Disable the ACME HTTP challenge")
	flag.BoolVar(&certmagic.Default.DisableTLSALPNChallenge, "disable-tls-alpn-challenge", certmagic.Default.DisableTLSALPNChallenge, "Disable the ACME TLS-ALPN challenge")
	flag.StringVar(&disabledMetrics, "disabled-metrics", "", "Comma-separated list of telemetry metrics to disable")
	flag.StringVar(&conf, "conf", "", "Casketfile to load (default \""+casket.DefaultConfigFile+"\")")
	flag.StringVar(&cpu, "cpu", "100%", "CPU cap")
	flag.BoolVar(&printEnv, "env", false, "Enable to print environment variables")
	flag.StringVar(&envFile, "envfile", "", "Path to file with environment variables to load in KEY=VALUE format")
	flag.BoolVar(&fromJSON, "json-to-casketfile", false, "From JSON stdin to Casketfile stdout")
	flag.BoolVar(&plugins, "plugins", false, "List installed plugins")
	flag.StringVar(&certmagic.Default.Email, "email", "", "Default ACME CA account email address")
	flag.DurationVar(&certmagic.HTTPTimeout, "catimeout", certmagic.HTTPTimeout, "Default ACME CA HTTP timeout")
	flag.StringVar(&logfile, "log", "", "Process log file")
	flag.BoolVar(&logTimestamps, "log-timestamps", true, "Enable timestamps for the process log")
	flag.IntVar(&logRollMB, "log-roll-mb", 100, "Roll process log when it reaches this many megabytes (0 to disable rolling)")
	flag.BoolVar(&logRollCompress, "log-roll-compress", true, "Gzip-compress rolled process log files")
	flag.StringVar(&casket.PidFile, "pidfile", "", "Path to write pid file")
	flag.BoolVar(&casket.Quiet, "quiet", false, "Quiet mode (no initialization output)")
	flag.StringVar(&revoke, "revoke", "", "Hostname for which to revoke the certificate")
	flag.StringVar(&serverType, "type", "http", "Type of server to run")
	flag.BoolVar(&toJSON, "casketfile-to-json", false, "From Casketfile stdin to JSON stdout")
	flag.BoolVar(&version, "version", false, "Show version")
	flag.BoolVar(&validate, "validate", false, "Parse the Casketfile but do not start the server")
	casket.RegisterCasketfileLoader("flag", casket.LoaderFunc(confLoader))
	casket.SetDefaultCasketfileLoader("default", casket.LoaderFunc(defaultLoader))
}